I have the following simple test file for the component. I based the test on this React documentation https://reactjs.org/docs/test-utils.html#act
import ReactDOM from 'react-dom/client';
import { act } from 'react-dom/test-utils';
import App from './App'
import { screen } from '#testing-library/react'
let container: HTMLElement;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
it('can render and update a counter', () => {
act(() => {
ReactDOM.createRoot(container).render(<App />);
});
const title = screen.getByText('My App');
expect(title).toBeInTheDocument()
});
The test does pass, but I always receive an annoying error:
Warning: A suspended resource finished loading inside a test, but the event was not wrapped in act(...).
When testing, code that resolves suspended data should be wrapped into act(...):
act(() => {
/* finish loading suspended data */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
When I remove from the a component which uses react lazy loading the error message goes away. So how can I test over React Lazy Loading without this kind of issue for React 18?
Here is my setupTest.ts
import '#testing-library/jest-dom';
Here is my package.json dependencies
"dependencies": {
"#react-spring/web": "^9.4.5",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"styled-components": "^5.3.5"
},
"devDependencies": {
"#react-spring/types": "^9.4.5",
"#testing-library/jest-dom": "^5.16.5",
"#testing-library/react": "^13.2.0",
"#testing-library/user-event": "^13.5.0",
"#types/jest": "^27.5.1",
"#types/react": "^18.0.9",
"#types/react-dom": "^18.0.5",
"#types/styled-components": "^5.1.25",
"#typescript-eslint/eslint-plugin": "^5.36.1",
"#typescript-eslint/parser": "^5.36.1",
"eslint": "^8.23.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-typescript": "^3.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.1",
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "^2.7.1",
"react-scripts": "5.0.1",
"typescript": "^4.6.4"
}
I already tried several solutions like using await waitFor(...), findBy(...), removing the act method from the test file, but no success yet.
I'm using Node 16.16
I just resolved it by inserting this lines at the end of the test:
await screen.findByText('some text');
I understood that since changes occurs after the initial render, we need to "tell" the Testing Library that it does and to wait for it. It does not need the act() wrapping the render method then.
did you try putting your
const title = screen.getByText('My App');
line of code inside act(){...}?
Related
I have a working nextjs app and am wanting to add Cypress component tests for my react components.
e2e cypress tests are working without issue, but when trying to implement component tests I'm receiving the error, "Cannot read properties of undefined (reading 'displayName')" when trying to mount a component.
I followed the documentation at https://docs.cypress.io/guides/component-testing/component-framework-configuration#Next-jsn and also accepted the configuration that was generated by the cypress tool when I ran yarn cypress.
My code with component testing issue is at https://gitlab.com/kennyrbr/activ/-/tree/cypress-testing/web
Here is where I'm attempting to mount .
import React from 'react';
import { mount } from '#cypress/react';
import { NavBar } from '../../components/NavBar';
describe('NavBar.cy.ts', () => {
it('playground', () => {
cy.mount(`<NavBar />`);
});
});
My package.json is
{
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"gen": "graphql-codegen --config codegen.yml",
"cypress": "cypress open"
},
"dependencies": {
"#graphql-codegen/typescript-urql": "^3.6.1",
"#urql/exchange-graphcache": "^4.4.3",
"daisyui": "^2.22.0",
"formik": "^2.2.9",
"graphql": "^16.5.0",
"next": "latest",
"next-urql": "^3.3.3",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-is": "^18.2.0",
"urql": "^2.2.2",
"yup": "^0.32.11"
},
"devDependencies": {
"#cypress/react": "^6.1.1",
"#cypress/webpack-dev-server": "^2.2.0",
"#graphql-codegen/cli": "^2.8.0",
"#graphql-codegen/typescript": "^2.7.1",
"#graphql-codegen/typescript-operations": "^2.5.1",
"#testing-library/cypress": "^8.0.3",
"#types/node": "17.0.35",
"#types/react": "18.0.9",
"#types/react-dom": "18.0.5",
"autoprefixer": "^10.4.7",
"cypress": "^10.6.0",
"html-webpack-plugin": "^5.5.0",
"postcss": "^8.4.14",
"tailwindcss": "^3.1.2",
"typescript": "4.7.2",
"webpack": "^5.74.0",
"webpack-dev-server": "^4.10.0"
}
}
Here's the error which displays after running yarn cypress and choosing component testing for the 'NavBar.cy.ts' test.
N.B., I did add a few dev dependencies because I was receiving a webpack warning early on.
Any help is greatly appreciated.
edit:
I had added an incorrect displayName assignment to some of my components in an attempt to get cypress component testing working - and had forgotten to remove in a previous commit. This wasn't even the issue as displayName couldn't be read from undefined, so I think the issue is that the component/s aren't available to cypress. In any case, it was wrong and I've removed.
The basic problem is the parameter you are passing into cy.mount() isn't being compiled to JSX.
Two things should fix it
take the quotes off the JSX, so it should be cy.mount(<NavBar />);
change the extension of the spec file to NavBar.cy.tsx
It's not really a working nextjs app, you are getting the exact same message from a different component SelectActivType.tsx when you you run the app (outside of the Cypress test).
In terms of the NavBar, the code should be adjusted from this
export const NavBar: React.FC<NavBarProps> = ({}) => {
NavBar.displayName = 'ActivTypes';
const router = useRouter();
return (
...
);
}
to this
export const NavBar: React.FC<NavBarProps> = ({}) => {
const router = useRouter();
return (
...
);
}
// move the offending line outside of the function
NavBar.displayName = 'ActivTypes';
You cannot add a property to a function inside the function definition.
For reference see how to set displayName in a functional component [React].
I am trying to test a react typescript project using jest but it's giving a confusing error:
Error image
Here is my package.json:
"dependencies": {
"#testing-library/jest-dom": "^5.16.4",
"#testing-library/react": "^12.1.5",
"#testing-library/user-event": "^13.5.0",
"#types/jest": "^27.4.1",
"#types/node": "^16.11.26",
"#types/react": "^17.0.43",
"#types/react-dom": "^17.0.14",
"jest": "^27.5.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^6.2.2",
"react-scripts": "5.0.0",
"ts-jest": "^27.1.4",
"typescript": "^4.6.3",
"web-vitals": "^2.1.4",
},
"devDependencies": {
"#types/react-test-renderer": "^18.0.0",
"react-test-renderer": "^18.1.0"
}
I wrote this basic test which gives the error:
import renderer from 'react-test-renderer'
import AddShipmentButton from './AddShipmentButton'
it('works', () => {
const tree = renderer.create(<AddShipmentButton />).toJSON()
expect(tree).toMatchSnapshot()
})
I had to install the dependencies using --legacy-peer-deps. What could be the issue? Thanks in advance.
The problem was that I installed the latest version of react-test-renderer v18.0.1 when the React version is v17.0.2. Installing react-test-renderer version 17.0.2 solved this issue.
Upgrade your app dependencies like this
"react": "~18.0.0",
"react-dom": "^18.0.0",
"react-test-renderer": "^18.0.0"
import is wrong as defined on React docs, try with this way
import TestRenderer from 'react-test-renderer';
import AddShipmentButton from './AddShipmentButton'
it('works', () => {
const tree = TestRenderer.create(<AddShipmentButton />).toJSON()
expect(tree).toMatchSnapshot()
})
Read usage of TestRenderer here
Make sure you are using the same version of react and react-test-renderer
You can change the version of node package using npm install [package-name]#[version-number]
I am working on a major project which is based on react-17. I am facing an error while snapshot testing using React Testing Library. JSON for the project is ---
"dependencies": {
"#testing-library/jest-dom": "^5.11.4",
"#testing-library/react": "^11.1.0",
"#testing-library/user-event": "^12.1.10",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"react-test-renderer": "^17.0.2",
"web-vitals": "^1.0.1"
},
I created a small side project which is based on react-18 for snapshot testing. Here snapshot testing is working fine. JSON for this ---
"dependencies": {
"#testing-library/jest-dom": "^5.16.4",
"#testing-library/react": "^13.1.1",
"#testing-library/user-event": "^13.5.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-scripts": "5.0.1",
"react-test-renderer": "^18.0.0",
"web-vitals": "^2.1.4"
},
This code for snapshot is from the side project (where it is working fine), i am using same code for snapshot in my major project as well ---
import { render, screen, fireEvent, getByTestId } from '#testing-library/react';
import App from './App';
import React from "react";
import renderer from 'react-test-renderer';
test('snapshot test', () => {
const component = renderer.create(<App/>).toJSON();
expect(component).toMatchSnapshot();
});
what i need is a new code of snapshot which will be compatible with major project react-17.
(I am not allowed to update dependencies)
The error is:
Cannot find module 'react-test-renderer' from .........
I'm trying to access data in the contextAPI via storybook but I couldn't manage it.
Please, keep in mind that there isn't any issue with the original pages, the context is working properly.
React version: 17.0.2
Storybook version: 6.2.7
Here is the devDep:
"devDependencies": {
"#storybook/addon-actions": "^6.2.7",
"#storybook/addon-essentials": "^6.2.7",
"#storybook/addon-links": "^6.2.7",
"#storybook/node-logger": "^6.2.7",
"#storybook/preset-create-react-app": "^3.1.7",
"#storybook/react": "^6.2.7",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.23.1",
"eslint-plugin-react-hooks": "^4.2.0",
"node-sass": "^5.0.0",
"prettier": "^2.2.1",
"sass": "^1.32.8"
}
I've added a decorator for the wrapper in preview.js file of Storybook.
addDecorator((storyFn) => <GlobalStore>{storyFn()}</GlobalStore>);
Then, in the X.stories.js, I'm trying to call useContext as usual:
import { GlobalContext } ...
import { useContext } ...
export const SampleStory = () => {
const { Variable } = useContext(GlobalContext);
But I'm am facing this error in the story:
Cannot read property 'Variable' of undefined
As a solution, I created a new component as a new/separated file and imported it through X.stories.js. This solution works but in this way, I have to create lots of unnecessary files which is useless.
Can you please tell me the correct way for that issue?
Thanks in advance, Cheers,
I am having an error when I build my application in react. I noticed this error only when I tried to build application.
When I stopped dev server and ran it again, it showed the same error. It seems that I made some change that only showed when I started the server again or make build:
Module not found: Error: Can't resolve 'buffer' in '\node_modules\htmlparser2\lib' BREAKING CHANGE: webpack < 5
used to include polyfills for node.js core modules by default.This is
no longer the case. Verify if you need these module and configure a
polyfill for it.
If you want to include a polyfill, you need to install 'buffer'. If
you don't want to include a polyfill, you can use an empty module like
this:
resolve.alias: { "buffer": false }
error Command failed with exit code 1.
My application is made in CRA and Typescript. This is my package.json:
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "react-scripts start",
"build": "cross-env NODE_OPTIONS='--max-old-space-size=4096' react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"dependencies": {
"#apollo/react-hooks": "^4.0.0",
"#date-io/moment": "^1.3.13",
"#material-ui/core": "^4.11.0",
"#material-ui/icons": "^4.9.1",
"#material-ui/lab": "^4.0.0-alpha.56",
"#material-ui/pickers": "^3.2.10",
"#optimizely/react-sdk": "^2.4.0",
"apollo-boost": "^0.4.9",
"classnames": "^2.2.6",
"formik": "^2.2.5",
"graphql": "^15.4.0",
"lodash": "^4.17.20",
"moment": "^2.29.1",
"react": "^16.13.1",
"react-app-polyfill": "^2.0.0",
"react-dom": "^16.13.1",
"react-google-recaptcha": "^2.1.0",
"react-masonry-css": "^1.0.14",
"react-router-dom": "^5.2.0",
"react-test-renderer": "^16.13.1",
"react-toastify": "^6.1.0",
"reset-css": "^5.0.1",
"use-debounce": "^5.1.0"
},
"devDependencies": {
"#testing-library/jest-dom": "^5.11.6",
"#testing-library/react": "^11.2.1",
"#testing-library/user-event": "^12.2.2",
"#types/classnames": "^2.2.11",
"#types/enzyme": "^3.10.8",
"#types/enzyme-adapter-react-16": "^1.0.6",
"#types/jest": "^26.0.15",
"#types/lodash": "^4.14.165",
"#types/moment": "^2.13.0",
"#types/node": "^14.14.9",
"#types/react": "^16.9.56",
"#types/react-dom": "^16.9.9",
"#types/react-google-recaptcha": "^2.1.0",
"#types/react-router-dom": "^5.1.6",
"cross-env": "^7.0.2",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"enzyme-to-json": "^3.6.1",
"husky": "^4.3.0",
"jest-dom": "^4.0.0",
"jest-sonar-reporter": "^2.0.0",
"lint-staged": "^10.5.1",
"node-sass": "^5.0.0",
"prettier": "^2.2.0",
"ts-jest": "^26.4.4",
"typescript": "^4.1.2"
}
}
You need to install the buffer package
npm install buffer
You have to Install this
npm install assert browserify-zlib buffer process stream-browserify util .
it will help you out
I found a solution to my problem. It is a bit weird that it didn't show up as test error.
SOLUTION
To solve this I just replaced location of TEST_ID to be in my component, and that my-component.test file to import it from there:
My component
import React, { FunctionComponent } from 'react';
/* Tests */
export const TEST_ID = 'my-component-test-id';
export const MyComponent: FunctionComponent = () => {
return <div data-test-id={TEST_ID}>123</div>;
};
Test
import React from 'react';
import { cleanup } from '#testing-library/react';
import { mount } from 'enzyme';
import { TEST_ID } from './my-component';
import MyComponent from './my-component'
afterEach(cleanup);
it('Render My component and have some value', () => {
const wrapper = mount(<MyComponent />);
const myComponent = wrapper.find(`[data-testid='${TEST_ID}']`);
expect(myComponent).toHaveValue('some value');
});
Analysis
Apparently if you import some value (in my case a constant) from .test file, if you try and build your app, the mentioned error will show up.
In my case I had a component:
MyComponent
import React, { FunctionComponent } from 'react';
/* Tests */
import { TEST_ID } from './test/my-component.test';
export const MyComponent: FunctionComponent = () => {
return <div data-test-id={TEST_ID}>some value</div>;
};
The TEST_ID was imported from my-component.test file. The purpose of that constant was to have that test id set for component so I can find that element based of that test id in my test.
Test
import React from 'react';
import { cleanup } from '#testing-library/react';
import { mount } from 'enzyme';
import MyComponent from './my-component'
afterEach(cleanup);
export const TEST_ID = 'my-component-test-id';
it('Render My component and have some value', () => {
const wrapper = mount(<MyComponent />);
const myComponent = wrapper.find(`[data-testid='${TEST_ID}']`);
expect(myComponent).toHaveValue('some value');
});
you need to install 'buffer' : npm install buffer oR npm install buffer --f