我正在尝试以开玩笑的方式为我的Web组件项目编写测试。我已经使用了带有es2015预设的babel。我在加载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();
});
});
以下是jest抛出的错误
Test suite failed to run
TypeError: Cannot read property 'ownerDocument' of null
at src/components/sample-component/sample-component.js:4:39
更新 根据AndreasKö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__
的情况下尝试了上述代码。同时将文档设置为全局。
答案 0 :(得分:10)
我已经在jest中使用setUpFiles
属性解决了这个问题。这将在jsdom之后和每次测试之前执行,这对我来说是完美的。
在Jest配置中设置setupFiles,例如:
"setupFiles": ["<rootDir>/browserMock.js"]
// browserMock.js
Object.defineProperty(document, 'currentScript', {
value: document.createElement('script'),
});
理想情况是加载webcomponents.js以填充jsdom。
答案 1 :(得分:10)
与其他人所说的相似,但不是试图自己模拟DOM,而是使用JSDOM:
<强> __嘲笑__ / client.js 强>
import { JSDOM } from "jsdom"
const dom = new JSDOM()
global.document = dom.window.document
global.window = dom.window
然后在你的jest配置中:
"setupFiles": [
"./__mocks__/client.js"
],
答案 2 :(得分:3)
这是我项目中名为 super-project 的文件夹中的结构,该文件夹位于 super-project :
GetSize(int):
cmp edi, 1
sbb eax, eax
and eax, 98
add eax, 150
ret
您需要将Jest设置为在测试中使用模拟:
dom.js :
GetSize:
mov eax, 248
test edi, edi
je .L1
mov eax, 150
.L1:
ret
user.js :
__mocks__
user.test.js :
import { JSDOM } from "jsdom"
const dom = new JSDOM()
global.document = dom.window.document
global.window = dom.window
jest.config.js :
export function create() {
return document.createElement('table');
}
参考:
您需要创建一个手动模拟:
https://jestjs.io/docs/en/manual-mocks.html
答案 3 :(得分:2)
我可以使用nodejs上的global
范围模块解决同样的问题,使用模拟文档设置文档,在我的例子中,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 :(得分:2)
我一直在为自己正在进行的项目准备模拟文档。我在React组件中调用document.querySelector()
,需要确保它正常工作。最终这对我有用:
it('should test something', () => {
const spyFunc = jest.fn();
Object.defineProperty(global.document, 'querySelector', { value: spyFunc });
<run some test>
expect(spyFunc).toHaveBeenCalled()
});
答案 5 :(得分:1)
如果像我一样,您希望将文档模拟为未定义(例如,对于服务器端/客户端测试),我可以在我的测试套件中使用object.defineProperty而无需使用setupFiles
示例:
beforeAll(() => {
Object.defineProperty(global, 'document', {});
})
答案 6 :(得分:0)
如果需要为属性定义测试值,则会采用稍微细化的方法。每个属性都需要单独定义,并且还需要创建属性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
答案 7 :(得分:0)
我找到了另一个解决方案。假设您要在组件内部通过className(document.getElementsByClassName)获得对DOM中元素的引用。您可以执行以下操作:
let wrapper
beforeEach(() => {
wrapper = mount(<YourComponent/>)
jest.spyOn(document, 'getElementsByClassName').mockImplementation(() =>
[wrapper.find('.some-class').getDOMNode()]
)
})
这样,您可以手动将getElementsByClassName的返回值设置为等于.some-class的引用。可能有必要通过调用wrapper.setProps({})重新呈现组件。
希望这对您有所帮助!
答案 8 :(得分:-2)
希望这会有所帮助
const wrapper = document.createElement('div');
const render = shallow(<MockComponent{...props} />);
document.getElementById = jest.fn((id) => {
wrapper.innerHTML = render.find(`#${id}`).html();
return wrapper;
});