Troubleshooting Angular testing using Jest: Problem encountered with triggerEventHandler

I'm currently working on an Angular application and testing it with JEST. Everything seems to be running smoothly until I encounter an issue with event interactions in Angular.

The test below works as expected:

it('should delegate click to component', () => {
  jest.spyOn(component, 'add');
  const button = fixture.debugElement.query(By.css('button > fa-icon[icon="plus"]'));
  button.nativeElement.click();
  expect(component.add).toHaveBeenCalled();
});

However, when I attempt to use the fixture's

triggerEventHandler('click', null)
method, the spy is not getting invoked.

it('should delegate click to component', () => {
  jest.spyOn(component, 'add');
  const button = fixture.debugElement.query(By.css('button > fa-icon[icon="plus"]'));
  button.triggerEventHandler('click', null);
  expect(component.add).toHaveBeenCalled();
});

I've tried wrapping it in fakeAsync, using tick() and flush(), but unfortunately, it doesn't solve the issue.

The main concern here is not just with this specific case. The bigger challenge arises when I need to test custom event bindings.

I'm puzzled as to why using the native element's click function works (which I've heard leverages the DOM's native event bubbling), but using the fixture's triggerEventHandler does not. Can anyone shed some light on this issue and suggest a solution?

Thank you in advance.

Additional Information

Here is the jest configuration I am using (copied from package.json):

"jest": {
"preset": "jest-preset-angular",
"setupTestFrameworkScriptFile": "<rootDir>/src/setup-jest.ts",
"verbose": true,
"testURL": "http://localhost/",
"transform": {
  "^.+\\.(ts|html)$": "<rootDir>/node_modules/jest-preset-angular/preprocessor.js",
  "^.+\\.js$": "babel-jest"
},
"transformIgnorePatterns": [
  "node_modules/(?!(@ngrx|ngx-bootstrap))"
],
"globals": {
  "ts-jest": {
    "tsConfigFile": "src/tsconfig.spec.json",
    "useBabelrc": true
  },
  "__TRANSFORM_HTML__": true
}

}

Answer №1

Your button click handler may work differently than expected. Keep in mind that using button.nativeElement.click() is not the same as

button.triggerEventHandler('click', null)
. The former will generate a real event object with a target, while the latter will have what you specify, in this case null. Therefore, it is recommended to use:

  button.triggerEventHandler('click', { target: button.nativeElement })

It is not clear why you should opt for triggerEventHandler instead of nativeElement.click().

Answer №2

My issue was resolved when I realized that my click handler was trying to access a property on the event, leading to a null pointer exception. I solved it by passing a proper event object to triggerEventHandler instead of null.

it('should handle click events on the component', () => {
  jest.spyOn(component, 'add');
  const button = fixture.debugElement.query(By.css('button > fa-icon[icon="plus"]'));
  button.triggerEventHandler('click', new Event('click'));
  expect(component.add).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

What is the best way to synchronize API definitions between the server and client using TypeScript?

My setup involves a server (TypeScript, NestJS) and a client (TypeScript, Angular) that communicate with each other. Right now, I have the API response DTO classes defined in both the server to output data and in the client to decode the responses into a ...

What causes the failure of `click()` on a WebElement?

I am currently utilizing protractor within an angular application. The page model I have is structured as follows: export interface TileElement { idx: number; icon: string; title: string; element: WebElementPromise; } getModels() { //used as wfc. ...

The Angular 8 application is opting for "module" scripts over es5 when loading on IE11

My Angular 8 application is not loading on IE11. After analyzing the index.html, I discovered that it only contains scripts with the attribute type="module" and no es5: <script src="/runtime.js" type="module"></script ...

Page Breaks - Patience in anticipation of dataSource readiness

I am facing an issue with my pagination service and component. The dataSource appears empty when the page is loaded for the first time, but by the second time it is populated and I can display the dataTable and paginate successfully. Is there a workaround ...

What is the best way to transfer my static files to the desired output directory in a TypeScript Express application?

I am attempting to transfer my static files from the input directory to the output directory using Express. I found guidance in this tutorial, which utilized shell.js for copying static files. The code responsible for this operation is located in CopyAsse ...

Uncovering redundant fields in TypeScript and detecting errors through type inference

Encountering an unusual edge case with the TS compiler regarding type inference. Surprisingly, the code snippet below (with commented lines intact) should trigger a compile error, but it doesn't. interface IReturned { theField?: string; } interfa ...

Ways to include various inputs with chip

I am currently working on a project that involves implementing an email field using the chip component. However, I have encountered an issue where pasting multiple email values for the first time inserts them into the field successfully. But when I try to ...

The SortKey<> function is ineffective, even though the individual types it uses work perfectly fine

After my initial inquiry about TypeScript, the focus shifted to this current topic. In my previous question, I was attempting to develop a generic sort() method that could function with an array of sort keys defined by the SortKey type featured there (and ...

Emphasize Text on an HTML Webpage

I am currently experimenting with the filter function to highlight specific search text. Take a look at the image below for reference. https://i.sstatic.net/I2yY0.png I have utilized ion-search from Ionic version 3 for this task. As shown in the code sn ...

Experiencing a compilation issue while attempting to apply the class-transformer

Encountering an issue while working with a basic example that involves class-transformer. error TS1240: Unable to resolve signature of property decorator when called as an expression. Argument of type 'ClassFieldDecoratorContext<Root, Project[]> ...

Since making the switch from Angular 5 to 6, I've been consistently encountering a frustrating issue: the error message "timers in xml2js cannot

As mentioned in the title, I am constantly encountering a strange error. Despite attempting to uninstall it using npm uninstall xml2js, nothing has proven effective thus far. https://i.stack.imgur.com/DccM7.png ...

Guide to setting up trading-vue-js plugins within a nuxt.js environment

I've been working on a website using nuxt.js and the trading-vue-js plugins, similar to Tradingview.com. After installing the trading-vue-js plugins in my project and attempting to write the code, I encountered an error in the 'trading-vue-js&ap ...

Encountering a problem while trying to incorporate Mapbox GL JS into an Angular 8 web application

I'm currently working on incorporating mapbox into my simple web application, but I'm encountering difficulties when attempting to add it. At this point, I've already created a mapbox service and a map component. My approach involved using ...

What are the appropriate Typescript typings for React Components that have the ability to return a string or their child components directly?

What are the suitable types for a React Component that can also output a string or directly its children, in addition to a JSX.Element? For example: type PropsStringExample = Readonly<{ returnString: boolean; }>; type PropsChildrenExample = Readon ...

The outcome of a promise is an undefined value

I am facing an issue where I need to access the result of my API call outside the promise, but the value I receive is always undefined. Within the OrderService : public async getOrderPrice(device: string) : Promise<any> { this.urlOrderPrice = th ...

The type 'MutableRefObject<undefined>' cannot be assigned to the type 'LegacyRef<HTMLDivElement> | undefined'

I have created a customized hook that takes a ref object and observes its behavior: import { useState, useEffect, MutableRefObject } from "react"; const UseOnScreen = (ref: MutableRefObject<undefined>) => { const [isIntersecting, setI ...

Updating from Angular version 12.0.4 to 12.1.0 results in a runtime error. As a temporary solution, we are reverting back to version 12.0

There is a related issue discussed here: Angular: TypeError: Cannot read property 'firstCreatePass' of null However, the problem in that case pertains to different Angular versions and the solution provided did not resolve my issue. The recurring ...

Typescript and RxJS: Resolving Incompatibility Issues

In my development setup, I work with two repositories known as web-common and A-frontend. Typically, I use npm link web-common from within A-frontend. Both repositories share various dependencies such as React, Typescript, Google Maps, MobX, etc. Up until ...

Using Angular services in a lazily loaded module

There is a service named routing.service that subscribes to routing events and updates the Translate service when a parameter changes. The constructor code looks like this: this.router.events.subscribe(val => { if (val instanceof ActivationEnd ) { ...

Having trouble locating the Angular Material core theme within the asp.net core 2.0 template using Angular 5

CustomConfig.js const treeModules = [ '@angular/animations', '@angular/common', '@angular/compiler', '@angular/core', '@angular/forms', '@angular/http', '@angular ...