Tran Son Hoang
Estoy implementando una prueba unitaria para un archivo que contiene window.location.href
y necesito comprobarlo.
Mi versión de broma es 22.0.4
. Todo está bien cuando ejecuto mi prueba en la versión del nodo> = 10
Pero me sale este error cuando lo ejecuto v8.9.3
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Not implemented: navigation (except hash changes)
No tengo idea al respecto. He buscado en muchas páginas para encontrar la solución o cualquier pista sobre esto para descubrir qué sucedió aquí.
[UPDATE] – Eché un vistazo profundo al código fuente y creo que este error es de 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)
archivo de navegación.js
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);
};
no implementado.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);
};
Veo algunas lógicas extrañas en estos archivos.
const scriptSource = whatwgURL.percentDecode(Buffer.from(urlString)).toString();
- luego verifique la cadena y devuelva el error
Versión alternativa que funcionó para mí con jest
solo:
let assignMock = jest.fn();
delete window.location;
window.location = { assign: assignMock };
afterEach(() => {
assignMock.mockClear();
});
Referencia:
https://remarkablemark.org/blog/2018/11/17/simulacro-de-ubicacion-de-ventana/
-
solo para agregar a esto, personalmente tuve que incluir todas las claves del objeto window.location para que esto funcionara, asignando todas las funciones a AssignMock y todo lo demás a una cadena, excepto ancestorOrigins, que acabo de configurar en nulo. Esto puede deberse a que mi configuración de eslint se enojó conmigo, por lo que podría no ser necesario para todos. Aparte de eso, ¡esto funcionó para mí en 2021!
– Jabinator1
24 de agosto de 2021 a las 22:38
-
Para mecanografiado:
window.location = ({ assign: assignMock as any }) as Location;
–Logan Cundiff
17 de marzo de 2022 a las 16:11
Akhilesh.tiwari
Solución alternativa: puede burlarse del objeto de ubicación
const mockResponse = jest.fn();
Object.defineProperty(window, 'location', {
value: {
hash: {
endsWith: mockResponse,
includes: mockResponse,
},
assign: mockResponse,
},
writable: true,
});
-
Para reacción iónica usuarios Puede colocar este código en su setupTests.ts expediente.
– oso benny
12 de julio de 2020 a las 16:12
Enfrenté un problema similar en una de mis pruebas unitarias. Esto es lo que hice para resolverlo.
- Reemplazar
window.location.href
conwindow.location.assign(url)
O
window.location.replace(url)
-
JSDOM lo hará todavía quejarse
window.location.assign
no se ha implementado.Error: Not implemented: navigation (except hash changes)
-
Luego, en una de sus pruebas unitarias para el componente / función anterior que contiene
window.assign(url)
owindow.replace(url)
defina lo siguientesinon.stub(window.location, 'assign');
sinon.stub(window.location, 'replace');
- Asegúrate de importar sinon
import sinon from 'sinon';
Con suerte, esto debería solucionar el problema para usted como lo hizo para mí.
La razón por la que JSDOM se queja de la Error: Not implemented: navigation (except hash changes)
es porque JSDOM no implementa métodos como window.alert
, window.location.assign
etc.
Referencias:
-
Sí. Apliqué esta solución reemplazando
href
porassign
y funciona bien– Tran Son Hoang
8 de febrero de 2019 a las 13:22
-
Obtener este error en TypeScript TypeError: el descriptor para la asignación de propiedades no es configurable ni escribible 9 | > 10 | sinon.stub(ventana.ubicación, ‘asignar’); | ^ 11 | sinon.stub(ventana.ubicación, ‘reemplazar’);
–Viraj Singh
2 de febrero de 2022 a las 6:55
Puedes usar broma-ubicación-simulacro paquete para eso
Ejemplo de uso con CRA (create-react-app)
// src/setupTests.ts
import "jest-location-mock";
Encontré una buena referencia que explica y resuelve el problema: https://remarkablemark.org/blog/2018/11/17/simulacro-de-ubicacion-de-ventana/
Debido a que las pruebas se ejecutan en Node, no puede entender window.location, por lo que debemos simular la función:
Ex:
delete window.location;
window.location = { reload: jest.fn() }
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;
});
Afortunado
Lo siguiente funcionó para mí:
const originalHref = window.location.href;
afterEach(() => {
window.history.replaceState({}, "", decodeURIComponent(originalHref));
});
feliz codificación 🙂