How to use Jest "projects" config with create-react-app?
I am building a react project which has 2 separate Jest configs for my frontend and backend tests. My frontend tests use React Testing Library which requires the "jsdom" test environment and my backend tests use mongoose which requires the "node" test environment. I am trying to use the jest "projects" config in my package.json in order to run the two testing suites simultaneously with their respective environments like so:
{
"jest": {
"projects": [
"backend/config/jest.config.js",
"src/jest.config.js"
]
}
}
However, when I try to run the tests, I get this message:
Out of the box, Create React App only supports overriding these Jest options:
• clearMocks
• collectCoverageFrom
• coveragePathIgnorePatterns
• coverageReporters
• coverageThreshold
• displayName
• extraGlobals
• globalSetup
• globalTeardown
• moduleNameMapper
• resetMocks
• resetModules
• restoreMocks
• snapshotSerializers
• transform
• transformIgnorePatterns
• watchPathIgnorePatterns.
These options in your package.json Jest configuration are not currently supported by Create React App:
• projects
If you wish to override other Jest options, you need to eject from the default setup. You can do so by running npm run eject but remember that this is a one-way operation. You may also file an issue with Create React App to discuss supporting more options out of the box.
I'm not quite sure what do to here. Any way to make the jest "projects" option work the create-react-app?
See also questions close to this topic
-
Unable to catch and log the error from axios request
I'm validating user input and result in express and am returning 422 if the input is invalid and a 400 if result is empty. The problem is that I can't log the response object when an error occurs.
Nodejs:
if (q === '' || q.length < 3 || q.length > 150) { console.log('invalid query'); return res.sendStatus(422).send('Search not found'); } else { try { // Fetch redis data const data = await GET_ASYNC('data'); // stuff here // Result Validation if (!Array.isArray(data) || !data.length) { res.status(400).send('Search not found'); } else { // do stuff res.status(200).send(data); } } catch (err) { console.error(err); res.sendStatus(500); // Server error }
Now my react code:
const searchDb = useCallback(async() => { const CancelToken = axios.CancelToken; const source = CancelToken.source(); try { axios.get(`/api/bestProduct?q=${searchValue}`, { cancelToken: source.token }) .then(res => { console.log(res) // nothing shows up const data = res.data; setData(data) }); } catch (err) { if (axios.isCancel(err)) { console.log(err.response); // nothing shows up } else { console.log('hello??') // nothing return setError(`There's been a problem on our end.`) } } }, [])
I've looked at other solution and tried to log the res and res.status but nothing shows up. This is what my console looks like during the error:
-
Dynamic object keys... Cannot create property on string
I'm trying to make an input automatically store its value in an object. The key should be the input's id. Ex: {screen1_input1: 'whatever'}. The first character does that. The second character crashes with "TypeError: Cannot create property on string". I think I see what's happening but I don't know how to fix it.
import { useState } from 'react' function Demo() { const [contentData, setContentData] = useState({}) const onChange = (e) => { let oldData = contentData setContentData(oldData[e.target.id] = e.target.value) console.log('*') } const Screen1 = () => { return ( <> <input type="text" id="screen1_input1" onChange={onChange} /> </> ) } return ( <> <h2 className="Demo"> {Screen1()} </h2> </> ) } export default Demo
-
How can I extract a nested array of objects and put them in the core array?
I am working on a functionality where I need to group some items and also ungroup them.
Some days ago I asked this question: How can I group specific items within an object in the same array and delete them from the core array? where a couple of people helped me solving the grouping part. But it is very related to this question.
What I need to do now, is to ungroup the items with the exact same requirement: ungroup the
checked === true
group and put the items back from where they came from and remove all duplicates.Here is a reproducible demo with both functionalities: https://codesandbox.io/s/ts-react-grouping-forked-rmwhr?file=/src/App.tsx
And here the relevante piece of code:
const handleUngroupingQuestions = (): void => { const questionAddedCopy: VariableConfig[] = [...questionAdded] const filteredByChecked: VariableConfig[] = questionAddedCopy.filter((q: VariableConfig) => isCheck.includes(q.id)) if (isCheck.length) { setCheck([]) const extractGroup = (i: number): VariableConfig[] => filteredByChecked[i].questionGroup const addChecked = (q: VariableConfig): VariableConfig => ({ ...q, questionGroup: [] }) // @TODO // Remove this when we have a proper data structure clearVariable() const nestChecked = (qs: VariableConfig[], found = false) => qs.flatMap((q: VariableConfig, i: number) => { if (filteredByChecked.includes(q)) { if (found) { return [] } else { found = true return [...[addChecked(q)], ...extractGroup(i)] } } else { return [q] } }) const getNew = [...nestChecked(questionAdded)] console.log({ getNew: JSON.stringify(getNew, null, 2) }) addQuestion(getNew.filter((g, i, a) => a.indexOf(g) === i)) } }
For some reason right now I am getting an error:
Cannot read property 'questionGroup' of undefined
Something is happening with an index.
So what I need is to group all of the items with the checked property being true. Then click on
ungroup
and bring the items back to its original position and deleting the current group. I must be able to do that even when there are multiple groups of questions.What am I missing?
-
Jest mock middleware response
I am trying to mock a middleware response, and i am trying to use
jest.spyOn()
but can't seem to get it workingMy controller.ts has the following
import someMiddleware from '../someMiddleware; .... .... this.route.post('/getData', someMiddleware, setValue)
In someMiddlware.ts
//making a fetch call based on data in req.body ..... const data = await fetchData(url, data) next() .....
In my test file controller.test.ts
describe('Test Data', () => { beforeEach(() => { someMiddlewareSpyOn = jest.spyOn(meddelware, "someMiddleware"); }); afterEach(() => { jest.resetModules(); jest.resetAllMocks(); }); it('response status should be a 200', async () => { someMiddlewareSpyOn.mockResolvedValue({data:[].....}); const res = await request(app.getServer()) .post('/getData'); expect(res.status).toBe(200); }) });
The above does not work, looking for assistance on how to do this.
-
Testing Controller and Service in Jest
I'm fairly new to Jest and have been trying (with no luck) to figure out how to write tests for my controller. I'm not sure how to write the test as it calls another function. It would be great if I could get pointed in the right direction at least. Thanks in advance.
controller.ts
import * as Services from './services'; export async function GetCountriesList(req: Request, res: Response): Promise<void> { const response = await Services.GetCountriesList(); res.status(response.code).json({ status: response.status, message: response.message, count: response.count, data: response.data }); }
service.ts
import db from '../../modules/db'; import { DBGenericDataResponse } from '../../types/models'; export async function GetCountriesList(): Promise<DBGenericDataResponse> { const lQuery = 'somquery'; const responseMessage: DBGenericDataResponse = { code: 200, status: 'ok', message: '', count: 0, data: [], error: '' }; try { const dbResult = await db.query<any>(lQuery); responseMessage.message = 'Countries returned'; responseMessage.count = dbResult.rows.length; responseMessage.data = dbResult.rows; } catch (err) { responseMessage.code = 400; responseMessage.status = 'error'; responseMessage.message = 'Error retrieving Countries List'; responseMessage.error = err; } return responseMessage; }
-
Warning: <TEXT /> is using incorrect casing
console.error node_modules/react-dom/cjs/react-dom.development.js
Warning:
<TEXT />
is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.I have the issue with Jest and react-pdf
In the component where I'm using the react-pdf components this is written as:
<Text>
, but when performing the test it's appearing as<TEXT>
My component:
const HeaderPDF: React.FC<Props> = (props: Props) => { return ( <View style={styles.headerContainer} fixed> <View style={styles.headerTop}> <Text style={styles.textBoldTopHeader}> "Some text" </Text> <View style={styles.headerTopInputContainer}> <View style={styles.headerTopInputTextContainer}> <Text style={styles.textInputTopHeader}>Route</Text> </View> <View style={styles.inputSmall} /> </View> </View> </View> ); };
The test:
import React from 'react'; import { render } from 'tests/support/customRender'; import HeaderPDF from ../../HeaderPDF'; describe('HeaderPDF', () => { it('Renders a HeaderPDF component successfully', () => { const { container } = render( <HeaderPDF someProps /> ); expect(container).toMatchSnapshot(); }); });
-
How to initialize random state when using React?
I am trying to initialize my React app with a randomized state, but while developing I realized that React.StrictMode will try to render your component twice in order to find bugs. This causes the initial print to console to be different from what's actually printed on the screen.
Am I using
useState
correctly or is React telling me to do something else?Code:
App.js
export function Game(props) { const [theSecret, _] = useState( Array(4) .fill() .map(() => getRandomInt(4)) ); console.log(theSecret) return <button>{theSecret}</button> }
index.js
ReactDOM.render( <React.StrictMode> <Game /> </React.StrictMode>, document.getElementById('root') );
-
How to use import global sass variables with create-react-app (ejected)
Please see this repo for further information and reproduction.
I am using an ejected create-react-app and I want to be able to use global sass variables in an individual stylesheet without having to import the stylesheet. I think using
sass-resources-loader
is what I should use (although if there is a better way of doing this, please let me know). I have updated the create-react-app ejected webpack config here, but whenever I runyarn start
, I still get the complaint:SassError: Undefined variable: "$boxSize". on line 5 of src/SampleComponent/sampleComponent.scss , height: $boxSize;
Is there something that I am doing wrong in trying to use
sass-resources-loader
or should I be using something different instead? Thanks, and here are some file snippets below for more context:file structure:
src/ - SampleComponent/ - SampleComponent.js - SampleComponent.scss - styles/ - sizes.scss - index.js
SampleComponent.js:
import * as styles from './sampleComponent.scss'; const SampleComponent = () => ( <div className={styles.div}> <h3>hello world</h3> </div> ); export default SampleComponent;
sampleComponent.scss:
.div { align-items: center; background: pink; display: flex; height: $boxSize; justify-content: center; margin: 5rem; width: $boxSize; }
sizes.scss:
$boxSize: 30rem;
-
TypeError: Failed to update a ServiceWorker for scope - An unknown error occurred when fetching the script. (Create React App)
I'm using an un-ejected version of create react app (v3.2 react-scripts). I'm alerting the users of new versions of the code that have been pushed via service workers. When the service worker detects an update, we pop open a toast notification asking the user to refresh the browser.
This works great for the most part unless the user has multiple tabs open.
We have roughly 30 people who use this tool daily (it's an internal tool for my company). Nearly every update works for every user. They receive the notification to refresh, they refresh the browser and they have the new code. Sporadically one random user will receive the following error:
TypeError: Failed to update a ServiceWorker for scope - with script ('/service-worker.js'): An unknown error occurred when fetching the script.
Usually this happens to a single user and more often than not this user has multiple tabs open. Once the user hits this state, the polling for update checks fails repeatedly and the user never receives the notification to update and therefore is stuck with the old version of the code with no idea the application has been updated.
After the user hits the error above, they will receive the following error until all tabs are closed and they refresh:
TypeError: Failed to update a ServiceWorker for scope - with script ('/service-worker.js'): ServiceWorker script evaluation failed
The only code that has been changed in the default service worker are the 2 blocks noted below:
function registerValidSW(swUrl, config) { navigator.serviceWorker .register(swUrl) .then(registration => { **** CODE ADDED START ***** // Check for updates every 5 minutes setInterval(() => { try { registration.update(); } catch(e) { config.onFailedUpdate(); } }, (1000 * 60) * 5); **** CODE ADDED END ***** registration.onupdatefound = () => { const installingWorker = registration.installing; if (installingWorker == null) { return; } installingWorker.onstatechange = () => { if (installingWorker.state === 'installed') { if (navigator.serviceWorker.controller) { console.log( 'New content is available and will be used when all' ); **** CODE ADDED START ***** // Trigger toast notification to inform user of update if (config && config.onUpdate) { config.onUpdate(registration); } **** CODE ADDED END *****
If anyone knows what could be causing these sporadic "Unknown errors when fetching the script" to occur it would be greatly appreciated.
I attempted to introduce try/catch blocks throughout the service worker, registration and periodic checks but the script fetch error doesn't seem to bubble up to a point that I can catch it and alert the user there's been a problem.
Any help would be appreciated.
-
Preserving generic types through another generic type in TypeScript
I'm considering submitting a patch (or patches) of the type declarations in
@testing-library/react
and/or@testing-library/dom
. Currently, all queries onRenderResult
return variants ofHTMLElement
, which leaves me writing a lot of code likeconst myDiv = wrapper.getByText('some text') as HTMLDivElement;
The simplest solution is to make the queries generic.
export type GetByText = <T extends HTMLElement = HTMLElement>(/* ... */) => T export const getByText: GetByText
Then I can just do:
const myDiv = wrapper.getByText<HTMLDivElement>('some text');
While this works in TS Playground, something in
@testing-library/react
is preventing the generic form from being passed along toRenderResult
's methods.These are the relevant snippets of the current versions of
@testing-library/react
and@testing-library/dom
.@testing-library/dom
types/queries.d.ts
export type GetByText = ( container: HTMLElement, id: Matcher, options?: SelectorMatcherOptions, ) => HTMLElement export const getByText: GetByText
types/get-queries-for-element.d.ts
import * as queries from './queries'; export type BoundFunction<T> = T extends ( attribute: string, element: HTMLElement, text: infer P, options: infer Q, ) => infer R ? (text: P, options?: Q) => R : T extends (a1: any, text: infer P, options: infer Q, waitForElementOptions: infer W) => infer R ? (text: P, options?: Q, waitForElementOptions?: W) => R : T extends (a1: any, text: infer P, options: infer Q) => infer R ? (text: P, options?: Q) => R : never; export type BoundFunctions<T> = { [P in keyof T]: BoundFunction<T[P]> }; export type Query = ( container: HTMLElement, ...args: any[] ) => Error | Promise<HTMLElement[]> | Promise<HTMLElement> | HTMLElement[] | HTMLElement | null; export interface Queries { [T: string]: Query; } export function getQueriesForElement<T extends Queries = typeof queries>( element: HTMLElement, queriesToBind?: T, ): BoundFunctions<T>;
@testing-library/react
(may or may not be relevant)
types/index.d.tsexport type RenderResult< Q extends Queries = typeof queries, Container extends Element | DocumentFragment = HTMLElement > = { // ... } & {[P in keyof Q]: BoundFunction<Q[P]>}
Alongside the change I made above, making each query's type generic, I changed
Query
inget-queries-for-element.d.ts
:export type Query = <T extends HTMLElement>( container: HTMLElement, ...args: any[] ) => Error | Promise<T[]> | Promise<T> | T[] | T | null;
I'm nearly certain the issue is in
BoundFunction
orgetQueriesForElement()
, as when I made these changes (which I am like 37% confident are right), I get an error:Type 'typeof import(".../node_modules/@testing-library/dom/types/queries")' does not satisfy the constraint 'Queries'. Property 'getByLabelText' is incompatible with index signature. Type 'GetByText' is not assignable to type 'Query'. Type 'HTMLElement' is not assignable to type 'T | Error | T[] | Promise<T[]> | Promise<T>'. Type 'HTMLElement' is not assignable to type 'T'. 'HTMLElement' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'HTMLElement'. ts(2344)
There might be another problem in
@testing-library/react
(and thus, the other testing-library packages), but fixing this is the first step.Part of my problem is that I don't actually understand what
BoundFunction
is doing. What do I need to do to make maketypeof queries
satisfy theQueries
constraint? -
React testing library test window opens with correct URL
I have the following test, that's working fine, but I want to be able to test that when "Contact" is clicked a new window opens and contains the correct URL. I thought to use spyOn but I'm not sure that's the best option.
let queryByText: any, helpURL: string, contactURL: string; beforeEach(() => { helpURL = "https://www.google.com"; contactURL = "https://www.yahoo.com"; ({ queryByText } = render( <MockContext config={{ helpURL, contactURL }}> <ToolsMenu /> </MockContext> )); }); afterEach(() => { queryByText = null; }); test("After clicking Tools Menu ellipsis and then Contact confirm call uses correct URL", () => { userEvent.click(screen.getByRole("button")); window.open = jest.fn(); fireEvent.click(screen.getByText("Contact")); expect(window.open).toHaveBeenCalledWith(contactURL, "_blank"); });
-
How to test Context file using Jest or testing Library
I am new to testing, can anyone guide me on how to test context. I have called an API inside a function how do I test response or a function using jest or a react testing library.
CodesandBox Link: Code
context API file
where I have called the API in userDataFunc, I would like to test the function exist or not and its response both bor success response and catch response
import React, { Component, createContext } from "react"; import axios from "axios"; export const globalC = createContext(); export class Gprov extends Component { state = { authLogin: null, authLoginerror: null, count: 1, user: null }; componentDidMount() {} userDataFunc = async () => { await axios(`https://jsonplaceholder.typicode.com/users`) .then((res) => { if (res.status === 200) { this.setState({ userData: res.data }); } }) .catch((err) => this.setState({ userDataerror: err }) ); }; handleChange = (e) => { this.setState({ [e.target.name]: e.target.value }); }; handleSubmit = (e) => { e.preventDefault(); this.setState({ user: this.state.username }); }; render() { return ( <globalC.Provider value={{ ...this.state, loginData: this.loginData, handleChange: this.handleChange, handleSubmit: this.handleSubmit, userDataFunc: this.userDataFunc }} > {this.props.children} </globalC.Provider> ); } }