angular-testing-library icon indicating copy to clipboard operation
angular-testing-library copied to clipboard

karma in watch mode broken form tests when refresh

Open jadir-junior opened this issue 3 years ago • 4 comments

I try test a form required, the first time test pass normal, but when I change the file and karma refresh the tests all tests in form broken

app.component.ts

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

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

@Component({
  selector: 'app-root',
  template: `
    <form [formGroup]="form">
      <input type="text" formControlName="name" aria-label="name" />
      <div *ngIf="name.invalid && name.touched">
        <p aria-label="error name" *ngIf="name.errors?.['required']">
          Campo obrigatorio
        </p>
      </div>
    </form>
  `,
})
export class AppComponent {
  form: FormGroup = this.fb.group({
    name: ['', [Validators.required]],
  });

  constructor(private fb: FormBuilder) {}

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

**app.component.testing-library.spec.ts **

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

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

describe('Testing library Form', () => {
  const { getByLabelText, getByText } = screen;
  const setup = () => {
    return render(AppComponent, {
      imports: [ReactiveFormsModule],
    });
  };

  it('should render a component with testing library', async () => {
    await setup();

    expect(getByLabelText('name')).toBeInTheDocument();
  });

  it('should show erro message required with testing library', async () => {
    const { fixture } = await setup();
    fixture.detectChanges();

    const input = getByLabelText('name');

    await userEvent.click(input);
    await userEvent.tab();

    console.log('COMMENT TO REFRESH');

    expect(getByText('Campo obrigatorio')).toBeInTheDocument();
  });
});

At first time the testing pass:

Screenshot from 2022-07-25 13-35-38

But when I change some file, this happen:

Screenshot from 2022-07-25 13-36-58

When I refresh with F5, the tests back to pass:

Screenshot from 2022-07-25 13-38-01 Screenshot from 2022-07-25 13-38-11

I thought that was karma or karma-launch, but if I test with normal library angular this work normally app.component.ts

import { ComponentFixture, TestBed } from '@angular/core/testing';

import { AppComponent } from './app.component';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';

const dispatchFakeEvent = (
  element: EventTarget,
  type: string,
  bubbles: boolean = false
): void => {
  const event = document.createEvent('event');
  event.initEvent(type, bubbles, false);
  element.dispatchEvent(event);
};

const markFieldAsTouched = (element: DebugElement) => {
  dispatchFakeEvent(element.nativeElement, 'blur');
};

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

  const setup = async () => {
    await TestBed.configureTestingModule({
      declarations: [AppComponent],
      imports: [ReactiveFormsModule],
    }).compileComponents();

    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  };

  it('should render a component with testing angular', async () => {
    await setup();

    expect(component).toBeTruthy();
  });

  it('should show erro message required with testing angular', async () => {
    await setup();

    const appComponent: DebugElement = fixture.debugElement;

    const input = appComponent.query(By.css('input'));
    markFieldAsTouched(input);

    fixture.detectChanges();

    const error = appComponent.query(By.css('p')).nativeElement;

    expect(error).toBeTruthy();
    expect(error).toHaveTextContent('Campo obrigatorio');
  });
});

the env in my github: https://github.com/jadir-junior/angular-karma-and-testing-library

jadir-junior avatar Jul 25 '22 16:07 jadir-junior

Hi, thanks for the reproduction. I tried to reproduce it, but I wasn't really successful. Is this something that always fails for you, because I tried changing the component and the test multiple times but the test keeps passing.

I suspect that it's a timing issue. Could you try the following assertion?

// use findBy instead of getBy
expect(await screen.findByText('Campo obrigatorio')).toBeInTheDocument();

timdeschryver avatar Jul 26 '22 05:07 timdeschryver

I have to simulate:

bug

In the ChromeHeadless work normally

jadir-junior avatar Jul 26 '22 12:07 jadir-junior

@jadir-junior thanks again. It seems like it doesn't blur correctly, you could use fireEvent.blur for now which should work:

  it('should show error message required with testing library', async () => {
    await setup();

    const input = getByLabelText('name');
    fireEvent.blur(input);
    expect(screen.getByText('Campo obrigatorio')).toBeInTheDocument();
  });

timdeschryver avatar Jul 26 '22 16:07 timdeschryver

The browser needs to be focused, see https://github.com/testing-library/user-event/issues/553

rothsandro avatar Jul 28 '22 11:07 rothsandro

Needs to be fixed in userEvent

timdeschryver avatar Dec 14 '22 12:12 timdeschryver