📢 Je vous présente le livre Angular

  • 1) Il offre un contenu clair et concis, tout en couvrant une multitude de concepts d'Angular.
  • 2) Le livre est structurĂ© en trois niveaux : dĂ©butant, intermĂ©diaire et avancĂ©
  • 3) traite des pratiques les plus rĂ©centes d'Angular, comme les signaux, les vues diffĂ©rĂ©es, la gestion des flux, entre autres
  • 4) De plus, vous y trouverez plusieurs liens vers des exemples de code source pour approfondir vos connaissances en pratique.

Skip to content

Comment tester un formulaire ngModel ? ​

Voici un composant:

ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-signup',
  template: `
    <form action="#">
        <div>
            <label for="email" class="label">Votre email</label>
            <input type="email" name="email" [(ngModel)]="email" id="email" class="input" placeholder="name@company.com" required="">
        </div>
        <button type="submit" class="button">Créer le compte</button>
    </form>
  `
})
export class SignupComponent {
  email: string = ''
}

Le test unitaire serait alors le suivant:

ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { SignupComponent } from './signup.component';

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

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

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

    // test la propriété email après avoir rempli le champ email
    it('should have email property', async () => {
        const emailInput = fixture.nativeElement.querySelector('input[type="email"]');
        emailInput.value = 'aa@aa.net'
        emailInput.dispatchEvent(new Event('input'));
        await fixture.whenStable()
        fixture.detectChanges()
        expect(component.email).toBe(emailInput.value)
    })
});
  1. emailInput.dispatchEvent(new Event('input')) simule un événement "input" sur l'élément emailInput. Cela permet de déclencher toutes les mécaniques liées à la modification de la valeur d'un champ dans le formulaire, telles que la mise à jour de la propriété email liée à ce champ via [(ngModel)]="email".

  2. await fixture.whenStable() attend que tous les observables liés à l'application soient résolus avant de continuer à exécuter le reste du code. Cela garantit que toutes les mises à jour liées à la modification de la valeur du champ email ont été effectuées avant de tester la valeur de la propriété email.

TIP

ngModelest asynchrone

fixture.detectChanges() déclenche une nouvelle itération de détection de modifications dans l'application. Cela permet de prendre en compte les modifications apportées à la propriété email lors de la simulation de l'événement "input" sur l'élément emailInput.

Tester ​

Le composant:

ts
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-signup',
  template: `
    <form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
        <div>
            <label for="email" class="label">Votre email</label>
            <input type="email" name="email" formControlName="email" id="email" class="input" placeholder="name@company.com" required="">
        </div>
        <button type="submit" class="button">Créer le compte</button>
    </form>
  `
})
export class SignupComponent {
  signupForm = new FormGroup({
    email: new FormControl('', [Validators.required, Validators.email])
  });

  onSubmit() {
    console.log(this.signupForm.value);
  }
}

et le test unitaire:

ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { SignupComponent } from './signup.component';

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

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

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

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

    it('form should be invalid', () => {
        expect(component.signupForm.valid).toBeFalsy();
    });

    it('email field validity', () => {
        let email = component.signupForm.controls['email'];
        expect(email.valid).toBeFalsy();

        email.setValue("test");
        expect(email.hasError('email')).toBeTruthy();

        email.setValue("test@test.com");
        expect(email.valid).toBeTruthy();
    });
});

Chaque mois, recevez en avant-première notre newsletter avec les dernières actualités, tutoriels, astuces et ressources Angular directement par email !