Replay

Apprendre Angular en 1h

Je me donne un objectif: vous faire découvrir et apprendre Angular en 1 heure: composant, syntaxe dans les templates, les directives, les signaux, les routeurs, les services, l'injection de dépendances, les observables et les requêtes HTTP. Le nécessaire pour faire une application Angular !.

Skip to content

Vous souhaitez recevoir de l'aide sur ce sujet ? rejoignez la communauté Angular.fr sur Discord.

Comment tester un formulaire ngModel ?

Voici un composant:

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

@Component({
  selector: 'app-signup',
  imports: [FormsModule],
  standalone: true,
  template: `
    <form action="#">
        <div>
            <label for="email" class="label">Votre email</label>
            <input type="email" name="email" [(ngModel)]="email" id="email" class="input" placeholder="[email protected]" 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({
            imports: [SignupComponent, 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 = '[email protected]'
        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 { ReactiveFormsModule, FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-signup',
  standalone: true,
  imports: [ReactiveFormsModule],
  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="[email protected]" 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({
            imports: [SignupComponent, 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("[email protected]");
        expect(email.valid).toBeTruthy();
    });
});