Currently I am receiving the following error in my jest unit test in an Angular application that is testing a component that uses ChartJS.
TypeError: auto_1.default is not a constructor
The chart/graph displays fine and I am able to switch between different datasets that feed into this presentation component from an external data source.
I have tried importing the Chart from 'chart.js/auto'; into the test, mocking various functions that create the chart and to no success. Importing ChartJS into a test file, or creating a new chart to test in the test does nothing and I still receive the same error.
The .spec file:
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { GraphDisplayComponent } from './graph-display.component';
describe('GraphDisplayComponent', () => {
let component: GraphDisplayComponent;
let fixture: ComponentFixture<GraphDisplayComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [GraphDisplayComponent],
}).compileComponents();
fixture = TestBed.createComponent(GraphDisplayComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
The .ts of the component
import {
Component,
ElementRef,
Input,
OnInit,
ViewChild,
} from '@angular/core';
import Chart from 'chart.js/auto';
@Component({
selector: 'app-graph-display',
templateUrl: './graph-display.component.html',
styleUrls: ['./graph-display.component.scss'],
})
export class GraphDisplayComponent implements OnInit {
@Input() chartData: any;
@ViewChild('canvas', { static: true }) canvas!: ElementRef;
chart!: any;
ngOnInit() {
this.chart = new Chart(this.canvas.nativeElement, this.chartData);
}
}
>Solution :
The error TypeError: auto_1.default is not a constructor you’re encountering usually stems from a problem with module import/export semantics. The problem is likely that Jest, under its default configuration with Angular, uses CommonJS to handle module imports/exports. When combined with certain libraries or versions of libraries (like Chart.js) that are distributed using ES modules, this mismatch can lead to errors.
A few steps you can take to fix this:
-
Jest Configuration
Ensure that your Jest configuration is properly set up to handle ES modules. A package named
jest-preset-angularhelps set up Angular with Jest. If you’re not already using it, I recommend trying it. -
Mocking Chart.js
In many cases, you might not want actually to instantiate or run the real Chart.js in your tests. Instead, you can mock it. This can avoid the error entirely and make your test run faster.
At the top of your
.specfile, before any other imports:jest.mock('chart.js/auto', () => ({ default: jest.fn().mockImplementation(() => ({ // any mock methods or properties you need })) }));This mocks out the
Chartconstructor so it doesn’t do anything. If you need to test that the constructor is called, or that methods on the chart instance are called, you can add more to the mock. -
ES Module Handling
If you want to handle ES modules directly, you might need to update your Jest config and use Babel to help Jest understand ES modules. This is a more involved solution, but can be necessary for some setups. Here’s a simplified version:
-
Install the necessary Babel packages:
npm install --save-dev @babel/preset-env @babel/preset-typescript -
Create or update a
.babelrcfile:{ "presets": [ "@babel/preset-env", "@babel/preset-typescript" ] } -
Update your Jest configuration to use Babel:
{ "transform": { "^.+\\.tsx?$": "babel-jest" } }
-
Remember, sometimes the simplest way to get your tests running is to mock out parts of the system that aren’t directly related to what you’re testing. If you’re not explicitly testing the behavior of Chart.js, then mocking it might be your best bet.