Skip to content

detectChanges needed if using user-event#click #491

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
lebbers opened this issue Oct 3, 2024 · 1 comment · Fixed by #494
Closed

detectChanges needed if using user-event#click #491

lebbers opened this issue Oct 3, 2024 · 1 comment · Fixed by #494

Comments

@lebbers
Copy link

lebbers commented Oct 3, 2024

In a Karma + jasmine setup, I need to explicitly call detectChanges after I've used the @testing-library/user-event#click event on a button that routes to another component. Is that how it should behave or am I doing something wrong here?

In angular-testing-library/apps/example-app-karma/src/app/examples/login-form.spec.ts i've added the following test. If the detectChanges call is removed the test fails.

it('test click event with router.navigate', async () => {
  const user = userEvent.setup();
  const { detectChanges } = await render(`<router-outlet></router-outlet>`, {
    routes: [
      {
        path: '',
        component: LoginComponent,
      },
      {
        path: 'logged-in',
        component: LoggedInComponent,
      },
    ],
  });

  expect(screen.getByRole('heading', { name: 'Login' })).toBeVisible();
  expect(screen.getByRole('button', { name: 'submit' })).toBeInTheDocument();

  const email = screen.getByRole('textbox', { name: 'email' });
  const password = screen.getByLabelText('password');

  await user.type(email, '[email protected]');
  await user.type(password, 'with_valid_password');

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

  await user.click(screen.getByRole('button', { name: 'submit' }));
  detectChanges(); // <-- Removing this will fail the test

  await waitFor(() => expect(screen.queryByRole('heading', { name: 'Login' })).not.toBeInTheDocument());

  expect(await screen.findByRole('heading', { name: 'Logged In' })).toBeVisible();
});

@Component({ /*...*/ });
class LoginComponent {
  // ...
  constructor(private fb: FormBuilder, private router: Router) {}
  // ...
  onSubmit(_fg: FormGroup): void {
    this.router.navigate(['logged-in']);
  }
}

@Component({
  selector: 'app-logged-in',
  standalone: true,
  template: ` <h1>Logged In</h1> `,
})
class LoggedInComponent {}
@timdeschryver
Copy link
Member

It's better to use waitForElementToBeRemoved in this case.
See #494 for a complete example.

await waitForElementToBeRemoved(() => screen.queryByRole('heading', { name: 'Login' }));

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