1
resposta

Warning no Jest: "Navigation triggered outside Angular zone"

Oi, pessoal! Estou seguindo o curso de Angular e Jest aqui na Alura e reparei que, ao rodar um teste específico, recebo o seguinte warning no console:

console.warn
      Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?

      45 |     this.livroService.adicionarLivro(novoLivro);
      46 |     this.formulario.reset();
    > 47 |     this.router.navigate(['lista-livros']);
         |                 ^
      48 |   }
      49 | }
      50 |

      at _Console.warn (node_modules/@angular/core/fesm2022/core.mjs:30757:17)
      at _Router.navigateByUrl (node_modules/@angular/router/fesm2022/router.mjs:5513:30)
      at _Router.navigate (node_modules/@angular/router/fesm2022/router.mjs:5552:21)
      at FormularioComponent.adicionarLivro (src/app/paginas/formulario/formulario.component.ts:47:17)       
      at src/app/paginas/formulario/formulario.component.spec.ts:53:15

O teste passa normalmente, e na aplicação a navegação funciona corretamente, mas esse warning aparece no terminal durante a execução do teste.

O método que estou testando é o seguinte:

adicionarLivro() {
    const novoLivro = {
      ...this.formulario.value,
      genero: this.generos.find((g) => g.id === this.formulario.value.genero),
    };

    this.livroService.adicionarLivro(novoLivro);
    this.formulario.reset();
    this.router.navigate(['lista-livros']);
}

E o teste que estou rodando:

it('deveria adicionar um novo livro', () => {
    // Arrange
    const novoLivro = {
      titulo: 'É assim que acaba',
      autoria: 'Colleen Hoover',
      imagem:
        'https://images-na.ssl-images-amazon.com/images/I/51Z4t9bZ7HL._SX331_BO1,204,203,200_.jpg',
      genero: 'romance',
      dataLeitura: '2021-09-15',
      classificacao: 5,
    };

    const adicionarLivroSpy = jest.spyOn(service, 'adicionarLivro');
    const routerSpy = jest.spyOn(component['router'], 'navigate');

    // Act
    component.formulario.setValue(novoLivro);
    component.adicionarLivro();

    // Assert
    expect(adicionarLivroSpy).toHaveBeenCalledWith({
      ...novoLivro,
      genero: component.generos.find((g) => g.id === novoLivro.genero),
    });

    expect(component.formulario.value).toEqual({
      titulo: null,
      autoria: null,
      imagem: null,
      genero: null,
      dataLeitura: null,
      classificacao: null,
    });

    expect(routerSpy).toHaveBeenCalledWith(['lista-livros']);
});

Fiquei com dúvida se esse warning pode impactar algo no futuro ou se posso simplesmente ignorá-lo, já que o teste está passando. Alguém sabe o motivo exato desse aviso aparecer e se há alguma recomendação específica para lidar com isso?

Desde já, obrigado!

1 resposta

Oi, Danilo! Como vai?

Esse warning acontece porque a navegação do Angular está sendo acionada fora da Angular Zone, ou seja, fora do contexto de detecção de mudanças do framework. Isso pode levar a problemas sutis no comportamento da UI, mesmo que o teste passe normalmente.

Para resolver isso, você pode envolver a chamada da navegação dentro do NgZone. No seu código, altere o método adicionarLivro da seguinte forma:

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

export class FormularioComponent {
  
  constructor(private router: Router, private ngZone: NgZone) {}

  adicionarLivro() {
    const novoLivro = {
      ...this.formulario.value,
      genero: this.generos.find((g) => g.id === this.formulario.value.genero),
    };

    this.livroService.adicionarLivro(novoLivro);
    this.formulario.reset();

    // Envolvendo a navegação no NgZone
    this.ngZone.run(() => {
      this.router.navigate(['lista-livros']);
    });
  }
}

O que mudou?

  • Adicionei a injeção de NgZone no construtor do componente.
  • Modifiquei a navegação para ser executada dentro de this.ngZone.run(() => { ... }), garantindo que o Angular detecte corretamente a mudança de estado.

Por que isso acontece?

O Jest simula o comportamento assíncrono do Angular de forma diferente do navegador real, e a navegação pode acabar sendo disparada fora da Angular Zone. O NgZone.run() força a execução dentro do ciclo de detecção de mudanças, evitando esse aviso.

Preciso me preocupar com esse warning?

O teste ainda passa porque a navegação está funcionando, mas é bom corrigir esse detalhe para evitar comportamentos inesperados no futuro, principalmente se houver assincronismo envolvido.

Espero ter ajudado. Conte com o apoio do Fórum na sua jornada. Fico à disposição.

Abraços e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado