'Clicking on first component to enable second component to test different actions using jasmine

I have two components which are related to charts. Component 1 holds number-cards information and Component 2 holds line-graph information.

After clicking on any card in number-card-component we will show line-graph by enabling line-graph-component.

Test Case: Need to click on a button in line-graph-component using jasmine test case.

Issue Facing: As line-graph-component is enabled only after clicking a card in number-card-component I am unable to click the button in line-graph-component.

number-card-component.ts

import { Component, OnDestroy, OnInit } from '@angular/core';
import { ScaleType } from '@swimlane/ngx-charts';
import { BehaviorSubject, Subscription } from 'rxjs';

@Component({
  selector: 'app-number-card',
  templateUrl: './number-card.component.html',
  styleUrls: ['./number-card.component.scss']
})
export class NumberCardComponent implements OnInit {

  cardsData: any[] = [];
  displayChart = false;
  constructor(private service: MyService) { }

  ngOnInit(): void {
    this.getMetricsSubscription = this.service.getNumbers()
      .subscribe((data: any) => {
        this.cardsData = data;
      })
  }

  onSelect(event: any) {
    this.displayChart = true;
  }

}

line-chart-component

import { Component, OnInit } from '@angular/core';
import { ScaleType } from '@swimlane/ngx-charts';

@Component({
  selector: 'app-line-chart',
  templateUrl: './line-chart.component.html',
  styleUrls: ['./line-chart.component.scss']
})
export class LineChartComponent implements OnInit {

  chartContent: any[] = [];
 
  constructor(private service: MyService) {
  }

  ngOnInit(): void {
    this.service.chartInfo.subscribe((chartData) => {
      this.chartContent = chartData;
    });
  }

  closeChart() {
    console.log('chart is closed');
  }
}

number-card-html

<ngx-charts-number-card
  [results]="cardsData"
  (select)="onSelect($event)">
</ngx-charts-number-card>
<app-line-chart *ngIf=displayChart></app-line-chart>

line-chart-html

<ngx-charts-line-chart  [results]="chartContent">
</ngx-charts-line-chart>
<button (click)="closeChart()">Close</button>

jasmine-test-case

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { of } from 'rxjs';

import { LineChartComponent } from './line-chart.component';
import { NumberCardComponent } from '../summary-card/summary-card.component'

describe('LineChartComponent', () => {
  let component: LineChartComponent;
  let fixture: ComponentFixture<LineChartComponent>;
  let service: Service;
  let cardComponent: ComponentFixture<NumberCardComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      declarations: [LineChartComponent],
      providers: [MyService],
      schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA]
    })
      .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(LineChartComponent);
    cardComponent = TestBed.createComponent(NumberCardComponent);
    service = TestBed.inject(MyService);
    component = fixture.componentInstance;
    fixture.detectChanges();

    spyOn(service, 'getNumbers').and.returnValue(of(
        [
          { name: "Metric 1", value: 877 },
          { name: "Metric 2", value: 111 }
        ]
    ));

  });


  it('on closeChart method ChartData information needs to be reset', fakeAsync(() => {

    fixture.debugElement.nativeElement.querySelectorAll('button')[1].click();
    // component.closeChart();

    expect(component.closeChart).toHaveBeenCalled();
  }));

});


Solution 1:[1]

You're showing a test for LineChartComponent but I think you need a test for NumberCardComponent.

Set up a test for it as well and do the following:

it('should display chart on select', () => {
  const card = fixture.debugElement.query(By.css('ngx-charts-number-card'));
  // first argument is event name, 2nd argument is the $event object mocked
  card.triggerEventHandler('select', {});
  // call detect changes so the HTML updates
  fixture.detectChanges();
  const chart = fixture.debugElement.query(By.css('app-line-chart'));
  expect(chart).toBeTruthy();
});

Check out triggerEventHandler here: https://netbasal.com/simulating-events-in-angular-unit-tests-5482618cd6c6, it is a very well written article.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AliF50