Jsdom: jest: SecurityError: localStorage no está disponible para orígenes opacos

Creado en 27 jul. 2018  ·  80Comentarios  ·  Fuente: jsdom/jsdom

Cuando ejecuto un jest con mis casos de prueba. Muestra el siguiente error cuando actualizo el paquete. En mis casos de prueba, no se utiliza localStorage. ¿Como puedo solucionar este problema?

 SecurityError: localStorage is not available for opaque origins

      at Window.get localStorage [as localStorage] (node_modules/jsdom/lib/jsdom/browser/Window.js:257:15)
          at Array.forEach (<anonymous>)


working as intended

Comentario más útil

@gokulkrishh Lo configuré en http://localhost/ pero cualquier URL válida parece funcionar.

Todos 80 comentarios

Resumen de la discusión a continuación:

  • La solución es establecer una URL para su jsdom, lo que podría necesitar hacerse a través de la configuración de su entorno de prueba. La URL predeterminada, de " about: blank ", provocará errores al intentar acceder a localStorage.
  • La causa principal suele ser que las bibliotecas recorran todas las propiedades de jsdom y las agreguen a la global; incluso si nunca usa localStorage en sus pruebas, alguna biblioteca o marco de prueba del que depende lo está "usando" de esta manera. Tenga en cuenta que esta técnica de bucle y copia no se admite explícitamente , por lo que no es sorprendente que el código que lo hace pueda romperse en una versión menor.

Transcripción del comentario a continuación sobre la pregunta de si se trata de un "cambio importante", que desde entonces ha estado oculto por la función "ver más comentarios" de GitHub:

Gracias, pero a partir de este momento no creo que ese sea el mejor camino a seguir. No es un cambio rotundo para jsdom implementar nuevas funciones de plataforma web; esa es una versión menor.

Es posible que los dependientes, incluso los dependientes más utilizados, escriban un código desafortunado que detecte nuevas características y genere una excepción si aparecen. Espero que todos podamos estar de acuerdo en que incluso si existen tales dependientes, jsdom no debería renunciar para siempre a agregar nuevas funciones en versiones menores.

La situación aquí no es tan drástica, pero parece similar. Todavía no he visto a nadie rastrear el código Jest ofensivo, por lo que es difícil decirlo exactamente, pero parece que están realizando una operación que está explícitamente interrumpida por el curso normal del desarrollo de jsdom, y que no funcionaría en una web. navegador que implementa localStorage.

Me doy cuenta de que esta es una situación difícil para aquellos de ustedes afectados, sin culpa suya, por una interacción desafortunada con respecto a cómo su dependencia directa está (ab) usando su dependencia indirecta. Pero tengo la esperanza de que esto se pueda abordar en el nivel correcto, de corregir el código con errores de Jest, en lugar de eliminar una función útil de todos los usuarios de jsdom debido a los errores de un dependiente.

Respuesta original al PO, para contexto:

Parece probable que no esté configurando una URL en sus pruebas, pero usted, o quizás Jest, está accediendo a window.localStorage . Los mantenedores de Jest pueden saber más sobre la mejor solución, pero escuché que hay una forma de establecer URL en sus pruebas de Jest.

Este es un problema muy reciente que parece haber aparecido con 11.12.0 . Recibo estos mismos errores cuando uso jest con enzyme .

Sí, comencé a tener el problema después de actualizar de 11.11.0 a 11.12.0 . La configuración de testURL en la configuración de broma soluciona el problema.

@ ben-mckernan Hola, ¿Cuál es la URL que diste para solucionar este problema?

@gokulkrishh Lo configuré en http://localhost/ pero cualquier URL válida parece funcionar.

Supongo que esto es probablemente específico de Enzyme, porque Enzyme hace lo que los documentos de jsdom advierten explícitamente que no debe hacer . No es demasiado sorprendente que se rompió en un lanzamiento menor, desafortunadamente :(

Esto también se rompió para mí :(

@ ben-mckernan Gracias 👍

(Los comentarios "+1" se marcarán como spam; no es útil enviar un correo electrónico a todos en el hilo del problema).

Disculpas. Sólo trato de ayudar.

Puede confirmar agregar testURL a jestConfig como sugirió @ ben-mckernan que lo solucionó.

Y también estamos usando Enzyme, si eso ayuda a confirmar su intuición.

Para la prueba de la aplicación de electrones, simplemente lo configuré en "archivo: /", que también funciona.

@miamollie Agregué testURL según la sugerencia de @ ben-mckernan (Usando Jest + Enzyme, no estoy seguro de que esté relacionado con la enzima. Error proveniente de jest-environment-jsdom que usa jsdom). Debido a eso, mis otros archivos de prueba están fallando. Solo para tu información. Vea si funciona para usted. Sus casos de prueba pueden ser diferentes a los míos (TestURL podría funcionar para usted).

@domenic Solo estoy usando broma. Así que no estoy seguro de que sea un problema de enzimas.

@gokulkrishh Sí, lo mismo, detuvo el error de seguridad localStorage pero hizo que algunas otras pruebas fallaran.

La solución @ ben-mckernan lo arregló. ¡Gracias!

@ ben-mckernan Estoy usando jest en una configuración angular (con jest-preset-angular), mismo error, misma solución. Entonces no es un problema de enzimas.

Parece que Jest necesita cambiar el valor predeterminado de testURL para que esto se mitigue (actualmente es about:blank ).

@DcsMarcRemolt Estaba depurando el problema. Jest está usando un módulo de dependencia llamado jest-environment-jsdom en su paquete.json -> "jsdom": "^11.5.1" caret (^) debido a que npm ha instalado jsdom como 11.12.0 (que es la nueva versión publicada hoy). Entonces se rompió para la mayoría de los usuarios. El problema ya se creó en broma y está vinculado aquí. Cuidado con eso.

Reabriré este problema para darle más visibilidad. Vea el primer comentario de Domenic para una solución.

Agregando lo siguiente a la configuración de jest en package.json:
"testEnvironment": "node"
me resuelve el problema.
Gracias a

Ya no puedo sobrescribir y simular la implementación de JSDOM en localStorage desde esta actualización.

Dado que este fue un cambio rotundo no intencional para muchas personas, quizás la mejor opción de control de daños sería:

  • Revertir este cambio.
  • Versión de lanzamiento 11.12.1 con el cambio revertido para restaurar el comportamiento esperado.
  • Extraiga o desapruebe la versión 11.12.0 con una advertencia.
  • Si el nuevo comportamiento se desea tal como está, suelte 12.0.0 para indicar que hay un cambio importante.

Gracias, pero a partir de este momento no creo que ese sea el mejor camino a seguir. No es un cambio rotundo para jsdom implementar nuevas funciones de plataforma web; esa es una versión menor.

Es posible que los dependientes, incluso los dependientes más utilizados, escriban un código desafortunado que detecte nuevas características y genere una excepción si aparecen. Espero que todos podamos estar de acuerdo en que incluso si existen tales dependientes, jsdom no debería renunciar para siempre a agregar nuevas funciones en versiones menores.

La situación aquí no es tan drástica, pero parece similar. Todavía no he visto a nadie rastrear el código Jest ofensivo, por lo que es difícil decirlo exactamente, pero parece que están realizando una operación que está explícitamente interrumpida por el curso normal del desarrollo de jsdom, y que no funcionaría en una web. navegador que implementa localStorage.

Me doy cuenta de que esta es una situación difícil para aquellos de ustedes afectados, sin culpa suya, por una interacción desafortunada con respecto a cómo su dependencia directa está (ab) usando su dependencia indirecta. Pero tengo la esperanza de que esto se pueda abordar en el nivel correcto, de corregir el código con errores de Jest, en lugar de eliminar una función útil de todos los usuarios de jsdom debido a los errores de un dependiente.

Gracias por aclararlo. Estoy de acuerdo en que si el problema se debe al uso de jsdom de una manera no admitida como se describe anteriormente, entonces técnicamente no es una violación de semver y jest debería lanzar un parche.

Mi solución es usar una lista negra al recorrer todas jsdom y agregarlas al


El código

const { JSDOM } = require('jsdom');
const Node = require('jsdom/lib/jsdom/living/node-document-position');

// We can use jsdom-global at some point if maintaining these lists is a burden.
const whitelist = ['HTMLElement', 'Performance'];
const blacklist = ['sessionStorage', 'localStorage'];

function createDOM() {
  const dom = new JSDOM('', { pretendToBeVisual: true });
  global.window = dom.window;
  global.Node = Node;
  global.document = dom.window.document;
  // Not yet supported: https://github.com/jsdom/jsdom/issues/317
  global.document.createRange = () => ({
    setStart: () => {},
    setEnd: () => {},
    commonAncestorContainer: {
      nodeName: 'BODY',
      ownerDocument: document,
    },
  });
  global.navigator = {
    userAgent: 'node.js',
  };

  Object.keys(dom.window)
    .filter(key => !blacklist.includes(key))
    .concat(whitelist)
    .forEach(key => {
      if (typeof global[key] === 'undefined') {
        global[key] = dom.window[key];
      }
    });
}

module.exports = createDOM;


No rellene los globales de jsdom en el nodo global

Bueno, paso por ahora. Necesito que las pruebas se ejecuten en jsdom y en navegadores reales. Es el enfoque más simple que se me ocurre, ha funcionado durante años. No veo el mismo potencial en las alternativas sugeridas.
Usar jsdom-global también podría funcionar.

Bueno, paso por ahora. Necesito que las pruebas se ejecuten en jsdom y en navegadores reales.

Si sus pruebas pueden ejecutarse dentro de "navegadores reales", también pueden ejecutarse de la misma manera en jsdom, solo proporcione el mismo HTML. Al asignar a lo global en su lugar, está introduciendo una complejidad y diferencias adicionales en comparación con la forma en que ejecutaría la prueba en un navegador.

Para su información, estoy teniendo el mismo problema con Mocha, no con Jest, después de actualizar jsdom a 11.12.0 .

Hola, solo quiero entender por qué se introducen los cambios en primer lugar.

Mis casos de uso son simplemente afirmar una función para asegurarme de que la escribí correctamente, es tan simple como:

const fib = require('./index');

test('Fib function is defined', () => {
  expect(typeof fib).toEqual('function');
});

test('calculates correct fib value for 1', () => {
  expect(fib(1)).toEqual(1);
});

screenshot 2018-07-30 21 10 39

y, sin embargo, el resultado de la prueba parece ser un mensaje de error de que acabo de hacer una gran aplicación en la biblioteca React with Redux y cosas así, mientras que la realidad es que simplemente pruebo una función tan simple como

//index.js, yes, only one line, no react no redux no enzyme 
function add(a, b) {}

Por cierto, testURL y testEnvironment "hack" no me funcionan. Este es mi package.json:

    "jest": {
        "testURL": "http://localhost/",
        "testEnvironment": "node"
    },

entonces mi pregunta es por qué toda la molestia de introducir cambios importantes, mientras que a veces solo queremos un corredor de prueba que simplemente "funcione"

@ khmy2010 Su código y sus preguntas involucran a Jest más que a jsdom. Te sugiero que crees un problema en su repositorio .

El mismo mensaje de error con el operador y casi todos los que están aquí (excepto que no estoy
usando enzima). Si no está relacionado, debería abrir un problema en broma. Lo siento por
ese.

El 30 de julio de 2018 a las 21:32, "Zirro" [email protected] escribió:

@ khmy2010 https://github.com/khmy2010 Su código y sus preguntas implican
Bromean más de lo que hacen jsdom. Le sugiero que cree un problema en su
repositorio https://github.com/facebook/jest en su lugar.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/jsdom/jsdom/issues/2304#issuecomment-408864079 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AVrB3uOLy7l4JKbStKWPtGi0oHfAaQbYks5uLwrpgaJpZM4Vi8gP
.

Si está creando su instancia jsdom , puede pasar una URL personalizada como segundo parámetro:

const url = 'http://localhost';
const jsdom = new JSDOM('<!doctype html><html><body></body></html>, { url });

Esto podría ser útil si está usando Enzyme + Mocha @srodrigo

Esto rompió la infraestructura existente. Esta debería ser la versión principal 12.0.0 y no la versión secundaria 11.12.0. Las versiones menores no deben romper el código existente.

Domenic explica en este comentario (si no se muestra al hacer clic en el enlace, desplácese hacia arriba y cargue los comentarios ocultos) por qué esto no se vio como un cambio importante. Es de esperar que el código de los paquetes dependientes que hace cosas que hemos desanimado durante años sea arreglado pronto por sus responsables.

Además de la corrección anterior, tuve que agregar esto a la raíz de la configuración de prueba: --env=jsdom

Añadiendo lo siguiente a mi jest.config.js

testURL: 'http://localhost',

resuelve el problema. ¡Gracias!

(Mantenedor de Jest aquí.) ¿Crees que tiene sentido desde la perspectiva de Jest cambiar del valor predeterminado about:blank a, por ejemplo, localhost ?

No estoy seguro de si soy lo suficientemente inteligente como para expresar mi opinión sobre esto, pero desde el punto de vista del desarrollador, diría que localhost tiene más sentido, about: blank es un caso que nunca es una realidad. Estamos probando nuestras aplicaciones que prácticamente nunca tienen sobre: URL en

El equipo de Jest ha agregado un valor predeterminado más inteligente por testURL : https://github.com/facebook/jest/pull/6792

@SimenB Yo diría que es una buena idea.

Obteniendo el mismo error que el OP, pero en mi situación ha estado causando MUCHOS problemas. Bloqueamos las versiones de los paquetes que usamos y solo podemos cambiarlos al comienzo de un ciclo de lanzamiento. Actualmente estamos hacia el final del ciclo de lanzamiento, por lo que nuestros entornos de desarrollador tienen las versiones de todos los paquetes y sus dependencias desde hace aproximadamente un mes, pero cuando hicimos que el servidor de compilación creara una compilación, tomó la versión actual de todos paquetes. Entonces, si bien todas las pruebas pasan localmente, todas fallan en el servidor de compilación.

Usamos la opción "setupTestFrameworkScriptFile" en el archivo de configuración de jest para hacer alguna configuración, incluyendo polyfills para (entre otras cosas) localStorage y sessionStorage (ya que usamos ambos en nuestra aplicación). Básicamente es window.localStorage = window.localStorage || { ... } , y lo mismo para sessionStorage, donde ... es un montón de funciones simuladas. Ahora nada de eso funciona, incluso si lo cambio para anular siempre el valor predeterminado ( window.localStorage = { ... } ).

Además, tenemos pruebas unitarias que prueban específicamente cosas como sessionStorage.getItem se llaman, pero después de configurar "testURL" en " http: // localhost ", como se recomendó anteriormente para resolver los errores de localStorage, todos fallan. Aunque tenemos window.sessionStorage.getItem = jest.fn(); , hacer un expect(window.sesssionStorage.getItem).toHaveBeenCalled() subsiguiente falla diciendo que no es una función simulada.

Si bien estoy de acuerdo en que la adición de una función es un cambio de versión menor, y no un cambio rotundo, cuando es algo que es una parte estándar de los navegadores, y la nueva implementación aparentemente no puede ser anulada o burlada, ese _es_ un cambio rotundo .

La única solución que he encontrado para mi problema es agregar jsdom a mi package.json y especificar una versión de 11.11.0. Esto no es ideal y causará trabajo adicional más adelante cuando actualice los paquetes nuevamente, pero al menos por ahora nos desbloquea.

Si tiene código, por ejemplo, código de burla, que funciona en los navegadores pero no en jsdom, presente un nuevo problema siguiendo la plantilla de problemas y podemos investigar. Que yo sepa, localStorage en jsdom es exactamente tan burlable como en los navegadores.

Le sugiero que no ejecute versiones diferentes en su servidor de compilación mientras sus desarrolladores lo están ejecutando.

"Le sugiero que no ejecute versiones diferentes en su servidor de compilación mientras lo hacen sus desarrolladores".

Si bien eso suena bien en teoría, a menos que todos los desarrolladores de paquetes dejen de usar "^" al especificar versiones de dependencia, o que confirmemos las miles de carpetas en nuestra carpeta node_modules, eso nunca sucederá. De una máquina de desarrollo a la siguiente, es probable que haya ligeras diferencias en algunas de las dependencias de un nivel o dos hacia abajo. Todo lo que puedo hacer es especificar las versiones exactas de los paquetes que son dependencias directas de nuestra aplicación.

Totalmente de acuerdo con @mrobrian sobre "^". La cosa más loca de todas. npm debería eliminar esta forma para describir las dependencias.

La solución de packge-lock.json y yarn.lock está rota por diseño. Tal vez ayude con las versiones, pero luego crea otros problemas con la revisión del código y la combinación y, a menudo, es necesario volver a crear este archivo mediante la eliminación. Está bien si las dependencias se actualizan con poca frecuencia, pero las actualizamos con mucha frecuencia.

Por lo tanto, nuestro .npmrc :

save-exact = true
package-lock = false

me ayudó a agregar estas nuevas líneas al package.json:

"jest": {
    "verbose": true,
    "testURL": "http://localhost/"
  },

Si está utilizando jsdom, asegúrese de incluir url

const dom = new JSDOM (``, {
url: "https://example.org/",
});

¿A los desarrolladores de bromas les gustaría comentar por qué "testEnvironment": "node" ahora se requiere para proyectos CLI / nodo (para evitar el error localStorage ) cuando antes no era necesario? ¿Es un error?

Si esto es de alguna manera por diseño, ¡realmente necesita un mensaje de error mejor! Recibo este error en mis dos proyectos que usan Jest: dos proyectos simples sin navegador con pocas dependencias. Ciertamente no usan jsdom / localStorage.

Este no es el lugar adecuado para hacer preguntas a los desarrolladores de Jest: jsdom es un proyecto separado. Dicho esto, los comentarios anteriores ya contienen las respuestas a sus preguntas.

package.json

   ...
  "jest": {
    "testEnvironment": "node",
    "roots": [
      "test/javascript"
    ]
  },

Esto funciona para mi.

@ p8ul tenía razón, no olvide especificar " http: // localhost " (URL configurada por defecto desde Jest 23.5.0, ver # 6792):

const dom = new JSDOM(``, {
url: "http://localhost",
});

Todo funciona para mí.
Ni siquiera es necesario agregar:

"testEnvironment": "node"

jest 23.5.0 ahora incluye una solución para esto, por lo que las soluciones alternativas ya no deberían ser necesarias:

https://github.com/facebook/jest/issues/6766#issuecomment -412516712

Similar a @ mica16 https://github.com/jsdom/jsdom/issues/2304#issuecomment -412663502

const dom = new JSDOM(``, {
  url: "http://localhost",
});

Fue el único cambio que necesitábamos hacer para evitar este error.

Estamos usando moca / enzima. No se incluye broma en nuestro conjunto de pruebas.

La configuración de --env node en la línea de comando también funciona.

@gokulkrishh Lo configuré en http://localhost/ pero cualquier URL válida parece funcionar.

"location.href" sería bueno entonces. :)

@domenic Recomiendo actualizar su comentario en la parte superior para decir que los mantenedores de Jest arreglaron este error en la versión 23.5.0: https://github.com/facebook/jest/issues/6766#issuecomment -412516712

Me comprometo a configurar testURL para jest-config en http://localhost workes.

agregue la clave en el archivo de configuración y vuelva a intentar "jest": {"testURL": " http: // localhost% 26quot% 3B / },
use ip-port en lugar de localhost
Esto podría resolver el problema

Encontré el problema después de detectar algunos problemas de seguridad al ejecutar npm audit . Después de arreglarlos usando npm audit fix encontré este problema.

Dado que esto se ha solucionado en Jest durante algún tiempo, intentemos cerrarlo y ver si terminamos con muchos duplicados o si las cosas se han calmado lo suficiente.

"broma": {
"verbose": verdadero,
"testURL": " http: // localhost / "
}
Agregue este fragmento de código en el archivo package.json.
Funcionó para mí.

también puede agregar esto a la prueba afectada si no se necesita jsdom allí

`` `javascript 1.6
/ **

  • @ jest-environment nodo
    * /

it ('mi prueba', () => {
esperar (2 + 2) .toBe (4);
});
''

Probé ambas opciones:

1) Agregue esto al principio de un archivo de prueba:

/**
 * @jest-environment node
 */

2) Agregue esta estrofa al package.json:

"jest": {
    "testURL": "http://localhost/"
  }

Ambas opciones funcionaron.

Lo hice funcionar agregando el archivo package.json:

"jest": {
    "verbose": true,
    "testURL": "http://localhost/"
  }

@gokulkrishh Lo configuré en http: // localhost / pero cualquier URL válida parece funcionar.

Soy un novato ¿Puede decirme exactamente en qué lugar de Jest.config.js configuré testURL?

@haiphu En jest.config.js como a continuación

{
"testURL": "http://localhost/"

// Your other config
}

Agregué lo siguiente a mi package.json y ahora funciona bien :)

  "jest": {
    "testURL": "http://localhost/"
  },

No estoy seguro de por qué, pero mi error fue causado por tener diferentes versiones de mecanografiado.

Tengo una configuración de repositorio único con espacios de trabajo de hilo + lerna. Todos los paquetes tenían typescript@^3.3.3 en su package.json. Agregué un nuevo paquete e instalé el último typescript@^3.5.3 . Cuando ejecuté pruebas en los paquetes existentes, recibí este error.

Si muevo todos los paquetes a la misma versión, ya sea typescript@^3.3.3 o typescript@^3.5.3 , el error desaparece. No tuve que jugar con el testURL .

@ tylerreece22 @gokulkrishh ¡ Funcionó para mí! 😄

Para aquellos que se preguntan qué hace la directiva de configuración testURL jest, consulte https://jestjs.io/docs/en/configuration#testurl -string

Para aquellos que configuran las opciones en jsdom directamente (cuando usan Mocha, por ejemplo). Pon esto en tu setup.js:

let jsdom = require('jsdom-global')(
    undefined,
    {
        url: "http://localhost"
    }
);

Extrañamente ... No tengo jsdom en uso ... Estoy usando jest para probar algunos paquetes de solo nodo, pero este error comenzó a bloquear CI al actualizar las versiones de jest a la última dentro del rango ^11 ... Estoy seguro de que otras personas están experimentando problemas similares ... ninguno de los cambios recomendados hasta ahora parece solucionarlo

si no está usando jsdom entonces querrá establecer la propiedad de configuración de jest testEnvironment en node . (no es necesario tocar testURL )
https://jestjs.io/docs/en/configuration#testenvironment -string

Para cualquiera que busque la solución real, es new JSDOM('', { url: 'https://localhost' })

Intente usar esto en su archivo package.json

"broma": {
"verbose": verdadero,
"testURL": " http: // localhost / "
}

¿Por qué la configuración de la URL no me funciona ... estoy usando react-native ... hay algo más que me falta?

¿Por qué la configuración de la URL no me funciona ... estoy usando react-native ... hay algo más que me falta?

Tuvimos el mismo problema. En nuestra aplicación teníamos este código

const { JSDOM } = require('jsdom');
const jsdom = new JSDOM('<!doctype html><html><body></body></html>');

Resulta que tuvimos que agregar la URL al constructor JSDOM

const { JSDOM } = require('jsdom');
const jsdom = new JSDOM('<!doctype html><html><body></body></html>', {
  url: 'http://localhost/',
});

Eso solucionó el problema.

¿Por qué la configuración de la URL no me funciona ... estoy usando react-native ... hay algo más que me falta?

Tuvimos el mismo problema. En nuestra aplicación teníamos este código

const { JSDOM } = require('jsdom');
const jsdom = new JSDOM('<!doctype html><html><body></body></html>');

Resulta que tuvimos que agregar la URL al constructor JSDOM

const { JSDOM } = require('jsdom');
const jsdom = new JSDOM('<!doctype html><html><body></body></html>', {
  url: 'http://localhost/',
});

Eso solucionó el problema.

Esto funcionó para mí, ¡muchas gracias! poner la URL en la configuración de broma no parece funcionar con react-native. poner la URL en el constructor de jsdom hizo el truco.

Actualización de broma de 22 a 26 problema solucionado.

simplemente use la última versión de jest. actualmente estoy usando 26.5.0 en el año 2020 y mi problema está resuelto

Intente usar esto en su archivo package.json

"broma": {
"verbose": verdadero,
"testURL": " http: // localhost / "
}

Ese testURL es la URL predeterminada, lo que significa que no resuelve el problema, al menos no con Jest 26.x . Tuve que hacer lo que hizo @zuccha para

¿Fue útil esta página
0 / 5 - 0 calificaciones