Издевательский "документ" в шутку
Я пытаюсь написать тесты для моих проектов веб-компонентов в шутку. Я уже использую babel с предустановкой es2015. Перед загрузкой js файла я столкнулся с проблемой. Я выполнил фрагмент кода, в котором объект document
имеет объект currentScript
. Но в тестовом контексте оно равно null
. Поэтому я думал о насмешливости. Но jest.fn()
самом деле не помогает. Как я могу справиться с этой проблемой?
Кусок кода, в котором шутка не срабатывает.
var currentScriptElement = document._currentScript || document.currentScript;
var importDoc = currentScriptElement.ownerDocument;
Тестовый случай я написал. component.test.js
import * as Component from './sample-component.js';
describe('component test', function() {
it('check instance', function() {
console.log(Component);
expect(Component).toBeDefined();
});
});
Ниже приведена ошибка, вызванная шуткой
Test suite failed to run
TypeError: Cannot read property 'ownerDocument' of null
at src/components/sample-component/sample-component.js:4:39
Обновление: согласно предложению Андреаса Кёберле, я добавил несколько глобальных варсов и попытался насмехаться, как после
__DEV__.document.currentScript = document._currentScript = {
ownerDocument: ''
};
__DEV__.window = {
document: __DEV__.document
}
__DEV__.document.registerElement = jest.fn();
import * as Component from './arc-sample-component.js';
describe('component test', function() {
it('check instance', function() {
console.log(Component);
expect(Component).toBeDefined();
});
});
Но не повезло
Обновление: я пробовал код выше __dev__
. Также, установив документ как глобальный.
Ответы
Ответ 1
Я решил это использовать свойство setUpFiles
в шутку. Это будет выполняться после jsdom и перед каждым тестом, который идеально подходит для меня.
Установите setupFiles в конфигурации Jest, например:
"setupFiles": ["<rootDir>/browserMock.js"]
// browserMock.js
Object.defineProperty(document, 'currentScript', {
value: document.createElement('script'),
});
Идеальной ситуацией будет загрузка webcomponents.js для заполнения jsdom.
Ответ 2
Подобно тому, что говорили другие, но вместо того, чтобы пытаться издеваться над DOM самостоятельно, просто используйте JSDOM:
__mocks __/client.js
import { JSDOM } from "jsdom"
const dom = new JSDOM()
global.document = dom.window.document
global.window = dom.window
Тогда в вашем jest config:
"setupFiles": [
"./__mocks__/client.js"
],
Ответ 3
Я мог бы решить эту же проблему, используя global
модуль области на nodejs, установив документ с макетом документа, в моем случае, getElementsByClassName
:
// My simple mock file
export default {
getElementsByClassName: () => {
return [{
className: 'welcome'
}]
}
};
// Your test file
import document from './name.component.mock.js';
global.document = {
getElementsByClassName: document.getElementsByClassName
};
Ответ 4
Если вы, как я, вы хотите сделать фальшивый документ неопределенным (например, для тестов на стороне сервера/клиента), я смог использовать object.defineProperty внутри своих тестовых наборов без необходимости использовать setupFiles
Пример:
beforeAll(() => {
Object.defineProperty(global, 'document', {});
})
Ответ 5
Если вам нужно определить тестовые значения для свойств, есть несколько более гранулированный подход. Каждое свойство необходимо определить индивидуально, и также необходимо сделать свойства writeable
:
Object.defineProperty(window.document, 'URL', {
writable: true,
value: 'someurl'
});
См.: https://github.com/facebook/jest/issues/890
Это работало для меня, используя Jest 21.2.1
и Node v8.11.1
Ответ 6
Я боролся с насмешливым документом для проекта, в котором я участвую. Я вызываю document.querySelector()
внутри компонента React и должен убедиться, что он работает правильно. В конечном счете это то, что сработало для меня:
it('should test something', () => {
const spyFunc = jest.fn();
Object.defineProperty(global.document, 'querySelector', { value: spyFunc });
<run some test>
expect(spyFunc).toHaveBeenCalled()
});