How to unit test window.location.reload in angular 12 unit testing?
Asked Answered
H

4

6

In my angular project, I have a function

reloadPage(): void {
  window.location.reload();
}

So when ever I need to reload the page, I used to call this function.

Now I am trying to add the unit testing for this function but it is not working.

it("reloadPage: should be validated", () => {
    spyOn(window.location, 'reload').and.callFake(() => {
      //test
    });
    component.reloadPage();
});

It still reloads the page on unit testing

How can I achieve a unit test for this function? Any help could be appreciated. Thanks in advance

Hellen answered 1/8, 2021 at 6:24 Comment(1)
just as an idea, not sure if it would work - may reassign the reload method with a spy? window.location.reload = jasmine.spy(). Don't forget to restore the reload method after the test runLuanneluanni
E
4

I found the following solution to work.

In your component, inject the window with an InjectionToken.

const MY_WINDOW_TOKEN = new InjectionToken<Window>('Window');

The constructor of your component then takes:

constructor(@Inject(MY_WINDOW_TOKEN) private window: Window) { ... }

In your module provide:

{ provide: MY_WINDOW_TOKEN, useValue: window }

In your test (spec) instead inject another (mock) window, by providing the mock / spy implementation in the TestBed configuration:

{ 
  provide: MY_WINDOW_TOKEN, 
  useFactory: () => {
    return jasmine.createSpyObj('Window', [...]);
  }
}

It basically comes down to isolating your subject of test from it's dependencies.

(Notice: all code is written from memory, and may need some modifications to actually work / compile)

Erastian answered 1/8, 2021 at 8:42 Comment(1)
this was super helpful, thanks... i was running into karma-coverage issues because window.location.reload causes the tests to fail with something like "your tests did a page reload!"Gibbon
S
4

You have to provide mock Window object in your TestBed.configureTestingModule

First create a window token

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

export const WINDOW = new InjectionToken('Window');

Create a mock object

windowMock = {
location: {
reload: jasmine.createSpy('reload')
 }
}

And then in providers

{provide: WINDOW, useValue: windowMock}
Shardashare answered 1/8, 2021 at 9:1 Comment(2)
Results in Cannot find name 'WINDOW'. Did you mean 'Window'?Liquidate
You have to create a window token before.Shardashare
S
1

I found a nice solution using an angular internal function with Location.

constructor(
    ...
    private location: Location
) {}

And use

this.location.historyGo(0);

To reload the page. In this way you will not have problems with the tests

Semiautomatic answered 23/11, 2022 at 16:53 Comment(0)
C
-1

There's no easy way to test if location.reload() has been called or not. It's not worth the headache either (also you should not refresh the page, this is a hack, and it's valuable on very rare occasions, like if you are playing with environment stuff on runtime)...

So to be able to test any logic for onEvent function instead (which is needed), and to skip any error derived by refreshing the page (which we are going to hide), you might have a component like this:

@Component({
  ...
})
export class SomethingComponent {
  ...

  onEvent = () => {
    ... some logic to test
    this.reloadPage();
  }

  private reloadPage = () => location.reload();
}

then the test will looking like this:

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

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

  beforeEach(() => {
    fixture = TestBed.createComponent(SomethingComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should do something onEvent', () => {
    // hack to change a private attribute of your component
    // strongly suggest not to use this as a routine
    component[ 'reloadPage' ] = () => null;

    component.onEvent();

    ... some tests here ...

    // do not test expect(location.reload).toHasBeenCalled()
    // it won't work and it's not worth make this working
  });
});

This will avoid the error on the refresh page and you'll be able to actually check any logic in your onEvent function.

Communication answered 10/3, 2022 at 9:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.