javascript - 在“Connect(Items)”的上下文中找不到“store”。要么将根组件包装在在 react.js 中?
问题描述
我正在使用 React 测试库编写带有计数器的简单测试。由于提到的与store有关的错误,我的测试失败了。
我尝试使用不同的方法来解决它,例如创建一个mockStore并将组件包装在Shallow和Provider周围。我也尝试在 index.js 中创建商店,但我已经导入了商店。我似乎无法指出问题所在。
如果有人能告诉我如何解决它,我将不胜感激。
这是我的代码:
商店.js:
import {createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension'
import rootReducer from './reducers'
const initialState = {
}
const middleware = [thunk]
const store = createStore(rootReducer, initialState, composeWithDevTools(applyMiddleware(...middleware)))
export default store;
index.js:
import "./index.css";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import store from "./store/store";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>,
document.getElementById("root")
);
reportWebVitals();
比尔.test.js:
import { screen, fireEvent, act } from "@testing-library/react";
import BillList from "../BillList";
import Adapter from 'enzyme-adapter-react-16'
import configureMockStore from "redux-mock-store";
import { shallow, configure } from "enzyme";
import { Provider } from "react-redux";
const mockStore = configureMockStore();
const store = mockStore({});
configure({adapter: new Adapter()});
describe("<BillList />", () => {
// will display 1 by default because there will be already an item when the page renders
test("display counter text", () => {
shallow(
<Provider store={store}>
<BillList />
</Provider>
)
expect(screen.queryByTestId("counter-text")).toBe("1");
});
// Button increments the price value by +1
test("increment counter", () => {
shallow(
<Provider store={store}>
<BillList />
</Provider>
)
const btnIncrement = screen.queryByTestId("btn-increment");
fireEvent.click(btnIncrement);
expect(screen.queryByTestId("counter-text")).toBe("2");
});
// Button decrements the price value by -1
test("decrement counter", () => {
shallow(
<Provider store={store}>
<BillList />
</Provider>
)
const btnDecrement = screen.queryByTestId("btn-decrement");
fireEvent.click(btnDecrement);
expect(screen.queryByTestId("counter-text")).toHaveTextContent("1");
});
});
BillList.js:
import React, { useState } from "react";
import "./Bill.css";
import { Link, useParams, Switch, Route } from "react-router-dom";
import { connect,} from "react-redux";
import { getItems } from "../store/actions/itemsActions";
function BillList({ items }) {
const [counter, setCounter] = useState(1);
const { id } = useParams();
var ust = parseFloat(0.18);
function Display(props) {
return <label style={{ marginLeft: ".5rem" }}>{props.message}</label>;
}
return (
<div className="bills">
<div
className="main-title"
style={{
textAlign: "center",
justifyContent: "center",
alignItems: "center",
fontSize: 14,
}}
>
<h1>Bakery</h1>
<h1>Company Gbr</h1>
<h1>Oranienburger Straße 120</h1>
<h1>10119 Berlin</h1>
</div>
<div className="bills-container">
{/* pass in the details */}
<div className="item-list">
{items &&
items.items
.filter((item) => item.id === Number(id))
.map((item) => (
<React.Fragment key={item.id}>
<div className="bill-time">
<div className="bill">
<h4>
{" "}
<strong>Bill: </strong>
{item.billNumber}
</h4>
</div>
<div className="time">
<h4>
{" "}
<strong>Time: </strong>
{item.created_datetime}
</h4>
</div>
</div>
<div className="lines-time">
------------------------------------------------------------------------------------------
</div>
{/* Counter */}
<div className="price-total">
<div className="head-title">
<div className="title">
<h3>
{" "}
<strong>Title: {item.title} </strong>
</h3>
</div>
<div className="counter" data-testid="counter-text">
<strong>
<Display message={counter} />x
</strong>
</div>
<div className="lines">------------</div>
</div>
<div className="increase">
<button onClick={() => setCounter(counter + 1)} data-testid="btn-increment">+</button>
</div>
<div className="decrease">
<button onClick={() => setCounter(counter - 1)} data-testid="btn-decrement">-</button>
</div>
{/* Price and total */}
<div className="price">
<h4>
<strong>Price: {parseFloat(item.price).toFixed(2)}€ </strong>
</h4>
</div>
<div className="a">A</div>
<div className="total">
<h4>Total: </h4>
</div>
<div className="total-price">
{parseFloat(item.price * counter).toFixed(2)}€
</div>
<div className="given">
<h4>Given: (iZettle)</h4>
</div>
<div className="given-price">
{parseFloat(item.price * counter).toFixed(2)}€
</div>
<div className="lines-taxes">
-------------------------------------------------------------------------------
</div>
<div className="gross">
<h4>
<strong>gross</strong>
</h4>
</div>
<div className="gross-price">{((parseFloat(item.price) * counter)).toFixed(2)}€</div>
<div className="taxes">
<h4>USt.%</h4>
</div>
<div className="percent">A=7%</div>
<div className="ust">
<h4>USt.</h4>
</div>
<div className="ust-percent">{(ust * counter).toFixed(2)} €</div>
{/* net - the USt */}
<div className="net">
<h4>net</h4>
</div>
<div className="net-result">
{(parseFloat(item.price) * counter - parseFloat(0.18 * counter)).toFixed(2)} €
</div>
</div>
</React.Fragment>
))}
</div>
{/* Paragraph */}
<div className="terminal">
<p> Table: Counter</p>
<p> Terminal: Terminal 1</p>
</div>
<div className="TSE-Transaktion ">
<p>
TSE-Transaktion
</p>
<p>TSE-Signatur-Nr. </p>
<p>
TSE-Start
</p>
<p>
TSE-Stop
</p>
<p>
TSE-Seriennummer
</p>
<p>
TSE-Zeitformat
</p>
<p>
TSE-Signatur
</p>
<p>
TSE-Hashalgorithmus
</p>
<p>
TSE Status
</p>
</div>
<div className="right-side">
<p>
1831
</p>
<p>
98009
</p>
<p>
2020-04-21T09:29:38.00000Z
</p>
<p>
2020-04-21T09:29:50.00000Z
</p>
<p>
5f2897cc074ae841330658eadd324661159f53b7ffd29215
</p>
<p>
utcTime
</p>
<p>
bXkPffFOcetbFokYrOqr/7EYrAc0PH6r
</p>
<p>
ecdsa-plain-SHA256
</p>
<p>
In evaluation
</p>
</div>
<div className="de11">
<p>Ust-Id: DE11111111</p>
</div>
{/* Button */}
</div>
<div className="button-path">
<Link data-testid="analyse-receipt-path" to="/">
<div className="button">
<button data-testid="analyse-receipt" className="main-button">Analyse Receipt</button>
</div>
</Link>
</div>
<Switch>
<Route path="/bills/:id" />
</Switch>
</div>
);
}
const mapStateToProps = (state) => {
return {
items: state.items,
};
};
const mapDispatchToProps = (dispatch) => {
return {
getItems: () => dispatch(getItems()),
};
};
export default connect(mapStateToProps, mapDispatchToProps) (BillList);
解决方案
您正在测试该组件,因此您无法访问它,Provider
因为它是父组件。您可以创建一个自定义包装器,以便您可以在每个测试中使用 Redux。使用以下您将使用reduxRender
而不是标准render
import { render} from '@testing-library/react'
import { Provider as ReduxProvider } from 'react-redux'
import store from './whereverYourStoreIs/store'
/** To be used whenever Redux is referenced */
const ReduxWrapper = ({ children }) => (
<ReduxProvider store={store}>
{children}
</ReduxProvider>
)
/**Render used for Redux */
const reduxRender = (ui, options) =>
render(ui, { wrapper: ReduxWrapper, ...options })
推荐阅读
- javascript - 如何使用 select2 显示选定的国家/地区?
- javascript - 如何使用 javascript 在下载功能中保存带有名称的文件?
- graphql - 你如何改变 GraphQL 中的关系字段?
- python - 需要从m文件中读取数字并将偶数存储在数组中并打印|| 蟒蛇程序
- python - 如何在 Xpath 中使用带有“类名”的“not”属性?
- bash - 在 mosquitto 中接收到某个消息时,Shell 脚本无法离开 while 循环
- javascript - 从 App.js 组件中的 login.js 组件设置状态 ReactJS 中的组件
- linux - 为 Linux 系统构建 Visual Studio 项目
- firebase - Flutter FCM onBackgroundMessage 处理程序给出空检查错误
- php - 如何将 foreach 的数据传递给模态窗口?