Jsdom: jest: SecurityError: localStorage não está disponível para origens opacas

Criado em 27 jul. 2018  ·  80Comentários  ·  Fonte: jsdom/jsdom

Quando executo jest com meus casos de teste. Mostra o seguinte erro quando atualizo o pacote. Em meus casos de teste, nenhum localStorage é usado. Como posso resolver 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

Comentários muito úteis

@gokulkrishh Eu o defini como http://localhost/ mas qualquer URL válido parece funcionar.

Todos 80 comentários

Resumo da discussão abaixo:

  • A correção é definir uma URL para seu jsdom, o que pode precisar ser feito por meio da configuração do ambiente de teste. A URL padrão, de " about: blank ", causará erros ao tentar acessar localStorage.
  • A causa raiz costuma ser o loop de bibliotecas em todas as propriedades jsdom e adicioná-las ao global; mesmo que você nunca use localStorage em seus testes, alguma biblioteca ou estrutura de teste da qual você depende está "usando" dessa maneira. Observe que essa técnica de loop e cópia é explicitamente sem suporte , portanto, não é surpreendente que o código que faz isso possa quebrar em uma versão menor.

Transcrição do comentário abaixo sobre a questão de saber se esta é uma "alteração importante", que desde então foi ocultada pelo recurso "ver mais comentários" do GitHub:

Obrigado, mas no momento não acredito que esse seja o melhor caminho a seguir. Não é uma mudança significativa para jsdom implementar novos recursos de plataforma da web; essa é uma versão secundária.

É possível para dependentes, mesmo dependentes amplamente usados, escrever um código infeliz que detecta novos recursos e lança uma exceção se eles aparecerem. Espero que todos possamos concordar que, mesmo que existam tais dependentes, jsdom não deve desistir para sempre de adicionar novos recursos em versões menores.

A situação aqui não é tão drástica, mas parece ser semelhante. Eu não vi ninguém rastrear o código ofensivo do Jest ainda, então é difícil dizer exatamente, mas parece que eles estão executando uma operação que é explicitamente interrompida pelo curso normal de desenvolvimento do jsdom e que não funcionaria em uma web navegador que implementa localStorage.

Sei que esta é uma situação difícil para aqueles de vocês afetados, não por culpa própria, por uma interação infeliz sobre como sua dependência direta está (ab) usando sua dependência indireta. Mas tenho esperança de que isso possa ser resolvido no nível certo, de consertar o código com bugs do Jest, em vez de remover um recurso útil de todos os usuários do jsdom devido aos bugs de um dependente.

Resposta original ao OP, para contexto:

Parece que você não está definindo uma URL em seus testes, mas você, ou talvez Jest, está acessando window.localStorage . Os mantenedores do Jest podem saber mais sobre a melhor correção, mas ouvi dizer que existe uma maneira de definir URLs em seus testes do Jest.

Este é um problema muito recente que parece ter surgido com 11.12.0 . Eu recebo esses mesmos erros ao usar jest com enzyme .

Sim, comecei a ter o problema depois de fazer upgrade de 11.11.0 para 11.12.0 . Definir testURL na configuração do jest corrige o problema.

@ ben-mckernan Olá, qual é a URL que você forneceu para corrigir isso?

@gokulkrishh Eu o defini como http://localhost/ mas qualquer URL válido parece funcionar.

Eu acho que isso provavelmente é específico da Enzyme, porque Enzyme faz o que o jsdom docs explicitamente avisa para não fazer ? Não é muito surpreendente que tenha quebrado em um pequeno lançamento, infelizmente :(

Isso quebrou para mim também :(

@ ben-mckernan Obrigado 👍

(Os comentários "+1" serão marcados como spam; enviar e-mails para todos no tópico do problema não é útil.)

Desculpas. Apenas tentando ajudar.

Pode confirmar a adição de testURL ao jestConfig como @ ben-mckernan sugeriu que corrigiu.

E estamos usando Enzyme também, se isso ajudar a confirmar sua intuição.

Para o teste de aplicativo de elétrons, apenas defini-o como "arquivo: /", que também funciona.

@miamollie Eu adicionei testURL acordo com a sugestão de @ben-mckernan (usando Jest + Enzyme, não tenho certeza se está relacionado à enzima. Erro vindo de jest-environment-jsdom que usa jsdom). Devido a isso, alguns outros arquivos de teste estão falhando. Apenas para sua informação. Veja se funciona para você. Seus casos de teste podem ser diferentes dos meus (TestURL pode funcionar para você).

@domenic estou apenas usando jest. Portanto, não tenho certeza se é um problema de enzima.

@gokulkrishh Sim, mesmo, ele parou o erro de segurança localStorage, mas fez alguns outros testes falharem.

A solução @ben-mckernan corrigiu o problema. Obrigado!

@ ben-mckernan Estou usando jest em uma configuração angular (com jest-preset-angular), mesmo bug, mesma solução. Portanto, não é um problema de enzima.

Parece que Jest precisa alterar o valor padrão de testURL para que isso seja mitigado (atualmente é about:blank ).

@DcsMarcRemolt Eu estava apenas depurando o problema. Jest está usando um módulo de dependência chamado jest-environment-jsdom em seu package.json -> "jsdom": "^11.5.1" caret (^) por causa disso npm instalou jsdom como 11.12.0 (que é a nova versão publicada hoje). Portanto, quebrou para a maioria dos usuários. O problema já foi criado em jest e vinculado aqui. Cuidado com isso.

Vou reabrir este problema para dar mais visibilidade. Veja o primeiro comentário de Domenic para uma solução.

Adicionando o seguinte à configuração jest em package.json:
"testEnvironment": "node"
resolve o problema para mim.
Agradecemos a @ blu3printchris por ajudar a resolver isso.

Não posso mais substituir e simular a implementação JSDOM em localStorage desde esta atualização.

Uma vez que esta foi uma alteração de interrupção não intencional para muitas pessoas, talvez a melhor opção de controle de danos seja:

  • Reverta esta alteração.
  • Libere a versão 11.12.1 com a alteração revertida para restaurar o comportamento esperado.
  • Puxe ou desative a versão 11.12.0 com um aviso.
  • Se o novo comportamento for desejado no estado em que se encontra, libere 12.0.0 para indicar que há uma alteração significativa.

Obrigado, mas no momento não acredito que esse seja o melhor caminho a seguir. Não é uma mudança significativa para jsdom implementar novos recursos de plataforma da web; essa é uma versão secundária.

É possível para dependentes, mesmo dependentes amplamente usados, escrever um código infeliz que detecta novos recursos e lança uma exceção se eles aparecerem. Espero que todos possamos concordar que, mesmo que existam tais dependentes, jsdom não deve desistir para sempre de adicionar novos recursos em versões menores.

A situação aqui não é tão drástica, mas parece ser semelhante. Eu não vi ninguém rastrear o código ofensivo do Jest ainda, então é difícil dizer exatamente, mas parece que eles estão executando uma operação que é explicitamente interrompida pelo curso normal de desenvolvimento do jsdom e que não funcionaria em uma web navegador que implementa localStorage.

Sei que esta é uma situação difícil para aqueles de vocês afetados, não por culpa própria, por uma interação infeliz sobre como sua dependência direta está (ab) usando sua dependência indireta. Mas tenho esperança de que isso possa ser resolvido no nível certo, de consertar o código com bugs do Jest, em vez de remover um recurso útil de todos os usuários do jsdom devido aos bugs de um dependente.

Obrigado por esclarecer. Eu concordo que se o problema for usar jsdom de uma forma sem suporte, conforme descrito acima, então não é tecnicamente uma violação de sempre e a piada deve lançar um patch.

Minha solução alternativa é usar uma lista negra ao fazer um loop em todas as propriedades


O 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;


Não coloque jsdom globais no Node global

Bem, eu passo por agora. Preciso que os testes sejam executados no jsdom e em navegadores reais. É a abordagem mais simples que consigo pensar, funciona há anos. Não vejo o mesmo potencial nas alternativas sugeridas.
Usar jsdom-global também pode funcionar.

Bem, eu passo por agora. Preciso que os testes sejam executados no jsdom e em navegadores reais.

Se seus testes podem ser executados em "navegadores reais", eles podem ser executados da mesma maneira no jsdom - apenas forneça o mesmo HTML. Ao atribuir ao global, em vez disso, você está introduzindo complexidade e diferenças adicionais em comparação com a forma como executaria o teste em um navegador.

Para sua informação, estou tendo o mesmo problema com Mocha, não Jest, depois de atualizar jsdom para 11.12.0 .

Olá, eu só quero entender por que as mudanças foram introduzidas em primeiro lugar.

Meus casos de uso são simplesmente para declarar uma função para garantir que a escrevi corretamente, é tão simples 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

e, no entanto, o resultado do teste parece ser mensagens de erro de que acabei de fazer um grande aplicativo na biblioteca React with Redux e coisas assim, enquanto a coisa real é simplesmente testar uma função tão simples quanto

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

A propósito, testURL e testEnvironment "hackear" não funcionam para mim. Este é meu package.json:

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

então, minha pergunta é por que tanto trabalho para introduzir mudanças significativas, enquanto às vezes queremos apenas um executor de teste que simplesmente "funcione"

@ khmy2010 Seu código e questões envolvem Jest mais do que jsdom. Eu sugiro que você crie um problema no repositório deles .

Mesma mensagem de erro com o op e quase todos aqui (exceto eu não estou
usando enzima). Se não for relacionado, devo abrir uma questão de brincadeira. Sinto muito por
naquela.

Em 30 de julho de 2018 21:32, "Zirro" [email protected] escreveu:

@ khmy2010 https://github.com/khmy2010 Seu código e perguntas envolvem
Brincadeira mais do que jsdom. Eu sugiro que você crie um problema em seu
repositório https://github.com/facebook/jest .

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/jsdom/jsdom/issues/2304#issuecomment-408864079 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AVrB3uOLy7l4JKbStKWPtGi0oHfAaQbYks5uLwrpgaJpZM4Vi8gP
.

Se você estiver criando sua instância jsdom , poderá passar um url personalizado como um segundo parâmetro:

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

Isso pode ser útil se você estiver usando Enzyme + Mocha @srodrigo

Isso quebrou a infraestrutura existente. Esta deve ser a versão principal 12.0.0 e não a versão secundária 11.12.0. Versões menores não devem quebrar o código existente.

Domenic explica neste comentário (se não aparecer ao clicar no link, role para cima e carregue os comentários ocultos) porque isso não foi visto como uma alteração significativa. O código de pacotes dependentes que fazem coisas que desencorajamos por anos será corrigido por seus mantenedores em breve.

Além da correção acima, tive que adicionar isso à raiz da configuração de teste: --env=jsdom

Adicionando o seguinte ao meu jest.config.js

testURL: 'http://localhost',

resolveu o problema. Obrigado!

(O mantenedor do Jest aqui.) Você acha que faz sentido, da perspectiva do Jest, mudar do padrão about:blank para, por exemplo, localhost ?

Não tenho certeza se sou inteligente o suficiente para expressar minha opinião sobre isso, mas do ponto de vista do desenvolvedor eu diria que localhost faz mais sentido, sobre: ​​em branco é um caso que nunca é realidade. Estamos testando nossos aplicativos que praticamente nunca têm sobre: url em

A equipe do Jest adicionou um valor padrão mais inteligente para testURL : https://github.com/facebook/jest/pull/6792

@SimenB Eu diria que é uma boa ideia.

Recebendo o mesmo erro do OP, mas na minha situação tem causado MUITOS problemas. Bloqueamos as versões dos pacotes que usamos e só podemos alterá-los no início de um ciclo de lançamento. Estamos atualmente no final do ciclo de lançamento, portanto, nossos ambientes de desenvolvedor têm as versões de todos os pacotes e suas dependências há cerca de um mês, mas quando pedimos ao servidor de compilação para criar uma compilação, ele pegou a versão atual de todos pacotes. Portanto, embora todos os testes sejam aprovados localmente, todos eles falham no servidor de compilação.

Usamos a opção "setupTestFrameworkScriptFile" no arquivo de configuração jest para fazer algumas configurações, incluindo polyfills para (entre outras coisas) localStorage e sessionStorage (já que usamos ambos em nosso aplicativo). É basicamente window.localStorage = window.localStorage || { ... } , e o mesmo para sessionStorage, onde ... é um monte de funções simuladas. Agora nada disso está funcionando, mesmo se eu mudar para sempre substituir o padrão ( window.localStorage = { ... } ).

Além disso, temos testes de unidade que testam especificamente para coisas como sessionStorage.getItem sendo chamados, mas depois de definir "testURL" para " http: // localhost ", conforme recomendado acima para resolver os erros de localStorage, todos falham. Mesmo que tenhamos window.sessionStorage.getItem = jest.fn(); , fazer um expect(window.sesssionStorage.getItem).toHaveBeenCalled() subsequente falha ao dizer que não é uma função simulada.

Embora eu concorde que a adição de um recurso é uma alteração secundária da versão, e não uma alteração importante, quando é algo que é uma parte padrão dos navegadores e a nova implementação aparentemente não pode ser substituída ou simulada, essa _é_ uma alteração significativa .

A única solução que encontrei para meu problema é adicionar jsdom ao meu package.json e especificar uma versão 11.11.0. Isso não é o ideal e causará trabalho adicional mais tarde, quando atualizarmos os pacotes novamente, mas pelo menos por enquanto nos desbloqueia.

Se você tiver código, por exemplo, código de simulação, que funciona em navegadores, mas não em jsdom, registre um novo problema seguindo o modelo de problema e podemos investigar. Até onde sei, localStorage in jsdom é exatamente tão mockable quanto em navegadores.

Eu não sugiro que você execute versões diferentes em seu servidor de compilação enquanto seus desenvolvedores estão executando.

"Eu sugiro não executar versões diferentes em seu servidor de compilação enquanto seus desenvolvedores estão executando."

Embora isso pareça bom em teoria, a menos que todo desenvolvedor de pacote pare de usar "^" ao especificar versões de dependência, ou confirmemos as milhares de pastas em nossa pasta node_modules, isso nunca vai acontecer. De uma máquina de desenvolvedor para a próxima, provavelmente haverá pequenas diferenças em algumas das dependências um ou dois níveis abaixo. Tudo o que posso fazer é especificar as versões exatas dos pacotes que são dependências diretas de nosso aplicativo.

Concordo totalmente com @mrobrian sobre "^". A coisa mais louca de todas. O npm deve remover dessa forma para descrever as dependências.

A solução alternativa packge-lock.json e yarn.lock foi interrompida por design. Talvez ajude com as versões, mas depois cria outros problemas com revisão de código e mesclagem e, muitas vezes, você precisa recriar este arquivo por exclusão. Tudo bem se as dependências forem atualizadas raramente, mas nós atualizamos com muita frequência.

Portanto, nosso .npmrc :

save-exact = true
package-lock = false

isso me ajudou a adicionar essas novas linhas ao package.json:

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

Se você estiver usando jsdom, certifique-se de incluir url

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

Os desenvolvedores de brincadeiras gostariam de comentar por que "testEnvironment": "node" agora é necessário para projetos CLI / nó (para evitar o erro localStorage ) quando anteriormente não era necessário? É um bug?

Se isso for intencional, realmente precisa de uma mensagem de erro melhor! Estou recebendo este erro em ambos os meus projetos que usam Jest - dois projetos simples sem navegador com poucas dependências. Eles certamente não usam jsdom / localStorage.

Este não é o lugar certo para fazer perguntas aos desenvolvedores do Jest - jsdom é um projeto separado. Dito isso, os comentários acima já contêm as respostas para suas perguntas.

package.json

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

Funciona para mim.

@ p8ul estava certo, não se esqueça de especificar " http: // localhost " (URL definido por padrão desde Jest 23.5.0, consulte # 6792):

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

O todo funciona para mim.
Nem precisa adicionar:

"testEnvironment": "node"

jest 23.5.0 agora inclui uma correção para isso, portanto, as soluções alternativas não serão mais necessárias:

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

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

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

Foi a única mudança que precisávamos fazer para evitar esse erro.

Estamos usando mocha / enzima. Nenhuma brincadeira incluída em nosso conjunto de testes.

Definir --env node na linha de comando também funciona.

@gokulkrishh Eu o defini como http://localhost/ mas qualquer URL válido parece funcionar.

"location.href" seria bom então. :)

@domenic Eu recomendo atualizar seu comentário no topo para dizer que os mantenedores do Jest corrigiram esse bug na versão 23.5.0: https://github.com/facebook/jest/issues/6766#issuecomment -412516712

Eu comprometo a configuração de testURL para jest-config como http://localhost workes.

adicione a chave no arquivo de configuração e tente novamente "jest": {"testURL": " http: // localhost% 26quot% 3B / },
use ip-port em vez de localhost
Isso pode resolver o problema

Eu encontrei o problema depois de detectar alguns problemas de segurança ao executar npm audit . Depois de corrigi-los usando npm audit fix , encontrei esse problema.

Como isso foi corrigido no Jest há algum tempo, vamos tentar fechá-lo e ver se acabamos com muitas duplicatas ou se as coisas já se acalmaram o suficiente.

"jest": {
"verbose": verdadeiro,
"testURL": " http: // localhost / "
}
Adicione este trecho de código no arquivo package.json.
Funcionou para mim

você também pode adicionar isso ao teste afetado se jsdom não for necessário lá

`` `javascript 1.6
/ **

  • @ jest-environment node
    * /

it ('meu teste', () => {
expect (2 + 2) .toBe (4);
});
`` `

Testei as duas opções:

1) Adicione isso ao topo de um arquivo de teste:

/**
 * @jest-environment node
 */

2) Adicione esta estrofe ao package.json:

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

Ambas as opções funcionaram.

Fiz funcionar adicionando o arquivo package.json:

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

@gokulkrishh Eu defini como http: // localhost / mas qualquer URL válido parece funcionar.

Eu sou um novato Você pode me dizer exatamente onde no Jest.config.js eu defini o testURL?

@haiphu em qualquer lugar em jest.config.js como abaixo

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

// Your other config
}

Eu adicionei o seguinte ao meu package.json e agora funciona bem :)

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

Não sei por que, mas meu erro foi causado por ter diferentes versões de texto datilografado.

Tenho uma configuração mono-repo com espaços de trabalho yarn + lerna. Todos os pacotes tinham typescript@^3.3.3 em seu package.json. Eu adicionei um novo pacote e instalei o último typescript@^3.5.3 . Quando executei testes nos pacotes existentes, recebi este erro.

Se eu mover todos os pacotes para a mesma versão - typescript@^3.3.3 ou typescript@^3.5.3 , o erro desaparece. Eu não tive que mexer com testURL .

@ tylerreece22 @gokulkrishh Funcionou para mim! 😄

Para aqueles que estão se perguntando o que a diretiva de configuração testURL jest faz, consulte https://jestjs.io/docs/en/configuration#testurl -string

Para quem define as opções do jsdom diretamente (ao usar o Mocha, por exemplo). Coloque isso em seu setup.js:

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

Estranhamente .. Não tenho nenhum jsdom sendo usado .. Estou usando o jest para testar alguns pacotes apenas de nó, mas este erro começou a bloquear o CI ao atualizar as versões do jest para o mais recente dentro da faixa de ^11 .. Tenho certeza de que outras pessoas estão tendo problemas semelhantes. nenhuma das alterações recomendadas até agora parecem resolvê-lo

se você não estiver usando jsdom , defina a propriedade de configuração jest testEnvironment como node . (não há necessidade de tocar em testURL )
https://jestjs.io/docs/en/configuration#testenvironment -string

Para quem procura a solução real, é new JSDOM('', { url: 'https://localhost' })

Tente usar isso em seu arquivo package.json

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

Por que definir url não funciona para mim ... estou usando o react-native ... há mais alguma coisa que estou perdendo?

Por que definir url não funciona para mim ... estou usando o react-native ... há mais alguma coisa que estou perdendo?

Tivemos o mesmo problema. Em nosso aplicativo, tínhamos este código

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

Acontece que tivemos que adicionar o URL ao construtor JSDOM

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

Isso resolveu o problema.

Por que definir url não funciona para mim ... estou usando o react-native ... há mais alguma coisa que estou perdendo?

Tivemos o mesmo problema. Em nosso aplicativo, tínhamos este código

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

Acontece que tivemos que adicionar o URL ao construtor JSDOM

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

Isso resolveu o problema.

Isso funcionou para mim, muito obrigado! colocar o url na configuração do jest não parece funcionar com o reagente nativo. colocar o url no construtor de jsdom resolveu o problema.

Atualizar o jest de 22 para 26 corrigiu o problema.

simplesmente use a versão mais recente do gracejo. atualmente estou usando 26.5.0 no ano de 2020 e meu problema está resolvido

Tente usar isso em seu arquivo package.json

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

Esse testURL é o URL padrão, o que significa que não resolve o problema, pelo menos não com Jest 26.x . Eu tive que fazer o que @zuccha fez para contornar isso.

Esta página foi útil?
0 / 5 - 0 avaliações