0

I am writing unit tests for an angular application and I am not able to detect the UI changes when the form values change. Here is some sample code

html file

<form #myForm="ngForm" autocomplete="off">
    <table>
        <tbody>
            <tr>
                <td>User Name: *</td>
                <td>
                    <div class="error-field">
                        <input autofocus type="text" name="userName" [(ngModel)]="userName" #userName="ngModel" pattern="[a-zA-Z]{6,50}" required />
                        <span *ngIf="isRequired(userName)">This field is required.</span>
                        <span *ngIf="userName.invalid.pattern" class="username-pattern-label">Invalid user name</span>
                    </div>
                </td>
            </tr>
            <tr>
                <td colspan="2" style="text-align: center;">
                    <button class="clear-button" (click)="clearDetails()">Clear</button>
                    <button [disabled]="myForm.invalid" type="button" name="addButton" (click)="addDetails()">Add</button>
                </td>
            </tr>               
        </tbody>
    </table>
</form>

ts file

public isRequired(field: any) {
    return field.errors?.required && (field.touched || field.dirty);
}

spec file

it('should show user name is invalid', async() => {
    const userNameField = fixture.debugElement.query(By.css('input[name="userName"]')).nativeElement;
    userNameField.value = "123sdsad";
    userNameField.dispatchEvent(new Event("input"));
    fixture.detectChanges();
    fixture.whenStable().then(() => {
        const userNameField = fixture.debugElement.query(By.css('.username-pattern-label')).nativeElement;
    })
});

This testcase is failing because it cant find username-pattern-label span element.

Similarly when I enter a valid value Add button is not being enabled.

What am I doing wrong here?

Krishna Chaitanya
  • 2,533
  • 4
  • 40
  • 74
  • Copy component.ts, component.html and component.spec.ts file here as well. – Pa Ri Jun 07 '22 at 14:56
  • One initial observation is that `username-pattern-label` is a CSS class, not an element name, so you need to include a `.` in front of it in your query: `By.css('.username-pattern-label')`. – MikeJ Jun 08 '22 at 02:56
  • @MikeJ sorry that is a typo. I testcase has `.` in the class name and it still does not work – Krishna Chaitanya Jun 08 '22 at 12:27
  • @KrishnaChaitanya have a look at this issue logged in angular's repo: [dispatchEvent does not change the validation state of a form input](https://github.com/angular/angular/issues/23118). The response: "The test code above looks synchronous, but ngModel initial value is set asynchronously. There needs to be a tick() before any values are set for the test." So you might just need to wrap your test in `fakeAsync` and call `tick()` before checking for the validation element. – MikeJ Jun 08 '22 at 21:20

0 Answers0