jest-styled-components
jest-styled-components copied to clipboard
Cannot read property 'style' or 'filter' of undefined (react-native)
Probably related to #110.
I have themed styled-components for React Native and am testing them with just jest and react-test-renderer. The test for this example should pass, according to the theming section of the docs:
import { View } from 'react-native'
import renderer from 'react-test-renderer'
import styled from 'styled-components'
const theme = {
primary: '#000000'
}
const Foo = styled(View)`
background-color: ${props => props.theme.primary};
`
describe('Foo', () => {
it('renders the background color', () => {
const tree = renderer.create(<Foo theme={theme} />).toJSON()
expect(tree).toHaveStyleRule('background-color', '#000000')
})
})
I receive TypeError: Cannot read property 'filter' of undefined
, which stems from here but I couldn't tell you why it won't filter through the style prop.
I have jest-styled-components/native
imported in a test setup file, but other than that I have no other configs. Node versions are the same, packages are all latest versions.
Did you have any luck resolving this issue? I am also experiencing the same problem.
@connected-space Unfortunately I didn't and it's now a blocker for me. Hopefully someone will chime in soon.
Same problem here:
TypeError: Cannot read property 'filter' of undefined
16 | // Assert
17 | expect(getByTestId('label').props.children).toBe(label);
> 18 | expect(getByTestId('wrapper')).toHaveStyleRule('color', 'red');
| ^
19 | });
20 | });
21 | });
at Object.toHaveStyleRule (node_modules/jest-styled-components/src/native/toHaveStyleRule.js:4:38)
at Object.throwingMatcher (node_modules/expect/build/index.js:320:33)
at Object.<anonymous> (src/components/atoms/DatePicker/DatePicker.test.js:18:38)
I am also using react-native-testing-library
in my tests.
I don't know about other versions of styled-components
with react-native, but I'm using version 4.2 and using jest-styled-components
in react-native the styles are no longer added as a prop to the actual component. If using react-test-renderer
you can find your component in the result of calling toJSON() and it'll work:
// ...
import renderer from 'react-test-renderer'
import 'jest-styled-components'
const StyledButton = styled(Button)`
background-color: red;
`
test('nested styles', () => {
const jsonTree = renderer.create(<View><StyledButton>Test</StyledButton></View>)
const buttonComponent = jsonTree.children[0]
expect(buttonComponent).toHaveStyleRule('background-color','red')
})
However, this isn't practical if you're using react-native-testing-library
or native-testing-library
, or even if you want to find a deeply nested native component to check the styles on it, so I found the following work-around:
- Don't use
jest-styled-components/native
butjest-styled-components
- Force the component
$$typeof
property to act as if it were being generated from a toJSON() tree, like in the following example:
// ...
import { render } from 'native-testing-library'
import 'jest-styled-components'
const StyledButton = styled(Button)`
background-color: red;
`
test('nested styles', () => {
const { getByTestId } = render(<View><StyledButton testID='myTestTarget'>Test</StyledButton></View>)
const buttonComponent = getByTestId('myTestTarget')
// This below is the work-around, is basically faking the component as a 'react.test.json' one
buttonComponent.$$typeof = Symbol.for('react.test.json')
expect(buttonComponent).toHaveStyleRule('background-color','red')
})
This is obviously not ideal, but it'll work while jest-styled-component
adds support for v4 of styled-components
including for react-native
Iām having the same issue.
My environment is:
"jest": "24.9.0",
"jest-expo": "^36.0.1",
"jest-styled-components": "^7.0.0",
"styled-components": "5.0.0",
"react-native-testing-library": "^1.12.0"
Who are the maintainers of this?? I'm still seeing this same issue, over a year later. š
`ā should render
TypeError: Cannot read property 'primary' of undefined
5 | console.log(theme.colors.primary);
6 | const H1 = styled.h1`
> 7 | color: ${props => props.theme.colors.primary};
| ^
8 | font-size: ${props => props.theme.fontSize.heading1};
9 | font-weight: ${props => props.theme.fontWeight.bold};
10 | text-align: center;
`
Is there any solution for this? Im also facing same issue. Using styled components and trying to test it with react testing library... throws me error
im stuck with this! :(
I had experienced this problem too. Then I realized I had accidentally imported styled
from styled-components
and not styled-components/native
when styling the component I was testing.
Hope that helps someone.
Same here :(
@jrapala Thanks! For me, I was using styled-components/native
for all my components, but things like DefaultTheme and ThemeProvider was being imported from styled-components
! I didn't know styled-components/native
also had ThemeProvider and all
I had the same error, but I was able to fix it by changing the folder name from styled-components
to styledComponents
. So make sure there's no file or folder named styled-components
.
Hi! i'm getting the same issue with the latest stable version of react native and everything that comes prepackaged, with the following configuration:
package.json:
{
"dependencies": {
"@react-native-community/masked-view": "^0.1.10",
"@react-native-firebase/app": "^10.8.0",
"@react-native-firebase/auth": "^10.8.0",
"@react-navigation/drawer": "^5.12.3",
"@react-navigation/native": "^5.9.2",
"@react-navigation/stack": "^5.14.2",
"formik": "^2.2.6",
"react": "16.13.1",
"react-native": "0.63.4",
"react-native-gesture-handler": "^1.10.1",
"react-native-paper": "^4.7.1",
"react-native-reanimated": "^1.13.2",
"react-native-safe-area-context": "^3.1.9",
"react-native-screens": "^2.17.1",
"react-native-svg": "^12.1.0",
"react-native-vector-icons": "^8.0.0",
"styled-components": "^5.2.1",
"yup": "^0.32.9"
},
"devDependencies": {
"@babel/core": "^7.8.4",
"@babel/runtime": "^7.8.4",
"@react-native-community/eslint-config": "^1.1.0",
"babel-jest": "^25.1.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6",
"enzyme-to-json": "^3.6.1",
"eslint": "^6.5.1",
"jest": "^25.1.0",
"jest-environment-enzyme": "^7.1.2",
"jest-enzyme": "^7.1.2",
"jest-styled-components": "^7.0.3",
"metro-react-native-babel-preset": "^0.59.0",
"react-dom": "16.13.1",
"react-native-svg-transformer": "^0.14.3",
"react-test-renderer": "16.13.1"
},
"jest": {
"preset": "react-native",
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
},
"testEnvironment": "enzyme",
"testEnvironmentOptions": {
"enzymeAdapter": "react16"
},
"collectCoverage": true,
"collectCoverageFrom": [
"<rootDir>/src/**/**.js"
],
"coverageThreshold": {
"global": {
"branches": 90,
"functions": 90,
"lines": 90,
"statements": 90
}
},
"setupFilesAfterEnv": [
"jest-enzyme",
"<rootDir>/jest.setup.js",
"<rootDir>/node_modules/react-native-gesture-handler/jestSetup.js"
],
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|@?react-navigation)"
]
},
"resolutions": {
"styled-components": "^5"
}
}
babel.config.js:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
env: {
production: {
plugins: ['react-native-paper/babel'],
},
},
};
jest.setup.js:
import 'react-native-gesture-handler/jestSetup';
import 'jest-styled-components/native'; // doesn't work!
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
const {JSDOM} = require('jsdom');
const jsdom = new JSDOM();
const {window} = jsdom;
function copyProps(src, target) {
const props = Object.getOwnPropertyNames(src)
.filter((prop) => typeof target[prop] === 'undefined')
.map((prop) => Object.getOwnPropertyDescriptor(src, prop));
Object.defineProperties(target, props);
}
global.window = window;
global.document = window.document;
global.navigator = {
userAgent: 'node.js',
};
copyProps(window, global);
jest.mock('react-native-reanimated', () => {
const Reanimated = require('react-native-reanimated/mock');
// The mock for `call` immediately calls the callback which is incorrect
// So we override it with a no-op
Reanimated.default.call = () => {};
return Reanimated;
});
import {NativeModules} from 'react-native';
NativeModules.RNGestureHandlerModule = {
attachGestureHandler: jest.fn(),
createGestureHandler: jest.fn(),
dropGestureHandler: jest.fn(),
updateGestureHandler: jest.fn(),
State: {},
Directions: {},
};
NativeModules.ImagePickerManager = {
showImagePicker: jest.fn(),
};
NativeModules.Linking = {
canOpenUrl: jest.fn().mockResolvedValue(true),
openUrl: jest.fn().mockResolvedValue(true),
};
NativeModules.Platform = {
OS: 'iOS',
};
jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper');
jest.mock('react-native/Libraries/Animated/src/animations/TimingAnimation');
Enzyme.configure({adapter: new Adapter()});
I've been reading both this repo's issues, and stack overflow answers, but couldn't find any solution...The error i'm getting is:
TypeError: Cannot read property 'filter' of undefined
at Object.toHaveStyleRule (.../node_modules/jest-styled-components/src/native/toHaveStyleRule.js:4:40)
at __EXTERNAL_MATCHER_TRAP__ (.../node_modules/expect/build/index.js:342:30)
at Object.throwingMatcher (.../node_modules/expect/build/index.js:343:15)
at .../src/components/atoms/snackbar/snackbar.style.spec.js:26:60
at Object.<anonymous> (.../node_modules/jest-each/build/bind.js:76:13)
at Object.asyncJestTest (.../node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:100:37)
at .../node_modules/jest-jasmine2/build/queueRunner.js:45:12
at new Promise (<anonymous>)
at mapper (.../node_modules/jest-jasmine2/build/queueRunner.js:28:19)
at .../node_modules/jest-jasmine2/build/queueRunner.js:75:41
at processTicksAndRejections (internal/process/task_queues.js:93:5)
Any help would be appreciated!