history.back not behaving as expected in Karma

When I run a basic test case like this:

  fdescribe('Browser back button', () => {

    fit('should return to previous', async () => {

      const originalHref = window.location.href;
      window.history.pushState({}, 'Test', '/test');
      window.history.back();  // This doesn't seem to be working.
      expect(window.location.href).toEqual(originalHref);
    });

I get a failure with the message “Expected ‘http://localhost:9876/test’ to equal ‘http://localhost:9876/context.html’.” So clearly the pushState() worked but the back() did not.

Karma runs tests in an inner iframe. When I paste the first three lines in order into the browser’s JavaScript console, the navigation works as expected. So there must be something different between the behavior of the window and the behavior of the inner iframe in this case.

This is Karma 5.1 on Chrome.

Any thoughts?

Answer

The issue is that history.back() API is asynchronous

This method is asynchronous. Add a listener for the popstate event in order to determine when the navigation has completed.

So the navigation back is triggered but the test does not wait for it to complete and the check fails.

We need to convert the test into an asynchronous one by adding done param (it’s one method I know, maybe there are other ways too). And use popstate event handler to wait for navigation and complete the test.

fdescribe('Browser back button', () => {
  fit('should return to previous', (done) => {
    const originalHref = window.location.href;
    window.history.pushState({}, 'Test', '/test');

    window.history.back(); // gets executed asynchonously
    window.addEventListener('popstate', () => {
      // history.back() is done now
      expect(window.location.href).toEqual(originalHref);
      done();
    })
  });
});