Jest: Difference between revisions
(43 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
=Introduction= | =Introduction= | ||
This is a page to introduce Jest. Facebook employs a lot of the people who develop jest and can be and is used for test in other frameworks. | This is a page to introduce Jest. Facebook employs a lot of the people who develop jest and can be and is used for test in other frameworks.<br> | ||
<br> | |||
Example code can be found at [[https://github.com/danielstern/isomorphic-react here]] | |||
=Choices= | =Choices= | ||
Line 12: | Line 14: | ||
*Module mocking (stubbing objects) | *Module mocking (stubbing objects) | ||
=Getting Started= | =Getting Started= | ||
=Naming Test= | ==Running== | ||
We can run jest on it's own or continually with watch mode | |||
<syntaxhighlight lang="js"> | |||
jest --watch | |||
</syntaxhighlight> | |||
At least one "it" block must be found or jest will return an error. | |||
==Code Coverage== | |||
With Jest we can get a report by typing | |||
<syntaxhighlight lang="js"> | |||
npm test -- --coverage | |||
</syntaxhighlight> | |||
==Naming Test== | |||
The file names must be recognized as a test. | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
__tests__/*.js | __tests__/*.js | ||
Line 19: | Line 34: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=Example Test in Jest= | ==Example Test in Jest== | ||
<syntaxhighlight lang="js"> | <syntaxhighlight lang="js"> | ||
Describe is the suite, it is the test | Describe is the suite, it is the test | ||
describe("The question list ", ()=> { | |||
it ("should display a list of items", ()=> { | |||
expect(2+2).toEqual(4); | |||
}) | |||
it ("should display a list of items", ()=> { | |||
expect(2+4).toEqual(6); | |||
}) | |||
}) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=Setup and Teardown= | ==Setup and Teardown== | ||
This can be done using | This can be done using before each and before all. | ||
<syntaxhighlight lang="js"> | <syntaxhighlight lang="js"> | ||
BeforeEach BeforeAll | |||
beforeAll(()=>{ | |||
console.log("Hello"); | |||
}); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
and AfterEach AfterAll | and to tear down we can use AfterEach AfterAll | ||
<syntaxhighlight lang="js"> | <syntaxhighlight lang="js"> | ||
afterAll(()=>{ | |||
console.log("Hello"); | |||
}); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Note does not matter what order you write them in. | Note does not matter what order you write them in. | ||
=Skipping and Isolating Tests= | ==Skipping and Isolating Tests== | ||
Add keyword only to include tests | Add keyword only to include tests | ||
<syntaxhighlight lang="js"> | <syntaxhighlight lang="js"> | ||
it.only ("should display a list of items", ()=> { | |||
expect(2+2).toEqual(4); | |||
}) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Add keyword skip to exlude tests | Add keyword skip to exlude tests | ||
<syntaxhighlight lang="js"> | <syntaxhighlight lang="js"> | ||
it.skip ("should display a list of items", ()=> { | |||
expect(2+2).toEqual(4); | |||
}) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=Async Tests= | =Async Tests= | ||
<syntaxhighlight lang="js"> | <syntaxhighlight lang="js"> | ||
// Using a callback that is passed to the test force it to wait | |||
it('async test 1', done=> { | |||
setTimeout(done, 100) | |||
}); | |||
// Return a Promise which jest knows to wait for | |||
it('async test 2',()=> { | |||
return new Promise( | |||
resolve => setTimeout(resolve,100) | |||
); | |||
}); | |||
// Use await to wait before returning. | |||
it('async test 1', async ()=> | |||
await delay(100) | |||
); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=Mocking= | =Mocking= | ||
Create directory __mocking__ at the same level as | ==Why== | ||
*Reduces dependencies and makes testing faster | |||
*Prevents side effects | |||
*Control the scenario we wish to test e.g. timeout, corrupt data | |||
==What is Mocking== | |||
A mock is a replacement for known functionality which can be used to capture usage of the original function and fake a response to the users of the mock. | |||
==Setup== | |||
Create directory __mocking__ at the same level as npm node_module you are trying to mock. This makes your module get loaded in place of the original module. | |||
==Example== | |||
===Function to Mock=== | |||
/** | |||
* Fetch question details from the local proxy API | |||
*/ | |||
<syntaxhighlight lang="javascript"> | |||
export function * handleFetchQuestion ({question_id}) { | |||
const raw = yield fetch(`/api/questions/${question_id}`); | |||
const json = yield raw.json(); | |||
const question = json.items[0]; | |||
/** | |||
* Notify application that question has been fetched | |||
*/ | |||
yield put({type:`FETCHED_QUESTION`,question}); | |||
} | |||
</syntaxhighlight> | |||
===Mocking the JavaScript Fetch function=== | |||
In the code below we are attempting to mock the javascript fetch function where call the function and return a value. I orginally struggled with this because of the old syntax but it became a lot clear after so much work with node js and modern javascript | |||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
let __value = 42; | |||
// Old syntax | |||
// Replace a function which returns 42 | |||
const isomorphicFetch = jest.fn( (){ returns __value }); | |||
// Add a function to set the value | |||
isomorphicFetch.__setValue = function(v) {__value = v}; | |||
// Modern notation | |||
const isomorphicFetch = jest.fn( ()=> __value); | |||
isomorphicFetch.__setValue = v => __value = v; | |||
export default isomorphicFetch; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
===Mocking the handleFetchQuestion=== | |||
Now we need to mock the original function above using our ownversion of fetch. We set the value to be the format expected back from fetch which is an object which we can do because __setValue is not type aware [{"question_id": 42}] | |||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
import { handleFetchQuestion } from './fetch-question-saga'; | import { handleFetchQuestion } from './fetch-question-saga'; | ||
import fetch from 'isomorphic-fetch'; | import fetch from 'isomorphic-fetch'; | ||
/** | |||
* This test is an example of two important Jest testing principles, | |||
* 1) we're mocking the "fetch" module, so that we don't actually make a request every time we run the test | |||
* The module, isomorphic fetch, is conveniently mocked automatically be including the file __mocks__/isomorphic-fetch.js adjacent to to the Node.js folder | |||
* 2) we're using an async function to automatically deal with the fact that our app isn't synchronous | |||
*/ | |||
describe("Fetch questions saga",()=>{ | |||
beforeAll(()=>{ | |||
fetch.__setValue([{question_id:42}]); | |||
}); | |||
it("should get the questions from the correct endpoint in response to the appropriate action",async ()=>{ | |||
const gen = handleFetchQuestion({question_id:42}); | |||
/** | |||
* At this point, isomorphic fetch must have been mocked, | |||
* or an error will occur, or, worse, an unexpected side effect! | |||
*/ | |||
const { value } = await gen.next(); | |||
expect(value).toEqual([{question_id:42}]); | |||
/** | |||
* We can also assert that fetch has been called with the values expected (note that we used a spy in the file where we mock fetch.) | |||
*/ | |||
expect(fetch).toHaveBeenCalledWith(`/api/questions/42`); | |||
}); | |||
}); | |||
</syntaxhighlight> | |||
=Snapshot Testing= | |||
It is really hard to be excited about this. It seems so fragile. Basically it records the first run and makes comparisons on subsequent runs. Any change is flagged. | |||
<syntaxhighlight lang="javascript"> | |||
import React from 'react'; | |||
import TagsList from './TagsList' | |||
import renderer from 'react-test-renderer'; | |||
describe("The tags list",()=>{ | |||
/** | |||
* The tagsList can be tested against an expected snapshot value, as in below. | |||
*/ | |||
it ("renders as expected",()=>{ | |||
const tree = renderer | |||
.create(<TagsList tags={[`css`,`html`,`typescript`,`coffeescript`]}/>) | |||
.toJSON(); | |||
expect(tree).toMatchSnapshot(); | |||
}); | |||
}); | |||
</syntaxhighlight> | |||
=Component Testing= | |||
See also [[React_Testing_Components]] | |||
==Making Components More Testable== | |||
From best to worse. | |||
*No internal state - output is a idempotent product of the props | |||
*No side-effects, have these handled by sagas, thunks etc | |||
*No lifecycle hooks - fetching data handled on application level | |||
==Component Testing with Redux== | |||
===React and Redux=== | |||
These a perceived as a great match because it means | |||
*Components do not generate side effects, only actions | |||
*Components consist of display and container components | |||
*No state in Components | |||
So the approach to testing for React Redux Components is | |||
*Test Container and Display Separately | |||
*Use Unit test to verify methods and props on container | |||
*Use snapshot tests for the display | |||
===Redux and Testing mapStateToProps=== | |||
mapStateToProps is the function responsible for mapping state to the props. Our focus on testing here is only the mapping and not the content. i.e. that the state is appropriately mapped to the props. | |||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
Line 147: | Line 246: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==Component Testing with State== | |||
= | |||
Bit of a lot of code but here goes | Bit of a lot of code but here goes | ||
Create component | ===Create component=== | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
import React from 'react'; | import React from 'react'; | ||
Line 174: | Line 272: | ||
<section className="mt-3 mb-2"> | <section className="mt-3 mb-2"> | ||
<div className="notifications"> | <div className="notifications"> | ||
{this.state.count != -1 ? '${this.state.count} Notifications Awaiting!' : 'Loading...'} | {this.state.count != -1 | ||
? '${this.state.count} Notifications Awaiting!' | |||
: 'Loading...'} | |||
</div> | </div> | ||
</section> | </section> | ||
Line 181: | Line 281: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===Create a Service=== | |||
Create a Service | |||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
export default { | export default { | ||
Line 192: | Line 291: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===Test Case=== | |||
Test Case | And here is the test case | ||
<syntaxhighlight lang=" | <syntaxhighlight lang="js"> | ||
import NotificationsViewer from '../NotificationsViewer'; | import NotificationsViewer from '../NotificationsViewer'; | ||
import renderer from 'react-test-renderer'; | import renderer from 'react-test-renderer'; | ||
Line 234: | Line 333: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===Mocked Service=== | |||
Mocked Service src\services\__mocks__\NotificationService.js | Let's make a mocked service in the appropriate place next to the real service. src\services\__mocks__\NotificationService.js | ||
<syntaxhighlight lang="js"> | |||
<syntaxhighlight lang=" | |||
let count = 0; | let count = 0; | ||
export default { | export default { | ||
Line 249: | Line 347: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=Matchers in Jest= | =Matchers in Jest= | ||
Line 271: | Line 368: | ||
expect.stringMatching(string | regexp) | expect.stringMatching(string | regexp) | ||
expect.addSnapshotSerializer(serializer) | expect.addSnapshotSerializer(serializer) | ||
=Transpiling in Jest 2024= | |||
I am certainly not expert but here is what I know. There several types of formats for modules, | |||
*commonJS (uses require) | |||
*esm (uses import) | |||
==Introduction to issue== | |||
When you run jest you may sometimes see<br> | |||
[[File:Jest Error.png|600px]]<br> | |||
This is because the module, in this case MsalReactTester, cannot be loaded because it is an esm module and you are running jest with commonJS. | |||
==Solution== | |||
To solve this problem we need to transpile (convert) the module from esm to commonJS. To do this we need to config jest like this. | |||
<syntaxhighlight lang="js"> | |||
export default async (): Promise<Config> => { | |||
return { | |||
rootDir: '../', | |||
verbose: true, | |||
setupFilesAfterEnv: ['<rootDir>/configs/setupTests.ts'], | |||
testEnvironment: '<rootDir>/configs/jest.environment.ts', | |||
moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx'], | |||
moduleDirectories: ['node_modules', 'src'], | |||
moduleNameMapper: { | |||
'\\.(css|less|scss)$': 'identity-obj-proxy', | |||
}, | |||
transform: { | |||
'^.+\\.(ts|tsx)?$': 'ts-jest', | |||
'^.+\\.(js|jsx)$': ['babel-jest', { configFile: './configs/babel.config.js' }], | |||
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': | |||
'<rootDir>/configs/__mocks__/fileMock.js', | |||
'^.+\\.(css|sass|scss)$': '<rootDir>/configs/__mocks__/styleMock.js', | |||
}, | |||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], | |||
transformIgnorePatterns: ['/node_modules/(?!(uint8array-extras|msal-react-tester)/)'], | |||
... | |||
} | |||
</syntaxhighlight> | |||
The important lines is the transformIgnorePatterns which tells jest to ignore all modules except uint8array-extras or msal-react-tester. I am hopeless at regex so went there to prove it. You can see only the last two are selected and therefore ignored. | |||
[[File:Reg101 image1 jest.png | 400px]] | |||
==Other Configs== | |||
There are other configurations involved too and are provided here for completeness | |||
*setupTests.ts | |||
*jest.environment.ts | |||
<syntaxhighlight lang="ts"> | |||
// setupTests.ts | |||
import '@testing-library/jest-dom' | |||
import crypto from 'crypto' | |||
Object.defineProperty(window, 'crypto', { | |||
value: { | |||
randomUUID: () => crypto.randomUUID(), | |||
}, | |||
}) | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="ts"> | |||
// jest.environment.ts | |||
import Environment from 'jest-environment-jsdom' | |||
export default class CustomTestEnvironment extends Environment { | |||
async setup() { | |||
await super.setup() | |||
this.global.TextEncoder = TextEncoder | |||
this.global.TextDecoder = TextDecoder | |||
this.global.Response = Response | |||
this.global.Request = Request | |||
} | |||
} | |||
</syntaxhighlight> |
Latest revision as of 05:22, 4 December 2024
Introduction
This is a page to introduce Jest. Facebook employs a lot of the people who develop jest and can be and is used for test in other frameworks.
Example code can be found at [here]
Choices
Popular tools for testing are Enzyme and Jasmine/Mocha. Jest is built on top of Jasmine/Mocha. Jest works with or without React and has a great assertion library.
Why Not Enzyme
This has over 200+ issues open and 26 of these are bugs. Jest is recommended by the react team.
Jest vs Mocha
Jest and Mocha both run tests sync and async but jest also has the following features.
- Spies (stubbing methods to spy)
- Snapshot testing
- Module mocking (stubbing objects)
Getting Started
Running
We can run jest on it's own or continually with watch mode
jest --watch
At least one "it" block must be found or jest will return an error.
Code Coverage
With Jest we can get a report by typing
npm test -- --coverage
Naming Test
The file names must be recognized as a test.
__tests__/*.js
*.spec.js
*.test.js
Example Test in Jest
Describe is the suite, it is the test
describe("The question list ", ()=> {
it ("should display a list of items", ()=> {
expect(2+2).toEqual(4);
})
it ("should display a list of items", ()=> {
expect(2+4).toEqual(6);
})
})
Setup and Teardown
This can be done using before each and before all.
BeforeEach BeforeAll
beforeAll(()=>{
console.log("Hello");
});
and to tear down we can use AfterEach AfterAll
afterAll(()=>{
console.log("Hello");
});
Note does not matter what order you write them in.
Skipping and Isolating Tests
Add keyword only to include tests
it.only ("should display a list of items", ()=> {
expect(2+2).toEqual(4);
})
Add keyword skip to exlude tests
it.skip ("should display a list of items", ()=> {
expect(2+2).toEqual(4);
})
Async Tests
// Using a callback that is passed to the test force it to wait
it('async test 1', done=> {
setTimeout(done, 100)
});
// Return a Promise which jest knows to wait for
it('async test 2',()=> {
return new Promise(
resolve => setTimeout(resolve,100)
);
});
// Use await to wait before returning.
it('async test 1', async ()=>
await delay(100)
);
Mocking
Why
- Reduces dependencies and makes testing faster
- Prevents side effects
- Control the scenario we wish to test e.g. timeout, corrupt data
What is Mocking
A mock is a replacement for known functionality which can be used to capture usage of the original function and fake a response to the users of the mock.
Setup
Create directory __mocking__ at the same level as npm node_module you are trying to mock. This makes your module get loaded in place of the original module.
Example
Function to Mock
/**
* Fetch question details from the local proxy API */
export function * handleFetchQuestion ({question_id}) {
const raw = yield fetch(`/api/questions/${question_id}`);
const json = yield raw.json();
const question = json.items[0];
/**
* Notify application that question has been fetched
*/
yield put({type:`FETCHED_QUESTION`,question});
}
Mocking the JavaScript Fetch function
In the code below we are attempting to mock the javascript fetch function where call the function and return a value. I orginally struggled with this because of the old syntax but it became a lot clear after so much work with node js and modern javascript
let __value = 42;
// Old syntax
// Replace a function which returns 42
const isomorphicFetch = jest.fn( (){ returns __value });
// Add a function to set the value
isomorphicFetch.__setValue = function(v) {__value = v};
// Modern notation
const isomorphicFetch = jest.fn( ()=> __value);
isomorphicFetch.__setValue = v => __value = v;
export default isomorphicFetch;
Mocking the handleFetchQuestion
Now we need to mock the original function above using our ownversion of fetch. We set the value to be the format expected back from fetch which is an object which we can do because __setValue is not type aware [{"question_id": 42}]
import { handleFetchQuestion } from './fetch-question-saga';
import fetch from 'isomorphic-fetch';
/**
* This test is an example of two important Jest testing principles,
* 1) we're mocking the "fetch" module, so that we don't actually make a request every time we run the test
* The module, isomorphic fetch, is conveniently mocked automatically be including the file __mocks__/isomorphic-fetch.js adjacent to to the Node.js folder
* 2) we're using an async function to automatically deal with the fact that our app isn't synchronous
*/
describe("Fetch questions saga",()=>{
beforeAll(()=>{
fetch.__setValue([{question_id:42}]);
});
it("should get the questions from the correct endpoint in response to the appropriate action",async ()=>{
const gen = handleFetchQuestion({question_id:42});
/**
* At this point, isomorphic fetch must have been mocked,
* or an error will occur, or, worse, an unexpected side effect!
*/
const { value } = await gen.next();
expect(value).toEqual([{question_id:42}]);
/**
* We can also assert that fetch has been called with the values expected (note that we used a spy in the file where we mock fetch.)
*/
expect(fetch).toHaveBeenCalledWith(`/api/questions/42`);
});
});
Snapshot Testing
It is really hard to be excited about this. It seems so fragile. Basically it records the first run and makes comparisons on subsequent runs. Any change is flagged.
import React from 'react';
import TagsList from './TagsList'
import renderer from 'react-test-renderer';
describe("The tags list",()=>{
/**
* The tagsList can be tested against an expected snapshot value, as in below.
*/
it ("renders as expected",()=>{
const tree = renderer
.create(<TagsList tags={[`css`,`html`,`typescript`,`coffeescript`]}/>)
.toJSON();
expect(tree).toMatchSnapshot();
});
});
Component Testing
See also React_Testing_Components
Making Components More Testable
From best to worse.
- No internal state - output is a idempotent product of the props
- No side-effects, have these handled by sagas, thunks etc
- No lifecycle hooks - fetching data handled on application level
Component Testing with Redux
React and Redux
These a perceived as a great match because it means
- Components do not generate side effects, only actions
- Components consist of display and container components
- No state in Components
So the approach to testing for React Redux Components is
- Test Container and Display Separately
- Use Unit test to verify methods and props on container
- Use snapshot tests for the display
Redux and Testing mapStateToProps
mapStateToProps is the function responsible for mapping state to the props. Our focus on testing here is only the mapping and not the content. i.e. that the state is appropriately mapped to the props.
import { mapStateToProps } from '../QuestionDetail';
it("should map the state to props correctly", () => {
// Sample App State with sampleQuestion being object in state
const sampleQuestion {
question_id:42,
body: "Space is big"
};
const appState = {
questions: [sampleQuestion]
};
// Sample Props
const ownProps = {
question:42
});
const componentState = mapStateToProps(appState, ownProps)
expect(componentState).toEqual(sampleQuestion);
}
Component Testing with State
Bit of a lot of code but here goes
Create component
import React from 'react';
export default class extends React.Component {
constructor)(...args) {
super(...args);
this.state = {
count: -1
}
}
async comonentDidMount () {
let { count } = await NotificationService.GetNotification();
this.setState( {
count
});
}
render() {
return (
<section className="mt-3 mb-2">
<div className="notifications">
{this.state.count != -1
? '${this.state.count} Notifications Awaiting!'
: 'Loading...'}
</div>
</section>
)
}
}
Create a Service
export default {
async GetNoitifications() {
console.warning("REAL NOTIFICATION SERVICE!");
await delay(1000);
return { count: 42 };
}
}
Test Case
And here is the test case
import NotificationsViewer from '../NotificationsViewer';
import renderer from 'react-test-renderer';
import React from 'react';
import delay from 'redux-saga';
// NOTE Local module you need to pass in url of notification service
jest.mock('../../services/NotificationService');
// NOTE 2 this needs to be a require and needs to be after the jest. Making it
// an import will fail
const notificationService = require('../../services/NotificationService').default;
describe("The notification viewer", () => {
beforeAll( ()=> {
notificationService.__setCount(5);
});
it("should display the correct number of notifications", async()=> {
const tree = renderer
.create(
<NoticationsViewer/>
)
await delay();
const instance = tree.root;
// find by className the component
const component = instance.findByProps( { className: 'notificiations' });
const text = component.children[0];
export(text).toEqual("5 Notifications");
});
});
Mocked Service
Let's make a mocked service in the appropriate place next to the real service. src\services\__mocks__\NotificationService.js
let count = 0;
export default {
__setCount(__count) {
count = _count;
},
async GetNotifications() {
console.warn("Good Job! Using Mock");
}
}
Matchers in Jest
These can be found [1]
Some of them for quick reference.
expect(value) expect.extend(matchers) expect.anything() expect.any(constructor) expect.arrayContaining(array) expect.assertions(number) expect.hasAssertions() expect.not.arrayContaining(array) expect.not.objectContaining(object) expect.not.stringContaining(string) expect.not.stringMatching(string | regexp) expect.objectContaining(object) expect.stringContaining(string) expect.stringMatching(string | regexp) expect.addSnapshotSerializer(serializer)
Transpiling in Jest 2024
I am certainly not expert but here is what I know. There several types of formats for modules,
- commonJS (uses require)
- esm (uses import)
Introduction to issue
When you run jest you may sometimes see
This is because the module, in this case MsalReactTester, cannot be loaded because it is an esm module and you are running jest with commonJS.
Solution
To solve this problem we need to transpile (convert) the module from esm to commonJS. To do this we need to config jest like this.
export default async (): Promise<Config> => {
return {
rootDir: '../',
verbose: true,
setupFilesAfterEnv: ['<rootDir>/configs/setupTests.ts'],
testEnvironment: '<rootDir>/configs/jest.environment.ts',
moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx'],
moduleDirectories: ['node_modules', 'src'],
moduleNameMapper: {
'\\.(css|less|scss)$': 'identity-obj-proxy',
},
transform: {
'^.+\\.(ts|tsx)?$': 'ts-jest',
'^.+\\.(js|jsx)$': ['babel-jest', { configFile: './configs/babel.config.js' }],
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/configs/__mocks__/fileMock.js',
'^.+\\.(css|sass|scss)$': '<rootDir>/configs/__mocks__/styleMock.js',
},
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
transformIgnorePatterns: ['/node_modules/(?!(uint8array-extras|msal-react-tester)/)'],
...
}
The important lines is the transformIgnorePatterns which tells jest to ignore all modules except uint8array-extras or msal-react-tester. I am hopeless at regex so went there to prove it. You can see only the last two are selected and therefore ignored.
Other Configs
There are other configurations involved too and are provided here for completeness
- setupTests.ts
- jest.environment.ts
// setupTests.ts
import '@testing-library/jest-dom'
import crypto from 'crypto'
Object.defineProperty(window, 'crypto', {
value: {
randomUUID: () => crypto.randomUUID(),
},
})
// jest.environment.ts
import Environment from 'jest-environment-jsdom'
export default class CustomTestEnvironment extends Environment {
async setup() {
await super.setup()
this.global.TextEncoder = TextEncoder
this.global.TextDecoder = TextDecoder
this.global.Response = Response
this.global.Request = Request
}
}