Jest.js 如何修复错误:未执行:导航(哈希更改除外)

ibps3vxo  于 2023-04-18  发布在  Jest
关注(0)|答案(7)|浏览(352)

我正在对一个包含window.location.href的文件进行单元测试,我需要检查它。
我的jest版本是22.0.4
但是当我在v8.9.3上运行它时得到这个错误

console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
      Error: Not implemented: navigation (except hash changes)

我不知道这件事。我已经搜索了许多网页,以找出解决方案或任何提示,这要弄清楚这里发生了什么。
[更新] -我深入查看了源代码,我认为这个错误来自jsdom。

at module.exports (webapp/node_modules/jsdom/lib/jsdom/browser/not-implemented.js:9:17)
at navigateFetch (webapp/node_modules/jsdom/lib/jsdom/living/window/navigation.js:74:3)
exports.evaluateJavaScriptURL = (window, urlRecord) => {
  const urlString = whatwgURL.serializeURL(urlRecord);
  const scriptSource = whatwgURL.percentDecode(Buffer.from(urlString)).toString();
  if (window._runScripts === "dangerously") {
    try {
      return window.eval(scriptSource);
    } catch (e) {
      reportException(window, e, urlString);
    }
  }
  return undefined;
};
exports.navigate = (window, newURL, flags) => {
  // This is NOT a spec-compliant implementation of navigation in any way. It implements a few selective steps that
  // are nice for jsdom users, regarding hash changes and JavaScript URLs. Full navigation support is being worked on
  // and will likely require some additional hooks to be implemented.

  const document = idlUtils.implForWrapper(window._document);
  const currentURL = document._URL;

  if (!flags.reloadTriggered && urlEquals(currentURL, newURL, { excludeFragments: true })) {
    if (newURL.fragment !== currentURL.fragment) {
      navigateToFragment(window, newURL, flags);
    }
    return;
  }

  // NOT IMPLEMENTED: Prompt to unload the active document of browsingContext.

  // NOT IMPLEMENTED: form submission algorithm
  // const navigationType = 'other';

  // NOT IMPLEMENTED: if resource is a response...
  if (newURL.scheme === "javascript") {
    window.setTimeout(() => {
      const result = exports.evaluateJavaScriptURL(window, newURL);
      if (typeof result === "string") {
        notImplemented("string results from 'javascript:' URLs", window);
      }
    }, 0);
    return;
  }
  navigateFetch(window);
};

not-implemented.js

module.exports = function (nameForErrorMessage, window) {
  if (!window) {
    // Do nothing for window-less documents.
    return;
  }

  const error = new Error(`Not implemented: ${nameForErrorMessage}`);
  error.type = "not implemented";

  window._virtualConsole.emit("jsdomError", error);
};

我在这些文件里看到了一些奇怪的逻辑。

  1. const scriptSource = whatwgURL.percentDecode(Buffer.from(urlString)).toString();
    1.然后检查字符串并返回错误
ctzwtxfj

ctzwtxfj1#

另一个版本只适用于jest

let assignMock = jest.fn();

delete window.location;
window.location = { assign: assignMock };

afterEach(() => {
  assignMock.mockClear();
});

参考:https://remarkablemark.org/blog/2018/11/17/mock-window-location/

v2g6jxz6

v2g6jxz62#

替代解决方案:您可以模拟location对象

const mockResponse = jest.fn();
Object.defineProperty(window, 'location', {
  value: {
    hash: {
      endsWith: mockResponse,
      includes: mockResponse,
    },
    assign: mockResponse,
  },
  writable: true,
});
i1icjdpr

i1icjdpr3#

我在一个单元测试中遇到过类似的问题。

  • window.location.href替换为window.location.assign(url)window.location.replace(url)
  • JSDOM将仍然抱怨window.location.assign未实现。

Error: Not implemented: navigation (except hash changes)

  • 然后,在上述包含window.assign(url)window.replace(url)的组件/函数的一个单元测试中,定义以下内容
  • sinon.stub(window.location, 'assign');
  • sinon.stub(window.location, 'replace');
  • 确保导入Sinon import sinon from 'sinon';

希望,这应该为你解决这个问题,就像它为我做的那样。
JSDOM抱怨Error的原因:未执行:navigation(except hash changes)是因为JSDOM没有实现window.alertwindow.location.assign等方法。
参考文献:

  • https://www.npmjs.com/package/jsdom#virtual-consoles
brccelvz

brccelvz4#

您可以使用jest-location-mock包来实现此功能
CRA(create-react-app)的使用示例

// src/setupTests.ts
import "jest-location-mock";
rryofs0p

rryofs0p5#

我发现了一个很好的参考,解释和解决问题:https://remarkablemark.org/blog/2018/11/17/mock-window-location/
因为测试是在Node下运行的,所以它不能理解window.location,所以我们需要模拟这个函数:
例如:

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

yhqotfr86#

以下为我工作:

const originalHref = window.location.href;
  afterEach(() => {
    window.history.replaceState({}, "", decodeURIComponent(originalHref));
  });

happy coding:)

u0sqgete

u0sqgete7#

it('test', () => {
    const { open } = window;
    delete window.open;
    window.open = jest.fn();
    jest.spyOn(window, 'open');
    // then call the function that's calling the window
    expect(window.open).toHaveBeenCalled();
    window.open = open;
  });

相关问题