Angular component testing - Input text value with test case examples

In this tutorial, How to unit test input text control on UI form in Angular application.

In my previous post, Already discussed how to read input text value in Angular application.

I have an existing application created using the ng new cli command.

Let’s create an Angular component using the ng g c component command. It creates an angular component.

Let’s add an input text field and button binding to the template and typescript component.

In this component, We have an input type text and button On clicking the button, Displayed the entered value. The value of the input box is binding using two-way binding syntax -[(ngModel)].

Here is an Angular template component - input-text.component.html

<p>input-text works!</p>
<p>
  <input type="text" id="username" name="username" [(ngModel)]="username" />
</p>
<h1>{{username}}</h1>

<button type="button" (click)="clickme()">Clickme</button>

In the typescript component, Declare two-way binding variable in input-text.component.ts

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

@Component({
  selector: "app-input-text",
  templateUrl: "./input-text.component.html",
  styleUrls: ["./input-text.component.scss"],
})
export class InputTextComponent implements OnInit {
  constructor() {}
  username: string = "";
  clickme() {
    console.log("it does nothing", this.username);
  }

  ngOnInit(): void {}
}

Let’s write an angular component unit testing for this input text box.

Angular unit testing input text component

By default, angular CLI generates default spec files with the following lines of code Here are steps

  • TestBed provides an angular environment for test components.
  • Default TestBed module is configured with a testing module with components, directives, and services, finally compiling components using the compileComponents method.
  • Create a component using the createComponent method that returns the ComponentFixture
  • ComponentFixture is a wrapper component around the user component
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';

import { InputTextComponent } from './input-text.component';

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

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

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

  it('should create', () => {
    expect(component).toBeTruthy();

  });

Unit test the label of an input text in the Angular component

Sometimes, We need to do unit test labels on the UI form. As a developer, need to write a test case for checking for

  • label exists or not on UI components
  • Label name contains the text Enter username value

Here are steps

  • First, the label is queried using debug element. query

  • From a given ComponentFixture, We have a debugElement to access DOM elements.

  • Query method returns child elements using CSS selectors.

  • It returns the label element as well.

  • Assert label exists and outerText contains the given text using expect classes

    Here is a test case for

it("should check input label name", () => {
  let queryByLabel = fixture.debugElement.query(By.css("label[for=username]"));
  expect(queryByLabel).toBeTruthy();
  expect(queryByLabel.nativeElement).toBeTruthy();
  expect(queryByLabel.nativeElement.outerText).toContain("Enter username");
});

Unit testing for update and read input text values on UI Form

Let’s write unit test cases for setting input text values.

  • First retrieve input element usingBy.css with id selector

  • Set the value of the input box using the nativeElement method

  • Once the value is set, Dispatch an input event using the dispatchEvent method

  • Finally detectChanges using manual detection in Angular to update DOM objects.

it("Set Input type text value", async () => {
  const username = fixture.debugElement.query(By.css("#username"));
  username.nativeElement.value = "john";
  username.nativeElement.dispatchEvent(new Event("input"));
  fixture.detectChanges();
  fixture.whenStable().then(() => {
    fixture.detectChanges();
    console.log("sendInput : ", username.nativeElement.value);
    expect(username.nativeElement.value).toContain("john");
  });
});

Submit button to read the input text and validate the value

These test cases cover a setting input value and do button click and validate the input text value.

  • Get button and input using testing query element
  • Change input value and issue Input event
  • manually trigger a click event on the button
  • manually reload component using detectChanges
  • Finally, assert the input value with the displayed value

Here is an example code

it("Form submit click ", async () => {
  const submitButton = fixture.debugElement.query(By.css("#submit"));
  const username = fixture.debugElement.query(By.css("#username"));
  username.nativeElement.value = "asdf";
  username.nativeElement.dispatchEvent(new Event("input"));

  submitButton.triggerEventHandler("click", null);

  const displayText = fixture.debugElement.query(By.css("h1"));
  // manual detection
  fixture.detectChanges();
  expect(displayText.nativeElement.textContent).toBe("asdf");
});

Conclusion

You learned angular component testing for the following things.

  • Change and read input text value
  • input label testing on form
  • Button submit for input text form