Enzyme: highcharts not rendering with mount()

Created on 3 Aug 2016  路  9Comments  路  Source: enzymejs/enzyme

When I mount(<myHighchartsComponent />) my highcharts doesn't render in the div it was supposed to.
All that I get is:

<div id="579a8c5de9cf144f0c7653df"></div>

The component is being rendered perfectly in the browser.

More details:

componentDidMount() {
  this.chart = new highcharts.Chart(this.options);
}


render() {
    return <div id={this.props.widget.id}></div>;
  }

Any ideas?

Need To Reproduce

Most helpful comment

I'm also writing a component that wraps highcharts and wanted to share how i got around testing it. Should work for any 3rd party libraries that manipulate the DOM outside of React.

// create a dummy test element to attach to
const body = document.body;
body.insertAdjacentHTML('afterbegin', '<div id="chart-test"></div>');
const chartTestElement = document.getElementById('chart-test');

const plot = mount(
    <ChartComponent/>,
     {
       attachTo: chartTestElement 
     }
  );

// do whatever assertions.
// console.log(plot.html()) will show the rendered DOM

// detach to clean up, remove test node
plot.detach();
body.removeChild(chartTestElement);

hope this helps

All 9 comments

I think we need more information. I'm not seeing how highcharts gets rendered. I'm assuming this.options has a reference to that id for it to render in, but more context would be helpful.

All that I get is:
<div id="579a8c5de9cf144f0c7653df"></div>

Is that from calling .html() or .debug() ?

@blainekasten yes, this.options has a reference to that id.

the method was
const wrapper = mount(<SolidGauge widget={widget} widgetData={widgetData} />); console.log(wrapper.html());

highcharts gets rendered here:
componentDidMount() { this.chart = new highcharts.Chart(this.options); }

The thing is, this component renders in the browser.

Yeah, I've run into a similar issue using c3.js. I just get a div with an id using mount() but not the svg chart.

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

    componentDidMount() {
        stackedBars(this.props.staticChartData, this.props.influencerData);
    }

    render() {
        const { collapseId, helpText, rootClassName, staticChartData, title } = this.props;

        return(
            <div className={rootClassName}>
                <div className="panel panel-white" style={{position: 'relative'}}>
                    <ComponentHeading
                        collapseId={collapseId}
                        title={title}
                    />
                    <ComponentHelp
                        collapseId={collapseId}
                        title={title}
                    >
                        <p>{helpText}</p>
                    </ComponentHelp>
                    <div className="panel-body no-padding pl-5 pr-5">
                        <div id={staticChartData.id}></div>
                    </div>
                </div>
            </div>

        )
    }
}
console.log(component.debug());
<div className="panel-body no-padding pl-5 pr-5">
    <div id="au-chart-age-gender-distribution" />
</div>

Do you guys know off the top of your head if this is testable using React's TestUtils ? I'll try and look into this more later. Basically it seems like enzyme isn't aware of things injected into the DOM outside of the React lifecycle. I'm not too sure how much we can do here but it's definitely worth looking into as many people use 3rd party, non-react, libs within React components.

Oh, this issue happens with React's TestUtils as well. Sorry, forgot to mention that important information.
I have tried with shallow, mount, TestUtils.renderIntoDocument and even renderToString from react-dom/server

I have also done the jsdom setup before the test.
const jsdom = require('jsdom').jsdom; etc...

Yeah, so if this doesn't work with react's utils either, it is as I expected. Basically react is unable to know about DOM that is injected into it. I'm going to create a new ticket to spike and see if there is _anything_ enzyme can do to handle this problem. Otherwise, it might just need to be tested outside of enzyme/react. I don't really have a great suggestion for that either. If I had to guess this is what i would do:

_Mock Highcharts and make sure it is called with the appropriate arguments._

That way you aren't really testing Highcharts internal code (which you shouldn't be), but instead just making sure this component creates an instance of Highcharts, with the proper arguments, and called in the proper lifecycle.

I'm also writing a component that wraps highcharts and wanted to share how i got around testing it. Should work for any 3rd party libraries that manipulate the DOM outside of React.

// create a dummy test element to attach to
const body = document.body;
body.insertAdjacentHTML('afterbegin', '<div id="chart-test"></div>');
const chartTestElement = document.getElementById('chart-test');

const plot = mount(
    <ChartComponent/>,
     {
       attachTo: chartTestElement 
     }
  );

// do whatever assertions.
// console.log(plot.html()) will show the rendered DOM

// detach to clean up, remove test node
plot.detach();
body.removeChild(chartTestElement);

hope this helps

with Najamm code, it fails with
TypeError: First argument to Node.prototype.insertBefore must be a Node within highcharts.

any idea?

adding skipClone to the config allows me to go a step further but I am now blocked because somehow the generated React ref is not a NodeImpl instance. Help!

const defaultConfig = { chart: { skipClone:true, ...}

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ivanbtrujillo picture ivanbtrujillo  路  3Comments

AdamYahid picture AdamYahid  路  3Comments

SandroMachado picture SandroMachado  路  3Comments

ahuth picture ahuth  路  3Comments

blainekasten picture blainekasten  路  3Comments