Jasmine expected the spy on the onButtonClick to be called in Angular

Trying to write unit tests for my Angular 6 project has presented me with a challenge. Specifically, I am attempting to test a button with a click function, but every time I run the test file, an error is displayed.

Below is the code snippet:

HTML:

<div>
 <button (click)="onButtonClick(1)"><button>
 <button (click)="onButtonClick(2)"><button>
 <button (click)="onButtonClick(3)"><button>
</div>

comp.ts:

onButtonClick(key: number) {
  do something
}

spec.ts

import { async, ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing';

import { PanelButtonsComponent } from './panel-buttons.component';
import { By } from "@angular/platform-browser";

describe('PanelButtonsComponent', () => {
let component: PanelButtonsComponent;
let fixture: ComponentFixture<PanelButtonsComponent>;

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [PanelButtonsComponent]
  })
    .compileComponents();
}));

beforeEach(() => {
  fixture = TestBed.createComponent(PanelButtonsComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});



it("should call onButtonClick ", fakeAsync(() => {
  const onClickMock = spyOn(component, 'onButtonClick');

 fixture.debugElement.query(By.css('button')).triggerEventHandler('click', null);
  expect(onClickMock).toHaveBeenCalled();
}));


});

Test Result:

Expected spy onButtonClick to have been called.

Any ideas on how to address this issue? Your input is greatly appreciated.

Update

I came across another helpful article, and tried the following code:

it('should', async(() => {
  spyOn(component, 'onButtonClick');

  let button = 
  fixture.debugElement.nativeElement.querySelector('button');
  button.click();

  fixture.whenStable().then(() => {
    expect(component.onButtonClick).toHaveBeenCalled();
  })
}));

Unfortunately, this test case also failed to pass.

UPDATE 2:

In my HTML, there are two different click functions being called, which seems to be causing the error

<div>
 <button (click)="onButtonClick(1)"><button>
 <button (click)="onButtonClick(2)"><button>
 <button (click)="onButtonClick(3)"><button>
 <button (click)="onResetClick()"><button>
</div>

Answer №1

I believe I have found the solution to my query.

Initially, various functions are triggered upon clicking a button.

<div>
 <button (click)="onButtonClick(1)"><button>
 <button (click)="onButtonClick(2)"><button>
 <button (click)="onButtonClick(3)"><button>
 <button (click)="onResetClick()"><button>

This setup leads to errors during testing.

it("should call onButtonClick ", fakeAsync(() => {
  const onClickMock = spyOn(component, 'onButtonClick');

 fixture.debugElement.query(By.css('button')).triggerEventHandler('click', null);
  expect(onClickMock).toHaveBeenCalled();
}));

Expected spy onButtonClick to have been called.


To ensure successful testing, it is necessary to implement the following changes:

Add specific class names to HTML elements

<div>
 <button (click)="onButtonClick(1)" class="normalBtn"><button>
 <button (click)="onButtonClick(2)" class="normalBtn"><button>
 <button (click)="onButtonClick(3)" class="normalBtn"><button>
 <button (click)="onResetClick()" class="resetBtn"><button>
</div>

Subsequently, update the test cases as follows:

it('should call onButtonClick', fakeAsync(() => {
    fixture.detectChanges();
    spyOn(component, 'onButtonClick');
    let btn = fixture.debugElement.queryAll(By.css('.normalBtn'));
    for (let i = 0; i < btn.length; i++) {
      btn[i].triggerEventHandler('click', null);
    }

    tick(); // simulates the passage of time until all pending asynchronous activities finish
    fixture.detectChanges();
    expect(component.onButtonClick).toHaveBeenCalled();
  }));

  it("should call onResetClick ", fakeAsync(() => {
    fixture.detectChanges();
    spyOn(component, 'onResetClick');
    let btn = fixture.debugElement.query(By.css('.resetBtn'));
    btn.triggerEventHandler('click', null);
    tick(); // simulates the passage of time until all pending asynchronous activities finish
    fixture.detectChanges();
    expect(component.onResetClick).toHaveBeenCalled();
  }));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Integrate service once the constructor has completed execution

I created a service to connect with the Spotify API. When initializing this service in the constructor, it needs to retrieve the access token by subscribing to an Observable. However, there's an issue: The service is injected into my main component ...

Disabling a Field in Angular While Preserving its Value

Hey there, late night folks! I have a quick question about Angular. I'm working with a form that includes a specific field where I set the value using patchValue, but I also need to disable this field. The issue is that after disabling it, the value i ...

The issue of Azure AD integration with Angular and ASP.net web api is causing problems with the Msal Angular HTTP interceptor. The interceptor fails to attach

I am currently utilizing Azure AD for Authentication in my application, which consists of a Single Page Application (SPA) using Angular and an ASP.net core web API. I have encountered no issues when reading user information or making any GET calls from Ang ...

Facing the issue of "Protractor not syncing with the page" while trying to navigate an Angular website

I'm currently attempting to follow the tutorial for Protractor on the official Protractor website, but I've hit a roadblock at step 0. My setup involves using protractor and webdriver-manager version 6.0.0. I am running Linux (Ubuntu 18.06) as m ...

Ways to eliminate Typescript assert during the execution of npm run build?

How can I effectively remove Typescript asserts to ensure that a production build generated through the use of npm run build is free of assertions? Your assistance is appreciated ...

Encountering a TypeError while utilizing a custom hook for an Apollo mutation operation

I'm facing a tough time debugging an issue with my Apollo mutation in my NextJS application. The error I'm encountering is as follows: "TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))" It appears t ...

Accessing a property that does not exist under the type 'string' - how to iterate through nested JSON objects

I am currently working on iterating over nested objects and storing the outer object key along with the inner nested object values in arrays. My goal is to use this data to display them in a group bar chart using chart.js. let goodArray = []; let notgoodA ...

Steps to access information from Firebase database by providing the currentUserID:

Here is the firebase database and table information: . I am looking to extract data from the 'active' table based on userID. I attempted to do this in my service.ts file. getCurrentUserData(userID){ return new Observable(obs => { ...

Angular 4 Query Building Plugin

Looking for a query builder plugin compatible with Angular 4 to create nested queries in my project. Some options I found include: https://www.npmjs.com/package/angular2-query-builder (Requires Angular 4+ ) (For AngularJS) (For Angular JS). The c ...

The setupFile defined in Jest's setupFilesAfterEnv configuration is not recognized by the VSCode IDE unless the editor is actively open

I've put together a simplified repository where you can find the issue replicated. Feel free to give it a try: https://github.com/Danielvandervelden/jest-error-minimal-repro Disclaimer: I have only tested this in VSCode. I'm encountering diffic ...

The Angular 2.0 HTTP post request encountered an error when trying to respond with a status of 200 Ok for a null

I'm currently attempting to post data using http in Angular 2. I have added an http call with the corresponding API, and when I click the button, it should send data to my database. However, an error is showing up in the console. XMLHttpRequest canno ...

What could be causing the images to not display on my HTML page?

My program is designed to display an image based on the result of the random function. Here is my HTML: <div> <h2>Player 0:</h2> <div id="MainPlayer0"></div> </div> Next, in my TypeScript fi ...

Typescript for managing the Shopify admin API

Is there anyone who can confirm whether Shopify offers typescript definitions for their admin API? I'm specifically interested in finding types for Orders, Products, and Variants. I initially assumed that this package would have them, but it seems l ...

Updating seleniumjs types with the help of @types/selenium-webdriver is a simple process that can

We are currently using selenium version 4.0.0-alpha-7. How can we determine which version of @types/selenium-webdriver is compatible with this selenium release? Is there a way to map the seleniumJS release to its corresponding typing release? seleniumJS: ...

Transforming jQuery library functions into TypeScript syntax

I have developed a directive using TypeScript. Here is an example of the code: 'use strict'; module App.Directives { interface IPageModal extends ng.IDirective { } interface IPageModalScope extends ng.IScope { //modal: any ...

Using ngrx store select subscribe exclusively for designated actions

Is it possible to filter a store.select subscription by actions, similar to how we do with Effects? Here is an example of the code in question: this.store .select(mySelector) .subscribe(obj => { //FILTER SUBSCRIPTION BY ACTION this.object = ob ...

Angular 2 Shows No Mercy: AOT Promise Rejection Unhandled

I've built a small Angular 2 application that retrieves data from an ASP.net MVC Web API while utilizing Authentication. I'm attempting to employ Ahead Of Time compiler in Angular 2 and have executed the following command: node_modules \ ...

What could be causing the undefined properties of my input variables in Angular?

Currently, I am fetching data from a service within the app component and passing it down to a child component using @Input. Oddly enough, when I log the data in ngOnInit, it appears correctly in the child component. However, when I try to assign it to a v ...

TSLint has flagged issues related to the generic Handler

When working with TypeScript, I make use of an event dispatcher to manage events within classes. While my code functions properly, TSLint raises concerns about the way I declare the handler, leaving me puzzled by its feedback. The following is a snippet o ...

What effect does choosing an image in my user interface have on halting my Web API?

When launching my .NET Core 3 Web API in Visual Studio 2019, everything runs smoothly and handles requests without issue. However, an unexpected problem arises when I interact with my Angular UI. Upon navigating to a new section designed for selecting fil ...