开玩笑地嘲笑“文件”
Mocking `document` in jest
我正在开玩笑地为我的 Web 组件项目编写测试。我已经使用带有 es2015 预设的 babel。我在加载 js 文件时遇到问题。我遵循了一段代码,其中 document
对象有一个 currentScript
对象。但在测试上下文中它是 null
。所以我在想嘲笑同样的事情。但是 jest.fn()
并没有真正的帮助。我该如何处理这个问题?
jest 失败的一段代码。
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();
});
});
以下是jest抛出的错误
Test suite failed to run
TypeError: Cannot read property 'ownerDocument' of null
at src/components/sample-component/sample-component.js:4:39
更新:
根据 Andreas Köberle 的建议,我添加了一些全局变量并尝试模拟如下
__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__
的情况下尝试了上面的代码。也可以通过将文档设置为全局。
我开玩笑地使用 setUpFiles
属性 解决了这个问题。这将在 jsdom 之后和每次测试之前执行,这对我来说是完美的。
在 Jest 配置中设置 setupFiles,例如:
"setupFiles": ["<rootDir>/browserMock.js"]
// browserMock.js
Object.defineProperty(document, 'currentScript', {
value: document.createElement('script'),
});
理想情况是加载 webcomponents.js 以填充 jsdom。
我可以在 nodejs 上使用 global
scope 模块解决同样的问题,使用模拟文档设置文档,在我的例子中,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
};
如果你像我一样希望将文档模拟为未定义(例如,用于服务器端/客户端测试),我可以在我的测试套件中使用 object.defineProperty 而无需使用 setupFiles
示例:
beforeAll(() => {
Object.defineProperty(global, 'document', {});
})
如果您需要为属性定义测试值,可以使用一种更精细的方法。每个属性都需要单独定义,还需要使属性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
这对我有用
与其他人所说的类似,但与其尝试自己模拟 DOM,不如使用 JSDOM:
// __mocks__/client.js
import { JSDOM } from "jsdom"
const dom = new JSDOM()
global.document = dom.window.document
global.window = dom.window
然后在你的笑话配置中:
"setupFiles": [
"./__mocks__/client.js"
],
我一直在努力为我正在进行的项目模拟文档。我在 React 组件内调用 document.querySelector()
并需要确保它正常工作。最终这对我有用:
it('should test something', () => {
const spyFunc = jest.fn();
Object.defineProperty(global.document, 'querySelector', { value: spyFunc });
<run some test>
expect(spyFunc).toHaveBeenCalled()
});
希望对您有所帮助
const wrapper = document.createElement('div');
const render = shallow(<MockComponent{...props} />);
document.getElementById = jest.fn((id) => {
wrapper.innerHTML = render.find(`#${id}`).html();
return wrapper;
});
这是我名为 super-project 的项目中的结构,位于文件夹 super-project:
中
- 超级项目
- 配置
__mocks__
- dom.js
- 来源
- user.js
- 测试
- user.test.js
- jest.config.js
- package.json
您需要设置 Jest 以在测试中使用模拟:
dom.js:
import { JSDOM } from "jsdom"
const dom = new JSDOM()
global.document = dom.window.document
global.window = dom.window
user.js:
export function create() {
return document.createElement('table');
}
user.test.js:
import { create } from "../src/user";
test('create table', () => {
expect(create().outerHTML).toBe('<table></table>');
});
jest.config.js:
module.exports = {
setupFiles: ["./config/__mocks__/dom.js"],
};
参考文献:
您需要创建一个手动模拟:
https://jestjs.io/docs/en/manual-mocks.html
正在操纵 DOM 对象:
https://jestjs.io/docs/en/tutorial-jquery
我找到了另一个解决方案。假设在您的组件内部,您想通过 className (document.getElementsByClassName) 获取对 DOM 中元素的引用。您可以执行以下操作:
let wrapper
beforeEach(() => {
wrapper = mount(<YourComponent/>)
jest.spyOn(document, 'getElementsByClassName').mockImplementation(() =>
[wrapper.find('.some-class').getDOMNode()]
)
})
通过这种方式,您可以手动将 getElementsByClassName 的 return 值设置为等于 .some-class 的引用。可能需要通过调用 wrapper.setProps({}).
重新渲染组件
希望这对你们中的一些人有所帮助!
我正在开玩笑地为我的 Web 组件项目编写测试。我已经使用带有 es2015 预设的 babel。我在加载 js 文件时遇到问题。我遵循了一段代码,其中 document
对象有一个 currentScript
对象。但在测试上下文中它是 null
。所以我在想嘲笑同样的事情。但是 jest.fn()
并没有真正的帮助。我该如何处理这个问题?
jest 失败的一段代码。
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();
});
});
以下是jest抛出的错误
Test suite failed to run
TypeError: Cannot read property 'ownerDocument' of null
at src/components/sample-component/sample-component.js:4:39
更新: 根据 Andreas Köberle 的建议,我添加了一些全局变量并尝试模拟如下
__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__
的情况下尝试了上面的代码。也可以通过将文档设置为全局。
我开玩笑地使用 setUpFiles
属性 解决了这个问题。这将在 jsdom 之后和每次测试之前执行,这对我来说是完美的。
在 Jest 配置中设置 setupFiles,例如:
"setupFiles": ["<rootDir>/browserMock.js"]
// browserMock.js
Object.defineProperty(document, 'currentScript', {
value: document.createElement('script'),
});
理想情况是加载 webcomponents.js 以填充 jsdom。
我可以在 nodejs 上使用 global
scope 模块解决同样的问题,使用模拟文档设置文档,在我的例子中,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
};
如果你像我一样希望将文档模拟为未定义(例如,用于服务器端/客户端测试),我可以在我的测试套件中使用 object.defineProperty 而无需使用 setupFiles
示例:
beforeAll(() => {
Object.defineProperty(global, 'document', {});
})
如果您需要为属性定义测试值,可以使用一种更精细的方法。每个属性都需要单独定义,还需要使属性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
与其他人所说的类似,但与其尝试自己模拟 DOM,不如使用 JSDOM:
// __mocks__/client.js
import { JSDOM } from "jsdom"
const dom = new JSDOM()
global.document = dom.window.document
global.window = dom.window
然后在你的笑话配置中:
"setupFiles": [
"./__mocks__/client.js"
],
我一直在努力为我正在进行的项目模拟文档。我在 React 组件内调用 document.querySelector()
并需要确保它正常工作。最终这对我有用:
it('should test something', () => {
const spyFunc = jest.fn();
Object.defineProperty(global.document, 'querySelector', { value: spyFunc });
<run some test>
expect(spyFunc).toHaveBeenCalled()
});
希望对您有所帮助
const wrapper = document.createElement('div');
const render = shallow(<MockComponent{...props} />);
document.getElementById = jest.fn((id) => {
wrapper.innerHTML = render.find(`#${id}`).html();
return wrapper;
});
这是我名为 super-project 的项目中的结构,位于文件夹 super-project:
中- 超级项目
- 配置
__mocks__
- dom.js
- 来源
- user.js
- 测试
- user.test.js
- jest.config.js
- package.json
- 配置
您需要设置 Jest 以在测试中使用模拟:
dom.js:
import { JSDOM } from "jsdom"
const dom = new JSDOM()
global.document = dom.window.document
global.window = dom.window
user.js:
export function create() {
return document.createElement('table');
}
user.test.js:
import { create } from "../src/user";
test('create table', () => {
expect(create().outerHTML).toBe('<table></table>');
});
jest.config.js:
module.exports = {
setupFiles: ["./config/__mocks__/dom.js"],
};
参考文献:
您需要创建一个手动模拟:
https://jestjs.io/docs/en/manual-mocks.html
正在操纵 DOM 对象:
https://jestjs.io/docs/en/tutorial-jquery
我找到了另一个解决方案。假设在您的组件内部,您想通过 className (document.getElementsByClassName) 获取对 DOM 中元素的引用。您可以执行以下操作:
let wrapper
beforeEach(() => {
wrapper = mount(<YourComponent/>)
jest.spyOn(document, 'getElementsByClassName').mockImplementation(() =>
[wrapper.find('.some-class').getDOMNode()]
)
})
通过这种方式,您可以手动将 getElementsByClassName 的 return 值设置为等于 .some-class 的引用。可能需要通过调用 wrapper.setProps({}).
重新渲染组件希望这对你们中的一些人有所帮助!