Jest使用Object.entries引发TypeError

时间:2019-05-31 13:00:50

标签: javascript reactjs jestjs enzyme

我不知道开玩笑/酶有什么问题,但是它以某些令人沮丧的方式崩溃。

import React from 'react';
import Timeline from './Timeline';
import { configure, mount, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

const wrapper = mount(
    <Timeline/>
);

it('Should render the timeline component.', () => {
    expect(wrapper.find(Timeline)).toHaveLength(1);
});

此简单测试会引发此错误:

TypeError: Cannot convert undefined or null to object
        at Function.entries (<anonymous>)

      17 |                 <Row>
      18 |                     {
    > 19 |                         Object.entries(this.props.months).map((month) => {
         |                                ^
      20 |                             let onClick = () => {
      21 |                                 alert(month);
      22 |                             };

      at Timeline.entries [as render] (src/components/Dashboard/AReceber/Timeline.js:19:32)
      at finishClassComponent (node_modules/react-dom/cjs/react-dom.development.js:14741:31)
      at updateClassComponent (node_modules/react-dom/cjs/react-dom.development.js:14696:24)
      at beginWork (node_modules/react-dom/cjs/react-dom.development.js:15644:16)
      at performUnitOfWork (node_modules/react-dom/cjs/react-dom.development.js:19312:12)
      at workLoop (node_modules/react-dom/cjs/react-dom.development.js:19352:24)
      at renderRoot (node_modules/react-dom/cjs/react-dom.development.js:19435:7)
      at performWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:20342:7)
      at requestWork (node_modules/react-dom/cjs/react-dom.development.js:20090:7)
      at scheduleWork (node_modules/react-dom/cjs/react-dom.development.js:19911:5)
      at scheduleRootUpdate (node_modules/react-dom/cjs/react-dom.development.js:20572:3)
      at updateContainerAtExpirationTime (node_modules/react-dom/cjs/react-dom.development.js:20600:10)
      at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:20657:10)
      at ReactRoot.Object.<anonymous>.ReactRoot.render (node_modules/react-dom/cjs/react-dom.development.js:20953:3)
      at node_modules/react-dom/cjs/react-dom.development.js:21090:14
      at unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:20454:14)
      at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:21086:5)
      at Object.render (node_modules/react-dom/cjs/react-dom.development.js:21155:12)
      at render (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:425:26)
      at fn (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:342:37)
      at Object.batchedUpdates$1 [as unstable_batchedUpdates] (node_modules/react-dom/cjs/react-dom.development.js:20439:12)
      at Object.act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:1161:27)
      at act (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:342:13)
      at Object.wrapAct [as render] (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:411:16)
      at new ReactWrapper (node_modules/enzyme/build/ReactWrapper.js:134:16)
      at mount (node_modules/enzyme/build/mount.js:21:10)
      at Object.<anonymous> (src/components/Dashboard/AReceber/Timeline.test.js:10:17)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        4.698s
Ran all test suites related to changed files.

仅因为我使用Object.entries:

import React, { Component } from 'react';
import { withStyles } from '@material-ui/core/styles';
import { Col, Row } from 'reactstrap';

import { buttons } from '../../General/styles';

class Timeline extends Component {

    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div className="timeline-fabs">
                <Row>
                    {
                        Object.entries(this.props.months).map((month) => {
                            let onClick = () => {
                                alert(month);
                            };
                            if (month[1]) {
                                return <Col xs={1}>
                                    <button onClick={onClick} className="timeline-button timeline-button-active">
                                        {month}
                                    </button>
                                </Col>
                            }
                            return <Col xs={1}>
                                <button onClick={onClick} className="timeline-button">
                                    {month}
                                </button>
                            </Col>
                        })
                    }
                </Row>
                <div className="timeline-line" />
            </div>
        )
    }
}

export default withStyles(buttons)(Timeline);

这没有任何意义,我也不知道如何避免。

编辑(显示道具未定义):

<Timeline months={{
    "Jan": this.mockService.getRandomBoolean(),
    "Fev": this.mockService.getRandomBoolean(),
    "Mar": this.mockService.getRandomBoolean(),
    "Abr": this.mockService.getRandomBoolean(),
    "Mai": this.mockService.getRandomBoolean(),
    "Jun": this.mockService.getRandomBoolean(),
    "Jul": this.mockService.getRandomBoolean(),
    "Ago": this.mockService.getRandomBoolean(),
    "Set": this.mockService.getRandomBoolean(),
    "Out": this.mockService.getRandomBoolean(),
    "Nov": this.mockService.getRandomBoolean(),
    "Dez": this.mockService.getRandomBoolean()
}} />

1 个答案:

答案 0 :(得分:0)

事实证明@SrAxi(在评论中)是正确的。由于某种原因,它以undefined开头,然后用prop更新。我想出了一个丑陋的解决方案:

<Row>
    {
        Object.entries((() => {
            if (this.props.months) {
                return this.props.months
            }
            return {}
        })()).map((month) => {
            let onClick = () => {
                alert(month);
            };
            if (month[1]) {
                return <Col xs={1}>
                    <button onClick={onClick} className="timeline-button timeline-button-active">
                        {month}
                    </button>
                </Col>
            }
            return <Col xs={1}>
                <button onClick={onClick} className="timeline-button">
                    {month}
                </button>
            </Col>
        })
    }
</Row>

这很丑,但是行得通。我将这个答案留给未来的受害者。