React testing use mockstore with custom store to test it
I would like to test components that are using redux store in my project. Here is the function that I use fo getting some store elements:
const variable = store.getState().serverConfiguration.testValue;
When I am testing this component I use mockStore
to do that so my store is empty right? That is why I get error saying that TypeError: Cannot read property 'testValue' of undefined
Is there a way to pass my custom store to mockStore
so that it will be possible to test it correctly?
I tried to do that like this but it doesn't work:
const store = configureMockStore()({
serverConfiguration: {
testValue: "Admin"
}
});
1 answer
-
answered 2021-01-16 12:27
Stijn2404
Try this:
import configureStore from "redux-mock-store" const mockStore = configureStore([]); const store = mockStore({ serverConfiguration: { testValue: "Admin" } })
See also questions close to this topic
-
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...?
-
Is there any tool available to identify particular text in the href element?
Lets consider below href element, here I need to identify "cn=" text in the all the available href links. My page has 1000 href elements, in that I need to identify the href url which has "cn=" text.
href="/software-advice/article/maternity-benifits-of-office-cn=welcome-inc"
-
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?
-
UITesting: Opening a file in app bundle from Safari
I've written some XCUITests to verify deeplink handling logic in my app. I have a set of links in an html file that's part of the Resources bundle for my tests. I use
let path = Bundle(for: Self.self).path(forResource: deeplinkFileName, ofType: "html")
to find the full path to the file andlet safari = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari") safari.launch() guard safari.wait(for: .runningForeground, timeout: 5) else { throw DeeplinkError.safariAppLoadTimeout } safari.descendants(matching: .button)["URL"].tap() safari.typeText(path) safari.buttons["Go"].tap()
to launch Safari, type the path in the address bar, and open the file.
This works great on Simulator, but when I run my test suite on a physical device, Safari times out trying to open the file. I assume this is because it doesn't have access to open a file inside my app bundle.
Is there a location to which I could move this file, so that Safari can access it? If I understand it correctly, even the Documents directory is still inside the app sandbox and can't be accessed from outside the app.
-
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
-
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 ?
-
testing form validation using Enzyme
I'm trying to test if the error shows up on the screen when user submit the form with empty inputs!
I did this test and everything looks good to me ,but it says that length is 0 which means it didn't show up, where is my mistake ?
import React, { useState } from 'react'; import { login } from '../../../services/account-service'; import validate from '../../../utility/login-validate'; import { Button, Error, Form, Input, Label, NavLink, Sign, SignBtn } from './signin-style'; /** * Component to log in the website if you have valid information, and display errors if the information is invalid. */ function Signin() { const [email, setemail] = useState(''); const [errors, setErrors] = useState(null); const [password, setPassword] = useState(''); /** *this methode called when the user presses the submit button, first it will check if there is errors, if not it will submit the form! * * @param {React.SyntheticEvent} event click on submit button event! */ const handleSubmit = async (event) => { event.preventDefault(); /** * Function that check if the user inserted wrong information and put it on `error` variable!, then it will update the 'errors' state! */ const error = validate(email, password); setErrors(error); await login(email, password); }; /** * Method that handle the change on { email input } by taking the input value and setting it on 'email' state! * * @param {React.SyntheticEvent} event when user type in email input! */ const handleemailChange = (event) => { const user = event.currentTarget.value; setemail(user); }; /** * Method that handle the change on { password input } by taking the input value and setting it on 'password' state! * * @param {React.SyntheticEvent} event When user type in password input */ const handlePasswordChange = (event) => { const pass = event.currentTarget.value; setPassword(pass); }; return ( <Sign> <h1>Sign In</h1> <NavLink to="/login">Need an account?</NavLink> {errors ? <Error id="error">* Invalid email or password!</Error> : null} <Form> <div> <Label htmlFor="email"> <Input id="email" onChange={handleemailChange} placeholder="Email" type="text" value={email} /> </Label> </div> <div> <Label htmlFor="password"> <Input id="password" onChange={handlePasswordChange} placeholder="Password" type="password" value={password} /> </Label> </div> <SignBtn> <Button type="submit" onClick={handleSubmit}> Sign in </Button> </SignBtn> </Form> </Sign> ); } export default Signin;
my test :
import { shallow } from 'enzyme'; import React from 'react'; import '../../../setup-tests'; import Signin from './Signin'; describe('Signin component', () => { let wrapper; beforeEach(() => { wrapper = shallow(<Signin />); }); it('should display error on the screen on click', () => { const emailInput = wrapper.find('#email'); const passwordInput = wrapper.find('#password'); passwordInput.simulate('change', { currentTarget: { value: '' } }); emailInput.simulate('change', { currentTarget: { value: '' } }); const submitButton = wrapper.find('[type="submit"]'); submitButton.simulate('click'); expect(wrapper.find('#error')).toHaveLength(1); }); });
test return this when I run it :
Expected length: 1, Received length: 0, Received object: {}
-
callback function for `scroll` event doesn't get covered by enzyme test. (React.js)
This is my part of React component
... componentDidMount(): void { window.addEventListener('scroll', this.handleScroll, true); } handleScroll() { const hello = 'assign'; this.setState({blah: 'blah'}); /// whole function is not covered. } ...
enzyme test
describe('when is scrolled', () => { beforeEach(() => { wrapper.simulate('scroll', true); <-- simulate scroll }); test('should match snapshot', () => { expect(wrapper).toMatchSnapshot(); <<< should cover `handleScroll` }) });
This should cover
handleScroll
but enzyme test doesn't cover the whole function (for code coverage) -
Jest tests keep failing for React component that renders various HTML elements based on type by using switch statement
I have a React Component that takes an array and iterates over each node, styling and rendering HTML elements based on the types found within the array.
I have everything running properly and now I'm trying to write a test using Jest to check that:
- The component doesn't render anything when it receives an empty array
- The component renders the appropriate HTML elements based on type when it receives a populated array
I'm relatively new to Jest and testing and I'm not sure how to write the tests to check that the appropriate elements have rendered. Also my null check test keeps failing with the following error message:
FAIL src/components/RenderTextComponent.spec.js ● <RenderTextComponent /> › renders null for empty sections array expect(received).toEqual(expected) Expected value to equal: null Received: <RenderTextComponent /> Difference: Comparing two different types of values. Expected null but received object. 27 | 28 | it('renders null for empty sections array', () => { > 29 | expect(<RenderTextComponent {...emptySections} />).toEqual(null) | ^ 30 | }) 31 | 32 | it('renders', () => { at Object.it (src/components/RenderTextComponent.spec.js:29:50)
This is my testing file:
import React from 'react'; import { shallow } from 'enzyme' import RenderTextComponent from './RenderTextComponent' describe('<RenderTextComponent />', () => { let wrapper; const sections = {} const populatedSections = [ { type: "subtitle", text: ["This is a really cool subtitle filled with words of wonder"] }, { type: "body", text: ["This is an even cooler sentence that shows up as a paragraph.", "And this is a second sentence that shows up as a second paragraph."] } ] const emptySections = [] beforeEach(() => { wrapper = shallow(<RenderTextComponent {...sections} />); }); it('renders null for empty sections array', () => { expect(<RenderTextComponent {...emptySections} />).toEqual(null) }) it('renders', () => { expect(<RenderTextComponent {...populatedSections} />).toEqual(expect.anything()) }) })
And this is my original component that I'm testing:
import React from "react"; import styled from "styled-components"; function renderElements(sections) { const elements = []; if (!sections) return null; sections.map((section) => { switch (section.type) { case "title": return elements.push( section.text.map((string) => <Title>{string}</Title>) ); case "subtitle": return elements.push( section.text.map((string) => <Subtitle>{string}</Subtitle>) ); case "body": return elements.push( section.text.map((string) => <Body>{string}</Body>) ); default: return null; } }); return elements; } const RenderTextComponent = ({ sections }) => { return <>{renderElements(sections)}</>; }; export default RenderTextComponent; const Title = styled.h1` font-size: 28px; `; const Subtitle = styled.h4` font-size: 24px; `; const Body = styled.p` font-size: 18px; `