Jsdom: jest: SecurityError: localStorage недоступен для непрозрачных источников

Созданный на 27 июл. 2018  ·  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 Комментарий

Резюме нижеприведенного обсуждения:

  • Исправление состоит в том, чтобы установить URL-адрес для вашего jsdom, что может потребоваться через конфигурацию вашей тестовой среды. URL-адрес по умолчанию " about: blank " вызовет ошибки при попытке доступа к localStorage.
  • Основная причина часто заключается в том, что библиотеки перебирают все свойства jsdom и добавляют их к глобальным; даже если вы никогда не используете localStorage в своих тестах, какая-то библиотека или среда тестирования, от которых вы зависите, «используют» его таким образом. Обратите внимание, что этот метод циклического копирования и копирования явно не поддерживается , поэтому неудивительно, что код, который его выполняет, может сломаться в небольшом выпуске.

Транскрипция нижеприведенного комментария по вопросу о том, является ли это «критическим изменением», которое с тех пор было скрыто функцией GitHub «увидеть больше комментариев»:

Спасибо, но на данный момент я не считаю, что это лучший путь вперед. Для jsdom это не критическое изменение, связанное с реализацией новых функций веб-платформы; это второстепенная версия.

Иждивенцы, даже широко используемые иждивенцы, могут написать неудачный код, который обнаруживает новые функции и выдает исключение, если они появляются. Я надеюсь, что мы все сможем согласиться с тем, что даже если такие иждивенцы существуют, jsdom не должен навсегда отказываться от добавления новых функций в второстепенные выпуски.

Ситуация здесь не такая уж серьезная, но вроде бы похожая. Я еще не видел, чтобы кто-нибудь отследил оскорбительный код Jest, поэтому трудно сказать точно, но похоже, что они выполняют операцию, которая явно нарушается нормальным ходом разработки jsdom и не будет работать в Интернете. браузер, реализующий localStorage.

Я понимаю, что это тяжелая ситуация для тех из вас, на кого не по вашей вине повлияло неудачное взаимодействие относительно того, как ваша прямая зависимость (ab) использует вашу косвенную зависимость. Но я надеюсь, что это можно решить на правильном уровне, исправив ошибочный код Jest, вместо того, чтобы удалять полезную функцию у всех пользователей jsdom из-за ошибок одного зависимого.

Исходный ответ OP, для контекста:

Похоже, вы не устанавливаете URL-адрес в своих тестах, но вы или, возможно, Jest обращаетесь к window.localStorage . Сопровождающие Jest могут знать больше о лучшем исправлении, но я слышал, есть ли способ задать URL-адреса в ваших тестах Jest?

Это совсем недавняя проблема, которая, похоже, возникла с 11.12.0 . Я получаю те же ошибки при использовании jest с enzyme .

Да, у меня возникла проблема после обновления с 11.11.0 до 11.12.0 . Установка testURL в конфигурации jest устраняет проблему.

@ ben-mckernan Привет! Какой URL вы дали, чтобы это исправить ??

@gokulkrishh Я установил для него значение http://localhost/ но, похоже, работает любой действующий URL.

Я предполагаю, что это, вероятно, специфично для Enzyme, потому что Enzyme делает то, о чем явно предупреждают jsdom docs ? Неудивительно, что на второстепенном выпуске сломалось, к сожалению :(

У меня это тоже сломалось :(

@ ben-mckernan Спасибо 👍

(«+1» комментарии будут отмечены как спам; отправка сообщений всем участникам обсуждения проблемы бесполезна.)

Извинения. Просто пытаюсь помочь.

Можно подтвердить добавление testURL в jestConfig, поскольку @ ben-mckernan предложил исправить это.

И мы тоже используем Enzyme, если это поможет подтвердить вашу интуицию.

Для тестирования электронного приложения я просто установил его в «file: /», что тоже работает.

@miamollie Я добавил testURL согласно предложению @ ben-mckernan (используя Jest + Enzyme, не уверен, что это связано с ферментом. Ошибка исходит от jest-environment-jsdom который использует jsdom). Из-за этого некоторые другие мои тестовые файлы не работают. Просто к вашему сведению. Посмотрите, работает ли это для вас. Ваши тестовые примеры могут отличаться от моих (TestURL может сработать для вас).

@domenic Я использую только шутку. Так что я не уверен, что это проблема ферментов.

@gokulkrishh Да, тоже самое, это остановило ошибку безопасности localStorage, но привело к сбою некоторых других тестов.

Решение @ ben-mckernan исправило это. Спасибо!

@ ben-mckernan Я использую шутку в настройке angular (с jest-preset-angular), та же ошибка, такое же решение. Так что это не проблема ферментов.

Похоже, Jest нужно изменить значение по умолчанию testURL чтобы это было смягчено (в настоящее время это about:blank ).

@DcsMarcRemolt Я просто отлаживал проблему. Jest использует в своем пакете модуль зависимостей с именем jest-environment-jsdom Json -> "jsdom": "^11.5.1" caret (^) из-за этого npm установил jsdom как 11.12.0 (это новая версия, опубликованная сегодня). Так что у большинства пользователей это сломалось. Проблема уже создана в шутку и указана здесь. Остерегайтесь этого.

Я снова открою эту проблему, чтобы сделать ее более заметной. См. Первый комментарий Доменика для решения проблемы.

Добавляем в конфигурацию jest в package.json следующее:
"testEnvironment": "node"
решает проблему для меня.
Благодарим @ blu3printchris за помощь в решении этой проблемы.

После этого обновления я больше не могу перезаписывать и издеваться над реализацией JSDOM в localStorage.

Поскольку для многих это было непреднамеренным критическим изменением, возможно, лучшим вариантом контроля повреждений будет:

  • Отменить это изменение.
  • Выпуск версии 11.12.1 с отмененным изменением для восстановления ожидаемого поведения.
  • Извлечь или исключить версию 11.12.0 с предупреждением.
  • Если новое поведение желательно как есть, отпустите 12.0.0 чтобы указать на критическое изменение.

Спасибо, но на данный момент я не считаю, что это лучший путь вперед. Для jsdom это не критическое изменение, связанное с реализацией новых функций веб-платформы; это второстепенная версия.

Иждивенцы, даже широко используемые иждивенцы, могут написать неудачный код, который обнаруживает новые функции и выдает исключение, если они появляются. Я надеюсь, что мы все сможем согласиться с тем, что даже если такие иждивенцы существуют, jsdom не должен навсегда отказываться от добавления новых функций в второстепенные выпуски.

Ситуация здесь не такая уж серьезная, но вроде бы похожая. Я еще не видел, чтобы кто-нибудь отследил оскорбительный код Jest, поэтому трудно сказать точно, но похоже, что они выполняют операцию, которая явно нарушается нормальным ходом разработки jsdom и не будет работать в Интернете. браузер, реализующий localStorage.

Я понимаю, что это тяжелая ситуация для тех из вас, на кого не по вашей вине повлияло неудачное взаимодействие относительно того, как ваша прямая зависимость (ab) использует вашу косвенную зависимость. Но я надеюсь, что это можно решить на правильном уровне, исправив ошибочный код Jest, вместо того, чтобы удалять полезную функцию у всех пользователей jsdom из-за ошибок одного зависимого.

Спасибо за разъяснение. Я согласен с тем, что если проблема связана с использованием jsdom неподдерживаемым способом, как описано выше, то это технически не является нарушением semver, и шутка должна выпустить патч.

Мое обходное решение: используйте черный список при просмотре всех свойств jsdom и добавлении их в global.


Код

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 в глобальный узел Node

Ну, пока я прохожу. Мне нужны тесты для запуска в jsdom и в реальных браузерах. Это самый простой подход, который я могу придумать, он работает годами. Я не вижу такого же потенциала в предлагаемых альтернативах.
Использование jsdom-global тоже может работать.

Ну, пока я прохожу. Мне нужны тесты для запуска в jsdom и в реальных браузерах.

Если ваши тесты могут выполняться в «настоящих браузерах», они могут выполняться таким же образом и в jsdom - просто укажите тот же HTML. Назначая вместо этого global, вы вносите дополнительную сложность и различия по сравнению с тем, как вы запускаете тест в браузере.

К вашему сведению, я столкнулся с той же проблемой с Mocha, а не с Jest, после обновления jsdom до 11.12.0 .

Привет, я просто хочу понять, почему изменения внесены в первую очередь.

Мои варианты использования - просто утверждать функцию, чтобы убедиться, что я написал ее правильно, это так же просто, как:

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 с библиотекой Redux и тому подобное, в то время как на самом деле я просто тестирую такую ​​простую функцию, как

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

Кстати, testURL и testEnvironment "хак" у меня не работают. Это мой package.json:

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

Итак, мой вопрос в том, почему все хлопоты по внесению критических изменений, в то время как иногда нам просто нужен тестовый бегун, который просто "работает"

@ khmy2010 Ваш код и вопросы связаны с Jest больше, чем с jsdom. Я предлагаю вам вместо этого создать проблему в их репозитории .

Такое же сообщение об ошибке с оператором и почти со всеми здесь (кроме меня
с помощью фермента). Если не связано, я должен открыть вопрос в шутку. Сожалею о
что.

30 июля 2018 г. в 21:32 "Zirro" [email protected] написал:

@ khmy2010 https://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 , вы можете передать настраиваемый 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. Незначительные выпуски не должны нарушать существующий код.

Доменик объясняет в этом комментарии (если он не отображается при нажатии на ссылку, прокрутите вверх и загрузите скрытые комментарии), почему это не было воспринято как критическое изменение. Код зависимых пакетов, который делает то

В дополнение к исправлению выше, мне пришлось добавить это в корень тестовой конфигурации: --env=jsdom

Добавление следующего в мой jest.config.js

testURL: 'http://localhost',

решил проблему. Спасибо!

(Сопровождающий Jest здесь.) Как вы думаете, имеет ли смысл с точки зрения Jest изменить значение по умолчанию about:blank на, например, localhost ?

Не уверен, что я достаточно умен, чтобы высказать свое мнение по этому поводу, но с точки зрения разработчика я бы сказал, что localhost имеет больше смысла, о: blank - это случай, которого никогда не бывает. Мы тестируем наши приложения, в которых практически никогда не бывает about: blank url

Команда Jest добавила более разумное значение по умолчанию для testURL : https://github.com/facebook/jest/pull/6792

@SimenB Я бы сказал, что это хорошая идея.

Получение той же ошибки, что и OP, но в моей ситуации это вызывает МНОГО проблем. Мы ограничиваем используемые версии пакетов, и мы можем изменить их только в начале цикла выпуска. В настоящее время мы приближаемся к концу цикла выпуска, поэтому в наших средах разработки есть версии всех пакетов и их зависимостей по состоянию на месяц назад, но когда мы попросили сервер сборки создать сборку, он получил текущую версию всех пакетов. пакеты. Таким образом, хотя все тесты проходят локально, все они терпят неудачу на сервере сборки.

Мы используем параметр «setupTestFrameworkScriptFile» в файле конфигурации jest, чтобы выполнить некоторую настройку, включая полифиллы для (среди прочего) localStorage и sessionStorage (поскольку мы используем оба в нашем приложении). Это в основном window.localStorage = window.localStorage || { ... } , и то же самое для sessionStorage, где ... - это набор фиктивных функций. Теперь ничего из этого не работает, даже если я изменю его, чтобы всегда переопределять значение по умолчанию ( window.localStorage = { ... } ).

Кроме того, у нас есть модульные тесты, которые специально проверяют вызываемые вещи вроде sessionStorage.getItem , но после установки для "testURL" значения " http: // localhost ", как рекомендовано выше для устранения ошибок localStorage, все они терпят неудачу. Несмотря на то, что у нас есть window.sessionStorage.getItem = jest.fn(); , выполнение последующего expect(window.sesssionStorage.getItem).toHaveBeenCalled() не позволяет сказать, что это не фиктивная функция.

Хотя я согласен с тем, что добавление функции является незначительным изменением версии, а не критическим изменением, когда это что-то, что является стандартной частью браузеров, и новая реализация, по-видимому, не может быть отменена или высмеяна, это _ является_ критическим изменением .

Единственное решение, которое я нашел для своей проблемы, - это добавить jsdom в мой package.json и указать версию 11.11.0. Это не идеально и потребует дополнительной работы позже, когда мы снова обновим пакеты, но на данный момент это разблокирует нас.

Если у вас есть код, например, имитирующий код, который работает в браузерах, но не в jsdom, сообщите о новой проблеме в соответствии с шаблоном проблемы, и мы сможем ее изучить. Насколько мне известно, localStorage в jsdom так же подделываем, как и в браузерах.

Я предлагаю не запускать разные версии на вашем сервере сборки, когда работают ваши разработчики.

«Я рекомендую не запускать разные версии на вашем сервере сборки, пока работают ваши разработчики».

Хотя в теории это звучит хорошо, но если каждый разработчик пакетов не перестанет использовать «^» при указании версий зависимостей или мы не зафиксируем тысячи папок в нашей папке node_modules, этого никогда не произойдет. От одной машины разработчика к другой, вероятно, будут небольшие различия в некоторых зависимостях на уровень или два ниже. Все, что я могу сделать, это указать точные версии пакетов, которые являются прямыми зависимостями нашего приложения.

Полностью согласен с @mrobrian насчет "^". Самая безумная вещь на свете. npm следует удалить этот способ описания зависимостей.

Обходной путь packge-lock.json и yarn.lock нарушен по дизайну. Может быть, это помогает с версиями, но тогда возникает еще одна проблема с проверкой кода и слиянием, и часто вам нужно воссоздать этот файл путем удаления. Ничего страшного, если зависимости обновляются редко, но мы обновляем очень часто.

Следовательно, наш .npmrc :

save-exact = true
package-lock = false

это помогло мне добавить эти новые строки в package.json:

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

Если вы используете jsdom, убедитесь, что вы указали URL-адрес

const dom = новый JSDOM (``, {
url: "https://example.org/",
});

Хотели бы разработчики-шутники прокомментировать, почему "testEnvironment": "node" теперь требуется для проектов CLI / node (чтобы избежать ошибки localStorage ), когда раньше это не требовалось? Это ошибка?

Если это каким-то образом задумано, действительно нужно более качественное сообщение об ошибке! Я получаю эту ошибку в обоих моих проектах, использующих Jest - двух простых небраузерных проектах с небольшими зависимостями. Они определенно не используют jsdom / localStorage.

Здесь не место задавать вопросы разработчикам Jest - jsdom - это отдельный проект. Тем не менее, комментарии выше уже содержат ответы на ваши вопросы.

package.json

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

Меня устраивает.

@ p8ul был прав, не забудьте указать " http: // localhost " (URL-адрес, установленный по умолчанию, начиная с Jest 23.5.0, см. # 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://github.com/facebook/jest/issues/6766#issuecomment -412516712

Я обязуюсь установить testURL для jest-config на http://localhost workes.

добавьте ключ в файл конфигурации и попробуйте еще раз "jest": {"testURL": " http: // localhost% 26quot% 3B / },
использовать ip-порт вместо localhost
Это может решить проблему

Я столкнулся с проблемой после обнаружения некоторых проблем с безопасностью при запуске npm audit . После их исправления с помощью npm audit fix я столкнулся с этой проблемой.

Поскольку это было исправлено в Jest в течение некоторого времени, давайте попробуем закрыть его и посмотреть, получится ли у нас много дубликатов или все уладилось.

"шутка": {
"многословный": правда,
"testURL": " http: // localhost / "
}
Добавьте этот фрагмент кода в файл package.json.
У меня это сработало.

вы также можете добавить это к затронутому тесту, если jsdom там не нужен

`` javascript 1.6
/ **

  • узел @ jest-environment
    * /

it ('мой тест', () => {
ожидать (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 Anywhere in jest.config.js как показано ниже

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

// Your other config
}

Я добавил ниже в свой package.json, и теперь он отлично работает :)

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

Не знаю почему, но моя ошибка была вызвана разными версиями машинописного текста.

У меня есть установка монорепозитория с рабочими областями пряжи + lerna. У всех пакетов в 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 ... Я использую шутку для тестирования некоторых пакетов только для узлов, но эта ошибка начала блокировать CI при обновлении версий jest до последней в диапазоне ^11 .. Я уверен, что другие люди наблюдаются похожие проблемы .. ни одно из рекомендуемых на данный момент изменений не исправляет

если вы не используете jsdom тогда вам нужно установить для свойства конфигурации jest testEnvironment значение node . (не нужно трогать testURL )
https://jestjs.io/docs/en/configuration#testenvironment -string

Для тех, кто ищет реальное исправление, это new JSDOM('', { url: 'https://localhost' })

Попробуйте использовать это в своем файле package.json

"шутка": {
"многословный": правда,
"testURL": " http: // localhost / "
}

Почему установка url не работает для меня ... я использую response-native ... что-то еще мне не хватает?

Почему установка url не работает для меня ... я использую response-native ... что-то еще мне не хватает?

У нас была такая же проблема. В нашем приложении у нас был этот код

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

Оказывается, нам пришлось добавить URL-адрес в конструктор JSDOM.

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

Это устранило проблему.

Почему установка url не работает для меня ... я использую response-native ... что-то еще мне не хватает?

У нас была такая же проблема. В нашем приложении у нас был этот код

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

Оказывается, нам пришлось добавить URL-адрес в конструктор JSDOM.

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

Это устранило проблему.

Это сработало для меня, большое спасибо! размещение URL-адреса в конфигурации шутки, похоже, не работает с react-native. размещение URL-адреса в конструкторе jsdom помогло.

Обновление шутки с 22 до 26 исправлена ​​проблема.

просто используйте последнюю версию jest. в настоящее время я использую 26.5.0 в 2020 году, и моя проблема решена

Попробуйте использовать это в своем файле package.json

"шутка": {
"многословный": правда,
"testURL": " http: // localhost / "
}

Этот testURL является URL-адресом по умолчанию, что означает, что он не решает проблему, по крайней мере, не с Jest 26.x . Чтобы обойти это, мне пришлось сделать то же, что и

Была ли эта страница полезной?
0 / 5 - 0 рейтинги