1

[EDITED]: an earlier version of this question mistakenly though the echarts variable was null, when it was the result of getElementById. I confirmed this by remove el from the function call, and that part of the test did not generate a similar error, implying that echarts was in fact available.


I am using create-react-app, which uses the jest test runner, and am using echarts.

import echarts from 'echarts/lib/echarts';

//...

    const el = document.getElementById('the-chart');
    this.chart = echarts.init(el);

//...

// lots of unecessary context ...'d out here:
  render() {
    const { classes } = this.props;
    return (
      <div className={...}>
        <div className={...}><!-- ... --></div>
        <div className={classes.metricsGraph} onClick={(e) => this.handleClick(e)}>
          <div id="the-chart" style={{width: "600px",height: "400px"}}></div>
        </div>
        <div className={...}><!-- ... --></div>
      </div>
    );
  }

This works when I load the page in a browser. However, when I run tests, I get, on this last line,

TypeError: Cannot read property 'getAttribute' of null

The value of el, returned by document.getElementById must be returning null, but only in the test environment. This code is being called in the components componentDidMount callback.

How can I proceed to make this test pass? Is there another way to get the element or another event I should wait for in the test environment to have this element accessible? Where can I look to discover why this is different in test vs browser?

I am relatively new to node / npm, jest, Javascript that sin't from the 90's, and React, so any pointers to things I'm not thinking about correctly would be greatly appreciated!

Andrew Schwartz
  • 4,440
  • 3
  • 25
  • 58
  • 1
    Could you show the code where the "the-chart" element is being rendered? In react it's better to use refs instead of getElementById, but I'd like to see some context – ezakto Apr 10 '19 at 21:18
  • Updated to add the relevant parts of the `render()` function! I'll play around with `React.createRef` to see if that can make this work. – Andrew Schwartz Apr 10 '19 at 21:27
  • I'm not entirely sure that getElementById is returning null, are you? Did you check with a quick console.log? It should be working if that's being called in componentdidmount.. Hmmm... Anyway, give refs a try, and go with `this.chart = echarts.init(this.myRef)` – ezakto Apr 10 '19 at 21:43
  • console.log confirms it. With `this.chartRef = React.createRef();` in the constructor, I'm getting `{ current: null }` for `this.chartRef` in the `componentDidMount` function. So it has the structure of a ref but it's still not getting the actual DOM element. Again it's gotta have something to do with the test runner, but I'm baffled. – Andrew Schwartz Apr 10 '19 at 21:51
  • Are you using shallow render for this test? – ezakto Apr 10 '19 at 21:53
  • I haven't specified it, and it looks like from [the docs](https://facebook.github.io/create-react-app/docs/running-tests#testing-components) it's not the default behavior, so I'm guessing no but am not 100% confident since I'm just using the scaffolded tests from create-react-app. – Andrew Schwartz Apr 10 '19 at 21:57
  • 1
    Hm, from a part of [this answer](https://stackoverflow.com/questions/43694975/jest-enzyme-using-mount-document-getelementbyid-returns-null-on-componen) I found that it might help to attach the created root element using `document.body.appendChild(div);`, where `div` is created as part of the test code. That gets me further -- the line in question succeeds but a related error happens down the line, another "can't do xyz to `null`" error. Blerg. I'll probe further into that error, but at least it's progress! – Andrew Schwartz Apr 10 '19 at 22:04
  • That's interesting, and definitely beyond me.. – ezakto Apr 10 '19 at 22:10

0 Answers0