Troubleshooting the malfunctioning of unit testing in HostListener directive

I'm currently facing an issue with unit testing a functionality that works perfectly on the front-end but the unit test is not working as expected. Below you can find my current unit test, which is still in progress as I am focusing on getting the basic test to function before moving on to more complex checks.

@Component({
  template : '<input appInputFilter filterType="alphanumericOnly" type="text" minlength="2">'
})
class TestComponent {

}

describe('InputFilterDirective', () => {

  let comp: TestComponent;
  let fixture: ComponentFixture<TestComponent>;
  let de: DebugElement;
 // const el: HTMLElement;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations : [InputFilterDirective, TestComponent]
    });

    fixture = TestBed.createComponent(TestComponent);

    comp = fixture.componentInstance;

    de = fixture.debugElement.query(By.directive(InputFilterDirective));
  });

  it('should create instance of inputFilter', () => {
    expect(comp).toBeTruthy();
    expect(de).toBeDefined();
  });

  it('should only allow onlyNumbers', async(() => {

    fixture.detectChanges();


    const keyEvent = new KeyboardEvent('keydown', {'code': 'KeyQ'});
    const input = de.nativeElement as HTMLInputElement;
    input.dispatchEvent(keyEvent);
    expect(input.value).toEqual('q');


    expect(true).toBeTruthy();
  }));
});

Here is the full directive code:

 import { Directive, ElementRef, HostListener, Input  } from '@angular/core';

@Directive({
  selector: '[appInputFilter]',

})
export class InputFilterDirective {

  private el : any;
  private specialKeys : Array<string> = ['Backspace', 'Tab', 'End', 'Home'];

  @Input() public filterType : any;

  constructor(el: ElementRef) {
    this.el = el;
   }

   @HostListener('keydown', ['$event'])
   onKeyDown(event: KeyboardEvent) {

    if (this.specialKeys.indexOf(event.key) !== -1) {
      return;
    }

    switch (this.filterType) {
      case 'onlyNumber':
        this.appFilter(event, new RegExp(/\D/g));
      break;
      case 'alphanumericOnly':
        this.appFilter(event, new RegExp(/\W/g));
      break;
      case 'alphabeticAndSpecial':
        this.appFilter(event, new RegExp(/[^a-zA-Z'-]/));
      break;
      case 'ipAddress':
        this.appFilter(event, new RegExp(/[^0-9.]/g));
      break;
    }
   };

  appFilter(event: KeyboardEvent, regex: RegExp) {
    const current: string = this.el.nativeElement.value;
    const next: string = current.concat(event.key);

    if (next && String(next).match(regex)) {
      event.preventDefault();
    }
  };
}

Additional information:

  • I've tried various KeyEvents such as typing '1' without success.
  • The unit test has been run both asynchronously and synchronously.
  • I have followed tips from Stack Overflow regarding how others have tested HostListeners, but unfortunately, it's not working for me and I'm unsure why.

Any help would be greatly appreciated. As mentioned, this is just a basic test where I'm using the filter to specifically target alphanumeric characters (as seen in the directive code).

If the issue lies with detecting changes, I'm open to listening for "preventDefault" to make the test work. Feel free to suggest any adjustments needed.

Answer №1

One successful method I've employed is utilizing the triggerEventHandler on the directive element. Take a look at the following example:

it('verifying addition of "c2d-dropzone-active" class to element after dragenter event', async done => {
  fixture.detectChanges();
  const el: any = element.query(By.directive(C2dDropzoneDirective));
  expect(el.nativeElement.className).not.toContain('c2d-dropzone-active');
  el.triggerEventHandler('dragenter', mockEvent);
  fixture.detectChanges();
  await fixture.whenStable();
  expect(el.nativeElement.className).toContain('c2d-dropzone-active');
  done();
});

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

The justify-content: space-between property does not work in a nested flex box scenario

I'm currently working on styling a cart in Angular and facing an issue with aligning the price all the way to the right of the cart. I attempted using `space-between` within the outer div, which worked fine, but when applied to the inner div, it doesn ...

Tips for concealing or revealing an existing element with *ngfor

I am currently facing an issue with hiding and showing an element in Angular 4. This is the HTML code I am working with: <div class='row'> <div class='col-md-4 imgTxt' *ngFor="let path of imagePaths" > <img [id] ...

Separate the string by commas, excluding any commas that are within quotation marks - javascript

While similar questions have been asked in this forum before, my specific requirement differs slightly. Apologies if this causes any confusion. The string I am working with is as follows - myString = " "123","ABC", "ABC,DEF", "GHI" " My goal is to spli ...

What is the most effective way to use a withLatestFrom within an effect when integrating a selector with props (MemoizedSelectorWithProps) sourced from the action?

I am struggling to utilize a selector with props (of type MemoizedSelectorWithProps) in an effect inside WithLatestFrom. The issue arises because the parameter for the selector (the props) is derived from the action payload, making it difficult for withLat ...

What strategies can I use to enable CSS focus on PrimeNG's textarea component?

I am having trouble with getting the CSS hover effect to work on my PrimeNG textarea. Below is the CSS I am using. The class for invalid functions is working, but the hovering is not. .is-invalid { .ql-toolbar.ql-snow { border: 1px solid $red !impo ...

Removing a column in an Angular application using the xlsx library

I'm trying to figure out how to remove the last column from a table when using the xlsx library. I'm working on saving data from my Angular application, but there is one column called "description" which just contains icons and I don't want ...

Exploring the differences in object shapes using TypeScript

I'm currently working on defining an object that has the ability to hold either data or an error. export type ResultContainer = { data: any; } | { error: any; }; function exampleFunction():ResultContainer { return { data: 3 } } ...

Issues with code functionality following subscription via a POST request

I'm currently facing an issue with a service that utilizes an HTTP post request to communicate with the database. Unfortunately, when I try to implement this in my .ts file, nothing seems to happen after subscribing to the post. The post itself works ...

Using React with an Array of Promises in Typescript

I have a function that looks like this: function queryProposals(hash:string) { let result = api?.query.backgroundCouncil.proposalOf( hash,(data1:any)=>{ let injectedData = data1.toPrimitive().args.account as InjectedAccou ...

TypeScript's standard React.Children interface for compound components

One of my components is a Table, which can have children that are Column components: <Table data={data}> <Column cell={(c) => c.date} header="Date" /> <Column cell={(c) => c.count} header="Count" /> & ...

Troubleshooting Issue with Angular 5: Inability to Hide Elements for Non-Authenticated Users

Below is the code from app.component.html <nav class='navbar navbar-default'> <div class='container-fluid'> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-targ ...

List the attributes that have different values

One of the functions I currently have incorporates lodash to compare two objects and determine if they are identical. private checkForChanges(): boolean { if (_.isEqual(this.definitionDetails, this.originalDetails) === true) { return false; ...

The error message "Angular formGroup requires a FormGroup instance. Kindly provide one."

I used angular reactiveforms to create a form. The default data is successfully printed on the form, however, I am facing an error in the console that says "formGroup expects a FormGroup instance. Please pass one in." Can someone guide me on how to resolve ...

Troubleshooting issue: Angular 7 form template not resetting with form.reset()

I'm having trouble resetting the input value and ngmodel control state in my form. Here's the code from TrackPage.html: <form #trackForm="ngForm"> <div class="form__field" style="padding-top: 10px; "> <search-in ...

The attribute 'Error' is not available for the object of type 'MovieData | ResponseError'. This attribute is also not present in objects of type 'MovieData'

Question Answered I am currently working with two interfaces, MovieData and ResponseError. export interface MovieData { Poster: string; Title: string; Plot: string; imdbID: string; } The ResponseError interface looks like this: export interface R ...

The property express.json() is not recognized

Why doesn't Typescript recognize the express.json() function, even though many tutorials claim it should compile without errors? Could I have overlooked something in my code? An example tutorial that suggests this code works: https://auth0.com/blog/n ...

Creating a Redis client in Typescript using the `redis.createClient()` function

I'm currently trying to integrate Redis (v4.0.1) into my Express server using TypeScript, but I've encountered a small issue. As I am still in the process of learning TypeScript, I keep getting red underline errors on the host parameter within th ...

Storing files or Blobs within Json data in Angular/Javascript

Is it possible to include a file inside a JSON when sending data through ajax? colors: [ {_id: "5bec42f02797800f447241d1", color: "#777", image: File(79666)}, {_id: "5bec8cf91fb21b3a2477d817", color: "#566", image: File(79666)} ] If not, what is the alt ...

"An issue has been noticed with Discord.js and Discordx VoiceStateUpdate where the return

Whenever I attempt to retrieve the user ID, channel, and other information, I receive a response of undefined instead of the actual data import { VoiceState } from "discord.js"; import { Discord, On } from "discordx"; @Discord() export ...

What is the process for including external parameters in the webpack setup?

I'm attempting to create my project with webpack and here is my webpack configuration file. import * as path from 'path'; import * as webpack from 'webpack'; import { fileURLToPath } from 'url ...