I'm trying to use apexcharts
and ng-apexcharts
on my home component. It was easy to get it working, but it's breaking my unit tests. I tried to look it up, but couldn't find anything that worked for me. The error happens on cleanup.
HomeComponent
:
@Component({
selector: 'hu-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'],
standalone: true,
imports: [
NavbarComponent,
BarChartComponent
],
})
export class HomeComponent {}
home html:
<hu-navbar></hu-navbar>
<hu-bar-chart test-id="bar-chart"></hu-bar-chart>
BarChartComponent
:
@Component({
selector: 'hu-bar-chart',
standalone: true,
imports: [CommonModule, NgApexchartsModule],
templateUrl: './bar-chart.component.html',
styleUrls: ['./bar-chart.component.scss'],
})
export class BarChartComponent {
@Input() series: ApexAxisChartSeries | ApexNonAxisChartSeries;
@Input() chart: ApexChart;
constructor() {
this.series = [...];
this.chart = {...};
}
}
bar chart html:
<apx-chart test-id="bar-chart" [series]="series" [chart]="chart"></apx-chart>
HomeComponent
's spec file:
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
let authenticationMock: AuthenticationMockService; // use mock to decouple unit tests from Firebase
let page: HTMLElement;
beforeEach(async () => {
authenticationMock = new AuthenticationMockService();
await TestBed.configureTestingModule({
imports: [HomeComponent],
})
.overrideProvider(AuthenticationService, { useValue: authenticationMock })
.compileComponents();
fixture = TestBed.createComponent(HomeComponent);
fixture.detectChanges();
component = fixture.componentInstance;
page = fixture.debugElement.nativeElement;
});
it('should create', () => {
fixture.whenStable().then(() => {
expect(component).toBeTruthy();
});
});
it('should show the navbar', () => {
expect(navbar()).not.toBeNull();
});
it('should show the bar chart', () => {
expect(barChart()).not.toBeNull();
});
function navbar() {
return page.querySelector('hu-navbar');
}
function barChart() {
return page.querySelector('[test-id="bar-chart"]');
}
});
And finally, the error:
console.error
Error during cleanup of component {
component: HomeComponent { __ngContext__: 7 },
stacktrace: TypeError: Cannot read properties of undefined (reading 'node')
...
This error happens in every test. So far, I have only tried to add the following cleanup:
afterEach(() => {
setTimeout(() => {
fixture.destroy();
}, 100);
});
But that didn't help. I'm thinking maybe a solution is to mock it, but couldn't find info on how to do it.
There is a smiliar question that hasn't been answered, but it's about react-apexcharts
, not ng-apexcharts
.
The solution to this problem is to add the following code to your .spec.ts
. This should go inside the beforeEach
that is auto-generated with ng generate
:
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [...],
}).compileComponents();
// Add the code below
Object.defineProperty(window, 'ResizeObserver', {
writable: true,
value:
window.ResizeObserver ||
jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
})),
});
Object.defineProperty(global.SVGElement.prototype, 'getScreenCTM', {
writable: true,
value: jest.fn(),
});
Object.defineProperty(global.SVGElement.prototype, 'createSVGMatrix', {
writable: true,
value: jest.fn().mockReturnValue({
x: 10,
y: 10,
// eslint-disable-next-line @typescript-eslint/no-empty-function
inverse: () => {},
// eslint-disable-next-line @typescript-eslint/no-empty-function
multiply: () => {},
}),
});
// Code to add ends here
fixture = TestBed.createComponent(TheComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});