Reputation: 730
Issue
I'm able to mock the cookie in Jest, but it won't change the state of my components once the cookie is mocked.
For example, when a user visits my app, I want to check if a cookie of ACCESS_TOKEN exists, if it exists, render a saying "Hi, Username".
When testing, I'm able to create the cookie and get the values with console.log(), but my component won't render the because the test does not think redux-store has the cookie.
Here's what my redux-store looks like (Redux store is not the problem, all my tests that does not rely on cookies and soley relies on store are working):
Root.tsx
export const store = createStore(
reducers,
{ authStatus: { authenticated: Cookies.get("ACCESS_TOKEN") } },
//if our inital state (authStauts) has a cookie, keep them logged in
composeWithDevTools(applyMiddleware(reduxThunk))
);
const provider = ({ initialState = {}, children }) => {
return <Provider store={store}>{children}</Provider>;
};
export default provider
App.tsx
import Root from "./Root"; //root is provider variable in Root.tsx
ReactDOM.render(
<React.StrictMode>
<Root>
<App />
</Root>
</React.StrictMode>,
document.getElementById("root")
);
Welcome.tsx
const Welcome =(props) => {
return(
<div>
{props.authStatus && <h3> Hello USERNAME</h3>}
</div>
}
}
const mapStateToProps = (state) => {
return {
authStatus: state.authStatus.authenticated,
};
};
export default connect(mapStateToProps, {})(Welcome);
Here's my test:
import Cookies from "js-cookie"
beforeEach(async () => {
//Before the component renders, create a cookie of ACCESS_TOKEN.
//Method 1 (Works, console.log() below would show the value, but component won't render):
//jest.mock("js-cookie", () => ({ get: () => "fr" }));
//Method 2 (Works, console.log() below would show the value, but component won't render):
//Cookies.get = jest.fn().mockImplementation(() => "ACCESS_TOKEN");
//Method 3 (Works, console.log() below would show the value, but component won't render)):
// Object.defineProperty(window.document, "cookie", {
// writable: true,
// value: "myCookie=omnomnom",
// });
app = render(
<Root>
<MemoryRouter initialEntries={["/"]} initialIndex={0}>
<Routes />
</MemoryRouter>
</Root>
);
console.log("Cookie Val", Cookies.get());
app.debug(); //I want to see that the <h3> is rendered, but it's not being rendered.
});
Why is this occurring?
Resources used:
How to mock Cookie.get('language') in JEST
Use Jest to test secure cookie value
Upvotes: 1
Views: 7211
Reputation: 17514
I'm not exactly sure how did you combine things together but I'm gonna drop you a full example that you can follow and fix your code as bellow, please check inline comments:
// Provider.jsx
import React from 'react';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import Cookies from "js-cookie";
// the reducer I assume as same as you created
const authReducer = (state = {}, action) => {
return {
...state,
...action.payload,
}
}
const store = createStore(
authReducer,
{ authStatus: { authenticated: Cookies.get("ACCESS_TOKEN") } }
);
export default ({ initialState = {}, children }) => {
return <Provider store={store}>{children}</Provider>;
};
// Routes.jsx
// should be the same as you did
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Welcome from "./Welcome";
export default (props) => {
return (
<Switch>
<Route exact path="/" component={Welcome} />
</Switch>
)
}
Finally the test file:
// index.test.js
import React from 'react';
import Cookies from "js-cookie"
import "@testing-library/jest-dom"
import { screen, render } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import Routes from "./Routes";
import Provider from "./Provider";
// Mock your cookie as same you did
// but should be the same level with `import` things
jest.mock("js-cookie", () => ({ get: () => "fr" }), {
// this just for being lazy to install the module :)
virtual: true
});
it('should pass', () => {
render(
<Provider>
<MemoryRouter initialEntries={["/"]} initialIndex={0}>
<Routes />
</MemoryRouter>
</Provider>
);
expect(screen.queryByText('Hello USERNAME')).toBeInTheDocument()
})
PS: The link I created the test for you: https://repl.it/@tmhao2005/js-cra (ref at src/Redux
to see full example)
Upvotes: 1