Реагируйте на компонент тестирования в Jest.js и получите TypeError: Невозможно прочитать свойство 'map' из неопределенного - PullRequest
0 голосов
/ 25 сентября 2019

У меня есть проект, созданный create-реагирующим приложением с использованием стилизованных компонентов, и я пытаюсь протестировать некоторые элементы 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, если он; 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;

Ошибка консоли:

 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 при рендеринге.

Ответы [ 2 ]

1 голос
/ 25 сентября 2019

Вы не поставляете реквизит в простом тесте.Поскольку вы не определяете значения по умолчанию, карты не определены.

it('Simple test', () => {
  const wrapper = shallow(<BattleGround />)
  console.log(wrapper)
})
0 голосов
/ 25 сентября 2019

Вы пытались добавить условие к renderCards, как показано ниже, что обеспечит запуск функции карты только при загрузке карт из реквизита?

renderCard = () => {
    const { cards } = this.props;

    return cards ? cards.map((card, key) => {
      return <CardItem card={card} key={key} id={key + 1} />;
    }: null);
  };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...