jest is not able to find helper functions
i am using react-mobx store in my react project while running test-case jest is not able to find helper functions that is in my component, getting error: tests/components/common/Sidebar/Sidebar.test.js ● Test suite failed to run
ReferenceError: regeneratorRuntime is not defined
**test.js**
const stores = {
applicationModel: {},
}
describe('Breadcrumb', () => {
it('should not render the breadcrumb with no items', () => {
const properties = {
breadcrumb: [
{
name: '',
path: '',
params: {}
},
],
separator: '',
applicationModel: {}
}
const renderedComponent = shallow(<Breadcrumb.wrappedComponent {...properties}/>)
const expectedRenderedHTML = <div className='test' />
expect(renderedComponent).toContainReact(expectedRenderedHTML)
})
**jest.config.js**
module.exports = {
verbose: true,
setupFiles: [
'<rootDir>/setupTests.js',
'<rootDir>/src/utils/helpers.js',
'<rootDir>/src/utils/api.js',
'<rootDir>/src/utils/functions.js'
],
testRegex: '(/__tests__/.*|(\\.|/)test)\\.jsx?$',
moduleNameMapper: {
'\\.(css|scss)$': '<rootDir>/__mocks__/styleMock.js',
},
setupTestFrameworkScriptFile: '<rootDir>/node_modules/jest-enzyme/lib/index.js',
transform: {
'.*': '<rootDir>/node_modules/babel-jest',
},
collectCoverage: true,
}
See also questions close to this topic
-
passing my function to useeffect crashes my app
Hi Im trying to implement openpay services to my react native app but when i try to generate the TokenID from the credit card info i got problems with the use effect
this is the code
useEffect(() => { let isCancelled = false; if (vCardNameOwner && vCardNumber && vCardExpirationMonth && vCardExpirationYears && vCardCVV) { openpay.createCardToken({ holder_name: vCardNameOwner, card_number: vCardNumber, expiration_month: vCardExpirationMonth, expiration_year: vCardExpirationYears, cvv2: vCardCVV, }) .then((token) => setvTokenId(token), console.log( '/////generacion de token//////' ,token)); } return () => { isCancelled = true; }; }, [vCardNameOwner, vCardNumber, vCardExpirationMonth, vCardExpirationYears, vCardCVV]);
that code makes my app to crash because token isnt declared and i dont know how to re do the operation so it can work fine
if i delete the useeffect thing and leave just the openpay function with hardcoded values everything work well but i need it to take the values that the user insert in the form
openpay.createCardToken({ holder_name: vCardNameOwner, card_number: vCardNumber, expiration_month: vCardExpirationMonth, expiration_year: vCardExpirationYears, cvv2: vCardCVV, }) .then((token) => setvTokenId(token), console.log( '/////generacion de token//////' ,token));
thanks a lot for your time
-
CORS in react app and django restframework
We have a rest api built with Django and as client we gonna use react-js application to get data from server .
Our problem is Django API does not support CORS headers so I want to disable this option in react.
How can i disable React CORS the way react dont check cors headers ?
-
TypeError: Cannot destructure property 'name' of 'e.target' as it is undefined. with DatePicker in React Hooks
I will be grateful for any help. Unable to assign value from DatePicker field. All other input fields work fine. Why can't I assign a value to a variable in a DatePicker field?
import React, { useState } from 'react'; import useForm from './useForm'; import validate from './validateInfo'; import './Form.css'; import DatePicker from "react-datepicker"; import "react-datepicker/dist/react-datepicker.css"; const FormInput = ({ submitForm }) => { const { handleChange, values, handleSubmit, errors } = useForm(submitForm, validate); console.log(values); const [date, setDate] = useState(new Date()); console.log(date) return ( <div className="form-content-right"> <form className="form" onSubmit={handleSubmit}> <h1>Neuen Fehler eingeben. </h1> <div className="form-inputs"> <div> <label htmlFor="startDate" className="form-label"> Datum </label> <DatePicker id="startDate" type="date" name="startDate" className="form-input" value={date.toString()} onChange={handleChange} /> </div> // ... some other input fields... <button className="form-input-btn" type='submit'> eingeben </button> </form> </div> ) } export default FormInput;
Could the problem be with the value type or format of variable (date)?
-
Accessing jasmine with testRunner set to jest-circus results in: ReferenceError: jasmine is not defined
On default
jest
allows you to simply accessjasmine
globally. But as soon as you switch thetestRunner
tojest-circus
,jasmine
is undefined. Following is a minimal, reproducible example:babel.config.js
module.exports = { presets: [["@babel/preset-env", { targets: { node: "current" } }]], };
jasmine.spec.js
it("check jasmine", () => { console.log(jasmine); });
jest.config.js
module.exports = { rootDir: ".", testRunner: "jest-circus/runner", };
package.json
{ "name": "test-jest", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "jest" }, "author": "", "license": "ISC", "dependencies": { "@babel/core": "^7.12.10", "@babel/preset-env": "^7.12.11", "babel-jest": "^26.6.3", "jest": "^26.6.3", "jest-circus": "^26.6.3" } }
Running this test will cause following output:
$ npm test > test-jest@1.0.0 test /Users/yusufaran/Projects/test/test-jest > jest FAIL ./jasmine.spec.js ✕ check jasmine (1 ms) ● check jasmine ReferenceError: jasmine is not defined 1 | it("check jasmine", () => { > 2 | console.log(jasmine); | ^ 3 | }); 4 | at Object.<anonymous> (jasmine.spec.js:2:15) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 1.01 s Ran all test suites. npm ERR! Test failed. See above for more details.
If you remove/comment the
testRunner
line injest.config.js
(so it fallbacks to the default runner) it works as expected.Question
How can I access global
jasmine
object withtestRunner
set tojest-circus/runner
? If I can't, why? -
Angular Testing - How to cover the lines in my test file
I am new to Angular/Typescript/Javascript. The challenge I am facing right now since few hours is: I have this function to test:
setupIFrame($event: any): void { this.iframeWrappers = document.getElementsByClassName('iframe-wrapper'); this.iframeButtons = document.getElementsByClassName('iframe-button'); const closeListener: any = (payload) => { if (payload.data?.eventId === 'closeEvent') { this.iframeWrappers[$event.rowIndex].classList.remove('open'); window.removeEventListener('message', closeListener, false); } } this.iframeButtons[$event.rowIndex].addEventListener('click', () => { this.iframeWrappers[$event.rowIndex].classList.add('open'); window.addEventListener('message', closeListener, false); }, false); }
But I cannot cover the
closeListener
and these two lines:this.iframeWrappers[$event.rowIndex].classList.add('open'); window.addEventListener('message', closeListener, false);
What can I do in order to cover these two lines? This is my current test:
it('test iFrame setup', () => { Object.defineProperty(document, 'getElementsByClassName', { value: mockedGetElementsByClassName }) configureTestBed(); const rowIndex: RowIndex = {rowIndex: 0}; expect(component).toBeTruthy(); expect(fixture).toMatchSnapshot(); component.setupIFrame(rowIndex); expect(document.getElementsByClassName).toBeCalledTimes(2); expect(mockedIFrameButton.addEventListener).toBeCalledWith('click', expect.any(Function), false); // expect(mockedIFrameWrapper.classList.add).toBeCalled(); });
I feel like mocking the
getElementsByClassName
function is not the right thing to do, but otherwise I would get a undefined HTMLElement and cannot call the addEventListener function either. But I am very unsure how to approach the test properly tbh :/ -
Jest: Maximum call stack size exceeded when creating a mock that import a module
I want to set a mock from a module, but Jest keep to throw this error. I didn't want to put mocks next to node_modules, so I mapped the folder in the jest config file, but I don't think that's the problem.
folder structure:
-- node_modules
-- src
---- module_to_test-ts
-- tests
---- __ mocks __
---- test.tsRangeError: Maximum call stack size exceeded > 26 | jest.mock('jsonwebtoken', () => require('@Mocks/jsonwebtoken')); | ^
jest.config.js
moduleNameMapper: { '^@App/(.*)$': '<rootDir>/src/$1', '^@Mocks/(.*)$': '<rootDir>/tests/__mocks__/$1', },
-
mobx-state-tree error while converting to anonymousModel
What should happen - succesfully create RootStore from defaultSnapshot and reset it when needed, successful backcuping in localStorage. What happens - getting an error while trying to apply a snapshot, when attempting to open page, just by running code even without interacting with it.
When checking types manually I do not see problems with type mistakes, so can not understand why it throws error.
Error
Error: [mobx-state-tree] Error while converting `{"token":"","myInnerInfo":{"login":"","type":""},"myDisplayInfo":{"login":"","type":""},"loginInfo":{"login":"","type":""},"loginList":[],"loading":false,"logined":false}` to `AnonymousModel`: at path "/myInnerInfo/login" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object). at path "/myInnerInfo/type" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object). at path "/myDisplayInfo/login" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object). at path "/myDisplayInfo/type" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object). at path "/loginInfo/login" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object). at path "/loginInfo/type" value `""` is not assignable to type: `AnonymousModel` (Value is not a plain object).
File structure
store.js (imported in index.js)
import { types, flow, onSnapshot, applySnapshot } from 'mobx-state-tree'; import { values } from 'mobx'; import axios from 'axios'; const defaultSnapshot = { token: '', myInnerInfo: { login: '', type: '' }, myDisplayInfo: { login: '', type: '' }, loginInfo: { login: '', type: '' }, loginList: [], loading: false, logined: false, } const User = types .model({ login: '', type: '', }).actions(self => ({ setUserInfo({ login, type }) { self.login = login; self.type = type; } })) const RootStore = types .model({ token: '', myInnerInfo: types.map(User), myDisplayInfo: types.map(User), loginInfo: types.map(User), loginList: types.array(types.string), loading: false, logined: false, }).views(self => ({ get loginListLength() { return values(self.loginList).length; }, })).actions(self => ({ // setToken (token) { // self.token = token; // }, // setMyInnerInfo (userInfo) { // self.myInnerInfo.setUserInfo(userInfo); // }, // setMyDisplayInfo (userInfo) { // self.myDisplayInfo.setUserInfo(userInfo); // }, // setLoginInfo (userInfo) { // self.loginInfo.setUserInfo(userInfo); // }, // setLoginList (loginList) { // self.loginList = loginList; // }, // setLoading (loading) { // self.loading = loading; // }, // setLogined (logined) { // self.logined = logined; // }, // reset() { // self.token = ''; // self.myInnerInfo = User.create({}); // self.myDisplayInfo = User.create({}); // self.loginInfo = User.create({}); // self.loginList = []; // self.loading = false; // self.logined = false; // }, register: flow(function* register(login, password) { self.loading = true; try { const res = yield axios({ method: 'POST', url: `${process.env.REACT_APP_HOST}/users/register`, data: { login, password }, }); alert('Registered'); self.loading=false; } catch (e) { console.error(e); alert(`Error registering! Please retry!`); resetStore(); } }), login: flow(function* login(login, password) { self.loading = true; try { const res = yield axios({ method: 'POST', url: `${process.env.REACT_APP_HOST}/users/login`, data: { login, password }, }); self.token = res.data.token; self.myInnerInfo.setUserInfo(res.data.user); self.myDisplayInfo.setUserInfo({ login: '', type: '' }); self.loginInfo.setUserInfo({ login: '', type: '' }); self.loginList = []; alert('Logined'); self.logined = true; self.loading=false; } catch (e) { console.error(e); alert(`Error logining! Please retry!`); resetStore(); } }), unlogin() { self.loading = true; self.logined = false; self.token = ''; self.myInnerInfo.setUserInfo({ login: '', type: '' }); self.myDisplayInfo.setUserInfo({ login: '', type: '' }); self.loginInfo.setUserInfo({ login: '', type: '' }); self.loginList = []; alert('Unlogined'); self.loading=false; }, getMyInfo: flow(function* getMyInfo() { self.loading = true; try { const res = yield axios({ method: 'GET', url: `${process.env.REACT_APP_HOST}/users/my-info`, headers: {'Authorization': self.token ? `Bearer ${self.token}` : ''}, }); // self.token = res.data.token; // self.myInnerInfo.setUserInfo(res.data.user); self.myDisplayInfo.setUserInfo(res.data); // self.loginInfo.setUserInfo({}); // self.loginList = []; alert('Loaded information'); // self.logined = true; self.loading=false; } catch (e) { console.error(e); alert(`Error loading information! Please retry!`); resetStore(); } }), getLoginList: flow(function* getLoginList() { self.loading = true; try { const res = yield axios({ method: 'GET', url: `${process.env.REACT_APP_HOST}/users/list-logins`, headers: {'Authorization': self.token ? `Bearer ${self.token}` : ''}, }); // self.token = res.data.token; // self.myInnerInfo.setUserInfo(res.data.user); // self.myDisplayInfo.setUserInfo(res.data); // self.loginInfo.setUserInfo({}); self.loginList = res; alert('Loaded list'); // self.logined = true; self.loading=false; } catch (e) { console.error(e); alert(`Error loading list! Please retry!`); resetStore(); } }), getUserInfo: flow(function* getUserInfo(login) { self.loading = true; try { const res = yield axios({ method: 'GET', url: `${process.env.REACT_APP_HOST}/users/my-info/${login}`, headers: {'Authorization': self.token ? `Bearer ${self.token}` : ''}, }); // self.token = res.data.token; // self.myInnerInfo.setUserInfo(res.data.user); // self.myDisplayInfo.setUserInfo(res.data); self.loginInfo.setUserInfo(res.data); // self.loginList = []; alert('Loaded information'); // self.logined = true; self.loading=false; } catch (e) { console.error(e); alert(`Error loading information! Please retry!`); resetStore(); } }), })); const store = RootStore.create(); if(!(localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY] && JSON.parse(localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY]))) { localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY] = JSON.stringify(defaultSnapshot); } applySnapshot(store, JSON.parse(localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY])); onSnapshot(store, snapshot => { localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY] = JSON.stringify(snapshot); console.info(snapshot); }); export default store; export function resetStore() { localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY] = JSON.stringify(defaultSnapshot); applySnapshot(store, JSON.parse(localStorage[process.env.REACT_APP_LOCALSTORAGE_KEY])); }
package.json
{ "name": "client", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^11.2.3", "@testing-library/user-event": "^12.6.0", "axios": "^0.21.1", "mobx": "^6.0.4", "mobx-react": "^7.0.5", "mobx-state-tree": "^5.0.0", "react": "^17.0.1", "react-dom": "^17.0.1", "react-scripts": "4.0.1", "web-vitals": "^0.2.4" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } }
-
React component not updating when the MobX object updates
I just started using MobX so pardon me if I am missing something very trivial here. To get my feet wet I just built a simple add subtract project that makes use of contexts. There are 3 components I made AddButton, SubtractButton and Answer. All reading and updating an instance of a class that makes use of observable.
CodeSandbox: https://codesandbox.io/s/stoic-chandrasekhar-kz5e9?file=/src/App.tsx
The intention is to update the Answer component whenever the AnswerStore changes. (The answer is wrapped in observer HOC)
This is what the store looks like
export class AnswerStore { @observable answer = 0; @action add() { console.log("Adding 1 to ", this.answer); this.answer = this.answer + 1; } @action sub() { console.log("Subtracting 1 from ", this.answer); this.answer = this.answer - 1; } } const context = React.createContext({} as AnswerStore); export const useStore = () => React.useContext(context);
The Answer component looks like this
import { observer } from "mobx-react-lite"; import React from "react"; import { useStore } from "./store"; const answer = observer(() => { const store = useStore() return <h1>Answer is: {store.answer}</h1>; }) export default answer
Again I am not sure what I am missing here :/
-
Use `ListBox` from `@headlessui/react` with Mobx?
Before using ListBox:
store/index.ts
import { action, makeObservable, observable } from 'mobx' import type { IFrameItStore, TrafficSignal } from '@/types/index' export class FrameItStore implements IFrameItStore { trafficSignal: TrafficSignal = { shape: 'circle', } constructor() { makeObservable(this, { trafficSignal: observable, updateTrafficSignal: action.bound, }) } updateTrafficSignal({ shape }: TrafficSignal) { if (shape) this.trafficSignal.shape = shape } }
Shape.tsx
import { observer } from 'mobx-react' import * as React from 'react' import { useFrameItStore } from '@/store/index' import type { TrafficSignalShape } from '@/types/index' export const Shape = observer(() => { const frameItStore = useFrameItStore() return ( <> <label htmlFor="shape" className="mb-1 text-sm font-medium text-blue-gray-500"> Shape </label> <select id="shape" className="block w-full px-3 py-2 mb-2 bg-white border border-gray-300 rounded-md shadow-sm text-blue-gray-500 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" value={frameItStore.trafficSignal.shape} onChange={(e: React.ChangeEvent<HTMLSelectElement>) => { const shape = e.target.value as TrafficSignalShape frameItStore.updateTrafficSignal({ shape }) }} > <option value="circle">Circle</option> <option value="square">Square</option> </select> </> ) })
App.tsx
<Shape />
After using ListBox:
Select.tsx
import * as React from 'react' import { Listbox, Transition } from '@headlessui/react' import clsx from 'clsx' import { Selector, Check } from '@/components/icons/index' type Option = { id: string name: string img: string } interface IProps { label?: string options: Array<Option> } export const Select = ({ label, options }: IProps) => { const [selectedOption, setSelectedOption] = React.useState<Option>(options[0]) return ( <Listbox value={selectedOption} onChange={setSelectedOption}> {({ open }) => ( <> <Listbox.Label className="mb-1 text-sm font-medium text-blue-gray-500"> {label} </Listbox.Label> <div className="relative mt-1"> <Listbox.Button className="relative w-full py-2 pl-3 pr-10 text-left bg-white border border-gray-300 rounded-md shadow-sm cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"> <span className="flex items-center"> <img src={selectedOption.img} alt={selectedOption.name} className="flex-shrink-0 w-6 h-6 rounded-full" /> <span className="block ml-3 truncate">{selectedOption.name}</span> </span> <span className="absolute inset-y-0 right-0 flex items-center pr-2 ml-3 pointer-events-none"> <Selector /> </span> </Listbox.Button> <div className="absolute w-full mt-1 bg-white rounded-md shadow-lg"> <Transition show={open} leave="transition duration-100 ease-in" leaveFrom="opacity-100" leaveTo="opacity-0" > <Listbox.Options static className="py-1 overflow-auto text-base rounded-md max-h-56 ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm" > {options.map((option) => ( <Listbox.Option as={React.Fragment} key={option.id} value={option}> {({ active, selected }) => ( <li className={clsx('relative py-2 pl-3 cursor-default select-none pr-9', { 'text-white bg-indigo-600': active, 'text-gray-900': !active, })} > <div className="flex items-center"> <img src={option.img} alt={option.name} className="flex-shrink-0 w-6 h-6 rounded-full" /> <span className={clsx('ml-3 block truncate', { 'font-semibold': selected, 'font-normal': !selected, })} > {option.name} </span> </div> {selected && ( <span className={clsx('absolute inset-y-0 right-0 flex items-center pr-4', { 'text-white': active, 'text-indigo-600': !active, })} > <Check /> </span> )} </li> )} </Listbox.Option> ))} </Listbox.Options> </Transition> </div> </div> </> )} </Listbox> ) }
App.tsx
const shapes = [ { id: '1', name: 'Circle', img: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80', }, { id: '2', name: 'Square', img: 'https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80', }, ] <Select label="Shape" options={shapes} />
How do I convert the After part to use MobX like the Before part?
I tried passing
value
&onChange
as it is in the Before part to Select like:App.tsx
<Select label="Shape" options={shapes} value={frameItStore.trafficSignal.shape} onChange={(e: React.ChangeEvent<HTMLSelectElement>) => { const shape = e.target.value as TrafficSignalShape frameItStore.updateTrafficSignal({ shape }) }} />
Select.tsx
interface IProps { label?: string value: any onChange: (value: any) => void options: Array<Option> } export const Select = ({ label, options, value, onChange }: IProps) => { const [selectedOption, setSelectedOption] = React.useState<Option>(options[0]) return ( <Listbox value={value} onChange={onChange}> . . . </Listbox> ) }
But it doesn't select anything & I don't know what to do of
selectedOption
?