Вы хотите запросить _функцию_ или сообщить _ об ошибке? Сообщить об ошибке
Каково текущее поведение?
Вызов следующего из набора тестов:
Object.defineProperty(location, "hostname", {
value: "example.com",
writable: true
});
выдает следующую ошибку:
TypeError: Cannot redefine property: hostname
at Function.defineProperty (<anonymous>)
Какое ожидаемое поведение?
Код не должен вызывать исключения, а window.location.hostname === "example.com"
должен оценивать значение true.
Судя по всему , jsdom
теперь делает window.location не подделываемым . Единственный способ изменить значения в window.location
- использовать reconfigure
, но (согласно # 2460) Jest не предоставляет jsdom
для тестирования.
Укажите точную конфигурацию Jest и укажите свой Jest, узел,версия пряжи / npm и операционная система.
Версия Jest : 22.0.1
Версия узла : 8.6.0
Версия пряжи : 1.2.0
ОС : macOS High Sierra 10.13.2
У меня похожая проблема. Вы можете создать свое собственное окружение JSDOME и выставить объект jsdom в глобальном масштабе следующим образом.
const JSDOMEnvironment = require('jest-environment-jsdom');
module.exports = class CustomizedJSDomEnvironment extends JSDOMEnvironment {
constructor(config) {
super(config);
this.global.jsdom = this.dom;
}
teardown() {
this.global.jsdom = null;
return super.teardown();
}
};
И затем вы можете вызвать jsdom.reconfigure в своем тестовом примере, как вам нравится
Это хороший обходной путь, спасибо, что поделились!
Вы должны вернуть super.teardown();
поскольку это обещание, кстати
Отлично, @oliverzy - я попробую. Спасибо!
Есть ли подходящее место, чтобы это задокументировать? Кажется, этот вопрос возникает довольно часто; надеюсь, будущие проблемы можно было бы сократить, если бы это было интегрировано в документацию?
Это решение не совсем сработало.
Внутри наших тестовых файлов кажется, что global
установлен как объект window
JSDom.
Другими словами, внутри набора тестов global
совпадает с window
, но внутри класса, расширяющего JSDOMEnvironment
, global
поступает из среды Node.
В результате, имея это:
describe("test suite", () => {
it("should not fail", () => {
global.jsdom.reconfigure({
url: "https://www.example.com/"
});
});
});
не выполняется, потому что global.jsdom
не определено.
Я обошел это, сделав это, но я не особо беспокоюсь об этом.
const JSDOMEnvironment = require("jest-environment-jsdom");
module.exports = class JSDOMEnvironmentGlobal extends JSDOMEnvironment {
constructor(config) {
super(config);
this.dom.window.jsdom = this.dom;
}
};
В этой среде global.jsdom
внутри набора тестов равно this.dom
, и приведенный выше набор тестов работает.
Мне кажется, что установка jsdom
в качестве собственного свойства window
объект неизбежно развалится - есть ли более чистый способ сделать это?
вам нужно написать jsdom
вместо global.jsdom
в ваших тестах.
@oliverzy Как это?
describe("test suite", () => {
it("should not fail", () => {
jsdom.reconfigure({
url: "https://www.example.com/"
});
});
});
Это вызывает jsdom is not defined
, но я могу неправильно интерпретировать.
@ simon360 Настройте testEnvironment
с кодом из @oliverzy , см. https://facebook.github.io/jest/docs/en/configuration.html#testenvironment -string
@danielbayerlein в моей конфигурации Jest есть следующее:
"testEnvironment": "@wel-ui/jest-environment-jsdom-global"
где @wel-ui/jest-environment-jsdom-global
- имя пакета в нашем монорепозитории. Однако среда используется правильно, потому что решение, устанавливающее jsdom
на window
работает должным образом.
Кстати, кто-нибудь знает, почему исходное решение не работает в новой версии?
Вот этот:
Object.defineProperty(location, "hostname", {
value: "example.com",
writable: true
});
@modestfake, который мы обновили с JSDOM @ 9 до JSDOM @ 11 , я предполагаю, что они изменили способ определения переменной
@SimenB Понятно . Только что нашел описание метода jsdom reconfigure
.
Верхнее свойство окна помечено в спецификации [Unforgeable], что означает, что это не настраиваемое собственное свойство и, следовательно, не может быть переопределено или затенено обычным кодом, выполняющимся внутри jsdom, даже с использованием Object.defineProperty.
Я добавил новый репозиторий, чтобы продемонстрировать это поведение. Кто-нибудь может воспроизвести его путем клонирования локально?
@ simon360 воспроизведено
@ simon360 Я нашел. Вы пропустили ключевое слово this
при определении global.jsdom
:
const JSDOMEnvironment = require("jest-environment-jsdom");
module.exports = class JSDOMEnvironmentGlobal extends JSDOMEnvironment {
constructor(config) {
super(config);
this.global.jsdom = this.dom;
}
teardown() {
this.global.jsdom = null;
return super.teardown();
}
};
А как насчет location.search
? Я не нашел упоминания об этом https://github.com/tmpvar/jsdom/blob/05a6deb6b91b4e02c53ce240116146e59f7e14d7/README.md#reconfiguring -the-jsdom-with-reconfiguresettings
@andrewBalekha Что насчет этого?
jsdom.reconfigure({
url: 'https://www.example.com/endpoint?queryparam1=15&queryparam2=test'
});
Спасибо @modestfake - извините за
Хорошо, теперь я вижу - this.global
в объекте среды Jest устанавливается как global
в тестовом файле Jest. В этом есть смысл - спасибо, что помогли мне пройти через это! Если есть достаточный интерес, я мог бы упаковать исправленную версию этого репо и поместить ее в npm
как jest-environment-jsdom-global
.
Однако я надеюсь, что в будущем в Jest появится более чистый способ сделать это. Это не простой способ изменить window.location
-
Может ли быть новый докблок, например, за @jest-environment
? Например...
/**
* @jest-url https://www.example.com/
*/
Или, может быть, JSDom может быть выставлен в специальной части объекта jest
- что-то вроде:
jest.environment.jsdom.reconfigure({
url: "https://www.example.com/"
});
(что будет иметь дополнительное преимущество в виде возможности изменить window.top
)
Мы объединили # 5003. Не уверен, что возможность добавить его как докблок имеет смысл. @cpojer? Мы также можем отказаться от testUrl
, поскольку это может быть предоставлено с помощью этой новой опции.
Если будет достаточно интереса, я могу упаковать исправленную версию этого репо и поместить ее в
npm
какjest-environment-jsdom-global
.
Я думаю, что это имеет смысл в любом случае, поскольку он делает больше, чем просто позволяет вам устанавливать URL-адрес - он предоставляет среде полный JSDOM.
@andrewBalekha Object.defineProperty(location, 'search', { ...options });
выдает ту же ошибку, что и window.location
. Спасибо за предложение.
Object.defineProperty (window.location, 'href', {
установить: newValue => {currentUrl = newValue; },
});
У меня было это в предыдущих версиях, и теперь выдает ошибку.
Если я добавлю возможность записи: true
выдает другое исключение, которое я не могу указать как для доступа, так и для записи
Я опубликовал на npm новый пакет под названием jest-environment-jsdom-global
, который может помочь с проблемами, которые возникают у некоторых людей с Object.defineProperty
.
Есть ли у кого-нибудь обходной путь для { writable: true }
?
Например:
Object.defineProperty(window.location, 'href', { writable: true })
...
Object.defineProperty(window.location, 'hash', { writable: true })
...
Object.defineProperty(window.location, 'search', { writable: true })
@danielbayerlein прочитал эту
@modestfake Я уже читал эту ветку, и https://github.com/facebook/jest/issues/5124#issuecomment -352749005 отлично работает. Но у меня есть другой вариант использования. В Jest 21.xx я установил Object.defineProperty(window.location, 'href', { writable: true })
без URL - только { writable: true }
. Если я выставлю URL, то в тесте нет смысла.
@danielbayerlein какой
У меня есть функция, которая меняет URL-адрес.
routing.js
...
export function redirectToErrorPage () {
window.location.href = '/error.html'
}
...
routing.test.js
test('redirect to the error page', () => {
...
expect(window.location.href).toBe('/error.html')
...
})
В Jest 21.xx я установил Object.defineProperty(window.location, 'href', { writable: true })
Я бы порекомендовал переключиться на window.location.assign
, чтобы вы могли имитировать функцию.
@ simon360 Работает как шарм! Спасибо. 🤝
я использовал
history.pushState({}, "page 2", "/bar.html");
вместе с testURL
в конфигурации jest
Часть местоположения - не единственная проблема. Я не могу импортировать jsdom
отдельно для вызова jsdom.reconfigureWindow
(потому что эта функция больше не существует в последней версии jsdom). Я делал это, чтобы протестировать код, который работает иначе, если window !== top
. В последней версии jest больше нет способа добиться этого, в которой используется более новая версия jsdom.
@andyearnshaw метод jsdom.reconfigure
имеет в своем объекте элемент windowTop
.
Если вы используете среду JSDOM ( jest-environment-jsdom-global
), которую я указал выше, вы можете сделать:
jsdom.reconfigure({
windowTop: YOUR_VALUE
});
в ваших тестах, чтобы выслушать высшую ценность.
Я использую это, и он отлично работает, спасибо!
Вт, 30 января 2018 г., 13:40 simon360, [email protected] написал:
@andyearnshaw https://github.com/andyearnshaw файл jsdom.reconfigure
Метод имеет в своем объекте член windowTop.Если вы используете среду JSDOM (jest-environment-jsdom-global), я
по ссылке выше, вы можете:jsdom.reconfigure ({
windowTop: YOUR_VALUE
});в ваших тестах, чтобы выслушать высшую ценность.
-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/facebook/jest/issues/5124#issuecomment-361595999 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/ABvdEzCLlWtzr0udscL0C6KUxpgXHZRhks5tPxvJgaJpZM4RGN7C
.
Использование window.history.pushState
и testUrl
сработало для меня
https://github.com/facebook/jest/issues/5124#issuecomment -359411593
Собираюсь закрыть это, так как со стороны Jest нечего делать, и существуют обходные пути (не стесняйтесь продолжать обсуждение!)
Обновление с jsdom v8.5.0 до v11.6.2 решило проблему для меня. Итак, мой package.json
включает:
"jest": "^21.2.1",
"jest-cli": "^21.2.1",
"jsdom": "^11.6.2",
Он сломается, если я обновлю jest и jest-cli до v22.2.2.
@ andr-3-w какая-то конкретная причина, по которой у вас есть jsdom в вашем package.json? Он идет в комплекте с Jest.
@SimenB , хороший вопрос, нет необходимости в jsdom
в нашем package.json
. Спасибо!
Итак, без использования jsdom напрямую, вот решение, которое я придумал для своих вещей:
Работает для Jest 21.2.1 (я тестировал на этом):
Зайдите в настройки Jest (например, я буду использовать package.json):
"jest": {
"testURL": "http://localhost"
}
Теперь вы можете изменить объект window.location, а затем вы можете установить URL-адрес, который вам нравится во время тестов.
it('Should set href url to testURL', () => {
// Here I set href to my needs, opinionated stuff bellow
const newUrl = 'http://localhost/editor.html/content/raiweb/it/news/2018/02/altered-carbon-best-cyberpunk-tv-series-ever.html';
Object.defineProperty(window.location, 'href', {
writable: true,
value: newUrl
});
console.log(window.location.href);
});
it('Should set pathname url to testURL', () => {
// Here I set href to my needs, opinionated stuff bellow
const newUrl = '/editor.html/content/raiweb/it/news/2018/02/altered-carbon-best-cyberpunk-tv-series-ever.html';
Object.defineProperty(window.location, 'pathname', {
writable: true,
value: newUrl
});
console.log(window.location.pathname);
});
Надеюсь, это кому-то поможет.
Прекратите публиковать это, это не работает на jest ":" ^ 22.4.2 "
@UserNT Я отметил версию, на которой он работает, и широко использую ее в производственных тестах. Если это не работает в более новых версиях, извините, придумайте собственное решение, а не просто случайную трепку.
Просто для полноты, поскольку решение застряло в середине этой цепочки ...
Решение @ petar-prog91 будет работать с Jest 21, но не с Jest 22 с обновленным jsdom
.
Чтобы запустить последнюю версию Jest, используйте что-то вроде jest-environment-jsdom-global
(полное раскрытие, это мой пакет), чтобы открыть объект jsdom
и использовать jsdom.reconfigure
, который будет иметь такой же (или, по крайней мере, похожий) эффект.
https://github.com/facebook/jest/issues/5124#issuecomment -359411593 также работает для меня с шуткой 22
@ simon360 Привет, что мне делать, если мне нужно взломать сеттер location.href
?
В моих предыдущих тестах было много подобных тестов, а теперь все провалились ...
const setHrefMockFn = jest.fn();
beforeAll(() => {
Object.defineProperty(location, "href", {
get: () => "https://xxxxx",
set: setHrefMockFn
});
});
it("xxx", () => {
//...
expect(setHrefMockFn.mock.calls[0][0]).toBe(xxx);
});
@ simon360 не могли бы вы привести мне пример, как обновить тест, как показано ниже, с вашей библиотекой
beforeAll(() => {
=======
Object.defineProperty(window.location, 'href', {
writable: true
});
});
@abhijeetNmishra вы видели документацию ? Думаю, это ответит на ваш вопрос.
@ simon360 Да, исходя из моего понимания документации, требуется около
jsdom.reconfigure({
url: "https://www.example.com/"
});
который переопределяет URL-адрес глобально, а не для каждого теста. Пожалуйста помоги!
@abhijeetNmishra Я не уверен, что этот вопрос - лучшее место для обсуждения. Не могли бы вы открыть проблему в репозитории jest-environment-jsdom-global
где мы сможем ее решить? Спасибо!
@SimenB указанный обходной путь («используйте jest-environment-jsdom-global
») кажется крайне неоптимальным решением, очевидно, очень распространенной проблемы. Любой, кто обновляется до Jest 22, теперь должен добавить зависимость к этому стороннему пакету и (с точки зрения пользователя) переписать некоторые из своих тестов. Это регресс в поведении Джеста.
Есть ли решение, которое мы могли бы встроить в jest-environment-jsdom
по умолчанию? Рад сделать пиар под вашим руководством.
Очень жаль, что кому-то приходится прыгать через это множество обручей только для того, чтобы изменить window.location.href. Я только начал использовать Jest и собираюсь пересмотреть свой выбор фреймворка для тестирования с учетом этой проблемы. Неужели нет лучшего решения, чем предложенные выше уродливые хаки?
@ydogandjiev не стесняйтесь вносить свой вклад в проект, чтобы решить эту проблему. Помните, что это открытый исходный код, поэтому неистовство с комментариями типа «неприемлемо» и «смешно» никому не поможет.
@ msholty-fd Я хотел бы помочь, если смогу. Поскольку я только начинаю работать с jest и jsdom, я не уверен, что имею достаточно глубокое понимание этих библиотек, чтобы точно знать, как лучше всего улучшить этот опыт. Это что-то лучше всего в шутку или в jsdom? Похоже, что одна из этих библиотек в какой-то момент внесла изменения, которые нарушили подход Object.defineProperty; это изменение было сделано в jest или jsdom?
Итак, вот все варианты, которые я считаю предпочтительными в зависимости от количества строк, необходимых для изменения window.location; ни один из них в настоящее время не работает:
window.location.href = "https://www.example.com";
Использование Object.defineProperty не работает, потому что JSDOM сделал свойство местоположения окна [Unforgeable] :
Object.defineProperty(window.location, "href", {
value: "https://www.example.com",
configurable: true
});
Создание экземпляра jsdom и его настройка не работают, потому что jest, похоже, использует свой собственный экземпляр, который недоступен для легкого доступа:
import { JSDOM } from "jsdom";
...
const dom = new JSDOM();
dom.reconfigure({ url: "https://www.example.com" });
Чтобы заставить работать варианты 1 или 2, jsdom должен отказаться от своих текущих целей и вести себя как настоящий браузер. Следовательно, похоже, что единственный вариант, который у нас есть, - это упростить перенастройку экземпляра jsdom, который использует jest. Имеет ли смысл выставлять этот экземпляр непосредственно на глобальном объекте jest; т.е. разрешая что-то вроде этого:
jest.dom.reconfigure({ url: "https://www.example.com" });
Я все еще думаю, что делать location.assign('some-url')
лучше, чем location.href = 'some-url'
. Я считаю, что вызов функции более явный, чем назначение, и вы можете издеваться над функцией
@SimenB в тех случаях, когда код пытается _set_ location.href
, да, location.assign()
лучше. Но если вы тестируете поведение, которое _reads_ location.href
, location.assign()
не решает проблему, тем более что location.assign()
в JSDOM фактически ничего не делает.
Идея использования reconfigure
состоит в том, чтобы активировать путь кода, который доступен только тогда, когда location.href
сформирован определенным образом. В нашем случае у нас был некоторый код, который изменялся в зависимости от текущего домена - код вонючий, да, но он также необходим, и лучший способ смягчить неприятный запах кода - иметь тестовые инструменты, которые фиксируют поведение и гарантируют, что оно остается. на месте.
Есть ли способ использовать это с Enzyme и установленным компонентом для проверки перенаправления?
Перед обновлением Jest прошел тест ниже:
`` ''
it ('маршруты к правильному маршруту', () => {
Object.defineProperty(window.location, 'href', {
writable: true,
value: 'https://mysuperawesomesite.com/',
});
const component = mount(
<App {...props} />
);
const link = component.find('.class');
link.simulate('click');
expect(window.location.href).toEqual('https://mysuperawesomesite.com/new');
});
After upgrading Jest and implementing [jest-environment-jsdom-global](https://www.npmjs.com/package/jest-environment-jsdom-global), I tried the following to no avail:
```
it('routes to correct route', () => {
jsdom.reconfigure({
url: 'https://mysuperawesomesite.com/',
});
const component = mount(
<App {...props} />
);
const link = component.find('.class');
link.simulate('click');
expect(window.location.href).toEqual('https://mysuperawesomesite.com/new');
});
(window.location.href по-прежнему равно https://mysuperawesomesite.com/ , не был изменен на (https://mysuperawesomesite.com/new).
Событие щелчка на элементе не перенаправляет при использовании этого метода, а перенаправление происходит путем установки window.location.href.
Непонятно, как правильно это проверить, или если тесты, в которых ранее использовался Object.defineProperty, изначально были плохо построены. Спасибо заранее за любую помощь.
РЕДАКТИРОВАТЬ: РЕШЕНО
Удалось решить эту проблему, используя window.location.assign (url) вместо window.location.href = href. Это позволило мне отключить метод assign и проверить, правильно ли он вызывается. Увидеть ниже:
it('routes to correct route', () => {
window.location.assign = jest.fn();
const component = mount(
<App {...props} />
);
const link = component.find('.class');
link.simulate('click');
expect(window.location.assign).toBeCalledWith('https://mysuperawesomesite.com/new');
window.location.assign.mockRestore();
});
@SimenB Существует большая разница между .assign
и .href
вы можете прочитать на MDN. Первый имеет серьезное междоменное ограничение. В моем коде я хочу перенаправить родительскую страницу из iframe, в котором выполняется мой код. Это кросс-домены. И единственный способ сделать это - изменить href
.
Мне бы очень хотелось, чтобы эта проблема была открыта повторно, так как я не вижу текущего обходного пути, и мне придется просто не тестировать эту функцию. Что явно отстой.
Я в одной лодке с @soswow. Было бы здорово, если бы вы могли предоставить механизм для переопределения URL-адреса, так как я также удаляю несколько модульных тестов, пока эта функциональность не будет восстановлена.
Мне бы очень хотелось, чтобы эта проблема была открыта повторно, так как я не вижу текущего обходного пути, и мне придется просто не тестировать эту функцию. Что явно отстой.
Мы ничего не можем сделать со стороны шутки. Я уверен, что jsdom хотел бы, чтобы его поддержали пиарщиком. https://github.com/jsdom/jsdom/issues/2112
Вот простое решение, которое работает.
describe('changing location', () => {
const testURL = location.href;
beforeEach(() => history.replaceState({}, 'Login', '/login'));
afterEach(() => history.replaceState({}, 'Home', '/'));
it('works', () => {
expect(location.pathname).toBe('/login');
});
});
@vastus Как я прямо указал - проблема в кросс-доменах . History API не позволяет переключиться на другой домен, насколько я помню.
Поскольку location
не может быть переопределено непосредственно на объекте jsdom window
, один из возможных подходов - переопределить его на производном объекте:
global.window = Object.create(window);
Object.defineProperty(window, 'location', {
value: {
href: 'http://example.org/'
}
});
Я использую это для решения проблемы:
const windowLocation = JSON.stringify(window.location);
delete window.location;
Object.defineProperty(window, 'location', {
value: JSON.parse(windowLocation)
});
В духе @RubenVerborgh & annemarie35
Добавляем пример тестирования location.search
на основе решения @vastus :
test('gets passed query param and returns it as a string if it exists', () => {
history.replaceState({}, 'Test', '/test?customer=123');
const customerId = getQueryParam('customer');
expect(customerId).toBe('123');
});
@RubenVerborgh Прекрасно работает.
пытаться:
window.history.pushState({}, null, '/pathname?k=v');
Решение, подобное @sahalsaad :
`` javascript
const oldWindow = window.location;
удалить window.location;
window.location = {
... oldWindow,
// включаем любые пользовательские перезаписи, такие как следующая заглушка sinon
заменить: sinon.stub (),
};
// творим чудеса
window.location = oldWindow;
`` ''
@sahalsaad, спасибо! Я использовал вариант вашего решения для имитации window.location.search:
const location = {
...window.location,
search: queryString,
};
Object.defineProperty(window, 'location', {
writable: true,
value: location,
});
возможно лучшее решение:
import { URL } from 'whatwg-url';
const location = new URL(window.location.href);
location.assign = jest.fn()
location.replace = jest.fn()
location.reload = jest.fn()
delete window.location
window.location = location
Решил мою проблему, используя решение, данное @kdelmonte , мне пришлось издеваться над переменной window.location.search
. так что я использовал
window.history.pushState({}, null, '?skuId=1234')
Поскольку
location
не может быть переопределено непосредственно на объекте jsdomwindow
, один из возможных подходов - переопределить его на производном объекте:global.window = Object.create(window); Object.defineProperty(window, 'location', { value: { href: 'http://example.org/' } });
Ваш ответ - единственный, который работает в моей ситуации, спасибо!
Поскольку
location
не может быть переопределено непосредственно на объекте jsdomwindow
, один из возможных подходов - переопределить его на производном объекте:global.window = Object.create(window); Object.defineProperty(window, 'location', { value: { href: 'http://example.org/' } });
Ваш ответ - единственный, который работает в моей ситуации, спасибо!
Это больше не работает 😢
Поскольку
location
не может быть переопределено непосредственно на объекте jsdomwindow
, один из возможных подходов - переопределить его на производном объекте:global.window = Object.create(window); Object.defineProperty(window, 'location', { value: { href: 'http://example.org/' } });
Ваш ответ - единственный, который работает в моей ситуации, спасибо!
Это больше не работает 😢
У меня тоже не работает
Я решил это сделать:
delete window.location
window.location = {
href: 'http://example.org/,
}
Я использую следующий макет в качестве утилиты для работы с Location
export class MockLocation extends URL implements Location {
ancestorOrigins: any = []
toString = jest.fn().mockImplementation(() => this.toString())
assign = jest.fn(href => this.href = href)
replace = jest.fn(href => this.href = href)
reload = jest.fn()
constructor(
url: string = 'http://mock.localhost',
) {
super(url)
}
onWindow(window: Window) {
Object.defineProperty(window, 'location', {
writable: true,
value: this
});
return this
}
}
Тогда в моих тестах
let location: MockLocation
beforeEach(() => {
location = new MockLocation(MOCK_PARTNER_URL).onWindow(window)
})
Я обнаружил, что постоянно заглушаю такие хитрые объекты, и создал гибкую вспомогательную функцию:
export const safelyStubAndThenCleanup = (target, method, value) => {
const original = target[method]
beforeEach(() => {
Object.defineProperty(target, method, { configurable: true, value })
})
afterEach(() => {
Object.defineProperty(target, method, { configurable: true, value: original })
})
}
А затем использование:
describe('when on /pages', () => {
safelyStubAndThenCleanup(window, 'location', { pathname: '/pages' })
it('should do something neat', () => { /* ... */ })
})
И вы можете заглушить все, что захотите: pathname
, href
и т. Д. Это дает вам дополнительное бесплатное преимущество очистки.
Ключ в том, что вы не можете связываться с самим location
, поэтому просто замените location
подделкой, а затем верните ее, когда тест будет завершен.
Как я вижу в своем сеансе отладки, global.location
реализуется через геттер, а не через простое свойство. Разве не было бы безопаснее переопределить это так?
let originalLocationDescriptor;
beforeAll(() => {
originalLocationDescriptor = Object.getOwnPropertyDescriptor(global, 'location');
delete global.location;
global.location = {};
});
afterAll(() => {
Object.defineProperty(global, 'location', originalLocationDescriptor);
}):
Хотя трудно представить, зачем мне использовать исходный global.location
, это кажется немного более правильным.
И этот код, конечно, мне подходит. Я просто обращаюсь к location.pathname
, но этот объект можно легко расширить с помощью jest.fn()
если это необходимо.
Это сработало для меня, используя jest 26.5
function stubLocation(location) {
beforeEach(() => {
jest.spyOn(window, "location", "get").mockReturnValue({
...window.location,
...location,
});
});
}
stubLocation({ pathname: "/facebook/jest/issues/5124" });
test("mocks location prop", () => {
expect(window.location.pathname).toEqual("/facebook/jest/issues/5124");
});
Добавляем пример тестирования
location.search
на основе решения @vastus :test('gets passed query param and returns it as a string if it exists', () => { history.replaceState({}, 'Test', '/test?customer=123'); const customerId = getQueryParam('customer'); expect(customerId).toBe('123'); });
Это отлично сработало для моей проблемы.
Самый полезный комментарий
Я опубликовал на npm новый пакет под названием
jest-environment-jsdom-global
, который может помочь с проблемами, которые возникают у некоторых людей сObject.defineProperty
.