DEV Community

Cover image for [Angular] Probando Objetos Nativos del Navegador
Tato Petry
Tato Petry

Posted on

[Angular] Probando Objetos Nativos del Navegador

El Problema

Imaginá que estás creando una aplicación Angular y necesitás redireccionar al usuario a un sitio externo, como el sitio de la banda de grunge estadounidense Pearl Jam. Una forma común de hacer esto es manipulando el objeto window. Por ejemplo, podemos tener una función que cambia el window.location.href para redireccionar al usuario:

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

Ahora, ¿cómo probamos esto?

Probando la Función de Redireccionamiento

Probar código que manipula el objeto window puede ser complicado, ya que window es una API global del navegador. Pero tranquilo, ¡que hay solución! Aquí van algunos tips para hacerlo de una forma sencilla.

1. Usando Jasmine Spy

La primera solución es usar los spies de Jasmine para monitorear e interceptar llamadas a window.location.href. Veamos cómo hacer esto:

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

Otra forma es crear un mock del objeto window para usar en las pruebas. Podemos hacer esto inyectando window en el componente:

export function windowFactory() {
  return window;
}

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

Y en el componente, vamos a usar el objeto inyectado:

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

En la prueba, podemos crear un mock de 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. Asignando Mock a la Variable del Componente

Otra estrategia es crear una variable dentro del componente que guarda el objeto window. En las pruebas, podemos asignar un mock a esta variable. Así es como se hace:

En el componente, agregá una variable para 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

En la prueba, sustituimos la variable window del componente por un 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;  // Asignamos el mock aquí
    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

Conclusión

Probar código que interactúa con el objeto window en Angular puede parecer complicado, pero con estas estrategias, se vuelve mucho más fácil. Usar spies de Jasmine, crear un mock de window o usar una variable en el componente para el objeto window son enfoques eficaces que te ayudarán a mantener tus pruebas limpias y funcionales.

Top comments (0)