Jsdom: jest:SecurityError:localStorageは不透明なオリジンには使用できません

作成日 2018年07月27日  ·  80コメント  ·  ソース: jsdom/jsdom

テストケースでjestを実行すると。 パッケージをアップグレードすると、次のエラーが表示されます。 私のテストケースでは、localStorageは使用されていません。 この問題を解決するにはどうすればよいですか?

 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

最も参考になるコメント

@gokulkrishh http://localhost/に設定しましたが、有効なURLはすべて機能しているようです。

全てのコメント80件

以下の議論の要約:

  • 修正は、jsdomのURLを設定することです。これは、テスト環境の構成を通じて行う必要がある場合があります。 デフォルトのURLである「 about:blank 」は、localStorageにアクセスしようとしたときにエラーを引き起こします。
  • 根本的な原因は、多くの場合、ライブラリがすべてのjsdomプロパティをループし、それらをグローバルに追加することです。 テストでlocalStorageを使用したことがない場合でも、依存しているライブラリまたはテストフレームワークの中には、この方法でlocalStorageを「使用」しているものがあります。 このループとコピーの手法は明示的にサポートされていないため、マイナーリリースでそれを実行するコードが破損する可能性があることは驚くべきことではありません。

これが「重大な変更」であるかどうかについての以下のコメントの転写は、GitHubの「コメントをもっと見る」機能によって隠されています。

ありがとう、でも現時点では、それが最善の道だとは思いません。 jsdomが新しいWebプラットフォーム機能を実装することは重大な変更ではありません。 それはマイナーバージョンです。

扶養家族は、広く使用されている扶養家族でさえ、新しい機能を検出し、それらが出現した場合に例外をスローする不幸なコードを書く可能性があります。 そのような扶養家族が存在する場合でも、jsdomがマイナーリリースでの新機能の追加を永遠に諦めるべきではないことに私たち全員が同意できることを願っています。

ここでの状況はそれほど劇的ではありませんが、似ているようです。 問題のあるJestコードを追跡している人はまだいないので、正確に言うのは難しいですが、通常のjsdom開発の過程で明示的に中断され、Webでは機能しない操作を実行しているようです。 localStorageを実装するブラウザ。

これは、あなた自身の過失ではなく、あなたの直接的な依存関係があなたの間接的な依存関係をどのように(ab)使用しているかに関する不幸な相互作用によって影響を受けたあなたたちにとって難しい状況であることを理解しています。 しかし、1人の扶養家族のバグのために、すべてのjsdomユーザーから便利な機能を削除するのではなく、Jestのバグのあるコードを修正するという適切なレベルでこれに対処できることを願っています。

コンテキストのためのOPへの元の返信:

テストでURLを設定していないようですが、あなた、またはおそらくJestがwindow.localStorageアクセスしています。 Jestのメンテナは最善の修正についてもっと知っているかもしれませんが、JestテストでURLを設定する方法があると聞きました。

これはごく最近の問題で、 11.12.0です。 enzyme jestを使用すると、同じエラーが発生します。

はい、 11.11.0から11.12.0にアップグレードした後、問題が発生し始めました。 jest構成でtestURLを設定すると、問題が修正されます。

@ ben-mckernanこんにちは、これを修正するために指定したURLは何ですか?

@gokulkrishh http://localhost/に設定しましたが、有効なURLはすべて機能しているようです。

酵素はjsdomドキュメントが明示的に警告しないことを行うので、これはおそらく酵素固有だ

これは私にとっても壊れました:(

@ ben-mckernanありがとう👍

(「+1」コメントはスパムとしてマークされます。問題スレッドの全員に電子メールを送信することは役に立ちません。)

謝罪。 助けようとしているだけです。

@ ben-mckernanが修正したと提案したように、jestConfigにtestURLを追加することを確認できます。

そして、それがあなたの直感を確認するのに役立つなら、私たちは酵素も使用しています。

電子アプリのテストでは、「file:/」に設定するだけです。これも機能します。

@miamollie @ ben-mckernanの提案に従ってtestURLを追加しました(Jest + Enzymeを使用していますが、酵素が関連しているかどうかはわかりません。jsdomを使用するjest-environment-jsdomからエラーが発生します)。 そのため、他のいくつかのテストファイルが失敗しています。 参考までに。 それがあなたのために働くかどうか見てください。 あなたのテストケースは私のものとは異なるかもしれません(TestURLはあなたのために働くかもしれません)。

@domenic私は冗談だけを使っています。 ですから、それが酵素の問題かどうかはわかりません。

@gokulkrishhええ、同じ

@ ben-mckernanソリューションはそれを修正しました。 ありがとう!

@ ben-mckernan私は角度設定(jest-preset-angularを使用)でjestを使用していますが、同じバグ、同じ解決策です。 したがって、それは酵素の問題ではありません。

これを軽減するには、Jestがデフォルト値のtestURLを変更する必要があるようです(現在はabout:blank )。

@DcsMarcRemolt問題をデバッグしていました。 Jestは、package.jsonでjest-environment-jsdomという依存関係モジュールを使用しています-> "jsdom": "^11.5.1"キャレット(^)このnpmがjsdomを11.12.0としてインストールしたため(これは本日公開された新しいバージョンです)。 それで、それはほとんどのユーザーにとって壊れました。 問題はすでにjestで作成され、ここにリンクされています。 気をつけて。

視認性を高めるために、この号を再度開きます。 解決策については、Domenicから

package.jsonのjest構成に以下を追加します。
"testEnvironment": "node"
私のために問題を解決します。
これを解決するのを手伝ってくれた@ blu3printchrisの功績。

この更新以降、localStorageのJSDOM実装を上書きしてモックすることはできなくなりました。

これは多くの人にとって意図しない重大な変更であったため、おそらく最良のダメージコントロールオプションは次のようになります。

  • この変更を元に戻します。
  • バージョン11.12.1をリリースし、変更を元に戻して、期待される動作を復元します。
  • 警告付きでバージョン11.12.0をプルまたは非推奨にします。
  • 新しい動作がそのまま必要な場合は、 12.0.0をリリースして、重大な変更があることを示します。

ありがとう、でも現時点では、それが最善の道だとは思いません。 jsdomが新しいWebプラットフォーム機能を実装することは重大な変更ではありません。 それはマイナーバージョンです。

扶養家族は、広く使用されている扶養家族でさえ、新しい機能を検出し、それらが出現した場合に例外をスローする不幸なコードを書く可能性があります。 そのような扶養家族が存在する場合でも、jsdomがマイナーリリースでの新機能の追加を永遠に諦めるべきではないことに私たち全員が同意できることを願っています。

ここでの状況はそれほど劇的ではありませんが、似ているようです。 問題のあるJestコードを追跡している人はまだいないので、正確に言うのは難しいですが、通常のjsdom開発の過程で明示的に中断され、Webでは機能しない操作を実行しているようです。 localStorageを実装するブラウザ。

これは、あなた自身の過失ではなく、あなたの直接的な依存関係があなたの間接的な依存関係をどのように(ab)使用しているかに関する不幸な相互作用によって影響を受けたあなたたちにとって難しい状況であることを理解しています。 しかし、1人の扶養家族のバグのために、すべてのjsdomユーザーから便利な機能を削除するのではなく、Jestのバグのあるコードを修正するという適切なレベルでこれに対処できることを願っています。

明確にしていただきありがとうございます。 上記のようにサポートされていない方法でjsdomを使用したことが問題である場合、技術的にはsemver違反ではなく、jestがパッチをリリースする必要があることに同意します。

私の回避策は、すべてのjsdomプロパティをループしてグローバルに追加するときに、ブラックリストを使用することです。


コード

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;


jsdomグローバルをノードグローバルに詰め込まないでください

さて、とりあえず合格です。 jsdomと実際のブラウザでテストを実行する必要があります。 それは私が考えることができる最も単純なアプローチであり、何年もの間機能してきました。 提案された代替案に同じ可能性は見られません。
jsdom-globalを使用しても

さて、とりあえず合格です。 jsdomと実際のブラウザでテストを実行する必要があります。

テストを「実際のブラウザ」内で実行できる場合は、jsdomでも同じように実行できます。同じHTMLを提供するだけです。 代わりにグローバルに割り当てることで、ブラウザーでテストを実行する方法と比較して、さらに複雑で違いが生じます。

参考までに、 jsdom11.12.0にアップグレードした後、JestではなくMochaで同じ問題が発生しています。

こんにちは、そもそもなぜ変更が導入されたのかを理解したいだけです。

私のユースケースは、関数をアサートして正しく記述したことを確認することです。これは次のように簡単です。

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

それでも、テスト結果は、React with Reduxライブラリなどで大きなアプリケーションを実行したというエラーメッセージのように見えますが、実際には、次のような単純な関数をテストするだけです。

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

ちなみに、 testURLtestEnvironment 「ハック」は私にはうまくいきません。 これは私のpackage.jsonです:

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

だから私の質問は、時々私たちがただ「動作する」テストランナーが欲しいのに、なぜ壊れるような変更を導入するのに面倒なのかということです

@ khmy2010あなたのコードと質問は、jsdomよりもJestに関係しています。 代わりに、リポジトリに問題を作成することをお勧めします。

オペレーションとここにいるほとんどすべての人と同じエラーメッセージ(私がいない場合を除く)
酵素を使用)。 関連がない場合は、冗談で問題を開く必要があります。 申し訳ありません
それ。

2018年7月30日21:32、「Zirro」 [email protected]は次のように書いています。

@ khmy2010https ://github.com/khmy2010あなたのコードと質問には以下が含まれます
彼らがjsdomをするよりももっと冗談を言う。 私はあなたが彼らに問題を作成することをお勧めします
代わりにリポジトリhttps://github.com/facebook/jest


あなたが言及されたのであなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/jsdom/jsdom/issues/2304#issuecomment-408864079 、またはミュート
スレッド
https://github.com/notifications/unsubscribe-auth/AVrB3uOLy7l4JKbStKWPtGi0oHfAaQbYks5uLwrpgaJpZM4Vi8gP

jsdomインスタンスを作成している場合は、2番目のパラメーターとしてカスタムURLを渡すことができます。

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

これは、Enzyme + Mocha @ srodrigoを使用している場合に役立つ可能性があります

これは既存のインフラストラクチャを壊しました。 これはメジャーリリース12.0.0であり、マイナーリリース11.12.0ではありません。 マイナーリリースは既存のコードを壊してはなりません。

Domenicはこのコメントで(リンクをクリックしても表示されない場合は、上にスクロールして非表示のコメントをロードします)、これが重大な変更と見なされなかった理由を説明しています。 何年にもわたって私たちが思いとどまらせてきたことを実行する依存パッケージのコードは、メンテナによってすぐに修正されることを願っています。

上記の修正に加えて、これをテスト構成のルートに追加する必要がありました: --env=jsdom

私のjest.config.jsに以下を追加します

testURL: 'http://localhost',

問題を解決しました。 ありがとう!

(ここではJestのメンテナです。)Jestの観点から、デフォルトのabout:blankからたとえばlocalhostに変更するのは理にかなっていると思いますか?

私がこれについて意見を述べるのに十分賢いかどうかはわかりませんが、開発者の観点からは、localhostの方が理にかなっていると思います。about :blankは決して現実ではないケースです。 私たちは事実上決して持っていないアプリをテストしています:空白のURL

Jestチームは、 testURLよりスマートなデフォルト値を追加しました: https

@SimenBそれはいい考えだと思います。

OPと同じエラーが発生しますが、私の状況では多くの問題が発生しています。 使用するパッケージのバージョンをロックダウンし、リリースサイクルの開始時にのみ変更できます。 現在、リリースサイクルの終わりに近づいているため、開発者環境には約1か月前の時点ですべてのパッケージのバージョンとその依存関係がありますが、ビルドサーバーにビルドを作成させると、すべての現在のバージョンが取得されます。パッケージ。 したがって、すべてのテストはローカルで合格しますが、ビルドサーバーではすべて失敗します。

jest構成ファイルの「setupTestFrameworkScriptFile」オプションを使用して、localStorageとsessionStorageのポリフィルを含むいくつかのセットアップを実行します(アプリで両方を使用しているため)。 これは基本的にwindow.localStorage = window.localStorage || { ... }であり、sessionStorageでも同じです。 ...はモック関数の集まりです。 常にデフォルト( window.localStorage = { ... } )を上書きするように変更しても、これは機能しません。

さらに、 sessionStorage.getItem呼び出しなどを具体的にテストする単体テストがありますが、localStorageエラーを解決するために上記で推奨されているように、「testURL」を「 http:// localhost 」に設定すると、すべて失敗します。 window.sessionStorage.getItem = jest.fn();ありますが、後続のexpect(window.sesssionStorage.getItem).toHaveBeenCalled()と、モック関数ではないと言って失敗します。

機能の追加はマイナーなバージョン変更であり、重大な変更ではないことに同意しますが、それがブラウザの標準部分であり、新しい実装をオーバーライドまたはモックできないように見える場合、それは重大な変更です。 。

私が自分の問題に対して見つけた唯一の解決策は、パッケージ.jsonにjsdomを追加し、11.11.0のバージョンを指定することです。 これは理想的ではなく、後でパッケージを再度アップグレードするときに追加の作業が発生しますが、少なくとも今のところ、ブロックが解除されます。

ブラウザでは機能するがjsdomでは機能しないモックコードなどのコードがある場合は、問題テンプレートに従って新しい問題を提出してください。調査できます。 私の知る限り、jsdomのlocalStorageは、ブラウザの場合とまったく同じようにモック可能です。

開発者が実行しているため、ビルドサーバーで異なるバージョンを実行しないことをお勧めします。

「開発者が実行しているので、ビルドサーバーで異なるバージョンを実行しないことをお勧めします。」

理論的にはそれは良いことのように聞こえますが、すべてのパッケージ開発者が依存関係のバージョンを指定するときに「^」の使用をやめるか、node_modulesフォルダー内の何千ものフォルダーをコミットしない限り、それは起こりません。 ある開発者のマシンから次のマシンへと、1つまたは2つのレベル下の依存関係のいくつかにわずかな違いがある可能性があります。 私にできることは、アプリケーションの直接の依存関係であるパッケージの正確なバージョンを指定することだけです。

「^」について@mrobrianに完全に同意します。 これまでで最もクレイジーなこと。 npmは、依存関係を記述するためにこの方法を削除する必要があります。

packge-lock.jsonyarn.lockを使用した@domenicの回避策は、設計上壊れています。 バージョンには役立つかもしれませんが、コードレビューとマージで別の問題が発生し、多くの場合、削除してこのファイルを再作成する必要があります。 依存関係がめったに更新されなくても問題ありませんが、頻繁に更新されます。

したがって、私たちの.npmrc

save-exact = true
package-lock = false

この新しい行をpackage.jsonに追加するのに役立ちました。

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

jsdomを使用している場合は、必ずURLを含めてください

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

冗談の開発者は、以前は必要なかったのに、CLI /ノードプロジェクトに"testEnvironment": "node"が必要になった理由( localStorageエラーを回避するため)についてコメントしたいと思いますか? バグですか?

これがどういうわけか設計によるものである場合、それは本当により良いエラーメッセージを必要とします! Jestを使用する両方のプロジェクトでこのエラーが発生します-依存関係がほとんどない2つの単純な非ブラウザープロジェクトです。 彼らは確かにjsdom / localStorageを使用していません。

これは、Jest開発者に質問するのに適切な場所ではありません。jsdomは別のプロジェクトです。 そうは言っても、上記のコメントにはすでにあなたの質問に対する答えが含まれています。

package.json

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

わたしにはできる。

@ p8ulは正しかったので、「 http:// localhost 」を指定することを忘れないでください(Jest 23.5.0以降のデフォルトの設定URL、#6792を参照):

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

全体が私のために働きます。
追加する必要さえありません

"testEnvironment": "node"

jest 23.5.0にはこの修正が含まれているため、回避策は不要になりました。

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

@ mica16に類似https://github.com/jsdom/jsdom/issues/2304#issuecomment-412663502

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

このエラーを回避するために必要な変更はこれだけでした。

モカ/酵素を使用しています。 テストスイートには冗談は含まれていません。

コマンドラインで--env nodeを設定することもできます。

@gokulkrishh http://localhost/に設定しましたが、有効なURLはすべて機能しているようです。

その場合、「location.href」がいいでしょう。 :)

@domenic上部のコメントを更新して、Jestメンテナがバージョン23.5.0でこのバグを修正したことをお勧めします: https

jest-configのtestURLhttp://localhost設定することをコミットします。

設定ファイルにキーを追加して、「jest」を再試行します:{"testURL": " http:// localhost%26quot%3B / }、
ローカルホストの代わりにip-portを使用する
これで問題が解決する可能性があります

npm audit実行しているときにいくつかのセキュリティ問題を見つけた後、この問題が発生しました。 npm audit fixを使用して修正した後、この問題が発生しました。

これはJestでしばらくの間修正されているので、閉じて、重複がたくさん発生するかどうか、または問題が十分に解決したかどうかを確認してみましょう。

「冗談」:{
「詳細」:true、
"testURL": " http:// localhost / "
}
このコードスニペットをpackage.jsonファイルに追加します。
それは私のために働いた。

jsdomが必要ない場合は、影響を受けるテストにこれを追加することもできます

`` `javascript 1.6
/ **

  • @ jest-環境ノード
    * /

it( 'my test'、()=> {
expect(2 + 2).toBe(4);
});
`` `

私は両方のオプションをテストしました:

1)これをテストファイルの先頭に追加します。

/**
 * @jest-environment node
 */

2)このスタンザをpackage.jsonに追加します。

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

両方のオプションが機能しました。

package.jsonファイルに追加することで動作させました:

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

@gokulkrishh http:// localhost /に設定しましたが、有効なURLであればどれでも機能するようです。

私は初心者です。 Jest.config.jsのどこにtestURLを設定したかを正確に教えてください。

@haiphu jest.config.jsどこでも以下のように

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

// Your other config
}

以下をpackage.jsonに追加しましたが、正常に動作するようになりました:)

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

理由はわかりませんが、タイプスクリプトのバージョンが異なることが原因でエラーが発生しました。

ヤーンワークスペースとレルナを使用したモノレポのセットアップがあります。 すべてのパッケージのpackage.jsonにtypescript@^3.3.3れていました。 新しいパッケージを追加し、最新のtypescript@^3.5.3をインストールしました。 既存のパッケージでテストを実行すると、このエラーが発生しました。

すべてのパッケージを同じバージョン( typescript@^3.3.3またはtypescript@^3.5.3 )に移動すると、エラーはなくなります。 testURLをいじる必要はありません

@ tylerreece22 @gokulkrishh私のために働いた! 😄

jestのtestURL構成ディレクティブが何をするのか疑問に思っている人は、 https: //jestjs.io/docs/en/configuration#testurl-stringを参照して

jsdomのオプションを直接設定する人向け(たとえば、Mochaを使用する場合)。 これをsetup.jsに入れてください:

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

不思議なことに..私はjsdomを使用していません..いくつかのノードのみのパッケージをテストするためにjestを使用していますが、jestバージョンを^11範囲内で最新にアップグレードすると、このエラーがCIのブロックを開始しました..他の人はきっと同様の問題が発生しています..これまでに推奨された変更のいずれもそれを修正していないようです

jsdomを使用していない場合は、jest構成プロパティtestEnvironmentnodeに設定する必要があります。 ( testURLに触れる必要はありません)
https://jestjs.io/docs/en/configuration#testenvironment -string

実際の修正を探している人にとっては、 new JSDOM('', { url: 'https://localhost' })

package.jsonファイルでこれを使用してみてください

「冗談」:{
「詳細」:true、
"testURL": " http:// localhost / "
}

URLの設定が機能しないのはなぜですか... react-nativeを使用しています..他に不足しているものはありますか?

URLの設定が機能しないのはなぜですか... react-nativeを使用しています..他に不足しているものはありますか?

同じ問題がありました。 私たちのアプリケーションでは、このコードがありました

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

JSDOMコンストラクターにURLを追加する必要があったことがわかりました

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

これで問題は解決しました。

URLの設定が機能しないのはなぜですか... react-nativeを使用しています..他に不足しているものはありますか?

同じ問題がありました。 私たちのアプリケーションでは、このコードがありました

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

JSDOMコンストラクターにURLを追加する必要があったことがわかりました

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

これで問題は解決しました。

これは私のために働いた本当にありがとう! URLをjestconfigに配置しても、react-nativeでは機能しないようです。 URLをdejsdomコンストラクターに入れるとうまくいきました。

jestを22から26に更新して問題を修正しました。

単に最新バージョンのjestを使用してください。 現在、2020年に26.5.0を使用しており、問題は解決しています。

package.jsonファイルでこれを使用してみてください

「冗談」:{
「詳細」:true、
"testURL": " http:// localhost / "
}

そのtestURLはデフォルトのURLです。つまり、少なくともJest 26.xでは、問題は解決しません。 私はそれを回避するために@zucchaがしたことをしなければなりません

このページは役に立ちましたか?
0 / 5 - 0 評価