1
votes

I am using Enzyme to test a d3 chart component. I encounter a problem that d3.select cannot find the container div as well as this error message:

TypeError: Cannot read property 'getAttribute' of null

Here's my code:

Chart component file: ProgramMeasureTrendsComponent.js

  class ProgramMeasureTrendsComponent extends Component {
        constructor(props){
            super(props);
        }

        render() {
            return (
                <div className='programTrendChartContainer'></div>
               **this is the d3 container div that d3 select cannot find.**
            )
        }

        componentDidMount() {
            this.createBarChart()
           **use componentDidMount to render d3 chart.**
        }

        createBarChart() {
                let { parsedData,xAxisKeys,chartTitle,width,height,
                        marginTop,marginLeft,marginBottom,marginRight } = this.props;
                let keys = Object.keys(parsedData[0]).slice(0, 5);
                let container = d3.select('.programTrendChartContainer');<=== getting error at this line
    ......

Test case file:

describe('<ProgramMeasureTrendsComponent />', () => {
    it('Renders  ProgramMeasureTrends Component', () => {
        let store = mockStore({"dashboard":{"main":{"currentPeriod":"MONTH"}}});

        const input =  [
            {
                month:"Jan",
                elevated:0,
                group:"1486022400000",
                hyperCrisis:0,
                hyperStage1:0,
                hyperStage2:0,
                normal:0,
                total:0
            },
            {
                month:"Feb",
                elevated:0,
                group:"1488441600000",
                hyperCrisis:0,
                hyperStage1:0,
                hyperStage2:0,
                normal:0,
                total:0
            },
            {
                month:"Mar",
                elevated:0,
                group:"1491116400000",
                hyperCrisis:0,
                hyperStage1:0,
                hyperStage2:0,
                normal:0,
                total:0
            },
            {
                month:"Apr",
                elevated:0,
                group:"1493708400000",
                hyperCrisis:0,
                hyperStage1:0,
                hyperStage2:0,
                normal:0,
                total:0
            }

        ]
        let container = mount( <ProgramMeasureTrendsComponent
                                store={store}
                                parsedData = { input }
                                xAxisKeys = {["Jan","Feb","Mar","Apr"]}
                                chartTitle = 'd3 chart title'
                                width = '400'
                                height = '400'
                                marginTop = '20'
                                marginBottom = '20'
                                marginLeft = '20'
                                marginRight = '20'
                              />);

        container.debug();  

    });
})

Error output

<ProgramMeasureTrendsComponent /> Renders  ProgramMeasureTrends Component:
     TypeError: Cannot read property 'getAttribute' of null
      at Selection.selection_attr [as attr] (node_modules/d3-selection/build/d3-selection.js:590:16)
      at ProgramMeasureTrendsComponent.createBarChart (src/modules/dashboard/main/components/ProgramMeasureTrendsComponent.js:47:30)
      at ProgramMeasureTrendsComponent.componentDidMount (src/modules/dashboard/main/components/ProgramMeasureTrendsComponent.js:28:14)
      at node_modules/react-dom/lib/ReactCompositeComponent.js:265:25
      at measureLifeCyclePerf (node_modules/react-dom/lib/ReactCompositeComponent.js:75:12)
      at node_modules/react-dom/lib/ReactCompositeComponent.js:264:11
      at CallbackQueue.notifyAll (node_modules/react-dom/lib/CallbackQueue.js:76:22)
      at ReactReconcileTransaction.close (node_modules/react-dom/lib/ReactReconcileTransaction.js:80:26)
      at ReactReconcileTransaction.closeAll (node_modules/react-dom/lib/Transaction.js:206:25)
      at ReactReconcileTransaction.perform (node_modules/react-dom/lib/Transaction.js:153:16)
      at batchedMountComponentIntoNode (node_modules/react-dom/lib/ReactMount.js:126:15)
      at ReactDefaultBatchingStrategyTransaction.perform (node_modules/react-dom/lib/Transaction.js:140:20)
      at Object.batchedUpdates (node_modules/react-dom/lib/ReactDefaultBatchingStrategy.js:62:26)
      at Object.batchedUpdates (node_modules/react-dom/lib/ReactUpdates.js:97:27)
      at Object._renderNewRootComponent (node_modules/react-dom/lib/ReactMount.js:320:18)
      at Object._renderSubtreeIntoContainer (node_modules/react-dom/lib/ReactMount.js:401:32)
      at Object.render (node_modules/react-dom/lib/ReactMount.js:422:23)
      at Object.renderIntoDocument (node_modules/react-dom/lib/ReactTestUtils.js:91:21)
      at renderWithOptions (node_modules/enzyme/build/react-compat.js:200:24)
      at new ReactWrapper (node_modules/enzyme/build/ReactWrapper.js:94:59)
      at mount (node_modules/enzyme/build/mount.js:19:10)
      at Context.<anonymous> (test/modules/dashboard/ProgramMeasureTrendsComponent.spec.js:53:25)

In my app, this chart rendered properly without any error, but when I test it the above error is shown.

My guess is that the container div is not rendered when componentDidMount() is called in Enzyme's testing process.

Is Enzyme's component lifecycle different than the React lifecycle?

1

1 Answers

0
votes

Enzyme is limited to what React exposes, and React is not aware of the appended elements.

https://github.com/airbnb/enzyme/blob/master/docs/common-issues.md#testing-third-party-libraries