开玩笑:测试window.location.reload

Jim*_*mmy 15 javascript jestjs

如何编写测试以确保该方法reloadFn确实重新加载了窗口?我找到了这个资源,但不清楚在给定函数中发生窗口重载时编写测试时如何期望窗口重载。谢谢您的帮助!

const reloadFn = () => {
  window.location.reload(true);
}
Run Code Online (Sandbox Code Playgroud)

Sac*_*eph 12

主意

  1. 创建一个副本,然后删除窗口的location属性。
  2. 使用reload模拟的函数设置属性。
  3. 现在在测试完成时将原始值设置回原来的值。

代码:TypeScript 3.x 及以下

const location: Location = window.location;
delete window.location;
window.location = {
    ...location,
    reload: jest.fn()
};

// <code to test>
// <code to test>
// <code to test>

expect(window.location.reload).toHaveBeenCalledTimes(1);
jest.restoreAllMocks();
window.location = location;
Run Code Online (Sandbox Code Playgroud)

代码:打字稿 4+

TypeScript 4 有更严格的检查(这是一件好事),所以除了使用@ts-ignoreor抑制错误之外,我不确定是否有其他方法可以做到这一点@ts-expect-error

警告:抑制 TypeScript 验证可能很危险。

const location: Location = window.location;

// WARNING:
//     @ts-ignore and @ts-expect-error suppress TypeScript validations by ignoring errors.
//     Suppressing TypeScript validations can be dangerous.

// @ts-ignore
delete window.location;

window.location = {
    ...location,
    reload: jest.fn()
};

// <code to test>
// <code to test>
// <code to test>

expect(window.location.reload).toHaveBeenCalledTimes(1);
jest.restoreAllMocks();
window.location = location;
Run Code Online (Sandbox Code Playgroud)

  • 这是我发现的唯一可以与打字稿一起使用的解决方案。做得好。 (2认同)
  • 伙计,这应该是公认的答案,因为 window.location.reload 是只读的且不可配置。好东西!! (2认同)
  • delete window.location 在打字稿中导致错误“‘删除’运算符的操作数必须是可选的”。 (2认同)

小智 8

您还可以将 Murtaza Hussain 的解决方案简化为

  describe('refreshPage', () => {
    const { reload } = window.location;

    beforeAll(() => {
      Object.defineProperty(window, 'location', {
        writable: true,
        value: { reload: jest.fn() },
      });
    });

    afterAll(() => {
      window.location.reload = reload;
    });

    it('reloads the window', () => {
      refreshPage();
      expect(window.location.reload).toHaveBeenCalled();
    });
  });
Run Code Online (Sandbox Code Playgroud)


Mur*_*ain 6

Here’s the solution but refactored for better organization:

describe('test window location\'s reload function', () => {
  const { reload } = window.location;

  beforeAll(() => {
    Object.defineProperty(window.location, 'reload', {
      configurable: true,
    });
    window.location.reload = jest.fn();
  });

  afterAll(() => {
    window.location.reload = reload;
  });

  it('mocks reload function', () => {
    expect(jest.isMockFunction(window.location.reload)).toBe(true);
  });

  it('calls reload function', () => {
    reloadFn(); // as defined above..
    expect(window.location.reload).toHaveBeenCalled();
  });
});
Run Code Online (Sandbox Code Playgroud)

Thanks :)

  • 其中一个版本肯定发生了重大更改,因为这会抛出“TypeError:现在无法分配给对象“[object Location]”的只读属性“reload””。我添加了一个答案,其中包含我发现有效的解决方案(该线程中也有其他好的解决方案)。 (2认同)

Ste*_*age 6

您可以使用sessionStorage为每次重新加载保存一个值。只要浏览器没有关闭,该值将保留在sessionStorage中。页面重新加载时,该值将增加。验证新的重载与此值。通过将reloadFn()粘贴到控制台中进行测试。控制台将显示Reload count:1,并随每次重新加载而增加。

const reloadFn = () => {
  window.location.reload(true);
}

window.onload = function() {
    // get reloadCount from sessionStorage
    reloadCount = sessionStorage.getItem('reloadCount');

    // reloadCount will be null the first page load or a new value for each reload
    if (reloadCount) {
        // increment reloadCount
        reloadCount = parseInt(reloadCount) + 1;
        // save the new value to sessionStorage
        sessionStorage.setItem('reloadCount', reloadCount);
        console.log("Reload count: " + reloadCount);
    } else {
        // if reloadCount was null then set it to 1 and save to sessionStorage
        sessionStorage.setItem('reloadCount', 1);
        console.log("Page was loaded for the first time");
    }
}
Run Code Online (Sandbox Code Playgroud)