So beheben Sie den Fehler: Nicht implementiert: Navigation (außer Hash-Änderungen)

Lesezeit: 4 Minuten

Benutzeravatar von Tran Son Hoang
Tran Son Hoang

Ich implementiere einen Komponententest für eine Datei, die enthält window.location.href und ich muss es überprüfen.

Meine Scherzversion ist 22.0.4. Alles ist in Ordnung, wenn ich meinen Test auf Knotenversion>=10 ausführe

Aber ich bekomme diesen Fehler, wenn ich es ausführe v8.9.3

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

Ich habe keine Ahnung davon. Ich habe auf vielen Seiten gesucht, um die Lösung oder einen Hinweis darauf zu finden, um herauszufinden, was hier passiert ist.

[UPDATE] – Ich habe mir den Quellcode genau angesehen und denke, dass dieser Fehler von jsdom stammt.

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)

navigation.js-Datei

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);
};

nicht implementiert.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);
};

Ich sehe einige seltsame Logiken in dieser Datei.

  1. const scriptSource = whatwgURL.percentDecode(Buffer.from(urlString)).toString();
  2. dann String prüfen und Fehler zurückgeben

Alternative Version, die bei mir funktioniert hat jest nur:

let assignMock = jest.fn();

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

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

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

  • Um das noch hinzuzufügen, musste ich persönlich alle Schlüssel des window.location-Objekts einschließen, damit dies funktionierte, und alle Funktionen von assignMock und alles andere einer Zeichenfolge zuweisen, mit Ausnahme von ancestorOrigins, auf die ich gerade gesetzt habe Null. Dies kann daran liegen, dass meine Eslint-Einstellungen sauer auf mich werden, daher ist dies möglicherweise nicht für alle erforderlich. Abgesehen davon hat dies 2021 für mich funktioniert!

    – Jabinator1

    24. August 2021 um 22:38 Uhr

  • Für Typoskript: window.location = ({ assign: assignMock as any }) as Location;

    – Logan Cundiff

    17. März 2022 um 16:11 Uhr


Benutzeravatar von Akhilesh.tiwari
Akhilesh.tiwari

Alternative Lösung: Sie könnten das Standortobjekt verspotten

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

  • Für Ionische Reaktion Benutzer. Sie können diesen Code in Ihre einfügen setupTests.ts Datei.

    – Bennybär

    12. Juli 2020 um 16:12 Uhr

Ich hatte ein ähnliches Problem in einem meiner Unit-Tests. Hier ist, was ich getan habe, um es zu lösen.

  • Ersetzen window.location.href mit window.location.assign(url) ODER
    window.location.replace(url)

  • JSDOM wird still beschweren über window.location.assign nicht implementiert.

    Error: Not implemented: navigation (except hash changes)

  • Dann in einem Ihrer Unit-Tests für die oben genannte Komponente / Funktion enthalten window.assign(url) oder window.replace(url) definiere folgendes

    • sinon.stub(window.location, 'assign');
    • sinon.stub(window.location, 'replace');
    • Stellen Sie sicher, dass Sie sinon importieren import sinon from 'sinon';

Hoffentlich sollte dies das Problem für Sie beheben, wie es für mich getan hat.

Der Grund, warum sich JSDOM über die beschwert Error: Not implemented: navigation (except hash changes) liegt daran, dass JSDOM keine Methoden wie implementiert window.alert, window.location.assignetc.

Verweise:

  • Ja. Ich habe diese Lösung durch Ersetzen angewendet href von assign und es funktioniert gut.

    – Tran Son Hoang

    8. Februar 2019 um 13:22 Uhr

  • Diesen Fehler in Typoskript erhalten TypeError: Descriptor for Property Assign is non-configurable and non-writable 9 | > 10 | sinon.stub (window.location, ‘assign’); | ^ 11 | sinon.stub (window.location, ‘replace’);

    – Viraj Singh

    2. Februar 2022 um 6:55 Uhr

Sie können verwenden Scherz-Location-Mock Paket dazu

Anwendungsbeispiel mit CRA (create-react-app)

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

Ich habe eine gute Referenz gefunden, die das Problem erklärt und löst: https://remarkablemark.org/blog/2018/11/17/mock-window-location/

Da die Tests unter Node ausgeführt werden, kann es window.location nicht verstehen, also müssen wir die Funktion verspotten:

Ex:

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

Benutzeravatar von Majid Eltayeb
Majid Eltayeb

 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;
  });

Benutzeravatar von Luckylooke
Luckylooke

Folgendes hat bei mir funktioniert:

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

Viel Spaß beim Codieren 🙂

1438460cookie-checkSo beheben Sie den Fehler: Nicht implementiert: Navigation (außer Hash-Änderungen)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy