0

I have an issue when testing a component that renders a couple of text fields, an icon and a chart.

I'm rendering the chart on a <canvas> and for that I use the react hook useRef and all works beautiful.

My problem is when I try to render the component in my unit test. For that purpose I'm using jest and enzyme, so these are the files involved in this process:

React Component

import React, { useEffect, useRef } from 'react';
import Chart from 'chart.js';
import { useWidgetConfiguration } from '../utils/SummitHooks';

const styles = {
  canvas: { padding: '30px 30px' },
};

const widgetProperties = {
  title: { type: 'string', default: '' },
  percent: { type: 'number' },
};

const DougnutWithTextWidget = props => {
  const { widgetConf } = props;
  const chartRef = useRef();

  const widgetDisplayValues = useWidgetConfiguration(
    widgetProperties,
    widgetConf,
  );

  useEffect(() => {
    if (chartRef.current) {
      new Chart(chartRef.current.getContext('2d'), {
        type: 'doughnut',
        data: {
          labels: ['', widgetDisplayValues.title],
          datasets: [
            {
              data: [
                parseInt(100 - parseInt(widgetDisplayValues.percent)),
                parseInt(widgetDisplayValues.percent),
              ],
              backgroundColor: ['#f4f4f4', '#377d28'],
            },
          ],
          text: widgetDisplayValues.title,
        },
        options: {
          animation: {
            animateScale: true,
            animateRotate: true,
          },
          cutoutPercentage: 75,
          tooltips: false,
        },
      });
    }
  }, [widgetDisplayValues, chartRef]);

  Chart.defaults.global.legend = false;

  return (
    <div className='uk-container-expand'>
      <div className='widget-account-health-outer'>
        <div className='widget-account-health-inner'>
          <h1 className='uk-text-center'>{widgetDisplayValues.percent}%</h1>
          <span className='uk-h5 uk-text-bold'>
            {widgetDisplayValues.title}
          </span>
        </div>
        <canvas
          ref={chartRef}
          height='400'
          width='400'
          style={styles.canvas}
        ></canvas>
      </div>
    </div>
  );
};

export default DougnutWithTextWidget;

Test File

import React from 'react';
import { mount } from 'enzyme';
import DougnutWithTextWidget from '../components/organisms/DougnutWithTextWidget';

describe('Testing the Atomic Component <AccountBarChartWidget />', () => {
  let atomicComponent;

  const widgetConf = {
    title: 'GOALS HEALTH',
    percent: 57,
    chartType: 'doughnut',
    linkTo: '',
  };

  beforeAll(() => {
    atomicComponent = mount(<DougnutWithTextWidget widgetConf={widgetConf} />);
  });

  afterAll(() => {
    atomicComponent.unmount();
  });

  describe('Validate that the Atomic Component is displaying the data provided as wdgetConf', () => {
    it('Ensure that the right amount has been displayed', () => {
      // A simple test just for making sure the component is rendering without any problem
      expect(2 + 2).toEqual(4);
    });
  });
});

At this moment, when I use either shallow or render the test works fine, but my goal is to actually mount the component to make sure that the chart has been drawn.

This is the error I'm getting:

 Testing the Atomic Component <AccountBarChartWidget />
    Validate that the Atomic Component is displaying the data provided as wdgetConf
      ✕ Ensure that the right amount has been displayed (3ms)

  ● Testing the Atomic Component <AccountBarChartWidget /> › Validate that the Atomic Component is displaying the data provided as wdgetConf › Ensure that the right amount has been displayed

    TypeError: Cannot read property 'length' of null

      24 |   useEffect(() => {
      25 |     if (chartRef.current) {
    > 26 |       new Chart(chartRef.current.getContext('2d'), {
         |       ^
      27 |         type: 'doughnut',
      28 |         data: {
      29 |           labels: ['', widgetDisplayValues.title],

      at Object.acquireContext (node_modules/chart.js/dist/Chart.js:7739:19)
      at Chart.construct (node_modules/chart.js/dist/Chart.js:9307:26)
      at new Chart (node_modules/chart.js/dist/Chart.js:9294:7)
      at DougnutWithTextWidget (src/components/organisms/DougnutWithTextWidget.js:26:7)
      at commitHookEffectList (node_modules/react-dom/cjs/react-dom.development.js:22030:26)
      at commitPassiveHookEffects (node_modules/react-dom/cjs/react-dom.development.js:22064:11)
      at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:336:14)
      at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:385:16)
      at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:440:31)
      at flushPassiveEffectsImpl (node_modules/react-dom/cjs/react-dom.development.js:25392:7)
      at unstable_runWithPriority (node_modules/scheduler/cjs/scheduler.development.js:697:12)
      at runWithPriority$2 (node_modules/react-dom/cjs/react-dom.development.js:12149:10)
      at flushPassiveEffects (node_modules/react-dom/cjs/react-dom.development.js:25361:12)
      at Object.<anonymous>.flushWork (node_modules/react-dom/cjs/react-dom-test-utils.development.js:1041:10)
      at Object.act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:1155:9)
      at wrapAct (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:354:13)
      at Object.render (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:423:16)
      at new ReactWrapper (node_modules/enzyme/src/ReactWrapper.js:115:16)
      at mount (node_modules/enzyme/src/mount.js:10:10)
      at Object.beforeAll (src/__tests__/dougutWithTextWidget.test.js:16:23)

Has anybody tried to test something similar and can point me in the right direction?

1 Answer 1

1

I was finally able to crack this issue. I required support for the <canvas> tag in the test file and just importing jest-canvas-mock did the trick.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.