Skip to content

When I test a form with required, It doesn't works #373

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jadir-junior opened this issue Mar 6, 2023 · 7 comments · Fixed by #375
Closed

When I test a form with required, It doesn't works #373

jadir-junior opened this issue Mar 6, 2023 · 7 comments · Fixed by #375

Comments

@jadir-junior
Copy link

I don't know what happen or which version thats happen.

But my news tests in angular 15 doesn't woks

when I use a userEvent to click in input and click in another input, the ngIf that validate and show a message "required", doesn't works

I'm using karma with chromeheadless

package.json

{
  "name": "angular-test-15",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test --browsers ChromeHeadless"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^15.0.0",
    "@angular/common": "^15.0.0",
    "@angular/compiler": "^15.0.0",
    "@angular/core": "^15.0.0",
    "@angular/forms": "^15.0.0",
    "@angular/platform-browser": "^15.0.0",
    "@angular/platform-browser-dynamic": "^15.0.0",
    "@angular/router": "^15.0.0",
    "rxjs": "~7.5.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.12.0"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^15.0.2",
    "@angular/cli": "~15.0.2",
    "@angular/compiler-cli": "^15.0.0",
    "@testing-library/angular": "13.3.0",
    "@testing-library/jasmine-dom": "1.3.3",
    "@testing-library/user-event": "14.4.3",
    "@types/jasmine": "~4.3.0",
    "@types/testing-library__jasmine-dom": "1.3.0",
    "jasmine-core": "~4.5.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.0.0",
    "typescript": "~4.8.2"
  }
}

login.component

import {
  FormBuilder,
  FormControl,
  FormGroup,
  Validators,
} from '@angular/forms';

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

@Component({
  selector: 'app-login',
  template: `<h1>Login</h1>

    <form [formGroup]="form" (submit)="onSubmit(form)">
      <input type="email" aria-label="email" formControlName="email" />
      <div *ngIf="email.invalid && (email.dirty || email.touched)">
        <div *ngIf="email.errors?.['required']">Email is required</div>
      </div>
      <input type="password" aria-label="password" formControlName="password" />
      <div *ngIf="password.invalid && (password.dirty || password.touched)">
        <div *ngIf="password.errors?.['required']">Password is required</div>
      </div>
      <button type="submit" aria-label="submit" [disabled]="form.invalid">
        Submit
      </button>
    </form> `,
  styleUrls: ['./login.component.scss'],
})
export class LoginComponent {
  form: FormGroup = this.fb.group({
    email: ['', [Validators.required]],
    password: ['', [Validators.required]],
  });

  constructor(private fb: FormBuilder) {}

  get email(): FormControl {
    return this.form.get('email') as FormControl;
  }

  get password(): FormControl {
    return this.form.get('password') as FormControl;
  }

  onSubmit({}: FormGroup): void {}
}

login.component.spec

import { render, screen } from '@testing-library/angular';

import { LoginComponent } from './login.component';
import { ReactiveFormsModule } from '@angular/forms';
import userEvent from '@testing-library/user-event';

describe('LoginComponent', () => {
  const setup = async () => {
    return render(LoginComponent, {
      imports: [ReactiveFormsModule],
    });
  };

  it('should create a component with inputs and a button to submit', async () => {
    await setup();

    expect(screen.getByRole('textbox', { name: 'email' })).toBeInTheDocument();
    expect(screen.getByLabelText('password')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: 'submit' })).toBeInTheDocument();
  });

  it('should show a message required to password and login and a button must be disabled', async () => {
    const { container, debug } = await setup();

    await userEvent.click(screen.getByRole('textbox', { name: 'email' }));
    await userEvent.click(screen.getByLabelText('password'));
    await userEvent.tab();
    await userEvent.click(screen.getByRole('button', { name: 'submit' }));

    debug(container);
    expect(screen.getAllByText(/required/i).length).toBe(2);
    expect(screen.getByRole('button', { name: 'submit' })).toBeDisabled();
  });
});

timdeschryver added a commit that referenced this issue Mar 8, 2023
@timdeschryver
Copy link
Member

Hi, I don't seem to be able to reproduce this issue.
It could be the user-event version though, this library is still on user-event v13.

#375

@jadir-junior
Copy link
Author

Do you try with karma and chromeheadless?

@jadir-junior
Copy link
Author

jadir-junior commented Mar 8, 2023

when I test debug on container I have this log:

Chrome Headless 110.0.5481.177 (Linux x86_64): Executed 1 of 3 SUCCESS (0 secs / 0.103 secs)
LOG: '<div
  _nghost-a-c50=""
  id="root1"
  ng-version="15.2.1"
>
  <h1
    _ngcontent-a-c50=""
  >
    Login
  </h1>
  <form
    _ngcontent-a-c50=""
    class="ng-untouched ng-pristine ng-invalid"
    ng-reflect-form="[object Object]"
    novalidate=""
  >
    <input
      _ngcontent-a-c50=""
      aria-label="email"
      class="ng-untouched ng-pristine ng-invalid"
      formcontrolname="email"
      ng-reflect-name="email"
      type="email"
    />
    <input
      _ngcontent-a-c50=""
      aria-label="password"
      class="ng-untouched ng-pristine ng-invalid"
      formcontrolname="password"
      ng-reflect-name="password"
      type="password"
    />
    <button
      _ngcontent-a-c50=""
      aria-label="submit"
      disabled=""
      type="submit"
    >
       Submit
    </button>
  </form>

It doesn't show the divs with errors.

@timdeschryver
Copy link
Member

@jadir-junior I have moved the test file to the karma project and it's still green.
Have you tried using findBy instead of getBy? Perhaps it takes a while to become visible?

@jadir-junior
Copy link
Author

I put this code within await waitFor() then work, but why?

  it('should show a message required to password and login and a button must be disabled', async () => {
    const { container, debug } = await setup();

    await userEvent.click(screen.getByRole('textbox', { name: 'email' }));
    await userEvent.click(screen.getByLabelText('password'));
    await userEvent.click(screen.getByRole('button', { name: 'submit' }));

    await waitFor(() => {
      debug(container);
      expect(screen.getAllByText(/required/i).length).toBe(2);
    });

    expect(screen.getByRole('button', { name: 'submit' })).toBeDisabled();
  });

@jadir-junior
Copy link
Author

jadir-junior commented Mar 9, 2023

I tried with clone the testing-library/angular and really works with it.

but I tried create 3 new projects with angular 15, 14 and 13 and not works in these projects

@timdeschryver
Copy link
Member

I think the cause is user-event v14, this library uses v13 while you're using v14.
Perhaps that there's a small delay, which causes the error to not be visible immediately.
Using waitFor, waits until the elements are visible (or a timeout).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants