Home > Net >  Vue 2: How to unit test component that uses Chart.js (vue-chart-3)
Vue 2: How to unit test component that uses Chart.js (vue-chart-3)

Time:01-06

I have a vue2 project that uses ClassComponents and Chart.js (via vue-chart-3). I now have a simple component that wraps a DoughnutChart to manage data and stuff.

DBOverviewDoughnut.vue

<template>
  <div>
    <p>test</p>
    <DoughnutChart ref="doughnutRef" :chartData="sharesData"></DoughnutChart>
  </div>
</template>

<script lang="ts">
import Component from 'vue-class-component';
import Vue from 'vue';
import { DoughnutChart, ExtractComponentData } from 'vue-chart-3';
import { Prop, Ref } from 'vue-property-decorator';
import { ChartData } from 'chart.js';

@Component({ components: { DoughnutChart } })
export default class DBOverviewDoughnut extends Vue {
  @Prop()
  private sharesData!: ChartData<'doughnut'>;

  @Ref()
  private readonly doughnutRef!: ExtractComponentData<typeof DoughnutChart>;

  created(): void {
    this.assignColors();
  }

  mounted(): void {
    if (this.doughnutRef.chartInstance) {
      console.log(this.doughnutRef.chartInstance.data);
    }
  }

  assignColors(): void {
    this.sharesData.datasets[0].backgroundColor = [
      '#77CEFF',
      '#0079AF',
      '#123E6B',
      '#97B0C4',
      '#A5C8ED',
    ];
  }
}
</script>

Starting the program it will work fine and I can access the chartInstance inside the mounted hook.

But now I want to unit test my component. I thought on setting the propsData which will be the input data for the chart.

DBOverviewDoughnut.spec.ts

import DBOverviewDoughnut from '@/components/dashboard/DBOverviewDoughnut.vue';
import { mount, Wrapper } from '@vue/test-utils';
import { Share } from '@/Share';

describe('DBOverviewDoughnut', () => {
  let cut: Wrapper<DBOverviewDoughnut>;

  it('should render the correct amount of sections', () => {
    cut = mount(DBOverviewDoughnut, {
      propsData: {
        sharesData: {
          labels: ['TestShare1', 'TestShare2', 'TestShare3'],
          datasets: [{ data: [11, 22, 33] }]
        }
      }
    });
    const chart = cut.findComponent({ ref: 'doughnutRef' });
    console.log(chart);
  });
});

Using shallowMount() doesn't seem to work, because I only get this from logging (no chartInstance and its properties as in the production code):

VueWrapper {
      isFunctionalComponent: undefined,
      _emitted: [Object: null prototype] {},
      _emittedByOrder: [],
      selector: { ref: 'doughnutRef' }
    }

So I thought maybe I have to mount the component because the DoughnutChart is also a wrapper around the Chart.js charts. But when using mount() I get the following error:

console.error node_modules/vue/dist/vue.runtime.common.dev.js:621
    [Vue warn]: `createElement()` has been called outside of render function.

  console.error node_modules/vue/dist/vue.runtime.common.dev.js:621
    [Vue warn]: Error in render: "Error: [vue-composition-api] must call Vue.use(VueCompositionAPI) before using any function."
    
    found in
    
    ---> <DoughnutChart>
           <DBOverviewDoughnut>
             <Root>

I don't really know what I'm doing wrong. I registered the VueCompostionAPI in my main.ts:

import Vue from 'vue';
import { Chart, registerables } from 'chart.js';
import App from './App.vue';
import router from './router';
import store from './store';
import VueCompositionAPI from '@vue/composition-api';

Chart.register(...registerables);
Vue.use(VueCompositionAPI);

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount('#app');

Following this post doesn't solve the problem either.

Anyone got an idea what's going wrong? I'm a bit confused if the error has to do with my test setup or with the installation of chart.js or compositionApi.

CodePudding user response:

You need to use VueCompositionAPI inside your spec as well when you mount the component. You can do this by creating a local Vue instance inside your spec, adding VueCompositionAPI as a plugin to the instance and using the instance when you mount the component. https://vue-test-utils.vuejs.org/api/options.html#localvue

CodePudding user response:

Using localVue is really what I should have thought about. This and installing the canvas-package works, that I get additional information about my Ref-Element. However I still have to figure out what to do with it.

@AdriHM I want to test if the rendered chat gets the correct data I guess. Or if it displays it correctly (e.g. display the correct amount of sections) But the longer I think about it the less I'm sure it's the right thing to test. I don't want to test the Chart.js API though.

  •  Tags:  
  • Related