in our project we use react-intl for internationalisation. We are using jest as the testing framework and we decided to move our unit test utility library from enzyme to react-testing-library. But now, since there is no shallow rendering, I have to provide <IntlProvider ... /> in the test myself, no problem. But even if I do that, when testing terminal says Invalid hook call. Hooks can only be called inside of the body of a function component but when I run the project locally, no errors just runs normally as expected. P.S in the tests, Apollo provider works normally.
FirstNameFor.test.tsx
import { IntlProvider } from 'react-intl';
import { createMockClient } from 'mock-apollo-client';
import { ApolloProvider as ApolloProviderHooks } from '#apollo/react-hooks';
import { ApolloProvider } from 'react-apollo';
const wrapper = (mockProps, mockClient) => {
return (
<ApolloProvider client={mockClient}>
<ApolloProviderHooks client={mockClient}>
<IntlProvider locale="en">
<FirstNameForm
handleNext={mockProps.handleNext}
onboardingState={mockProps.onboardingState}
setHelpContent={mockProps.setHelpContent}
updateOnboardingState={mockProps.updateOnboardingState}
/>
</IntlProvider>
</ApolloProviderHooks>
</ApolloProvider>
);
};
describe('FirstNameForm Container', () => {
afterEach(() => {
jest.clearAllMocks();
cleanup();
});
it('should match snapshot', () => {
// Arrange
const mockProps = {
handleNext: jest.fn(),
onboardingState: {},
setHelpContent: jest.fn(),
updateOnboardingState: jest.fn(),
};
const mockClient = createMockClient();
// Act
const component = render(wrapper(mockProps, mockClient));
// Assert
expect(component).toMatchSnapshot();
});
});
FirstNameForm.tsx
export const FirstNameForm: React.FC<StepContentProps> = props => {
const [showMessageMutation] = useShowMessageMutation();
const intl = useIntl();
const formik = useFormik<FirstNameFormValues>({
...,
});
return <FirstNameFormComponent formik={formik} intl={intl} />;
};
Terminal Screenshot
package.json
{
"private": true,
"proxy": "http://localhost:5000",
"version": "0.1.57",
"scripts": {
"dev": "yarn graphql:generate && SKIP_PREFLIGHT_CHECK=true react-app-rewired start",
"build": "SKIP_PREFLIGHT_CHECK=true react-app-rewired build",
"testonly": "SKIP_PREFLIGHT_CHECK=true react-app-rewired test --env=jsdom",
"coverage": "SKIP_PREFLIGHT_CHECK=true react-app-rewired test --env=jsdom --coverage",
},
"jest": {
"coveragePathIgnorePatterns": [
"/node_modules/",
"src/types/",
"src/config/analytics/mp.d.ts",
"src/config/analytics/ua.d.ts"
],
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"resolutions": {
"#types/react": "16.8.17"
},
"dependencies": {
"#apollo/react-hooks": "3.1.3",
"animated-scroll-to": "1.2.2",
"apollo-cache": "1.3.2",
"apollo-cache-inmemory": "1.6.3",
"apollo-client": "2.6.3",
"apollo-link": "1.2.12",
"apollo-link-context": "1.0.18",
"apollo-link-error": "1.1.11",
"apollo-link-http": "1.5.15",
"apollo-link-ws": "1.0.18",
"apollo-utilities": "1.3.2",
"big.js": "5.2.2",
"copy-to-clipboard": "3.2.0",
"core-js": "3.0.1",
"date-fns": "1.30.1",
"downloadjs": "1.4.7",
"formik": "2.1.1",
"graphql": "14.3.0",
"graphql-subscriptions": "1.1.0",
"graphql-tag": "2.10.1",
"graphql-tools": "4.0.4",
"history": "4.9.0",
"intl": "1.2.5",
"js-cookie": "2.2.0",
"lodash": "4.17.11",
"owasp-password-strength-test": "1.3.0",
"qrcode.react": "0.9.3",
"query-string": "6.5.0",
"react": "16.8.6",
"react-apollo": "3.1.3",
"react-dom": "16.8.6",
"react-google-recaptcha": "1.1.0",
"react-intl": "3.1.8",
"react-router-dom": "5.1.0",
"recompose": "0.30.0",
"regenerator-runtime": "0.13.2",
"subscriptions-transport-ws": "0.9.16",
"validator": "10.11.0",
"victory": "34.0.0",
"yup": "0.27.0"
},
"devDependencies": {
"#apollo/react-testing": "3.1.3",
"#babel/cli": "7.4.4",
"#babel/core": "7.4.4",
"#babel/preset-env": "7.4.4",
"#graphql-codegen/add": "1.8.1",
"#graphql-codegen/cli": "1.8.1",
"#graphql-codegen/fragment-matcher": "1.8.1",
"#graphql-codegen/typescript": "1.8.1",
"#graphql-codegen/typescript-operations": "1.8.1",
"#graphql-codegen/typescript-react-apollo": "1.8.1",
"#testing-library/react": "10.0.4",
"#testing-library/jest-dom": "5.8.0",
"#types/testing-library__react": "10.0.1",
"#types/big.js": "4.0.5",
"#types/downloadjs": "1.4.1",
"#types/enzyme": "3.10.5",
"#types/graphql": "14.2.0",
"#types/js-cookie": "2.2.2",
"#types/node": "12.0.0",
"#types/owasp-password-strength-test": "1.3.0",
"#types/prop-types": "15.7.1",
"#types/qrcode.react": "0.8.2",
"#types/query-string": "6.3.0",
"#types/react": "16.8.17",
"#types/react-dom": "16.8.4",
"#types/react-google-recaptcha": "1.0.0",
"#types/react-router-dom": "5.1.0",
"#types/react-test-renderer": "16.9.0",
"#types/recompose": "0.30.6",
"#types/validator": "10.11.0",
"#types/victory": "33.1.0",
"#types/ws": "6.0.1",
"#types/yup": "0.26.13",
"babel-loader": "8.0.6",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.2",
"enzyme-to-json": "3.4.4",
"jest-canvas-mock": "2.2.0",
"jest-localstorage-mock": "2.4.0",
"merge-graphql-schemas": "1.5.8",
"npm-run-all": "4.1.5",
"patch-package": "6.1.2",
"postinstall-postinstall": "2.0.0",
"react-app-rewired": "2.1.3",
"react-scripts": "3.3.0",
"react-test-renderer": "16.8.6",
"source-map-explorer": "1.8.0",
"ts-jest": "25.3.1",
"ts-node": "8.1.0",
"typescript": "3.5.3"
}
}
The error comes from React itself, and most likely has nothing to do with react-intl.
There's a good chance you have multiple instances of React in conflict, for some reason only occurring in the test environment. I suspect it might have to do with react-app-rewired, not sure though.
The steps from the official help doc should help reveal whether duplicate Reacts is the source of the problem.
If that is the reason, here's some of the top solutions from the community:
Modify your webpack config to resolve the react alias (discussion)
resolve: {
alias: {
react: path.resolve('./node_modules/react'),
}
},
Modify your webpack config to set react as an external (PR example)
externals: {
react: 'react'
}
Or one of these other miscellaneous approaches
Related
I am making my first ever unit tests with Jest and React Testing Library on my react app.
This is a project I took over and has some pre-existing configuration and test setup which I'll admit I may not fully understand.
How I got to this error is this:
I already had one test up and running testing a component that doesn't use redux.
My next test needed to test a component that uses Redux and so I started to look at totally using React Testing Library and dropping Enzyme all together as the Enzyme isnt compatible with the latest React.
I kept getting an error along the lines of 'cannot import modules outside of node modules' and found out that babel cannot parse ES6.
And so I have been scouring the internet looking for solutions...
I have tried a few methods:
#babel/plugin-syntax-jsx
#babel/preset-react
most recently
However it seems it was not being picked up on as I was still getting the same error with the same suggestion which was:
Add #babel/preset-react (https://git.io/JfeDR) to the 'presets' section of your Babel config to enable transformation.
If you want to leave it as-is, add #babel/plugin-syntax-jsx (https://git.io/vb4yA) to the 'plugins' section to enable parsing.
I have added this to the presets and plugins of my babel config in my package-lock but still got the same error.
I also tried adding a .babelrc and babel.config.js file with the same preset and plugins but still get the same error.
There was some pre-existing code which I think could potentially be screwing things up somehow but I do not entirely understand it I'll be honest.
This is my package-lock:
{
"name": "hiro-flash",
"version": "0.1.0",
"private": true,
"dependencies": {
"#material-ui/core": "^4.11.4",
"#sentry/react": "^5.29.2",
"#sentry/tracing": "^5.29.2",
"autoprefixer": "7.1.6",
"axios": "^0.18.0",
"axios-cache-adapter": "^2.3.3",
"babel-core": "6.26.0",
"babel-eslint": "^8.2.6",
"babel-jest": "20.0.3",
"babel-loader": "7.1.2",
"babel-preset-react-app": "^3.1.2",
"babel-runtime": "6.26.0",
"bluebird": "^3.5.1",
"case-sensitive-paths-webpack-plugin": "2.1.1",
"chalk": "1.1.3",
"copy-to-clipboard": "^3.3.1",
"css-loader": "0.28.7",
"detect-browser": "^2.5.0",
"dotenv": "4.0.0",
"dotenv-expand": "4.2.0",
"eslint": "^4.19.1",
"eslint-config-react-app": "^2.1.0",
"eslint-loader": "1.9.0",
"eslint-plugin-flowtype": "2.39.1",
"eslint-plugin-import": "2.8.0",
"eslint-plugin-jsx-a11y": "5.1.1",
"eslint-plugin-react": "7.4.0",
"export-to-csv": "^0.2.1",
"express": "^4.16.3",
"extract-text-webpack-plugin": "3.0.2",
"file-loader": "1.1.5",
"file-saver": "^2.0.5",
"fs-extra": "3.0.1",
"html-webpack-plugin": "2.29.0",
"jest": "26.6.3",
"jest-cli": "26.6.3",
"jest-esm-transformer": "^1.0.0",
"jquery": "^3.3.1",
"jszip": "^3.6.0",
"jszip-utils": "^0.1.0",
"lodash": "^4.17.10",
"moment": "2.18.1",
"moment-business-days": "^1.1.3",
"moment-timezone": "^0.5.23",
"npm": "^5.10.0",
"object-assign": "4.1.1",
"path": "^0.12.7",
"postcss-flexbugs-fixes": "3.2.0",
"postcss-loader": "2.0.8",
"promise": "8.0.1",
"prop-types": "^15.6.2",
"raf": "3.4.0",
"react": "latest",
"react-accessible-accordion": "^3.3.3",
"react-dates": "^21.2.1",
"react-datetime": "^2.15.0",
"react-dev-utils": "^5.0.2",
"react-device-detect": "^1.9.10",
"react-dom": "latest",
"react-dropzone": "^11.3.2",
"react-ga": "3.2.0",
"react-hotjar": "^2.2.1",
"react-hover-observer": "^2.1.0",
"react-html-parser": "^2.0.2",
"react-quill": "^1.3.1",
"react-redux": "^5.0.7",
"react-responsive-modal": "^2.1.0",
"react-router": "^3.0.0",
"react-router-redux": "^4.0.8",
"react-select": "^2.0.0",
"react-sizes": "^1.0.4",
"react-table": "6.8.6",
"react-throttle-render": "^2.0.0",
"react-tippy": "^1.2.2",
"react-toastify": "^6.0.9",
"react-tooltip": "^4.2.11",
"recharts": "^1.8.5",
"redux": "^3.7.2",
"redux-api-middleware": "^2.3.0",
"redux-logger": "^3.0.6",
"redux-saga": "^0.16.0",
"redux-thunk": "^2.3.0",
"style-loader": "0.19.0",
"sw-precache-webpack-plugin": "0.11.4",
"url-loader": "0.6.2",
"webpack": "3.8.1",
"webpack-dev-server": "2.9.4",
"webpack-manifest-plugin": "1.3.2",
"whatwg-fetch": "2.0.3",
"xlsx": "^0.16.9"
},
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js"
},
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,mjs}"
],
"setupFiles": [
"<rootDir>/config/polyfills.js"
],
"testMatch": [
"<rootDir>/src/**/__tests__/**/*.{js,jsx,mjs}",
"<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"
],
"testEnvironment": "jsdom",
"testURL": "http://localhost",
"transform": {
"^.+\\.(js|jsx)$": "jest-esm-transformer",
"^.+\\.(mjs)$": "<rootDir>/node_modules/babel-jest",
"^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
"^(?!.*\\.(js|jsx|mjs|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
},
"transformIgnorePatterns": [
"[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"
],
"moduleNameMapper": {
"^react-native$": "react-native-web"
},
"moduleFileExtensions": [
"web.js",
"mjs",
"js",
"json",
"web.jsx",
"jsx",
"node"
]
},
"extensionsToTreatAsEsm": [
".js",
".jsx",
".ts"
],
"globals": {
"window": {
"location": {
"protocol": {}
}
}
},
"babel": {
"plugins": [
"#babel/plugin-syntax-jsx"
],
"presets": [
"#babel/preset-env",
"#babel/preset-react",
"react-app"
]
},
"eslintConfig": {
"extends": "react-app"
},
"devDependencies": {
"#babel/plugin-syntax-jsx": "^7.14.5",
"#testing-library/react": "^12.0.0",
"chai": "^4.2.0",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"node-sass": "^4.9.3",
"react-test-renderer": "^16.14.0",
"sass-loader": "^6.0.7",
"sinon": "^7.4.1"
}
}
this is my test:
import React from 'react';
import renderer from 'react-test-renderer';
import { PriceMonitor } from '../../components/priceMonitor/PriceMonitor';
describe('Price Monitor', () => {
const getTree = (activeUser = 'Test User 1', isOriginalUser = true, openPriceMonitorModal = jest.fn(),
resetActiveUser = jest.fn()) => {
const props = {
activeUser,
openPriceMonitorModal,
isOriginalUser,
resetActiveUser,
}
const component = renderer.create(<PriceMonitor {...props} />);
return component.toJSON();
}
const mockOnClick = jest.fn((username, newOriginalValue) => getTree(username, newOriginalValue));
it('renders original user (Test User 1)', () => {
const tree = getTree();
expect(tree).toMatchSnapshot();
});
it('changes user onClick (Test User 1 -> Test User 2)', () => {
const tree = getTree();
expect(tree).toMatchSnapshot();
expect(mockOnClick('Test User 2', false)).toMatchSnapshot();
});
it('renders non original user (Test User 2)', () => {
const tree = getTree('Test User 2', false)
expect(tree).toMatchSnapshot();
});
it('resets user onClick (Test User 2 -> Test User 1)', () => {
const tree = getTree('Test User 2', false);
expect(tree).toMatchSnapshot();
expect(mockOnClick('Test User 1', true)).toMatchSnapshot();
});
});
And then 2 files which were pre-existing,
this is test.js:
'use strict';
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'test';
process.env.NODE_ENV = 'test';
process.env.PUBLIC_URL = '';
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
throw err;
});
// Ensure environment variables are read.
require('../config/env');
const jest = require('jest');
const argv = process.argv.slice(2);
// Watch unless on CI or in coverage mode
if (!process.env.CI && argv.indexOf('--coverage') < 0) {
argv.push('--watch');
}
jest.run(argv);
fileTransform.js inside my jest folder:
'use strict';
const path = require('path');
// This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html
module.exports = {
process(src, filename) {
return `module.exports = ${JSON.stringify(path.basename(filename))};`;
},
};
Theres also a webpack.config.dev.js but Im not sure how much that is effecting this problem
Im a newb so apologies if this isnt clear enough - will be happy to provide more info.
This could be a very easy question, however I've not been able to find the answer for it anywhere.
How do I use a default locale with react-intl? Specifying a default message every time gets really messy. The way that I'm doing it at the moment doesn't seem to pick up the default message when the browser uses a locale that doesn't have a translation.
How I'm using it at the moment:
import React from 'react'
import { Route } from 'react-router-dom'
import { IntlProvider } from 'react-intl'
import { Provider } from 'react-redux'
import { MuiThemeProvider, CssBaseline } from '#material-ui/core'
// import translations
import da_translations from './translations/da.json'
import de_translations from './translations/de.json'
import el_translations from './translations/el.json'
import en_translations from './translations/en.json'
import defaultTheme from './themes/default'
import {
QueryParamProvider,
ExtendedStringifyOptions,
transformSearchStringJsonSafe,
} from 'use-query-params'
import configureStore from './redux/configure-store'
import { Routes } from './routes'
const store = configureStore()
const App = (): JSX.Element => {
const state = { locale: navigator.language.slice(0, 2) }
const messages: { [index: string]: any } = {
da: da_translations,
de: de_translations,
el: el_translations,
en: en_translations,
}
const queryStringifyOptions: ExtendedStringifyOptions = {
transformSearchString: transformSearchStringJsonSafe,
}
return (
<Provider store={store}>
<IntlProvider
defaultLocale={'en'}
locale={state.locale}
messages={messages[state.locale]}
>
<QueryParamProvider
ReactRouterRoute={Route}
stringifyOptions={queryStringifyOptions}
>
<MuiThemeProvider theme={defaultTheme}>
<CssBaseline />
<Routes />
</MuiThemeProvider>
</QueryParamProvider>
</IntlProvider>
</Provider>
)
}
export default App
edit:
package.json
{
"name": "myproj",
"version": "0.8.47",
"description": "frontend",
"private": false,
"main": "dist/index.js",
"dependencies": {
"#babel/register": "^7.12.1",
"#date-io/date-fns": "^1.3.13",
"#google-cloud/translate": "^6.0.3",
"#material-ui/core": "^4.11.1",
"#material-ui/icons": "4.2.1",
"#material-ui/lab": "^4.0.0-alpha.56",
"#material-ui/pickers": "^3.2.10",
"#types/axios": "^0.14.0",
"#types/history": "^4.7.3",
"#types/jest": "^24.9.1",
"#types/lodash": "^4.14.158",
"#types/node": "^12.12.7",
"#types/react": "^16.9.11",
"#types/react-dom": "^16.9.4",
"#types/react-html-parser": "^2.0.1",
"#types/react-intl": "^3.0.0",
"#types/react-redux": "^7.1.9",
"#types/react-resizable": "^1.7.2",
"#types/react-router-dom": "^5.1.2",
"#types/reselect": "^2.2.0",
"#types/seamless-immutable": "^7.1.13",
"accept-language": "^3.0.18",
"ag-grid-community": "^23.1.1",
"ag-grid-react": "^23.1.1",
"axios": "^0.19.1",
"chai": "^4.2.0",
"chartist": "0.10.1",
"classnames": "^2.2.6",
"clsx": "^1.1.0",
"date-fns": "^2.9.0",
"flexsearch": "^0.6.32",
"fs-extra": "^9.0.1",
"history": "4.9.0",
"immutable": "^4.0.0-rc.12",
"js-yaml": "^3.14.0",
"lodash": "^4.17.19",
"log4js": "^6.3.0",
"loglevel": "^1.6.6",
"minimist": "^1.2.5",
"perfect-scrollbar": "1.4.0",
"prop-types": "15.7.2",
"qs": "^6.9.4",
"query-string": "^6.13.1",
"react": "^16.12.0",
"react-chartist": "0.13.3",
"react-dom": "^16.12.0",
"react-google-maps": "9.4.5",
"react-html-parser": "^2.0.2",
"react-intl": "^3.11.0",
"react-redux": "^7.2.1",
"react-resizable": "^1.10.1",
"react-router-dom": "^5.1.2",
"react-scripts": "4.0.0",
"react-swipeable-views": "0.13.3",
"redux": "^4.0.5",
"redux-observable": "^1.2.0",
"reselect": "^4.0.0",
"seamless-immutable": "^7.1.4",
"use-query-params": "^1.1.6"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env jest-environment-jsdom-sixteen --verbose",
"eject": "react-scripts eject",
"install:clean": "rm -rf node_modules/ && rm -rf package-lock.json && npm install && npm start",
"lint:check": "eslint . --ext=js,jsx; exit 0",
"lint:fix": "eslint . --ext=js,jsx --fix; exit 0",
"build-package-css": "cp src/assets/css/material-dashboard-react.css dist/material-dashboard-react.css",
"build-package": "npm run build-package-css && babel src --out-dir dist"
},
"keywords": [],
"author": "tb",
"license": "MIT",
"homepage": "./",
"optionalDependencies": {
"#types/googlemaps": "3.37.3",
"#types/markerclustererplus": "2.1.33",
"ajv": "6.10.2"
},
"devDependencies": {
"#testing-library/dom": "^7.24.2",
"#testing-library/jest-dom": "^5.11.1",
"#testing-library/react": "^10.4.7",
"#testing-library/user-event": "^12.1.4",
"#types/chai": "^4.2.13",
"#types/classnames": "^2.2.10",
"#types/enzyme": "^3.10.5",
"#types/enzyme-adapter-react-16": "^1.0.6",
"#types/gulp": "^4.0.7",
"#types/jsdom": "^16.2.2",
"#typescript-eslint/eslint-plugin": "^4.7.0",
"#typescript-eslint/parser": "^4.7.0",
"axios-mock-adapter": "^1.18.2",
"cross-env": "^5.1.4",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"eslint-config-prettier": "6.0.0",
"eslint-plugin-prettier": "3.1.0",
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.2.0",
"gulp": "^4.0.2",
"gulp-append-prepend": "1.0.8",
"gulp-filter": "^6.0.0",
"gulp-prettier": "^3.0.0",
"husky": "^4.3.0",
"jest-environment-jsdom-sixteen": "^1.0.3",
"jsdom": "^16.2.2",
"prettier": "^2.1.2",
"pretty-quick": "^3.1.0",
"react-intl-translations-manager": "^5.0.3",
"ts-node": "^9.0.0",
"typescript": "^3.9.7"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": []
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged"
}
},
"jest": {
"transformIgnorePatterns": [
"node_modules/(?!(#ui5|lit-html)).*\\.js$"
]
}
}
I am trying to use react-redux hooks, however I get the error:
TypeError: (0 , _reactRedux.useDispatch) is not a function
Any ideas?
...
import { useDispatch, useSelector } from "react-redux";
import { StackActions, NavigationActions } from "react-navigation";
import CustomImage from "./CustomImage";
const VideoEpisode = props => {
const { id, title, description, video, preview, push, testLink } = props;
const dispatch = useDispatch();
return (
<TouchableHighlight
....
onPress={() => {
const resetAction = StackActions.reset({
...
});
dispatch(resetAction);
}}
>
...
</TouchableHighlight>
);
};
export default VideoEpisode;
package.json
{
"name": "iaapp",
"version": "0.0.1",
"scripts": {
"start": "react-native start",
"android": "react-native run-android",
"ios": "react-native run-ios",
"name": "Innovative Anatomy",
"flow": "flow",
"test": "node ./node_modules/jest/bin/jest.js --watchAll"
},
"jest": {
"preset": "react-native"
},
"dependencies": {
"#babel/plugin-proposal-decorators": "^7.4.4",
"#babel/runtime": "^7.0.0",
"#react-native-community/async-storage": "^1.6.1",
"react": "16.8.5",
"react-dom": "^16.8.6",
"react-native": "0.59.10",
"react-native-circular-progress": "^1.1.0",
"react-native-component-fade": "^1.0.2",
"react-native-elements": "^1.1.0",
"react-native-fade": "^1.0.3",
"react-native-fade-in-view": "^1.0.5",
"react-native-gesture-handler": "^1.1.0",
"react-native-responsive-image": "^2.3.1",
"react-native-share": "^1.2.1",
"react-native-splash-screen": "^3.2.0",
"react-native-svg": "^9.5.1",
"react-native-vector-icons": "^6.6.0",
"react-native-view-shot": "^2.6.0",
"react-native-webview": "^5.12.1",
"react-native-webview-bridge": "^0.40.1",
"react-navigation": "^3.0.9",
"react-navigation-backhandler": "^1.3.2",
"react-navigation-transitions": "^1.0.11",
"react-redux": "^7.1.0",
"redux": "^4.0.1",
"redux-persist": "^5.10.0",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"#babel/cli": "^7.5.5",
"#babel/core": "^7.5.5",
"#babel/preset-flow": "^7.0.0",
"jest": "^24.8.0",
"metro-react-native-babel-preset": "^0.54.1",
"prettier": "^1.18.2",
"react-native-dotenv": "^0.2.0",
"redux-logger": "^3.0.6"
},
"rnpm": {
"assets": [
"./assets/fonts"
]
},
"private": true
}
I had a similar problem with react.createcontext, and the only thing that seemed to work was to delete the node_modules folder and reinstall them (npm install).
Just make sure your package.json is configured correctly
Try upgrading your redux version { useDispatch } don't work on older ones
I also came around the same problem, tried everything deleting the node modules, clearing cache installing appropriate react-redux version but nothing worked. Later I found that the action which I was passing was not in proper format. Recheck the action action passed to dispatch function.
Fails to compile on using the simplest of grid implementations as follows. (But the same works on a react JS implementation)
Code is as follows for the react component.
import { connect } from 'react-redux';
import * as redux from 'redux';
import * as projectActions from '../../redux/actions/projectActions';
import * as authorActions from '../../redux/actions/authorActions';
import * as React from 'react';
import { bindActionCreators } from 'redux';
import { Project } from '../../interfaces/Project';
import { ApplicationState } from '../../redux/reducers/initialState';
import { Grid } from '#Progress/kendo-react-grid';
interface OwnProps {
}
type ReduxProps = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;
// type Props = StateFromProps & DispatchFromProps & NavbarComponentProps;
interface Pprops extends ReduxProps {
handleDeleteProject1: (project: Project) => void
}
class ProjectsPage extends React.Component<Pprops, any> {
state = {
redirectToAddProjectPage: false
};
componentDidMount() {
}
handleDeleteProject1 = async (project: Project) => {
}
render() {
return (
<>
<Grid></Grid>
</>
);
}
}
function mapStateToProps(
state: ApplicationState
, ownProps: OwnProps
) {
const projectsList = state.projectsStateSlice.projects;
return {
projects:
projectsList.map(project => {
const authorNamee = project.authorId.toString();
return {
...project,
authorName: authorNamee
};
}),
authors: state.authorsStateSlice.authors,
loading: 0
};
}
function mapDispatchToProps(dispatch: redux.Dispatch) {
return {
actions: {
loadProjects: bindActionCreators(projectActions.loadProjects, dispatch),
loadAuthors: bindActionCreators(authorActions.loadAuthors, dispatch),
deleteProject: bindActionCreators(projectActions.deleteProject, dispatch)
}
};
}
// prop types declarations
export default connect(mapStateToProps, mapDispatchToProps)(ProjectsPage);
My package.json is as follows:
{
"name": "cncy-react-redux",
"version": "0.1.0",
"private": true,
"scripts": {
"start:dev": "react-scripts start",
"prestart:api": "node tools/createMockDb.js",
"start:api": "node tools/apiServer.js",
"test": "jest",
"start": "run-p start:api start:dev"
},
"jest": {
"setupFiles": [
"./tools/testSetup.js"
],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|mp3|wav|m4a|aac|oga)$": "<rootDir>/tools/fileMock.js",
"\\.(css|less)$": "<rootDir>/tools/styleMock.js"
}
},
"dependencies": {
"#fortawesome/fontawesome-svg-core": "^1.2.26",
"#fortawesome/free-regular-svg-icons": "^5.12.0",
"#fortawesome/free-solid-svg-icons": "^5.12.0",
"#fortawesome/react-fontawesome": "^0.1.8",
"#reduxjs/toolkit": "^1.2.1",
"#testing-library/jest-dom": "^4.2.4",
"#testing-library/react": "^9.3.2",
"#testing-library/user-event": "^7.1.2",
"#types/bootstrap": "^4.3.1",
"#types/enzyme": "^3.10.4",
"#types/jest": "^24.0.24",
"#types/node": "^12.0.0",
"#types/react": "^16.9.0",
"#types/react-dom": "^16.9.0",
"#types/react-redux": "^7.1.5",
"#types/react-router-dom": "^5.1.3",
"#types/react-toastify": "^4.1.0",
"#types/redux": "^3.6.0",
"#types/redux-immutable-state-invariant": "^2.1.1",
"#types/redux-thunk": "^2.1.0",
"#types/reselect": "^2.2.0",
"bootstrap": "^4.4.1",
"immer": "2.1.3",
"node-sass": "^4.13.0",
"prop-types": "15.7.2",
"react": "^16.12.0",
"react-bootstrap": "^1.0.0-beta.16",
"react-dom": "^16.12.0",
"react-redux": "^7.1.3",
"react-router-dom": "^5.1.2",
"react-scripts": "3.3.0",
"react-toastify": "^5.4.1",
"redux": "^4.0.4",
"redux-immutable-state-invariant": "^2.1.0",
"redux-thunk": "^2.3.0",
"reselect": "^4.0.0",
"typescript": "~3.7.2",
"#progress/kendo-data-query": "1.5.2",
"#progress/kendo-date-math": "1.5.1",
"#progress/kendo-drawing": "1.6.0",
"#progress/kendo-react-animation": "3.9.0",
"#progress/kendo-react-buttons": "3.9.0",
"#progress/kendo-react-data-tools": "^3.9.0",
"#progress/kendo-react-dateinputs": "3.9.0",
"#progress/kendo-react-dialogs": "3.9.0",
"#progress/kendo-react-dropdowns": "3.9.0",
"#progress/kendo-react-excel-export": "3.9.0",
"#progress/kendo-react-grid": "3.9.0",
"#progress/kendo-react-inputs": "3.9.0",
"#progress/kendo-react-intl": "3.9.0",
"#progress/kendo-react-layout": "3.9.0",
"#progress/kendo-react-pdf": "3.9.0",
"#progress/kendo-react-popup": "3.9.0",
"react-transition-group": "4.3.0"
},
"devDependencies": {
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "1.11.2",
"fetch-mock": "^8.1.0",
"jest": "^24.9.0",
"json-server": "0.14.2",
"node-fetch": "^2.3.0",
"npm-run-all": "4.1.5",
"react-test-renderer": "16.8.4",
"react-testing-library": "^6.1.2",
"redux-immutable-state-invariant": "2.1.0",
"redux-mock-store": "^1.5.3",
"rimraf": "2.6.3",
"style-loader": "0.23.1"
},
"eslintConfig": {
"extends": "react-app",
"settings": {
"react": {
"version": "detect"
}
},
"root": true
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Throws the following error:
./src/components/projects/ProjectsPage.tsx
Cannot find file: 'main.js' does not match the corresponding name on disk: '.\node_modules#Progress\kendo-react-grid\dist\es#progress'.
When I dig into the node modules' directory that its claiming to throw the error from,
looks like this
.\node_modules#Progress\kendo-react-grid\dist\es\main.js
it doesn't apparently contain any directory called #progress inside of the es (.\node_modules#Progress\kendo-react-grid\dist\es#progress)
FYI: I also am a licensed developer.
Is this something to do with the licensing of the kendo UI by any chance?
This was too trivial. It was all about the wrong case I used inadvertently.
While importing the Grid control,
import { Grid } from '#Progress/kendo-react-grid';
It had to be #progress with "p" in lower case instead of #Progress.
That's it. But the error thrown would never have told me about this anyway.
Please be careful with the case.
Hope it helps someone.
I'm writing tests using Jest & Enzyme in React Native to fully test my components behaviors and inner functions.
Shallow test seems ok but when using mount it just throws
Here's my package.json.
{
"name": "Despirithium",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"buildandroid": "react-native bundle --platform=android --entry-file=index.android.js --bundle-output='android/app/src/main/assets/index.android.bundle?dev=false",
"test": "jest --watch"
},
"dependencies": {
"axios": "^0.15.*",
"dpath": "^2.0.2",
"evosphere-router": "0.1.9",
"immutable": "^3.8.1",
"intl": "^1.2.5",
"lodash": "^4.16.4",
"node-uuid": "^1.4.7",
"normalizr": "^2.2.1",
"react": "15.3.2",
"react-native": "0.36.0",
"react-native-drawer": "^2.3.0",
"react-native-i18n": "^0.1.1",
"react-native-image-picker": "^0.22.12",
"react-native-router-flux": "^3.35.0",
"react-native-tabs": "^1.0.9",
"react-redux": "^4.4.5",
"redux": "^3.6.0",
"redux-immutable": "^3.0.8",
"redux-logger": "^2.7.0",
"redux-thunk": "^2.1.0",
"string-template": "^1.0.0",
"tcomb-form-native": "^0.6.1"
},
"devDependencies": {
"babel-core": "^6.14.0",
"babel-jest": "^17.0.2",
"babel-plugin-transform-object-rest-spread": "^6.8.0",
"babel-plugin-transform-react-jsx": "^6.8.0",
"babel-plugin-transform-remove-console": "^6.8.0",
"babel-polyfill": "^6.13.0",
"babel-preset-latest": "6.14.0",
"babel-preset-react-native": "^1.9.0",
"babel-preset-react-native-stage-0": "^1.0.1",
"babel-register": "^6.14.0",
"enzyme": "^2.6.0",
"enzyme-to-json": "^1.3.0",
"faussaire": "^0.2.2",
"faussaire-util": "^0.1.0",
"jest": "^17.0.3",
"jest-enzyme": "^2.0.0",
"jest-react-native": "^17.0.3",
"react-addons-test-utils": "15.3.2",
"react-dom": "15.3.2",
"react-native-fs": "^2.0.1-rc.2",
"react-native-mock": "^0.2.7",
"react-test-renderer": "15.3.2",
"updtr": "^0.2.1"
},
"jest": {
"scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
"setupTestFrameworkScriptFile": "node_modules/jest-enzyme/lib/index.js",
"testEnvironment": "jsdom",
"moduleFileExtensions": [
"js",
"json",
"es6"
],
"preset": "jest-react-native"
}
}
For now my test is pretty simple.
global.Promise = require.requireActual('promise');
import 'react-native';
import React from 'react';
import { mount, shallow } from 'enzyme';
import { mountToJson } from 'enzyme-to-json';
import { LoginScene } from '../../../../../../src/bundles/application/ui/scene/public/LoginScene';
import configureStore from '../../../../../../src/configureStore';
import { Provider } from 'react-redux';
import { getState, getInstance } from '../../../../../../src/testing/enzymeUtils';
test('LoginScene', async () => {
const store = await configureStore();
let loginScene;
const wrapper = mount(
<Provider store={store}>
<LoginScene/>
</Provider>
);
expect(mountToJson(wrapper)).toMatchSnapshot();
loginScene = wrapper.find(LoginScene);
getInstance(loginScene)._handleFieldChange('username', 'despirithium');
getInstance(loginScene)._handleFieldChange('password', 'azerty');
expect(getState(wrapper.find(LoginScene)).username).toBe('despirithium');
expect(getState(wrapper.find(LoginScene)).password).toBe('azerty');
});
I would have shallow rendered this but since I need to wrap my scene into the Provider it's not possible.
You may need to wrap Provider in a div. "...Components must return a single root element..." -https://facebook.github.io/react/docs/components-and-props.html