React testing library/jest - How to write unit test for switch statement
I have a simple switch statement below and would like to write a unit test for it using React testing library and jest. The expression in the switch which is country is coming into the component as a prop. I've looked through other posts on here and even though I have found posts related to the testing switch cases, I haven't found anything that has been helpful for my situation. Any help would be greatly appreciated! Thanks guys and Happy New Years!
const mileageLabel = (country) => {
switch (country) {
case 'USA':
return 'Miles';
case 'CAN':
return 'Kilometers';
default:
return 'Miles';
}
};
See also questions close to this topic
-
Photoshop Scripting: How to know the part of the text that has overflowed
I want to spread a long text between multiple slides. I do this manually by looking where the text stops in one slide and resume it from there in one next slide (until the entire text has been printed).
Is there a way to automate this procedure? Maybe a method to retrive the parte of the text actually displayed?
-
how obfuscat entire folder js file using gulpfile.js
"Here is my gulpfile.js please let me know what should i have to add in this file to obfuscat all js files"
const gulp = require("gulp"); const minify = require("gulp-minify"); const JavaScriptObfuscator = require("javascript-obfuscator"); gulp.task("js", function () { return gulp .src("js/*.js") .pipe(gulp.dest("output/")); });
-
MatDialog : Theme display bug with FullscreenOverlayContainer
Sorry to bother you here, but we are facing an issue in our dev team.
We have a div that can be displayed as a full screen container by the navigator. Inside this div we open a modal MatDialog. This MatDialog is attached to the body not to the div, so we use FullscreenOverlayContainer to supports correct displaying of overlay elements in fullscreen mode. For our application, we uses 2 themes, one default and dark. When the modal MatDialog is opened from the div in full screen mode, the selected theme (default or dark) is well transmitted to the modal which is displayed correctly. On the other hand, when the div is not in full screen mode, the modal MatDialog doesn't receive the selected theme and is therefore not displayed correctly.
Thanks in advance for your time
-
Couldn't start project on Android: The system cannot find the path specified
I downloaded SDK into my D Drive so I have D:/AppData/Android/Sdk and it gave me the error of: Couldn't start project on Android: The system cannot find the path specified.
The environment variables is set to the same path in D Drive
-
Apollo UseLazyQuery on submit to check for duplicate records
Use Case: A user submits a form, prior to sending the data, I want to check for records with identical criteria and open a modal to show the duplicates and give the user the option to proceed with saving another record or not.
I attempted to implement this with uselazyquery on submit and then using the onCompleted callback to either save the record or display the modal with the response. However, I realized that if the user closes the modal without saving and then tries to save the record without changing any of the criteria, the query is not called again, and the onCompleted function never gets called.
I initially had tried to do this asyncronously rather than with the onCompleted callback, but that doesn't seem to work because I do not think useLazyQuery returns a promise. Does anyone have a better approach/solution to this?
-
Using Dispatch Function to Conditionally Render Components
So I've just refactored an app created in react using useContext/useReducer in order to manage the state better. I'm having a great time and have managed to get the dispatch function to work with bits you have to select.
HOWEVER. When it comes to conditionally rendering the start/stop button, I'm flummoxed. In my reducer function I have the following:const redFunc = (state, action) => { switch (action.type) { case "play": { return { ...state, isPlaying: true, }; } case "stop": { return { ...state, isPlaying: false, }; }
Which is passed down via React.createContext() to the components. The thing is, I don't really understand where to put the dispatch function in order to get isPlaying to actually change. Here is my start/stop button:
<input id="on-off" type="button" value={isPlaying ? "stop" : "start"} onClick={() => togglePlay()} />
So somewhere, I think I need to put this line of code in, as I understand it (please correct me if I'm wrong):
dispatch(isPlaying ? { type: "stop" } : { type: "start" });
Here it is in my togglePlay() function (which is definitely wrong as it doesn't work...):
const togglePlay = () => { if (isPlaying) { audioContextRef.current.suspend(); } else { audioContextRef.current.resume(); } dispatch(isPlaying ? { type: "stop" } : { type: "start" }); };
I feel like there's something fundamental I'm missing about the dispatch function but I can't figure it out, and I've spent SUCH a long time on it that I'm crying tears of Reacty sadness. Everything was wonderful when I could use
useState()
...Help...?
-
How to use jest to mock a function just for some specified arguments, but uses its original logic for any other arguments?
Say I have a function:
function complexCompute(num: number): string { switch(num) { case 1: return '...something...'; case 2: return '...something...'; case 3: return '...something...'; // more cases }
It is used many times in the code I want to test, but I want to mock it like this:
- when I pass the argument
num
is1
,complexCompute
returns my mocked stringmy-mock-string1
- when I pass any other argument, it uses its original logic
I can't find a way to do it, since if I mocked the module:
jest.mock('./complexCompute')
The mocked
complexCompute
doesn't have original logic. I have to define the mock value for argument1
, and also rewrite the whole logic for other arguments.Is there any way to do it?
- when I pass the argument
-
Jest ReferenceError: You are trying to `import` a file after the Jest environment has been torn down
I am trying to test my APIs using jest.
I am having this error show after each time I run the tests
PASS test/auth.test.js √ Create a new user (237 ms) √ SignIn with user (133 ms) √ Delete The user (144 ms) Test Suites: 1 passed, 1 total Tests: 3 passed, 3 total Snapshots: 0 total Time: 2.173 s, estimated 8 s Ran all test suites. ReferenceError: You are trying to `import` a file after the Jest environment has been torn down.
my test file
const auth = require("../routes/auth"); const fetch = require('node-fetch'); fetch.Promise = require("bluebird"); (async () => { beforeAll(done =>{ jest.useFakeTimers(); done(); }) afterAll(done => { done(); }) jest.setTimeout(10000) test("Create a new user", async () => { const status = await fetch(URL + "/api/auth/signUp", { method:"POST", headers: { 'Content-Type': 'application/json;charset=utf-8' }, body:JSON.stringify(SignUpReq) }) .then(res => res.status) await expect(status).toBe(201); }) test("SignIn with user", async () => { let status = await fetch(URL + "/api/auth/signin", { method:"POST", headers: { 'Content-Type': 'application/json;charset=utf-8' }, body:JSON.stringify(deleteUserReq) }) .then(res => res.status) await expect(status).toBe(200); }) test("Delete The user", async () => { const status = await fetch(URL + "/api/auth/deleteUser", { method:"DELETE", headers: { 'Content-Type': 'application/json;charset=utf-8', 'Authorization': 'Bearer <token>' }, body:JSON.stringify(deleteUserReq) }) .then(res => res.status) await expect(status).toBe(200); }) })()
The APIs test the actual database, not a mock DB
I tried
mongoose.connection.close()
jest.useFakeTimers();
changing jest timeout
adding done before and after all
using await before each expect
still, the error shows up
my env:
"node": "V12.19.0" "bcrypt": "^5.0.0", "bluebird": "^3.7.2", "cors": "^2.8.5", "express": "^4.17.1", "jsonwebtoken": "^8.5.1", "md5": "^2.3.0", "mongoose": "^5.11.8", "node-fetch": "^2.6.1", "jest": "^26.6.3"
my DB is hosted on mongo atlas
How can I remove this error message?
-
How to have stack trace for asynchron error in Jest?
In Jest, when I use a Promise which rejects, I can't see the stack trace in with my own code...
async function throwReject() { return Promise.reject("There is an asynchron error") } it("should display an asynchron error", async () => { await expect(throwReject()).rejects.toBe(1) })
For this test, I have this not very useful message :
expect(received).rejects.toBe(expected) // Object.is equality Expected: 1 Received: "There is an asynchron error" 12 | 13 | it("should display an asynchron error", async () => { > 14 | await expect(throwReject()).rejects.toBe(1) | ^ 15 | }) 16 | at Object.toBe (../../node_modules/expect/build/index.js:241:20) at _callee$ (unit/promise.spec.js:14:39) at tryCatch (../../node_modules/regenerator-runtime/runtime.js:63:40) at Generator.invoke [as _invoke] (../../node_modules/regenerator-runtime/runtime.js:293:22) at Generator.next (../../node_modules/regenerator-runtime/runtime.js:118:21) at asyncGeneratorStep (../../node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24) at _next (../../node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9) at ../../node_modules/@babel/runtime/helpers/asyncToGenerator.js:32:7 at Object.<anonymous> (../../node_modules/@babel/runtime/helpers/asyncToGenerator.js:21:12)
On the other way, for a synchron error, the stack trace is a lot better, whith the line which has thrown the error :
function throwError() { throw new Error("There is an error") } it("should display error", () => { expect(throwError()).toBe(1) })
● should display error
There is an error 1 | function throwError() { > 2 | throw new Error("There is an error") | ^ 3 | } 4 | 5 | async function throwReject() { at throwError (unit/promise.spec.js:2:9) at Object.<anonymous> (unit/promise.spec.js:10:10)
Do I wrote wrongly my tests ? Have you some resources to look at ?
-
Bash Script looking for string in parameter to set a variable
I'm quite new to linux, not so much in programing language. I'm looking for a way to set a variable (var2) to a given value depending on matching the last 3 Bytes of a MAc Adress in var1
Here's an example :
var1="AA:BB:CC:DD:EE:FF"
here is my "lookup table" base on the 3 last values of the mac adress"
DD:EE:FF > var2="Home" AB:CD:EF > var2="Garage" FE:DC:GH > var2="Bedroom1" ... (Max 20)
Important thing : The "lookup table" needs to be "readable" because it needs to be easily configurable. I would have used very ugly IF statements otherwise. :-)
Thanks to all the people who will take the time to help me on this.
-
How can I make the switch set to dark mode?
The code that I am using right now doesn't work.
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked){ AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); } else { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); } } }); }
I think it has something to do with the fact that in the code I use AppCompat and the theme is MaterialComponents:
<style name="Theme.Diligent" parent="Theme.MaterialComponents.Light.NoActionBar"> <!-- Primary brand color. --> <item name="colorPrimary">@color/blue</item> <item name="colorPrimaryVariant">@color/blue</item> <item name="colorOnPrimary">@color/black</item> <!-- Secondary brand color. --> <item name="colorSecondary">@color/teal_200</item> <item name="colorSecondaryVariant">@color/teal_700</item> <item name="colorOnSecondary">@color/black</item> <!-- Status bar color. --> <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> <!-- Customize your theme here. --> </style>
-
Why is my switch widget not sliding? I can't seem to change themes
I can't seem to figure out what is preventing the switch from changing states. I know if I set isDark to true, I get my dark theme, and if I set isDark to false I get my light theme. It might be possible that flutter is interpreting isDark as constantly being false. However, I am unsure as to how to fix that if that were the case. Regardless, something is stopping the switch and I can't figure it out. Any help is appreciated thank you.
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: ChangeThemeButton(), theme: _theme, // theme: MyThemes.lightTheme, // darkTheme: MyThemes.darkTheme, // themeMode: ThemeMode.system, routes: { 'homepage': (context) => HomePage(), 'sign-in': (context) => SignIn(), 'register': (context) => RegisterPage(), }, ); } } class ChangeThemeButton extends StatefulWidget { @override _ChangeThemeButtonState createState() => _ChangeThemeButtonState(); } class _ChangeThemeButtonState extends State<ChangeThemeButton> { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Switch( value: isDark, onChanged: (val) => { setState((){ val = isDark; themeProvider(val); }) }, ), ), ); } } var _theme = (isDark == false) ? MyThemes.lightTheme : MyThemes.darkTheme; bool val; bool isDark = false; bool themeProvider (bool val) { switch (val) { case false: return isDark == true; break; case true: return isDark == false; break; } return null; } class MyThemes { static final lightTheme = ThemeData( colorScheme: ColorScheme.light(), iconTheme: IconThemeData(color: Colors.black), bottomNavigationBarTheme: BottomNavigationBarThemeData( unselectedItemColor: Colors.white, selectedItemColor: Color(0xff9D4C8F), showUnselectedLabels: true, selectedIconTheme: IconThemeData( color: Color(0xff9D4C8F), ), unselectedIconTheme: IconThemeData( color: Colors.white, ), ), primaryColor: Colors.deepPurpleAccent[100], primaryColorDark: Colors.black54, secondaryHeaderColor: Colors.deepPurpleAccent[50], scaffoldBackgroundColor: Colors.white, cardColor: Colors.deepPurpleAccent, cardTheme: CardTheme(elevation: 5)); static final darkTheme = ThemeData( colorScheme: ColorScheme.dark(), iconTheme: IconThemeData(color: Colors.white), bottomNavigationBarTheme: BottomNavigationBarThemeData( unselectedItemColor: Colors.white38, selectedItemColor: Color(0xff9D4C8F), showUnselectedLabels: true, selectedIconTheme: IconThemeData( color: Color(0xff9D4C8F), ), unselectedIconTheme: IconThemeData( color: Colors.white, ), ), primaryColor: Colors.black, primaryColorDark: Colors.grey, secondaryHeaderColor: Colors.deepPurpleAccent[50], scaffoldBackgroundColor: Colors.white38, cardColor: Colors.deepPurpleAccent, cardTheme: CardTheme(elevation: 5) ); }
-
Error: Uncaught [TypeError: Cannot read property 'map' of undefined] react testing library
I've written some tests in react testing library on typescript. The tests past successfully but there are errors in the console that I cannot decipher, can someone help me out please. It happens after I have updated my test at the very end of the test. The component inputs the value
ohio
into a field and returns data based on that value, I'm mocking this in the test.the test I'm referring to is the
lands on the page and searches by state
after this line runs:act(() => { fireEvent.click(getByText("Sort")); }) expect(axiosMock.get).toHaveBeenCalledTimes(2);
the api is triggered on submit of the
Sort
button and the tests passes but it leaves a nasty error. Can someone explain this to me please?Here is my test file and the component I'm testing:
component - Brewerlist.tsx :
import React, { useEffect, useState } from 'react'; import { useLocation, useHistory } from 'react-router-dom'; import queryString from 'query-string'; import beer from '../assets/beerMug.png'; import axios from 'axios'; import Pagination from './Pagination'; import '../App.css'; type Breweries = { id: number; name: string; brewery_type: string; state: string; city: string; country: string; street: string; } function Brewerlist() { const [breweries, setBreweries] = useState<Breweries[]>([]); const [error, setError] = useState<any>(null); const [sortType, setSortType] = useState<string>(""); const [sortValue, setSortValue] = useState<string>(""); const [sortValueEmpty, setSortValueEmpty] = useState<boolean>(false); // const { response, error }: { response: object, error: string} = useFetch("https://api.openbrewerydb.org/breweries"); const location = useLocation(); const history = useHistory(); const path = window.location.pathname; const url = queryString.parse(location.search); const pageNo = Number(url.page) || 1; const [currentPage, setCurrentPage] = useState(pageNo); const [ordersPerPage] = useState(10); const indexOfLastOrder = currentPage * ordersPerPage; const indexOfFirstOrder = indexOfLastOrder - ordersPerPage; const currentOrders = breweries?.slice(indexOfFirstOrder, indexOfLastOrder); const paginate = (pageNumber: any) => setCurrentPage(pageNumber); //fetch breweries const fetchData = async () => { try { const res = await axios.get("https://api.openbrewerydb.org/breweries?per_page=50"); setBreweries(res?.data); } catch (error) { console.log(error); } } useEffect(() => { fetchData(); history.push(`${path}?page=${currentPage}`); }, [currentPage, history, path]); //handlers const handleSort = (event: React.ChangeEvent<HTMLSelectElement>) => { setSortType(event.target.value) } const handleSortValue = (event: React.ChangeEvent<HTMLInputElement>) => { setSortValue(event.target.value) } const hideError = () => { setSortValueEmpty(false) } //refresh results const refreshResults = () => { fetchData(); } //fetcher function const fetcher = async (api: string, type: string, val: string) => { const res = await axios.get(`${api}by_${type}=${val}`); setBreweries(res.data) } //fetch by term const fetchByType = async (type: string, value: string) => { if(sortValue === "") { setSortValueEmpty(true) } if(value && type === "state"){ try { fetcher("https://api.openbrewerydb.org/breweries?", type, value) } catch (error) { console.log(error); } } if(type === "brewery_type") { try { fetcher("https://api.openbrewerydb.org/breweries?", "type", value) } catch (error) { console.log(error); } } } const mapBreweries = () => { return ( <> {currentOrders.map((item: Breweries) => ( <div className="item" key={item.id}> <ul> <li><span className="title">Name:</span>{item.name}</li> <li><span className="title">State:</span>{item.state}</li> <li><span className="title">Brewery type:</span>{item.brewery_type}</li> <li><span className="title">Street:</span>{item.street || "N/A"}</li> <li><span className="title">Country:</span>{item.country}</li> <li><span className="title">City:</span>{item.city}</li> </ul> </div> ))} </> ) } return ( <React.Fragment> <div className="header"> <img src={beer} className="image" alt=""/> <h1>Sherman Brewery</h1> <img src={beer} className="image" alt=""/> </div> <div className="container"> <div className="selectContainer"> <label htmlFor="type">Sort by: </label> <select name="type" data-testid="select" onChange={handleSort}> <option value="" selected defaultValue="Sort By" disabled hidden>Sort By</option> <option data-testid="type-option" value="state">State</option> <option data-testid="type-option" value="brewery_type">Brewery Type</option> </select> <label htmlFor="sortBy">Search by {sortType === "state" ? "State: " : "Brewery Type: "} </label> <input data-testid="search" disabled={sortType ? false : true} name="sortby" type="text" onFocus={hideError} onChange={handleSortValue} /> <button disabled={sortType ? false : true} type="submit" onClick={() => fetchByType(sortType, sortValue)}>Sort</button> <button type="submit" onClick={refreshResults}>Refresh results</button> {sortValueEmpty ? <span className="error"> Please add a value</span> : null} </div> {mapBreweries()} <Pagination ordersPerPage={ordersPerPage} ordersAmount={breweries?.length} paginate={paginate} /> </div> </React.Fragment> ); } export default Brewerlist;
test file - Brewerlist.test.js
import "@testing-library/jest-dom"; import "@testing-library/jest-dom/extend-expect"; import React from "react"; import axiosMock from "axios"; import Brewerlist from "../components/Brewerlist"; import { cleanup, render, fireEvent, waitFor } from "@testing-library/react"; import { createMemoryHistory } from 'history'; import { Router } from 'react-router-dom'; import { fixtures } from './data'; import { ohio } from './ohioData'; import axios from "./axios"; import { act } from "react-dom/test-utils"; afterEach(cleanup); jest.mock("axios"); let data = fixtures; let url = "https://api.openbrewerydb.org/breweries?per_page=50"; it("lands on the page and displays data", async () => { axiosMock.get.mockResolvedValueOnce({ data }); const history = createMemoryHistory() const { getByText, getByLabelText } = render(<Router history={history}><Brewerlist /></Router>); await waitFor(() => expect(getByText("Sherman Brewery")).toBeInTheDocument()); await waitFor(() => expect(getByText("Avondale Brewing Co")).toBeInTheDocument()); expect(axiosMock.get).toHaveBeenCalledTimes(1) }); it("lands on the page and searches by state", async () => { axiosMock.get.mockResolvedValueOnce({ data }); const history = createMemoryHistory() const { getByText, getByLabelText, getAllByTestId, getByTestId } = render(<Router history={history}><Brewerlist /></Router>); await waitFor(() => expect(getByText("Sherman Brewery")).toBeInTheDocument()); await waitFor(() => expect(getByText("Avondale Brewing Co")).toBeInTheDocument()); fireEvent.change(getByTestId("select"), { target: { value: "state" } }); let typeOptions = getAllByTestId("type-option"); expect(typeOptions[0].selected).toBeTruthy(); expect(typeOptions[1].selected).toBeFalsy(); expect(getByText("Search by State:")).toBeInTheDocument(); const searchInput = getByTestId("search"); fireEvent.change(searchInput, { target: { value: "ohio" } }); expect(searchInput.value).toBe("ohio"); axiosMock.get.mockResolvedValueOnce({ ohio }); act(() => { fireEvent.click(getByText("Sort")); }) expect(axiosMock.get).toHaveBeenCalledTimes(2); await waitFor(() => expect(getByText("Magic City Brewing Company")).toBeInTheDocument()); })
axios.js - for mocking the api
export default { get: jest.fn().mockResolvedValue({ data: [{}] }), };
test data:
export const fixtures = [ { "id":2, "name":"Avondale Brewing Co", "brewery_type":"micro", "street":"201 41st St S", "address_2":null, "address_3":null, "city":"Birmingham", "state":"Alabama", "county_province":null, "postal_code":"35222-1932", "country":"United States", "longitude":"-86.774322", "latitude":"33.524521", "phone":"2057775456", "website_url":"http://www.avondalebrewing.com", "updated_at":"2018-08-23T23:19:57.825Z", "created_at":"2018-07-24T01:32:47.255Z" }, ]
export const ohio = [ { "id":2, "name":"Magic City Brewing Company", "brewery_type":"micro", "street":"201 41st St S", "address_2":null, "address_3":null, "city":"Birmingham", "state":"Ohio", "county_province":null, "postal_code":"35222-1932", "country":"United States", "longitude":"-86.774322", "latitude":"33.524521", "phone":"2057775456", "website_url":"http://www.avondalebrewing.com", "updated_at":"2018-08-23T23:19:57.825Z", "created_at":"2018-07-24T01:32:47.255Z" }, ]
the error returned when I run the
lands on the page and searches by state
testError: Uncaught [TypeError: Cannot read property 'map' of undefined] at reportException (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:62:24) at innerInvokeEventListeners (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:333:9) at invokeEventListeners (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3) at HTMLUnknownElementImpl._dispatch (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9) at HTMLUnknownElementImpl.dispatchEvent (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17) at HTMLUnknownElement.dispatchEvent (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34) at Object.invokeGuardedCallbackDev (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:3994:16) at invokeGuardedCallback (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:4056:31) at beginWork$1 (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:23964:7) at performUnitOfWork (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:22779:12) TypeError: Cannot read property 'map' of undefined at mapBreweries (/Users/nathan/Desktop/work/breweryapp/src/components/Brewerlist.tsx:108:26) at Brewerlist (/Users/nathan/Desktop/work/breweryapp/src/components/Brewerlist.tsx:145:14) at renderWithHooks (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:14985:18) at updateFunctionComponent (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:17356:20) at beginWork (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:19063:16) at HTMLUnknownElement.callCallback (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:3945:14) at HTMLUnknownElement.callTheUserObjectsOperation (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30) at innerInvokeEventListeners (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:318:25) at invokeEventListeners (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3) at HTMLUnknownElementImpl._dispatch (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9) at HTMLUnknownElementImpl.dispatchEvent (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17) at HTMLUnknownElement.dispatchEvent (/Users/nathan/Desktop/work/breweryapp/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34) at Object.invokeGuardedCallbackDev (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:3994:16) at invokeGuardedCallback (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:4056:31) at beginWork$1 (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:23964:7) at performUnitOfWork (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:22779:12) at workLoopSync (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:22707:5) at renderRootSync (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:22670:7) at performSyncWorkOnRoot (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:22293:18) at /Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:11327:26 at unstable_runWithPriority (/Users/nathan/Desktop/work/breweryapp/node_modules/scheduler/cjs/scheduler.development.js:646:12) at runWithPriority$1 (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:11276:10) at flushSyncCallbackQueueImpl (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:11322:9) at flushSyncCallbackQueue (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:11309:3) at scheduleUpdateOnFiber (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:21893:9) at setBreweries (/Users/nathan/Desktop/work/breweryapp/node_modules/react-dom/cjs/react-dom.development.js:16139:5) at fetcher (/Users/nathan/Desktop/work/breweryapp/src/components/Brewerlist.tsx:81:3) at VirtualConsole.<anonymous> (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45) at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:28) at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:333:9) at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3) at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9) at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17) console.error The above error occurred in the <Brewerlist> component: at Brewerlist (/Users/nathan/Desktop/work/breweryapp/src/components/Brewerlist.tsx:25:37) at Router (/Users/nathan/Desktop/work/breweryapp/node_modules/react-router/cjs/react-router.js:99:30) Consider adding an error boundary to your tree to customize error handling behavior. Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. at logCapturedError (node_modules/react-dom/cjs/react-dom.development.js:20085:23) at update.callback (node_modules/react-dom/cjs/react-dom.development.js:20118:5) at callCallback (node_modules/react-dom/cjs/react-dom.development.js:12318:12) at commitUpdateQueue (node_modules/react-dom/cjs/react-dom.development.js:12339:9) at commitLifeCycles (node_modules/react-dom/cjs/react-dom.development.js:20736:11) at commitLayoutEffects (node_modules/react-dom/cjs/react-dom.development.js:23426:7) at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:3945:14)
-
How to test react functional component async call
I have a functional component. Inside the component, I have called SpecialistsListService service. The service called the API via Axios. I have to test the async function getSpecialistsList and useEffect functions but I don't do that anyone helps me to solve the problem. When I used class component I simply call the method like await wrapper.instance.getSpecialistsList() then check the state but the functional component approach are different I think.
import React, { useState, useEffect } from "react"; import SpecialistsListService from "../../../services/specialists"; import SpecialistsPageView from "./SpecialistsPageView"; import "./index.scss"; export default function SpecialistsPage() { const [specialistsList, setSpecialistsList] = useState([]); const [isLoading, setIsLoading] = useState(true); const specialistsListService = new SpecialistsListService(); useEffect(() => { getSpecialistsList(); }, []); async function getSpecialistsList() { const specialistsListData = await specialistsListService.getSpecialistsList(); setSpecialistsList(specialistsListData); setIsLoading(false); } return ( <SpecialistsPageView isLoading={isLoading} specialists={specialistsList} /> ); }
-
Fire click event twice in react-testing-library
I'm trying to test if a button toggle works as expected.
This is my code.
<> <IconButton color="secondary" data-testid="HelpIconButton" ref={anchorRef} onClick={handleToggle}> <Help /> </IconButton> <Popper {...{ open }} anchorEl={anchorRef.current} transition disablePortal data-testid="HelpIconPopper"> {({ TransitionProps, placement }) => ( <Grow {...TransitionProps} style={{ transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom' }}> <Paper> <ClickAwayListener onClickAway={handleClose}> <MenuList autoFocusItem={open} onKeyDown={handleListKeyDown}> {menuItems.map(({ onClick, label }, index) => ( <MenuItem key={index} {...{ onClick }}> {label} </MenuItem> ))} </MenuList> </ClickAwayListener> </Paper> </Grow> )} </Popper> </>
In the browser, clicking the browser works as expected. Clicking on the
IconButton
toggles thePopper
, removing and adding it into the DOM. On test however, firing a click event placed thePopper
in the DOM but its not removed when fired again. Hence, the popper isn't toggled.Here is the test Code.
it('Ensures the help menu toggles when the help button is clicked.', () => { const { getByTestId, queryByTestId } = render(<HelpButton />); expect(queryByTestId('HelpIconPopper')).not.toBeInTheDocument(); fireEvent.click(getByTestId('HelpIconButton')); expect(queryByTestId('HelpIconPopper')).toBeInTheDocument(); fireEvent.click(getByTestId('HelpIconButton')); expect(queryByTestId('HelpIconPopper')).not.toBeInTheDocument(); });
A work around currently in use is using
fireEvent.doubleClick
it('Ensures the help menu toggles when the help button is clicked.', () => { const { getByTestId, queryByTestId } = render(<HelpButton />); expect(queryByTestId('HelpIconPopper')).not.toBeInTheDocument(); fireEvent.doubleClick(getByTestId('HelpIconButton')); expect(queryByTestId('HelpIconPopper')).not.toBeInTheDocument(); });
The second test passes.