What is the best way to evaluate typing into an input field?

My objective is to test the 'typing' functionality in an input element. The aim is to insert a value into the input element, verify that its binding successfully captures the value, and observe the entered value within the input element.

Below is the code snippet:

In app.component:

import { Component } from "@angular/core";

@Component({
  selector: "my-app",
  template: `
    <span>My input: </span>
    <input name="name-input" placeholder="Enter name" [(ngModel)]="name" />
  `,
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  name = "";
}

The testing block:

import { TestBed } from "@angular/core/testing";
import { FormsModule } from "@angular/forms";
import { AppComponent } from "./app.component";

describe("AppComponent", () => {
  var fixture: any;
  var app: AppComponent;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [AppComponent],
      imports: [FormsModule]
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    app = fixture.componentInstance;
  });

  it("should create the app", () => {
    expect(app).toBeTruthy();
  });

  it("should type text into input element", () => {
    let inputElement = fixture.nativeElement.querySelector(
      `input[name='name-input']`
    );

    inputElement.value = "someValue";
    inputElement.dispatchEvent(new Event("input"));
    fixture.detectChanges();

    expect(app.name).toBe("someValue");
  });
});

Upon executing:

inputElement.value = "someValue";
inputElement.dispatchEvent(new Event("input"));
fixture.detectChanges();

Expected Result: app.name should be equal to "someValue". Current Outcome: app.name remains an empty string: "".

You can access a StackBlitz demo illustrating this issue: https://stackblitz.com/edit/stackoverflow-input-question1q2w3e?

Answer №1

Here is the specific code you need:

it("should input text into element after initialization", () => {
  fixture.detectChanges(); // Runs ngOnInit Lifecycle hook

  let inputElement = fixture.nativeElement.querySelector(
    `input[name='name-input']`
  );

  inputElement.value = "someValue";
  inputElement.dispatchEvent(new Event("input"));

  fixture.detectChanges();
  expect(app.name).toBe("someValue");
});

The reason this works: As stated in the official documentation, calling fixture.detectChanges() triggers the ngOnInit() lifecycle hook, which solves the issue.

By modifying the value outside of ngOnInit() before triggering the hook, changes are reverted as the view resets to its original state upon the first fixture.detectChanges() call, undoing previous modifications (such as setting the input value).

Best regards.

Answer №2

To trigger a KeyboardEvent for the HTMLInputElement, you should do so within a fakeAsync environment.

This is how your unit test would appear:

it('#keydown should update app#name', fakeAsync(() => {

  // given
  let inputElement = fixture.nativeElement.querySelector(`input[name='name-input']`);
  
  // when
  let event = new KeyboardEvent('keydown', { key: 'x' });
  inputElement.dispatchEvent(event);
  tick();

  // then
  expect(app.name).toBe("x");
}));

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

Making retries with the RetryWhen filter in Angular 2 RxJS Observables when encountering errors in the status

I'm currently working with the Angular 2 HTTP library, which returns an observable. I'm trying to set up a retry mechanism for specific error statuses/codes. The problem I'm facing is that when the error status is not 429, Observable.of(err ...

Typescript: Utilizing a generic array with varying arguments

Imagine a scenario where a function is called in the following manner: func([ {object: object1, key: someKeyOfObject1}, {object: object2, key: someKeyOfObject2} ]) This function works with an array. The requirement is to ensure that the key field co ...

What is the best way to refresh existing data retrieved by React Query without having to fetch everything again?

My current code structure requires me to refetch all the data after a successful mutation, as the client-side tasks are not updated automatically. Is there a way to update the tasks directly when I create or delete a task? const { data: sessionData } = ...

Discover the step-by-step guide to implementing pagination using NG-ZORRO-Andt in your Angular

I am currently using NG-ZORRO Ant Design pagination on my HTML page and it is displaying correctly in my browser. However, I am struggling with linking the data from the API to the pagination feature. Here is the snippet of my HTML code: <div class ...

Obtain both the key and value from an Object using Angular 2 or later

I have a unique Object structure that looks like this: myCustomComponent.ts this.customDetails = this.newParameter.details; //the custom object details are: //{0: "uniqueInfo", // 5: "differentInfo"} The information stored in my ...

Mapping JSON data from an array with multiple properties

Here is a JSON object that I have: obj = { "api": "1.0.0", "info": { "title": "Events", "version": "v1", "description": "Set of events" }, "topics": { "cust.created.v1": { "subscribe": { ...

Injecting Basic Data Types into Your Angular 2 Service

I am facing an issue with a basic service that requires a single string parameter. import {Injectable} from 'angular2/core'; @Injectable() export class MyService { constructor(someValue: string) { } } When I remove the string param fro ...

404 error received from Angular 2 API call despite successful testing of service

I've been attempting to make a web service call from my Angular 2 application. private baseUrl: string = 'http://localhost:3000/api'; getPatterns(): Observable<Pattern[]> { const patterns$ = this.http .get(`${this.baseUrl ...

Is there a way to modify the style within a TS-File?

I've created a service to define different colors and now I want to set separate backgrounds for my columns. However, using the <th> tag doesn't work because both columns immediately get the same color. Here's my code: color-variatio ...

What steps can I take to resolve a dependency update causing issues in my code?

My program stopped working after updating one of the dependencies and kept throwing the same error. Usually, when I run 'ng serve' in my project everything works fine, but after updating Chartist, I encountered this error: An unhandled exception ...

Acquiring the url identifier along with parameters using the ActivatedRoute in Angular 2

I am attempting to retrieve a UUID from the URL (which is in the format of where uuid goes) and then utilize that UUID for an HTTP GET request. Currently, my app.component.ts appears as follows: private cardUuid: string; constructor(private service: App ...

Access to this feature is restricted when using a decorator in TypeScript with NodeJS

I have designed a decorator to handle async errors, but I am encountering difficulties in accessing it within class methods. My goal is to develop a reusable CRUD class that other classes can inherit from, with a method for CRUD operations. Decorator Code ...

TSLint is encountering the error code TS2459: The module "@azure/core-tracing" claims to have a local declaration of "Span" but does not export it, along with additional errors

I'm completely lost on how to tackle this error. The message I'm getting doesn't provide much insight, other than indicating an issue with the installation of '@azure/ai-text-analytics'. I've gone through the process of uninst ...

The specified property cannot be found within the type 'JSX.IntrinsicElements'. TS2339

Out of the blue, my TypeScript is throwing an error every time I attempt to use header tags in my TSX files. The error message reads: Property 'h1' does not exist on type 'JSX.IntrinsicElements'. TS2339 It seems to accept all other ta ...

The Typescript decorator is unable to access the property type within its own scope

I am currently in the process of developing a dependency injector for use in my VUE js project. Recently, I created an Inject decorator with the intention of accessing a property type. It was functioning perfectly fine yesterday, but now it seems that som ...

Is there a way to adjust the background color of the clicked tab with divs and revert the others back to their original color?

<span class="row top-bar-left align-items-center" style="width: 80%; float:left"> <div tabindex="1" class="link tab" routerLink="details" routerLinkActive="active" [qu ...

Angular 16 SSR encounters a TypeError when the 'instanceof' operator is used on a value that is not an object

I have been facing an issue while updating my Angular application from version 15 to 16. Everything seems to work fine with Angular, including building for Angular Universal without any errors. However, when I attempt to serve using npm run serve:ssr, it t ...

Incorporating .npmrc configuration into an Angular application

It seems like I'm missing a crucial step in this process. I went ahead and added an .npmrc file to the root of my angular project, inserting the following line: @example/xxx:registry=ssh/url/of/my/private/repo/in/bitbucket Subsequently, I included @e ...

Steps to reset an Angular material toggle button:1. Locate the

<div id="slider-group" *ngFor="let sliderToggle of sliderToggleGroup"> <div> <mat-slide-toggle (ngModelChange)="updateSlider($event,sliderToggle)" [(ngModel)]="sliderToggle.isChecked"> {{sliderToggle.na ...

The struggle continues in attempting to adjust Angular Material 2 dialog positioning using MdDialogConfig

Does anyone know how to adjust the position of an MdDialog? openDialog() { let config = new MdDialogConfig(); config.height = '15px'; config.position.left = '5px'; let dialogRef = this.dialog.open(BasicAlertDialog, config); dialogRef. ...