我有一个由create-react-app创建的项目,使用了样式化的组件,并且我试图以许多其他方式测试该组件的某些DOM元素,并且总是遇到相同的问题。例如,在这里我只想记录什么是浅收益。
这是我的BattleGround.js组件:
import React, { PureComponent, Fragment } from "react";
import { Title } from "../Common/TitleStyled/TitleStyled";
import { BattleWrapper } from "./BattleWrapperStyled/BattleWrapperStyled";
import { Table } from "./TableStyled/TableStyled";
import { Header } from "../Common/HeaderStyled/HeaderStyled";
import { Result } from "./ResultStyled/ResultStyled";
import { Button } from "../Common/ButtonStyled/ButtonStyled";
import { Loading } from "../Common/LoadingStyled/LoadingStyled";
import { ErrorPage } from "../Common/ErrorPageStyled/ErrorPageStyled";
import CardItem from "../CardItem/CardItem";
class BattleGround extends PureComponent {
state = {
atributes: [],
category: null,
loading: false
};
componentDidMount() {
this.setAtributes();
}
componentDidUpdate(prevProps) {
if (prevProps.cards !== this.props.cards) {
this.setState({
atributes: []
});
this.setAtributes();
}
}
renderCard = () => {
const { cards } = this.props;
return cards.map((card, key) => {
return <CardItem card={card} key={key} id={key + 1} />;
});
};
setAtributes = () => {
const { cards } = this.props;
cards.forEach(atr => {
this.setState(state => ({
atributes: [...state.atributes, atr.mass || atr.crew],
category: atr.mass ? "people" : "starships"
}));
});
};
checkWhoWins = () => {
const { atributes } = this.state;
if (atributes[0] === "unknown" || atributes[1] === "unknown") {
return <h2>Atribute unknown. Play again</h2>;
} else if (parseInt(atributes[0]) > parseInt(atributes[1])) {
return <h2>Player 1 Wins!</h2>;
} else if (parseInt(atributes[0]) < parseInt(atributes[1])) {
return <h2>Player 2 Wins!</h2>;
} else {
return <h2>Draw!</h2>;
}
};
playAgain() {
const { clearCards, fetchCards } = this.props;
const { category } = this.state;
this.setState({
loading: true
});
clearCards();
fetchCards(category);
fetchCards(category).then(() => this.closeLoading());
}
closeLoading() {
this.setState({
loading: false
});
}
render() {
const { errorFetch, resetGame } = this.props;
const { atributes, loading } = this.state;
return (
<Fragment>
<Header>
<Title>Moon Wars</Title>
{errorFetch && <ErrorPage>{errorFetch}</ErrorPage>}
</Header>
<BattleWrapper>
<Table>{this.renderCard()}</Table>
<Result>{atributes.length === 2 && this.checkWhoWins()}</Result>
<Button onClick={() => this.playAgain()}>PLAY AGAIN</Button>
<Button onClick={() => resetGame()}>Go Back</Button>
</BattleWrapper>
{loading && <Loading />}
</Fragment>
);
}
}
export default BattleGround;
这是我的BattleGround.test.js:
import BattleGround from "./BattleGround";
it("renders correctly", () => {
const wrapper = shallow(
<BattleGround
cards={ [{name: "Luke", mass: 10}] }
clearCards={() => {}}
fetchCards={() => {}}
errorFetch={() => {}}
resetGames={() => {}}
/>
);
expect(wrapper).toMatchSnapshot();
});
it("renders correctly detailed", () => {
const wrapper = render(
<BattleGround
cards={[{ name: "Luke", mass: 10 }]}
clearCards={() => {}}
fetchCards={() => {}}
errorFetch={() => {}}
resetGames={() => {}}
/>
);
expect(wrapper).toMatchSnapshot();
});
it('Simple test', () => {
const wrapper = shallow(<BattleGround />)
console.log(wrapper)
})
如果需要,这是我的testSetup.js:
import React from "react";
import Enzyme, { shallow, render, mount } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import { createSerializer } from "enzyme-to-json";
import sinon from "sinon";
import expectExport from "expect";
expectExport.addSnapshotSerializer(createSerializer({ mode: "deep" }));
Enzyme.configure({ adapter: new Adapter() });
global.React = React;
global.shallow = shallow;
global.render = render;
global.mount = mount;
global.sinon = sinon;
控制台错误:
FAIL src/components/BattleGround/BattleGround.test.js
✕ Simple test (36ms)
Renders check
✓ renders correctly (9ms)
✓ renders correctly detailed (60ms)
● Simple test
TypeError: Cannot read property 'map' of undefined
34 | const { cards } = this.props;
35 |
> 36 | return cards.map((card, key) => {
| ^
37 | return <CardItem card={card} key={key} id={key + 1} />;
38 | });
39 | };
at BattleGround.map [as renderCard] (src/components/BattleGround/BattleGround.js:36:18)
at BattleGround.renderCard [as render] (src/components/BattleGround/BattleGround.js:95:24)
at ReactShallowRenderer._mountClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:845:37)
at ReactShallowRenderer.render (node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:768:14)
at render (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:666:53)
at fn (node_modules/enzyme-adapter-utils/src/Utils.js:99:18)
at Object.render (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:666:18)
at new render (node_modules/enzyme/src/ShallowWrapper.js:397:22)
at shallow (node_modules/enzyme/src/shallow.js:10:10)
at Object.shallow (src/components/BattleGround/BattleGround.test.js:33:19)
很明显,当测试通过组件时,道具卡是未定义的,但我不知道为什么。渲染时,这些组件应具有来自App组件的道具。
答案 0 :(得分:1)
您没有在简单测试中提供道具。 由于您未定义默认值,因此未定义卡。
it('Simple test', () => {
const wrapper = shallow(<BattleGround />)
console.log(wrapper)
})
答案 1 :(得分:0)
您是否尝试过如下所示的条件向renderCards添加条件,以确保map功能仅在从道具加载卡片时才运行?
renderCard = () => {
const { cards } = this.props;
return cards ? cards.map((card, key) => {
return <CardItem card={card} key={key} id={key + 1} />;
}: null);
};