enzyme | JavaScript Testing utilities for React | Unit Testing library
kandi X-RAY | enzyme Summary
Support
Quality
Security
License
Reuse
- Convert a Fiber node into a buffer .
- Find the current path of the given fiber .
- Reduce tree based on CSS selector
- Determines if a node matches the attribute selector .
- Map React events to React events .
- Converts an instance into DOM tree .
- Wrap a property on an object .
- Matches a node against a token .
- Transform an rendered element .
- Internal recursive comparison function .
enzyme Key Features
enzyme Examples and Code Snippets
/* setup.js */ const { JSDOM } = require('jsdom'); const jsdom = new JSDOM(''); const { window } = jsdom; function copyProps(src, target) { Object.defineProperties(target, { ...Object.getOwnPropertyDescriptors(src), ...Object.getOwnPropertyDescriptors(target), }); } global.window = window; global.document = window.document; global.navigator = { userAgent: 'node.js', }; global.requestAnimationFrame = function (callback) { return setTimeout(callback, 0); }; global.cancelAnimationFrame = function (id) { clearTimeout(id); }; copyProps(window, global);
/* setup.js */ const { jsdom } = require('jsdom'); global.document = jsdom(''); global.window = document.defaultView; global.navigator = { userAgent: 'node.js', }; function copyProps(src, target) { const props = Object.getOwnPropertyNames(src) .filter((prop) => typeof target[prop] === 'undefined') .reduce((result, prop) => ({ ...result, [prop]: Object.getOwnPropertyDescriptor(src, prop), }), {}); Object.defineProperties(target, props); } copyProps(document.defaultView, global);
/* setup.js */ const { JSDOM } = require('jsdom'); const jsdom = new JSDOM(''); const { window } = jsdom; function copyProps(src, target) { Object.defineProperties(target, { ...Object.getOwnPropertyDescriptors(src), ...Object.getOwnPropertyDescriptors(target), }); } global.window = window; global.document = window.document; global.navigator = { userAgent: 'node.js', }; global.requestAnimationFrame = function (callback) { return setTimeout(callback, 0); }; global.cancelAnimationFrame = function (id) { clearTimeout(id); }; copyProps(window, global);
/* setup.js */ const { jsdom } = require('jsdom'); global.document = jsdom(''); global.window = document.defaultView; global.navigator = { userAgent: 'node.js', }; function copyProps(src, target) { const props = Object.getOwnPropertyNames(src) .filter((prop) => typeof target[prop] === 'undefined') .reduce((result, prop) => ({ ...result, [prop]: Object.getOwnPropertyDescriptor(src, prop), }), {}); Object.defineProperties(target, props); } copyProps(document.defaultView, global);
/* some_test.js */ // Import anything you would normally import `from 'enzyme'` from the Enzyme setup file import { shallow } from './test/enzyme'; // ...
Trending Discussions on enzyme
Trending Discussions on enzyme
QUESTION
Greetings I have a problem with Heroku because it's don't want to install legacy packages for my Shopify app, my Shopify app is on Github and I just set up everything that my application needs, but when I deploy the main branch on Heroku I get this error in Heroku console below, can someone help me fix this?
-----> Building on the Heroku-20 stack
-----> Using buildpack: heroku/nodejs
-----> Node.js app detected
-----> Creating runtime environment
NPM_CONFIG_LOGLEVEL=error
USE_NPM_INSTALL=true
NODE_VERBOSE=false
NODE_ENV=production
NODE_MODULES_CACHE=false
-----> Installing binaries
engines.node (package.json): unspecified
engines.npm (package.json): unspecified (use default)
Resolving node version 16.x...
Downloading and installing node 16.14.0...
Using default npm version: 8.3.1
-----> Restoring cache
Caching has been disabled because NODE_MODULES_CACHE=false
-----> Installing dependencies
Installing node modules (package.json + package-lock)
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: shopify-app-node@1.0.0
npm ERR! Found: react@16.14.0
npm ERR! node_modules/react
npm ERR! react@"^16.10.1" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^17.0.2 || ^18.0.0-0" from next@12.0.10
npm ERR! node_modules/next
npm ERR! next@"^12.0.2" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See /tmp/npmcache.CTfHl/eresolve-report.txt for a full report.
npm ERR! A complete log of this run can be found in:
npm ERR! /tmp/npmcache.CTfHl/_logs/2022-02-10T12_18_50_156Z-debug-0.log
-----> Build failed
We're sorry this build is failing! You can troubleshoot common issues here:
https://devcenter.heroku.com/articles/troubleshooting-node-deploys
Some possible problems:
- Node version not specified in package.json
https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version
Love,
Heroku
! Push rejected, failed to compile Node.js app.
! Push failed
My package.json
{
"name": "shopify-app-node",
"version": "1.0.0",
"description": "Shopify's node app for CLI tool",
"scripts": {
"test": "jest",
"dev": "cross-env NODE_ENV=development nodemon ./server/index.js --watch ./server/index.js",
"build": "NEXT_TELEMETRY_DISABLED=1 next build",
"start": "cross-env NODE_ENV=production node ./server/index.js"
},
"engines": {
"node": "16.14.0",
"npm": "8.4.1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Shopify/shopify-app-node.git"
},
"author": "Shopify Inc.",
"license": "MIT",
"bugs": {
"url": "https://github.com/shopify/shopify-app-node/issues"
},
"dependencies": {
"@babel/core": "7.12.10",
"@babel/polyfill": "^7.6.0",
"@babel/preset-env": "^7.12.11",
"@babel/register": "^7.12.10",
"@shopify/app-bridge-react": "^2.0.2",
"@shopify/app-bridge-utils": "^2.0.2",
"@shopify/koa-shopify-auth": "^4.1.2",
"@shopify/polaris": "^6.2.0",
"apollo-boost": "^0.4.9",
"axios": "^0.25.0",
"cross-env": "^7.0.3",
"dotenv": "^8.2.0",
"graphql": "^14.5.8",
"isomorphic-fetch": "^3.0.0",
"koa": "^2.13.1",
"koa-bodyparser": "^4.3.0",
"koa-compress": "^5.1.0",
"koa-cors": "0.0.16",
"koa-logger": "^3.2.1",
"koa-router": "^10.0.0",
"koa-session": "^6.1.0",
"mysql2": "^2.3.3",
"next": "^12.0.2",
"next-env": "^1.1.0",
"node-fetch": "^2.6.7",
"react": "^16.10.1",
"react-apollo": "^3.1.3",
"react-dom": "^16.10.1",
"sequelize": "^6.13.0",
"slugify": "^1.6.5",
"validator": "^13.7.0",
"webpack": "^4.44.1"
},
"devDependencies": {
"@babel/plugin-transform-runtime": "^7.12.10",
"@babel/preset-stage-3": "^7.0.0",
"babel-jest": "26.6.3",
"babel-register": "^6.26.0",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.6",
"husky": "^4.3.6",
"jest": "26.6.3",
"lint-staged": "^10.5.4",
"nodemon": "^2.0.7",
"prettier": "2.2.1",
"react-addons-test-utils": "15.6.2",
"react-test-renderer": "16.14.0"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,css,json,md}": [
"prettier --write"
]
}
}
ANSWER
Answered 2022-Feb-10 at 13:23Your lock file contains conflicting dependencies. Since you were able to reproduce the error locally using npm ci
we have a good way to test a fix locally.
It looks like you are depending directly on React 16. Is that something that you need directly, or is it just a dependency for Next.js?
If it's not something you need directly, upgrade it per the Next.js docs:
npm install react@latest react-dom@latest
That should modify your package-lock.json
. Then try installing from the lock file again with npm ci
. If that fixes things, commit the change and redeploy.
On the other hand, if you are directly depending on React 16 and cannot upgrade you'll have to consider rolling back to an earlier version of Next.js.
QUESTION
I try to rebuild an electron app but I got this error regarding the epoll installation.
Building module: epoll, Completed: 0gyp: name 'openssl_fips' is not defined while evaluating condition 'openssl_fips != ""' in binding.gyp while trying to load binding.gyp
✖ Rebuild Failed
An unhandled error occurred inside electron-rebuild
node-gyp failed to rebuild '/home/pi/ma-0042-cihaz-be/node_modules/epoll'.
For more information, rerun with the DEBUG environment variable set to "electron-rebuild".
Error: `gyp` failed with exit code: 1
Error: node-gyp failed to rebuild '/home/pi/ma-0042-cihaz-be/node_modules/epoll'.
For more information, rerun with the DEBUG environment variable set to "electron-rebuild".
at NodeGyp.rebuildModule (/home/pi/ma-0042-cihaz-be/node_modules/electron-rebuild/lib/src/module-type/node-gyp.js:109:19)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async ModuleRebuilder.rebuildNodeGypModule (/home/pi/ma-0042-cihaz-be/node_modules/electron-rebuild/lib/src/module-rebuilder.js:94:9)
at async Rebuilder.rebuildModuleAt (/home/pi/ma-0042-cihaz-be/node_modules/electron-rebuild/lib/src/rebuild.js:226:9)
at async Rebuilder.rebuild (/home/pi/ma-0042-cihaz-be/node_modules/electron-rebuild/lib/src/rebuild.js:184:17)
at async /home/pi/ma-0042-cihaz-be/node_modules/electron-rebuild/lib/src/cli.js:154:9
I am using a raspberry, I did update it too. But it didn't work. These are the dependencies installed.
{
"dependencies": {
"@babel/preset-react": "^7.14.5",
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"history": "^5.1.0",
"i2c-bus": "^5.2.2",
"jest": "^27.3.1",
"jest-fetch-mock": "^3.0.3",
"jsonwebtoken": "^8.5.1",
"mfrc522-rpi": "^2.1.3",
"moment": "^2.29.1",
"network-config": "^3.0.0",
"node-cron": "^3.0.0",
"node-fetch": "^2.6.5",
"node-wifi": "^2.0.15",
"pi-camera": "^1.6.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^6.0.0",
"realm": "^10.7.0",
"rpi-gpio": "^2.1.7",
"rpi-softspi": "^1.0.5",
"rpio": "^2.4.2",
"source-map-support": "^0.5.16"
},
"devDependencies": {
"@babel/core": "^7.15.5",
"@babel/node": "^7.15.4",
"@babel/plugin-transform-runtime": "^7.16.0",
"@babel/preset-env": "^7.15.6",
"babel-loader": "^8.2.2",
"electron": "8.2.0",
"electron-builder": "^22.11.7",
"electron-rebuild": "^3.2.3",
"electron-webpack": "^2.8.2",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6",
"enzyme-to-json": "^3.6.2",
"webpack": "~4.42.1"
}
}
I deleted node_modules with package-lock.json and installed everything again. I updated the raspberry with apt-get upgrade. I don't know how can I solve this issue. Do you have any ideas?
ANSWER
Answered 2021-Nov-09 at 06:01I have a same problem too, but i am using a serialport not epoll.
So, I think the cause of this problem is electron modules not the native module.
yarn run v1.22.15
$ electron-rebuild -f -w myapp
\ Building module: bindings, Completed: 0gyp: name 'openssl_fips' is not defined while evaluating condition 'openssl_fips != ""' in binding.gyp while trying to load binding.gyp
× Rebuild Failed
An unhandled error occurred inside electron-rebuild
node-gyp failed to rebuild 'C:\Users\node_modules\@serialport\bindings'.
For more information, rerun with the DEBUG environment variable set to "electron-rebuild".
Error: `gyp` failed with exit code: 1
Error: node-gyp failed to rebuild 'C:\Users\node_modules\@serialport\bindings'.
For more information, rerun with the DEBUG environment variable set to "electron-rebuild".
Error: `gyp` failed with exit code: 1
at NodeGyp.rebuildModule (C:\Users\node_modules\electron-rebuild\lib\src\module-type\node-gyp.js:109:19)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async ModuleRebuilder.rebuildNodeGypModule (C:\Users\node_modules\electron-rebuild\lib\src\module-rebuilder.js:94:9)
at async Rebuilder.rebuildModuleAt (C:\Users\node_modules\electron-rebuild\lib\src\rebuild.js:226:9)
at async Rebuilder.rebuild (C:\Users\node_modules\electron-rebuild\lib\src\rebuild.js:184:17)
at async C:\Users\node_modules\electron-rebuild\lib\src\cli.js:154:9
error Command failed with exit code 4294967295.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
This problem started yesterday. There were no problems in the last week.
I already installed the windows-build-tools, node-gyp, python 3.x.
I set the npm config & yarn config & python Env path, msvs_version too.
I reinstalled above packages many many times but not work electron-rebuild.
That is whole Error messages. There is no more Error messages.
What should we do?
QUESTION
After upgrading react-scripts to v5, craco start
does not work properly. App starts with no error but in browser, there is a blank page and if i open inspector, i only see index.html codes not react codes. It was working well with react-scripts@4.0.3. Here is my local files;
package.json
{
"name": "test-app",
"private": true,
"version": "0.1.0",
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"dependencies": {
...
"@babel/preset-react": "^7.16.7",
...
"@craco/craco": "^6.4.3",
...
"babel-loader": "^8.2.3",
...
"react": "^16.11.0",
"react-dom": "^16.11.0",
"react-scripts": "^5.0.0",
"scriptjs": "^2.5.9",
"single-spa": "^5.9.0",
"single-spa-react": "^4.6.1",
},
"devDependencies": {
"@babel/core": "7.7.2",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-decorators": "^7.17.2",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1",
"@babel/plugin-proposal-optional-chaining": "^7.6.0",
"@svgr/webpack": "6.2.1",
"@types/chance": "^1.0.8",
"@types/jest": "^24.9.0",
"@types/node": "^16.7.10",
"@types/react": "^16.9.18",
"@types/react-dom": "^16.9.5",
"@types/react-router-dom": "^5.1.3",
"@types/yargs": "^17.0.2",
"@typescript-eslint/eslint-plugin": "^4.14.1",
"@typescript-eslint/parser": "^4.14.1",
"@webpack-cli/serve": "^1.6.1",
"compression-webpack-plugin": "^9.2.0",
"css-loader": "3.2.0",
"dotenv": "^10.0.0",
"dotenv-expand": "5.1.0",
"dotenv-webpack": "^7.1.0",
"env-path": "^1.0.7",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.15.1",
"eslint": "^7.11.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-config-airbnb-typescript": "^12.3.1",
"eslint-config-react-app": "^6.0.0",
"eslint-config-standard": "^14.1.0",
"eslint-config-standard-jsx": "^8.1.0",
"eslint-import-resolver-typescript": "^2.4.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-flowtype": "5.2.0",
"eslint-plugin-import": "^2.20.0",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-standard": "^4.0.1",
"file-loader": "4.2.0",
"react-app-rewired": "^2.2.1",
"react-svg-loader": "^3.0.3",
"react-test-renderer": "^16.11.0",
"sass-loader": "8.0.0",
"style-loader": "1.0.0",
"systemjs-webpack-interop": "^2.3.7",
"terser-webpack-plugin": "5.3.1",
"tsconfig-paths-webpack-plugin": "^3.5.1",
"url-loader": "2.2.0",
"webpack": "^5.69.1",
"webpack-cli": "^4.9.2",
"webpack-manifest-plugin": "4.1.1",
"workbox-webpack-plugin": "6.4.2",
"yargs": "^17.1.1"
},
"scripts": {
"version": "node scripts/version.js",
"solid": "node scripts/solid.js",
"start": "craco start",
"build": "craco build"
},
"typings": "./src"
}
craco.config.ts
export default {
mode: 'development',
babel: {
plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]],
},
eslint: {
enable: false,
},
webpack: {
configure: (webpackConfig) => {
// add this line
// use System
webpackConfig.output.libraryTarget = 'system';
delete webpackConfig.optimization;
webpackConfig.externals = [
'react',
'react-dom',
'single-spa',
'react-router',
'react-router-dom',
'@mf-experiences',
];
return webpackConfig;
},
},
// Adding Server
devServer: (devServerConfig) => {
devServerConfig.proxy = {
'@mf-experiences': {
target: 'path...',
secure: false,
changeOrigin: true,
},
};
return devServerConfig;
},
};
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './styles/nullifier.scss';
import './styles/index.scss';
import './tracking/facebook.ts';
import App from './App';
import * as serviceWorkerRegistration from './serviceWorkerRegistration';
const setRealVh = () => {
document.documentElement.style.setProperty(
'--vh',
`${window.innerHeight * 0.01}px`
);
};
window.addEventListener('resize', setRealVh);
document.documentElement.style.setProperty('--intensity', `${768 * 0.005}px`);
ReactDOM.render(, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://cra.link/PWA
// serviceWorkerRegistration.register({
// onUpdate: (registration) => registration.waiting.postMessage({ type: 'SKIP_WAITING' }),
// });
serviceWorkerRegistration.unregister();
ANSWER
Answered 2022-Feb-23 at 10:05craco
's Github readme, states that it is supporting Create React App (CRA) 4.*
. By this statement, I'm assuming CRA 5
is not officially supported by craco
.
However, this repository utilizes both CRA 5
and craco
(but I have not verified that it is working). Use this repository to compare your setup (after verifying that the linked repositry is working), and try different settings/configs to see if you get further.
QUESTION
Given the function f!
below :
function f!(s::Vector, a::Vector, b::Vector)
s .= a .+ b
return nothing
end # f!
How can I define an adjoint for Zygote based on
Enzyme.autodiff(f!, Const, Duplicated(s, dz_ds). Duplicated(a, zero(a)), Duplicated(b, zero(b)))
?
Zygote.@adjoint f!(s, a, b) = f!(s, a, b), # What would come here ?
ANSWER
Answered 2022-Feb-15 at 10:30Could figure out a way, sharing it here.
For a given function foo
, Zygote.pullback(foo, args...)
returns foo(args...)
and the backward pass (which allows for gradients computations).
My goal is to tell Zygote
to use Enzyme
for the backward pass.
This can be done by means of Zygote.@adjoint
(see more here).
In case of array-valued functions, Enzyme
requires a mutating version that returns nothing
and its result to be in args
(see more here).
The function f!
in the question post is an Enzyme
-compatible version of a sum of two arrays.
Since f!
returns nothing
, Zygote
would simply return nothing
when the backward pass is called on some gradient passed to us.
A solution is to place f!
inside a wrapper (say f
) that returns the array s
and to define Zygote.@adjoint
for f
, rather than f!
.
Hence,
function f(a::Vector, b::Vector)
s = zero(a)
f!(s, a, b)
return s
end
function enzyme_back(dzds, a, b)
s = zero(a)
dzda = zero(dzds)
dzdb = zero(dzds)
Enzyme.autodiff(
f!,
Const,
Duplicated(s, dzds),
Duplicated(a, dzda),
Duplicated(b, dzdb)
)
return (dzda, dzdb)
end
and
Zygote.@adjoint f(a, b) = f(a, b), dzds -> enzyme_back(dzds, a, b)
inform Zygote
to use Enzyme
in the backward pass.
Finally, you can check that calling Zygote.gradient
either on
g1(a::Vector, b::Vector) = sum(abs2, a + b)
or
g2(a::Vector, b::Vector) = sum(abs2, f(a, b))
yields the same results.
QUESTION
I am checking a few of my Cox multivariate regression analyses' proportional hazard assumptions using time-dependent co-variates, using the survival
package. The question is looking at survival in groups with different ADAMTS13 levels (a type of enzyme).
Could I check if something is wrong with my code itself? It keeps saying Error in tt(TMAdata$ADAMTS13level.f) : could not find function "tt"
. Why?
Notably, ADAMTS13level.f
is a factor variable.
cox_multivariate_survival_ADAMTS13 <- coxph(Surv(TMAdata$Daysalive, TMAdata$'Dead=1')
~TMAdata$ADAMTS13level.f
+TMAdata$`Age at diagnosis`
+TMAdata$CCIwithoutage
+TMAdata$Gender.f
+TMAdata$`Peak Creatinine`
+TMAdata$DICorcrit.f,
tt(TMAdata$ADAMTS13level.f),
tt = function(x, t, ...)
{mtrx <- model.matrix(~x)[,-1]
mtrx * log(t)})
Thanks- starting with the fundamentals of my actual code or typos- I have tried different permutations to no avail yet.
ANSWER
Answered 2022-Feb-08 at 05:23@Limey was on the right track!
The time-transformed version of ADAMTS13level.f
needs to be added to the model, instead of being separated into a separate argument of coxph(...)
.
The form of coxph
call when testing the time-dependent categorical variables is described in How to use the timeSplitter by Max Gordon.
Other helpful documentation:
cox_multivariate_survival_ADAMTS13 <-
coxph(
Surv(
Daysalive,
'Dead=1'
) ~
ADAMTS13level.f
+ `Age at diagnosis`
+ CCIwithoutage
+ Gender.f
+ `Peak Creatinine`
+ DICorcrit.f
+ tt(ADAMTS13level.f),
tt = function(x, t, ...) {
mtrx <- model.matrix(~x)[,-1]
mtrx * log(t)
},
data = TMAdata
)
p.s. with the original data, there was also a problem because Daysalive
included a zero (0) value, which eventually resulted in an 'infinite predictor' error from coxph
, probably because tt
transformed the data using a log(t)
. (https://rdrr.io/github/therneau/survival/src/R/coxph.R)
QUESTION
I'm really trying to get an understanding of how to properly unit test with React + TS, but it's really been tough going so far. I have two very simple components I'm using to isolate things. I'll include the components at the bottom so I don't clutter things too much.
Pretty simple, click the Button
and the change from 'hello' to 'world' in the state variable data
is displayed in InnerComponent
. From everything I've seen, the pattern is to test for side effects in the document rather than trying to test the state changes themselves (and thank goodness for that, I had a nightmare of a time trying to access state in the wrapper instance with Typescript). However, eslint
hates screen
and TS cannot find findByText
. Instead I get the error Property 'findByText' does not exist on type 'Screen'.ts(2339)
on the noted lines in the test below:
/* OuterComponent.test.tsx */
import { findByText } from '@testing-library/react';
import { mount } from 'enzyme';
import React from 'react';
import OuterComponent from './OuterComponent';
describe('OuterComponent', () => {
it('does something on click', async () => {
const wrapper = mount();
/* eslint-disable-next-line no-restricted-globals */
expect(await screen.findByText('hello')).not.toBe(null); // error here
wrapper.find('Button').simulate('click');
/* eslint-disable-next-line no-restricted-globals */
expect(await screen.findByText('world')).not.toBe(null); // error here
});
});
This feels like a pretty standard scenario, so how do those of you who use TS test this type of thing? Here is OuterComponent
:
/* OuterComponent.tsx */
import React, { useState } from 'react';
import { Button } from 'react-bootstrap';
import InnerComponent from './InnerComponent';
const initialData = 'hello';
const OuterComponent: React.FC = () => {
const [data, setData] = useState(initialData);
const clickHandler = () => {
if (data === 'hello') {
setData('world');
} else {
setData('hello');
}
};
return (
Click
);
};
export default OuterComponent;
and here is InnerComponent
:
/* InnerComponent.tsx */
import React from 'react';
import { Card } from 'react-bootstrap';
interface TheseProps {
data: string;
}
const InnerComponent: React.FC = ({ data }) => {
return (
{data}
);
};
export default InnerComponent;
ANSWER
Answered 2022-Jan-05 at 22:58There is a separate "screen" object exported from '@testing-library/react'. that has the findByText method. you unfortunately have to manually grab screen out of the library as auto imports just think its the global "screen" when you don't import explicitly.
QUESTION
I have installed react-router-domV6. I am having the above error when I run my very basic test using Jest-Enzyme:
expect(shallow().length).toEqual(1);
I already came across this similar issue mentioned here, but I am already doing the provided answers. Even tried doing the import { BrowserRouter as Router } from "react-router-dom";
. What am I missing here?
index.js
import React, { Suspense } from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { StrictMode } from "react";
import { BrowserRouter } from "react-router-dom";
...
ReactDOM.render(
...
...
,
document.getElementById("root")
);
App.js
import React from "react";
import { useRoutes } from "react-router-dom";
import Routing from "./routes";
import useAuth from "./hooks/useAuth";
import { CreateCustomTheme } from "./theme";
import { ThemeProvider } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
import useSettings from "./hooks/useSettings";
import useScrollReset from "./hooks/useScrollReset";
import SplashScreen from "./components/splashScreen/SplashScreen";
const App = () => {
const content = useRoutes(Routing());
const { settings } = useSettings();
const auth = useAuth();
useScrollReset();
const theme = CreateCustomTheme({
direction: settings.direction,
responsiveFontSizes: settings.responsiveFontSizes,
roundedCorners: settings.roundedCorners,
theme: settings.theme,
});
return (
{auth.isInitialized ? content : }
);
};
export default App;
ANSWER
Answered 2021-Nov-19 at 05:09It seems the CustomerListTable
component you are testing in isolation doesn't have access to a routing context it's expecting as when it's rendered in the app normally. It's completely normal to need to wrap components when testing them with providers (redux, themes/styling, localization, routing, etc...) that are providing specific React Context values the component is accessing, typically via React hooks.
For the unit test you should wrap the component with the providers it's expecting to have.
expect(shallow(
).length).toEqual(1);
It's been a long time since I've used Enzyme, so I'm not certain the shallow
render will still work, but if it doesn't then swap to the full mount
test renderer.
QUESTION
I have literally trawled everywhere for an answer to this and possibly tried 99% of things out there so i decided to start a thread of its own so others can run their eyes over what i have currently and see if they can spot the issue.
i am very new to Jest testing and decided to try implement it onto our code base. i used this guide to make sure everything i done was perfect but still this error occurs A Practical Guide To Testing React Applications With Jest
I am testing this aginst a simple functional component which uses react-hook-form to produce a form on the page and then sends the completed form to our backend via a redux call
I have setup the setupTests.js file as:
import '@testing-library/jest-dom'
import { configure } from "enzyme"
import Adapter from "enzyme-adapter-react-16";
import '@testing-library/jest-dom/extend-expect';
configure({ adapter: new Adapter() });
Updated my package.json test command to
"test": "react-scripts test --env=jsdom --setupFiles ./src/setupTests.js"
Here is the test spec im trying to run with a simple test:
import React from 'react';
import { render as rtlRender, screen } from '@testing-library/react';
import { Provider } from 'react-redux';
import store from '../../../store';
import AddNewProperty from './AddNewProperty';
configure({ adapter: new Adapter() });
const render = component => rtlRender(
{component}
)
describe('Add New Property', () => {
test('component redners successfully', () => {
render()
// expect(screen.getByText('Apartment Number')).toBeInTheDocument();
})
});
here is the error returned on the screen for me:
FAIL src/components/Forms/Agency/AddNewProperty.spec.js
● Test suite failed to run
ReferenceError: expect is not defined
3 | import Adapter from "enzyme-adapter-react-16";
4 | import '@testing-library/jest-dom/extend-expect';
> 5 | configure({ adapter: new Adapter() });
| ^
at Object. (node_modules/@testing-library/jest-dom/dist/extend-expect.js:9:1)
at Object. (node_modules/@testing-library/jest-dom/dist/index.js:3:1)
at Object. (src/setupTests.js:5:1)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 0.167s
Ran all test suites related to changed files.
Watch Usage: Press w to show more.
I have all the packages installed in with the latest versions also
ANSWER
Answered 2021-Nov-11 at 18:05You would want to set up the files after the test framework has been installed
Here are a couple of ways you can go about doing it (For this particular question, method 1 is more relevant)
1)react-scripts
Replace/Add --setupFilesAfterEnv
instead of using --setupFiles
Example: "test": "react-scripts test --setupFilesAfterEnv
jest.config.js
setupFilesAfterEnv: [
'./setupTests.js',
],
Along with that make sure your node version is at least 12
QUESTION
I've been working with Javascript for a couple of years now, and with my current knowledge of the event loop I'm struggling to understand why this testing recipe from the React docs work. Would someone be able to break down exactly what happens in each step there? To me, it seems magical that this works in the test:
await act(async () => {
render(, container);
});
// expect something
The component looks like this (copying in case that link gets deprecated):
function User(props) {
const [user, setUser] = useState(null);
async function fetchUserData(id) {
const response = await fetch("/" + id);
setUser(await response.json());
}
useEffect(() => {
fetchUserData(props.id);
}, [props.id]);
if (!user) {
return "loading...";
}
return (
{user.name}
{user.age} years old
lives in {user.address}
);
}
There's no implicit or explicit return happening on the render, so how does act know to await the async stuff happening in the component (fetching etc)?
To me, this would make more sense:
await act(async () => render(, container));
or (which is the same thing):
await act(async () => {
return render(, container);
});
or even:
await act(render(, container));
But that doesn't seem to be how people use it, or how it was intended to be used, so I'm a bit lost. I've seen the same examples with enzymes mount
.
I don't want to create a fragile test, so I really want to understand this.
Does it have something to do with the callback being async i.e. does that append something to the event loop last, making it so that the await waits for everything inside render to happen before resolving?
I'm drawing a blank here and am struggling in the react doc jungle, because everyone seems to use this pattern, but no one really explains why or how it works.
Thanks for the help in advance!
ANSWER
Answered 2021-Nov-02 at 10:43When looking closer at the source code of react-dom
and react-dom/test-utils
it seems like what's making this whole thing work is this setImmediate call happening after the first effect flush in recursivelyFlushAsyncActWork.
It seems like act
chooses to use this recursivelyFlushAsyncActWork
simply because the callback has the signature of being "thenable", i.e. a Promise. You can see this here.
This should mean that what happens is (simplified) this:
- The
useEffect
callback is flushed (puttingfetch
on the event loop). - The
setImmediate
callback "ensures" our mock promise / fetch is resolved. - A third flush happens by a recursion inside the
setImmediate
callback (called byenqueueTask
) making the state changes appear in the DOM. - When there's nothing left to flush it calls the outer most
resolve
and ouract
resolves.
In the code that looks kinda like this (except this is taken from an older version of react-dom
from the node_modules of my React project, nowadays flushWorkAndMicroTasks
seems to be called recursivelyFlushAsyncActWork
):
function flushWorkAndMicroTasks(resolve) {
try {
flushWork(); // <- First effect flush (fetch will be invoked by the useEffect?)
enqueueTask(function () { // <- setImmediate is called in here (finishes the fetch)
if (flushWork()) { // <- Flush one more time and the next loop this will be false
flushWorkAndMicroTasks(resolve);
} else {
resolve(); // <- resolve is called when flushWork has nothing left to flush.
}
});
} catch (err) {
resolve(err);
}
}
Unless I'm mistaken this should mean that await act(async () => { render(...); });
"only" awaits one event loop unless a new task is added by the latest flush. I.e. it's possible to add promises recursively if there's a flush in between, also micro tasks such as promise chains will probably resolve during the first loop (since they are technically "blocking" (source)).
That means that if you add a timer or something else in your mock or React code that might naturally need multiple loops to resolve, it's not gonna be awaited because the "after" event is not captured before resolving since the then listeners are not attached / returned to the outer promise (please correct me if I'm wrong!).
QUESTION
I have the following React Component:
import { getSeasonsalCode } from "./DiscountCodes.js";
import React, { Component } from "react";
import Rating from "./Rating.js";
import ReactDOM from "react-dom";
import "regenerator-runtime/runtime";
class Product extends Component {
constructor(props) {
super(props);
this.handleEvent = this.handleEvent.bind(this);
this.state = {
name: "",
rating: 0,
};
}
setStarCount = (ct) => {
this.setState({ rating: ct });
};
render() {
var discount = getSeasonsalCode();
return (
{discount}
);
}
}
export default connect(mapStateToProps, null)(Product);
And the following product.test.js. It tests the Rating child component, which requires a callback function from the parent component to set the rating value:
import Rating from "../src/Rating.js";
import Product from "../src/Product.js";
import { shallow, mount } from "enzyme";
import expect from "expect";
import React from "react";
import { Provider } from "react-redux";
import { connect } from "react-redux";
import rootReducer from "../src/reducers/RootReducer.js";
import { createStore } from "redux";
describe("Product test suite", () => {
it("set rating", () => {
const store = createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()
);
const rf_wrapper = mount(
).dive();
const rf_instance = rf_wrapper.instance();
const sr_wrapper = shallow(
);
sr_wrapper.find("#star4").simulate("click");
expect(rf_wrapper.state("starcount")).toEqual(4);
});
});
When I run the test, I get a TypeError saying discount is null or undefined at this line:
{discount}
What is causing this issue?
ANSWER
Answered 2021-Oct-16 at 20:58Had to make a few changes to my original test suite and this is what worked for me:
import * as disc_module from '../src/DiscountCodes.js'
describe("Product test suite", () => {
it("set rating", () => {
const store = createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
var disc_mock_obj = {
"discount":{
"expiration": new Date()
"code": "OAABYT"
}}
jest
.spyOn(disc_module, 'getSeasonsalCode')
.mockImplementation(() => disc_mock_obj);
//Got rid of call to dive() since it was not needed
const rf_wrapper = mount( );
const prod_inst = rf_wrapper.find('Product');
//Find clickable child component of Rating by id or any other unique attribute
const child = rf_wrapper.find({'#star2'})
child.simulate('click')
expect(prod_inst.state('starcount')).toEqual(2);
});
});
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
Vulnerabilities
No vulnerabilities reported
Install enzyme
Support
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
Find more librariesExplore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits
Save this library and start creating your kit
Share this Page