[Angular] Testando Objetos Nativos do Navegador

tatopetry

Tato Petry

Posted on July 25, 2024

[Angular] Testando Objetos Nativos do Navegador

O Problema

Imagine que você está criando uma aplicação Angular e precisa redirecionar o usuário para um site externo, como o site da banda de grunge americana Pearl Jam. Uma forma comum de fazer isso é manipulando o objeto window. Por exemplo, podemos ter uma função que muda o window.location.href para redirecionar o usuário:

redirectToPearlJam() {
  window.location.href = 'https://pearljam.com';
}
Enter fullscreen mode Exit fullscreen mode

Agora, como a gente testa isso?

Testando a Função de Redirecionamento

Testar código que manipula o objeto window pode ser complicado, pois o window é uma API global do navegador. Mas calma, que tem solução! Aqui vão algumas dicas para fazer isso de uma forma tranquila.

1. Usando Jasmine Spy

A primeira solução é usar os spies do Jasmine para monitorar e interceptar chamadas ao window.location.href. Veja como fazer isso:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { YourComponent } from './your-component';

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

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [YourComponent]
    }).compileComponents();

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

  it('should redirect to Pearl Jam website', () => {
    spyOn(window, 'open');
    component.redirectToPearlJam();
    expect(window.open).toHaveBeenCalledWith('https://pearljam.com');
  });
});
Enter fullscreen mode Exit fullscreen mode

2. Mocking Window Object

Outra forma é criar um mock do objeto window para usar nos testes. Podemos fazer isso injetando o window no componente:

export function windowFactory() {
  return window;
}

@NgModule({
  providers: [
    { provide: 'Window', useFactory: windowFactory }
  ]
})
export class AppModule { }
Enter fullscreen mode Exit fullscreen mode

E no componente, vamos usar o objeto injetado:

import { Inject, Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class YourService {
  constructor(@Inject('Window') private window: Window) {}

  redirectToPearlJam() {
    this.window.location.href = 'https://pearljam.com';
  }
}
Enter fullscreen mode Exit fullscreen mode

No teste, podemos criar um mock do window:

import { TestBed } from '@angular/core/testing';
import { YourService } from './your-service';

describe('YourService', () => {
  let service: YourService;
  let mockWindow: { location: { href: string } };

  beforeEach(() => {
    mockWindow = { location: { href: '' } };

    TestBed.configureTestingModule({
      providers: [
        YourService,
        { provide: 'Window', useValue: mockWindow }
      ]
    });

    service = TestBed.inject(YourService);
  });

  it('should redirect to Pearl Jam website', () => {
    service.redirectToPearlJam();
    expect(mockWindow.location.href).toEqual('https://pearljam.com');
  });
});
Enter fullscreen mode Exit fullscreen mode

3. Atribuindo Mock à Variável do Componente

Outra abordagem é criar uma variável dentro do componente que guarda o objeto window. Nos testes, podemos atribuir um mock a essa variável. Aqui está como fazer isso:

No componente, adicione uma variável para o window:

export class YourComponent {
  private window: Window;

  constructor() {
    this.window = window;
  }

  redirectToPearlJam() {
    this.window.location.href = 'https://pearljam.com';
  }
}
Enter fullscreen mode Exit fullscreen mode

No teste, substituímos a variável window do componente por um mock:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { YourComponent } from './your-component';

describe('YourComponent', () => {
  let component: YourComponent;
  let fixture: ComponentFixture<YourComponent>;
  let mockWindow: { location: { href: string } };

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [YourComponent]
    }).compileComponents();

    fixture = TestBed.createComponent(YourComponent);
    component = fixture.componentInstance;
    mockWindow = { location: { href: '' } };
    component['window'] = mockWindow;  // Atribuímos o mock aqui
    fixture.detectChanges();
  });

  it('should redirect to Pearl Jam website', () => {
    component.redirectToPearlJam();
    expect(mockWindow.location.href).toEqual('https://pearljam.com');
  });
});
Enter fullscreen mode Exit fullscreen mode

Conclusão

Testar código que interage com o objeto window no Angular pode parecer complicado, mas com essas estratégias, fica bem mais fácil. Usar spies do Jasmine, criar um mock do window ou usar uma variável no componente para o objeto window são abordagens eficazes que vão te ajudar a manter seus testes limpos e funcionais.

💖 💪 🙅 🚩
tatopetry
Tato Petry

Posted on July 25, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related