Testing for disappearance of element using react testing library fails - jestjs

I am trying to test disappearance of dialog box when user clicks "cancel" button on my dialog box using the following test:
it("clicking on cancel hides the confirmation dialog", async() => {
render(<ConfirmationDialog />);
const cancelButton = screen.getByText("Cancel");
fireEvent.click(cancelButton);
await waitForElementToBeRemoved(() => screen.queryByText(/Cancel/i));
expect(screen.queryByText(/Cancel/i)).toBeNull();
});
But the above code throws an error :
TypeError: MutationObserver is not a constructor
24 | const cancelButton = screen.getByText("Cancel");
25 | fireEvent.click(cancelButton);
> 26 | await waitForElementToBeRemoved(() => screen.queryByText(/Cancel/i));
| ^
27 | expect(screen.queryByText(/Cancel/i)).toBeNull();
28 | });
29 | });
Can someone help me understanding this issue as I am new to testing library. Thanks in advance.

You need to mock MutationObserver in your test :
Add #sheerun/mutationobserver-shim package to your project
in setupTests.js (or other Jest configuration file), add the following code :
import MutationObserver from '#sheerun/mutationobserver-shim';
window.MutationObserver = MutationObserver;
Your UI framework certainly depends on it.
There may be other way to mock MutationObserver, this is how I do it but it may not be the best way.

Try this according to: https://github.com/testing-library/dom-testing-library/issues/477
npm install jest-environment-jsdom-sixteen
or
yarn add -D jest-environment-jsdom-sixteen
and then set it via env cli param
"scripts": {
...
"test": "react-scripts test --env=jest-environment-jsdom-sixteen",
...
}

Related

How do I run unit tests on Svelte component logic while also importing an environment variable?

I am trying to run Jest unit tests on function logic that is imported from a Svelte component. The program runs fine except when I try to import into Jest: I can console log the env variable in the line below ok.
The problem is that this line gives me an error when i try to run the unit test, I guess because its trying to import the file into the jest test. It runs fine when the program is actually running, but when the Jest test tries to import it, the context changes or ... something. Anyway, here's the line, from my file src/routes/signup/index.svelte:
// in the script tag of a svelte component
<script context="module">
const googleRecaptchaSiteKey =
typeof import.meta.env.VITE_GOOGLE_RECAPTCHA_KEY === "string"
? import.meta.env.VITE_GOOGLE_RECAPTCHA_KEY
: ""
export function foo() {
// ...
}
</script>
This code must run in my Jest test because it gives the error when I run npm test, so here's how I am executing that code:
import { foo } from "../src/routes/signup/index.svelte"
// It must execute the whole component when I import from it?
describe("signup page logic", () => {
test("ensure that the signup form button enablement conditions work properly", () => {
const failureOne = foo()
}
}
The error message itself:
/home/rlm/Code/projName/src/routes/signup/index.svelte:446
const googleRecaptchaSiteKey = typeof import.meta.env.VITE_GOOGLE_RECAPTCHA_KEY === "string"
^^^^
SyntaxError: Cannot use 'import.meta' outside a module
> 1 | import { updateEnabledSubmitSignup } from "../src/routes/signup/index.svelte"
Now since writing the above text, I have been adventuring for approx 27 minutes to discover a solution. What I have done is try to follow guides.
Per the instruction of Environment variables with SvelteKit I did:
in src/lib/variables.ts:
export const variables = {
foo: import.meta.env.VITE_FOO,
secondRecaptchaKey: import.meta.env.VITE_SECOND_RECAPTCHA_KEY,
}
And then I import it into the Svelte file: import { variables } from "../../lib/variables"
I run npm run dev and it console logs the value fine.
But then when I run npm test I get:
src/lib/variables.ts:3:23 - error TS1343: The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node12', or 'nodenext'.
3 secondRecaptchaKey: import.meta.env.VITE_SECOND_RECAPTCHA_KEY,
TS1343: The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'esnext', or 'system'
Test suite failed to run import.meta.env.VITE_* does also but I tried to follow it and it fails even after installing vite-plugin-environment and babel-plugin-transform-import-meta and adding them to the babel plugins:
export const variables = { // logs with all values undefined
foo: process.env.VITE_FOO,
secondRecaptchaKey: process.env.VITE_SECOND_RECAPTCHA_KEY,
}
TS1343: The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'esnext', or 'system' also has advice that fails for me, or i have done it wrong. In my current state npm test logs the env variables as undefined.
edit: For anyone in the future who has this problem, I was able to go around the problem by doing this totally-good-enough workaround:
jest.mock("../src/lib/envVariables", () => ({
envVariables: { foo: "bar", secondRecaptchaKey: "someMockValue" },
}))
I credit nstanard in this post for saving us from the hassle

Strapi unit testing with Jest, fails

I have a Strapi api and trying to run a unit test
this is the error in the console I am getting
yarn test
yarn run v1.22.5
$ jest --forceExit --detectOpenHandles
● process.exit called with "1"
8 | if (!instance) {
9 | /** the follwing code in copied from `./node_modules/strapi/lib/Strapi.js` */
> 10 | await Strapi().load();
| ^
11 | instance = strapi; // strapi is global now
12 | await instance.app
13 | .use(instance.router.routes()) // populate KOA routes
at Strapi.stop (node_modules/strapi/lib/Strapi.js:263:13)
at node_modules/strapi/lib/Strapi.js:391:16
at async Promise.all (index 5)
at Strapi.runBootstrapFunctions (node_modules/strapi/lib/Strapi.js:394:5)
at Strapi.load (node_modules/strapi/lib/Strapi.js:326:5)
at setupStrapi (tests/helpers/strapi.js:10:5)
at Object.<anonymous> (tests/app.test.js:8:3)
RUNS tests/app.test.js
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
I followed these instructions exactly.
How can I fix this issue?
Thanks
The issue is solved by changing the env folder name into environments

Mocking a custom node module using jest.mock method

So, I am new to mocking a module using jest.mock()
So here is the scenario, I have created a node module and uploaded to the private npm registry from where I can that module in my app.
If suppose the name of the module is #a/lp-mod and if this the index.js of that module:
export const lpr = async () => {
// some code that does something and returns some data back
}
export default {
lpr
}
now let us all suppose I need to mock this module (#a/lp-mod) and have to return some static data whenever lpr function is gets called in the context of a test case.
So here is the code I have written:
> proj_directory
|---->__mocks__
| |--->#a
| | |--->lp-mod --> this directory has index.js with mock data
|---->node_modules
| |--->#a
| | |--->lp-mod --> this directory has index.js inside /src
| | |---> src
| | | |---> index.js
|---->test
| |--->1.test.js --->
node_modules/#a/lp-mod/src/index.js
// some npm imports like axios
export const lpr = async () => {
// has some I/O calls, but let's just keep it simple
return Promise.resolve('I am original call')
}
export default {
lpr
}
__mocks__/#a/lp-mod/index.js
const p = jest.genMockFromModule('#a/lp-mod')
p.lpr = () => Promise.resolve('This is mocked call')
export default p
1.test.js
// before describe (test case) I wrote this
jest.mock('#a/lp-mod')
But I am getting undefined when the file is trying to import the original #a/lp-mod module for the usage inside the test context.
As per my expectation, it should get the mocked module and return the data from there only, if I am testing my app.
Please shed some light & bear with me incase some of the info is missing, please let me know in case there is any doubt.
Happy coding :)

TypeError: Cannot read property 'LENGTH_LONG' of undefined

I am doing jest testing in react native and I have used snackbar in my project. While executing jest i am getting this error.'LENGTH_LONG' is inbuilt variable in snackbar. I am posting where i have used 'LENGTH_LONG' variable and error message. Anyone please help me out
jest "login"
FAIL __tests__\jest\LoginScreen.test.js
● Test suite failed to run
TypeError: Cannot read property 'LENGTH_LONG' of undefined
10 | ScrollView
11 | } from "react-native";
> 12 | import Snackbar from 'react-native-snackbar';
13 |
14 | import { connect } from "react-redux";
15 | import { Button, Text, Divider } from "react-native-elements";
at Object.<anonymous> (node_modules/react-native-snackbar/lib/index.js:1:252)
at Object.<anonymous> (src/screens/login/loginScreen.js:12:26)
at Object.<anonymous> (__tests__/jest/LoginScreen.test.js:3:18)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 2.689s, estimated 4s
Ran all test suites matching /login/i.
Code is
render() {
return (
<View style={styles.mainContainer}>
{this.renderTopLogoContainer()}
{this.renderBottomContainer()}
{this.props.hasError ? Snackbar.show({
title: this.props.error.display_message,
duration: Snackbar.LENGTH_LONG
}) : null}
</View>
);
}
https://github.com/cooperka/react-native-snackbar/tree/master/example
add react-native-snackbar.js file in mocks folder
You have not mentioned whether you are trying to run in ios or android, recently I've seen this issue in ios because I've missed installing the pod.
Try this:
pod install in the ios directory
react-native run-ios
You can also use npm instead of yarn if you prefer.
create a file: 'react-native-snackbar.js' inside the folder 'mocks' with the code
module.exports = {
show: jest.fn()
};

Jest can not deal with insertAdjacentElement?

I want to test a quite simple JS function
export function displaySpinner() {
const loadingOverlayDOM = document.createElement('DIV');
const spinner = document.createElement('IMG');
loadingOverlayDOM.id = 'overlay-spinner';
loadingOverlayDOM.className = 'content-overlay';
spinner.className = 'is-spinning';
spinner.setAttribute('src', '/assets/img/svg/icons/spinner.svg');
l loadingOverlayDOM.insertAdjacentElement('beforeend', spinner);
document.body.insertAdjacentElement('beforeend', loadingOverlayDOM);
}
with this (for the purpose of this issue stripped down) Jest test code:
test('displaySpinner displays the spinner overlay in the current page', () => {
utils.displaySpinner();
});
But the test run yells at me:
FAIL app/helper/utils.test.js
● utils › displaySpinner displays the spinner overlay in the current page
TypeError: loadingOverlayDOM.insertAdjacentElement is not a function
at Object.displaySpinner (app/helper/utils.js:185:439)
at Object.<anonymous> (app/helper/utils.test.js:87:15)
at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)
at process._tickCallback (internal/process/next_tick.js:109:7)
Is this an error in Jest or am I missing something here?
I finally found the answer myself:
Jest uses jsdom which does not yet support the DOM function insertAdjacentElement (see this issue on GitHub and it's references). So I'll have to wait until jsdom implements it or use another method in my JS.
You can replace the default version of jsdom with an up-to-date version (e.g. 14) by installing the corresponding module:
npm install --save-dev jest-environment-jsdom-fourteen
or using yarn:
yarn add jest-environment-jsdom-fourteen --dev
and then using the jest testEnvironment config parameter:
{
"testEnvironment": "jest-environment-jsdom-fourteen"
}
Note that if you launch jest with the --env=jsdom argument, this will override the config file, so you need to remove it.

Resources