// @flow import React, { Component } from 'react' import { shallow, mount } from 'enzyme' import { resetStyled, expectCSSMatches } from './utils' let styled describe('basic', () => { /** * Make sure the setup is the same for every test */ beforeEach(() => { styled = resetStyled() }) it('should not throw an error when called with a valid element', () => { expect(() => styled.div``).not.toThrowError() const FunctionalComponent = () =>
; class ClassComponent extends Component<*, *> { render() { return
} } const validComps = ['div', FunctionalComponent, ClassComponent] validComps.forEach(comp => { expect(() => { const Comp = styled(comp) shallow() }).not.toThrowError() }) }) it('should throw a meaningful error when called with an invalid element', () => { const FunctionalComponent = () =>
; class ClassComponent extends Component<*, *> { render() { return
} } const invalidComps = [ undefined, null, 123, [],
, , , ] invalidComps.forEach(comp => { expect(() => { // $FlowInvalidInputTest const Comp = styled(comp) shallow() // $FlowInvalidInputTest }).toThrow(`Cannot create styled-component for component: ${comp}`) }) }) it('should not inject anything by default', () => { styled.div`` expectCSSMatches('') }) it('should inject component class when rendered even if no styles are passed', () => { const Comp = styled.div`` shallow() expectCSSMatches('.sc-a {}') }) it('should inject styles', () => { const Comp = styled.div` color: blue; ` shallow() expectCSSMatches('.sc-a { } .b { color:blue; }') }) it("should inject only once for a styled component, no matter how often it's mounted", () => { const Comp = styled.div` color: blue; ` shallow() shallow() expectCSSMatches('.sc-a {} .b { color:blue; }') }) it('Should have the correct styled(component) displayName', () => { const CompWithoutName = () => () =>
const StyledTag = styled.div`` expect(StyledTag.displayName).toBe('styled.div') const CompWithName = () =>
CompWithName.displayName = null const StyledCompWithName = styled(CompWithName)`` expect(StyledCompWithName.displayName).toBe('Styled(CompWithName)') const CompWithDisplayName = CompWithoutName() CompWithDisplayName.displayName = 'displayName' const StyledCompWithDisplayName = styled(CompWithDisplayName)`` expect(StyledCompWithDisplayName.displayName).toBe('Styled(displayName)') const CompWithBoth = () =>
CompWithBoth.displayName = 'displayName' const StyledCompWithBoth = styled(CompWithBoth)`` expect(StyledCompWithBoth.displayName).toBe('Styled(displayName)') const CompWithNothing = CompWithoutName() CompWithNothing.displayName = null const StyledCompWithNothing = styled(CompWithNothing)`` expect(StyledCompWithNothing.displayName).toBe('Styled(Component)') }) it('should allow you to pass in style objects', () => { const Comp = styled.div({ color: 'blue', }) shallow() expectCSSMatches('.sc-a {} .b { color:blue; }') }) it('should allow you to pass in a function returning a style object', () => { const Comp = styled.div(({ color }) => ({ color, })) shallow() expectCSSMatches('.sc-a {} .b { color:blue; }') }) describe('jsdom tests', () => { it('should pass the ref to the component', () => { const Comp = styled.div`` class Wrapper extends Component<*, *> { testRef: any; innerRef = (comp) => { this.testRef = comp } render() { return } } const wrapper = mount() const component = wrapper.find(Comp).first() expect(wrapper.instance().testRef).toBe(component.getDOMNode()) expect(component.find('div').prop('innerRef')).toBeFalsy() }) class InnerComponent extends Component<*, *> { render() { return null } } it('should not leak the innerRef prop to the wrapped child', () => { const OuterComponent = styled(InnerComponent)`` class Wrapper extends Component<*, *> { testRef: any; render() { return ( { this.testRef = comp }} /> ) } } const wrapper = mount() const innerComponent = wrapper.find(InnerComponent).first() expect(wrapper.instance().testRef).toBe(innerComponent.instance()) expect(innerComponent.prop('innerRef')).toBeFalsy() }) it('should pass the full className to the wrapped child', () => { const OuterComponent = styled(InnerComponent)`` class Wrapper extends Component<*, *> { render() { return } } const wrapper = mount() expect(wrapper.find(InnerComponent).prop('className')).toBe('test sc-a b') }) it('should pass the innerRef to the wrapped styled component', () => { const InnerComponent = styled.div`` const OuterComponent = styled(InnerComponent)`` class Wrapper extends Component<*, *> { testRef: any; innerRef = (comp) => { this.testRef = comp } render() { return } } const wrapper = mount() const innerComponent = wrapper.find(InnerComponent).first() const outerComponent = wrapper.find(OuterComponent).first() const wrapperNode = wrapper.instance() expect(wrapperNode.testRef).toBe(innerComponent.getDOMNode()) expect(innerComponent.prop('innerRef')).toBe(wrapperNode.innerRef) }) it('should respect the order of StyledComponent creation for CSS ordering', () => { const FirstComponent = styled.div` color: red; ` const SecondComponent = styled.div` color: blue; ` // NOTE: We're mounting second before first and check if we're breaking their order shallow() shallow() expectCSSMatches('.sc-a {} .d { color:red; } .sc-b {} .c { color:blue; }') }) it('handle media at-rules inside style rules', () => { const Comp = styled.div` > * { @media (min-width: 500px) { color: pink; } } ` shallow() expectCSSMatches( '.sc-a{ } @media (min-width:500px){ .b > *{ color:pink; } } ' ) }) it('should hoist non-react static properties', () => { const InnerComponent = styled.div`` InnerComponent.foo = 'bar' const OuterComponent = styled(InnerComponent)`` expect(OuterComponent).toHaveProperty('foo', 'bar') }) it('should not hoist styled component statics', () => { const InnerComponent = styled.div`` const OuterComponent = styled(InnerComponent)`` expect(OuterComponent.styledComponentId).not.toBe( InnerComponent.styledComponentId ) expect(OuterComponent.componentStyle).not.toEqual( InnerComponent.componentStyle ) }) it('generates unique classnames when not using babel', () => { const Named1 = styled.div.withConfig({ displayName: 'Name' })` color: blue; ` const Named2 = styled.div.withConfig({ displayName: 'Name' })` color: red; ` expect(Named1.styledComponentId).not.toBe(Named2.styledComponentId) }) it('honors a passed componentId', () => { const Named1 = styled.div.withConfig({ componentId: 'foo', displayName: 'Name', })` color: blue; ` const Named2 = styled.div.withConfig({ componentId: 'bar', displayName: 'Name', })` color: red; ` expect(Named1.styledComponentId).toBe('Name-foo') expect(Named2.styledComponentId).toBe('Name-bar') }) }) })