I am trying to test my component with jest and enzyme but unfortunately it can't find the style.
Here is the component:
interface StyledProps {
fluid: boolean;
}
const Button = styled(TouchableOpacity)<StyledProps>`
align-items: center;
justify-content: center;
${({ fluid }: StyledProps) => fluid && { width: '100%' }};
`;
const ButtonText = (styled as any).Text({
color: #fff,
fontSize: 16,
});
const GradientButton = ({ testID, onPress, title, fluid = false }: GradientButtonProps) => {
return (
<Button fluid={fluid} {...testLabel(testID)} onPress={onPress}>
<ButtonText>{title}</ButtonText>
</Button>
);
};
export default GradientButton;
And here is the test:
let wrapper: ShallowWrapper;
const component = <GradientButton testID={TEST_ID} title={TITLE} onPress={onPressSpy} />;
beforeEach(() => {
wrapper = shallow(component);
});
describe('<GradientButton />', () => {
it('renders fluid', () => {
wrapper.setProps({
fluid: true,
})
expect(wrapper).toHaveStyleRule('width', '100%');
});
});
Which gives me: No style rules found on passed Component
package.json:
"react": "16.5.1",
"styled-components": "^3.4.10",
"react-native": "0.57.1",
"jest-styled-components": "^6.2.2",
Thanks for opening this issue, @jmacioszek.
The test says "No style rules found on passed Component" because you are shallow rendering and the children components don't get resolved.
If you use mount, the tests will work.
I hope this helps.
@MicheleBertoli Thanks for your reply.
I've changed the code to work with mount (please note, it's react-native)
Now my test look as follows:
const component = (
<GradientButton testID={TEST_ID} title={TITLE} onPress={onPressSpy} fluid={true} />
);
describe('..', () => {
it('renders as fluid', () => {
const wrapper = mount(component);
expect(wrapper).toHaveStyleRule('width', '100%');
});
})
That unfortunately throws TypeError: Cannot read property '0' of undefined
@MicheleBertoli
TypeError: Cannot read property '0' of undefined was an issue on my side and bad styles passed to ButtonText.
Anyway, I have made mount to work in the following way (inside of jest setup file):
require('react-native-mock-render/mock');
const jsdom = require('jsdom');
const { JSDOM } = jsdom;
const { document } = new JSDOM('').window;
const g = global as any;
g.document = document;
g.window = document.defaultView;
Object.keys(document.defaultView).forEach(property => {
if (typeof g[property] === 'undefined') {
g[property] = document.defaultView[property];
}
});
Then the same test:
const component = (
<GradientButton testID={TEST_ID} title={TITLE} onPress={onPressSpy} fluid={true} />
);
describe('..', () => {
it('renders as fluid', () => {
const wrapper = mount(component);
expect(wrapper).toHaveStyleRule('width', '100%');
});
})
Gives me the same error No style rules found on passed Component
I have also tried that way:
describe('..', () => {
it('renders as fluid', () => {
const wrapper = mount(component);
expect(wrapper.find('TouchableOpacity').toHaveStyleRule('width', '100%');
});
})
What gives the same error.
However snapshot looks like that:
<TouchableOpacity
activeOpacity={0.2}
fluid={true}
onPress={[MockFunction]}
style={
Array [
Object {
"alignItems": "center",
"justifyContent": "center",
"width": "100%",
},
undefined,
]
}
testID="GradientButton"
>
Most helpful comment
Thanks for opening this issue, @jmacioszek.
The test says "No style rules found on passed Component" because you are shallow rendering and the children components don't get resolved.
If you use mount, the tests will work.
I hope this helps.