Reputation: 11
I've got project made by create-react-app, using styled components and I'm trying to test some DOM elements of this component in many other ways and always got the same issue. For example here I just want to log whats shallow return.
Here is my BattleGround.js component:
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;
Here is my 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)
})
And here is my testSetup.js if it;s need:
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;
Console Error:
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)
Obvious is that props cards is undefinded when the tests gone through the component but I don't know why. This components should have props from App component when render.
Upvotes: 1
Views: 2268
Reputation: 834
You are not supplying with props in simple test. Since you are not defining default values, cards is undefined.
it('Simple test', () => {
const wrapper = shallow(<BattleGround />)
console.log(wrapper)
})
Upvotes: 1
Reputation: 330
Have you tried adding a condition to the renderCards, as below, which will ensure the map function only runs when the cards are loaded from props?
renderCard = () => {
const { cards } = this.props;
return cards ? cards.map((card, key) => {
return <CardItem card={card} key={key} id={key + 1} />;
}: null);
};
Upvotes: 0