React 测试库 / Redux - 如何模拟 cookie?

React Testing Library / Redux - How to mock cookies?

问题

我可以在 Jest 中模拟 cookie,但一旦 cookie 被模拟,它就不会改变我组件的 状态

例如,当用户访问我的应用程序时,我想检查 ACCESS_TOKEN 的 cookie 是否存在,如果存在,则呈现一句“你好,用户名”。

测试时,我可以创建 cookie 并使用 console.log() 获取值,但我的组件不会呈现,因为测试不考虑 redux- store 有 cookie。

这是我的 redux-store 的样子(Redux store 不是问题,我所有的测试都不依赖于 cookie并且 soley 依赖于商店正在工作):

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);

这是我的测试:

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.
});

为什么会这样?

使用的资源:

How to mock Cookie.get('language') in JEST

我不太确定你是如何将这些东西组合在一起的,但我会给你一个完整的例子,你可以按照下面的方式修复你的代码,请检查内联评论:

// 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>
    )
}

最后是测试文件:

// 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:我为您创建的 link 测试:https://repl.it/@tmhao2005/js-cra(参考 src/Redux 查看完整示例)