Jestjs 开玩笑地嘲笑“文件”

Jestjs 开玩笑地嘲笑“文件”,jestjs,jsdom,babel-jest,Jestjs,Jsdom,Babel Jest,我试图开玩笑地为我的web组件项目编写测试。我已经在es2015预设中使用了巴贝尔。我在加载js文件时遇到了一个问题。我遵循了一段代码,其中document对象有一个currentScript对象。但在测试上下文中,它是null。所以我想嘲弄他们。但是jest.fn()在这方面并没有真正的帮助。我如何处理这个问题 jest失败的代码段 var currentScriptElement = document._currentScript || document.currentScript; var

我试图开玩笑地为我的web组件项目编写测试。我已经在es2015预设中使用了巴贝尔。我在加载js文件时遇到了一个问题。我遵循了一段代码,其中
document
对象有一个
currentScript
对象。但在测试上下文中,它是
null
。所以我想嘲弄他们。但是
jest.fn()
在这方面并没有真正的帮助。我如何处理这个问题

jest失败的代码段

var currentScriptElement = document._currentScript || document.currentScript;
var importDoc = currentScriptElement.ownerDocument;
我写的测试用例<代码>组件.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();
  });
});
但是没有运气


更新:我在没有
的情况下尝试了上述代码。另外,通过将文档设置为全局。

我在jest中使用了
setUpFiles
属性解决了这个问题。这将在jsdom之后和每个测试之前执行,这对我来说非常完美

在Jest配置中设置设置文件,例如:

"setupFiles": ["<rootDir>/browserMock.js"]


// browserMock.js
Object.defineProperty(document, 'currentScript', {
  value: document.createElement('script'),
});
“setupFiles”:[“/browserMock.js”]
//browserMock.js
Object.defineProperty(文档“currentScript”{
值:document.createElement('script'),
});

理想的情况是加载webcomponents.js来填充jsdom。

我可以使用nodejs上的
global
scope模块解决同样的问题,用mock of document设置document,在我的例子中,
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,而不必使用setupfile

例如:

beforeAll(() => {
  Object.defineProperty(global, 'document', {});
})

如果您需要为属性定义测试值,有一种更精细的方法。每个属性都需要单独定义,还需要使属性可写:

Object.defineProperty(window.document, 'URL', {
  writable: true,
  value: 'someurl'
});
见:


我使用Jest
21.2.1
和Node
v8.11.1

与其他人所说的类似,但不要试图自己模仿DOM,只需使用JSDOM:

模拟/client.js

从“JSDOM”导入{JSDOM}
constdom=newjsdom()
global.document=dom.window.document
global.window=dom.window
然后在您的玩笑配置中:

“设置文件”:[
“/\uuuu mocks\uuuu/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()
});
it('应该测试一些东西',()=>{
const spyFunc=jest.fn();
defineProperty(global.document,'querySelector',{value:spyFunc});
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;
    });
const wrapper=document.createElement('div');
const render=shallow();
document.getElementById=jest.fn((id)=>{
wrapper.innerHTML=render.find(`${id}`).html();
返回包装器;
});

这是我的名为super-project的项目中文件夹super-project中的结构:


  • 超级项目
    • 配置
      • \uuuuu mocks\uuuuu
        • dom.js
    • src
      • user.js
    • 测验
      • user.test.js
    • jest.config.js
    • package.json

您需要设置Jest以在测试中使用模拟:

dom.js

从“JSDOM”导入{JSDOM}
constdom=newjsdom()
global.document=dom.window.document
global.window=dom.window
user.js

导出函数create(){ 返回document.createElement('table'); }
user.test.js

从“./src/user”导入{create};
测试('创建表',()=>{
expect(create().outerHTML).toBe(“”);
});
jest.config.js

module.exports={
setupFiles:[”/config/\uuuuuu mocks\uuuuuu/dom.js“],
};

参考文献:

您需要创建一个手动模拟:

操作DOM对象:

Jest配置:

我找到了另一个解决方案。假设在组件内部,您希望通过类名(document.getElementsByClassName)获取对DOM中元素的引用。您可以执行以下操作:

let wrapper
beforeEach(() => {
    wrapper = mount(<YourComponent/>)
    jest.spyOn(document, 'getElementsByClassName').mockImplementation(() => 
        [wrapper.find('.some-class').getDOMNode()]
    )
})
let包装器
在每个之前(()=>{
包装器=mount()
jest.spyOn(文档'getElementsByClassName').mockImplementation(()=>
[wrapper.find('.some class').getDOMNode()]
)
})
通过这种方式,您可以手动将getElementsByClassName的返回值设置为.some类的引用。可能需要通过调用wrapper.setProps({})重新加载组件


希望这对你们中的一些人有所帮助

你试过使用
global.document
吗?是的。我试过了。运气不好。所以我基本上使用了jsdom,比如
constJSDOM=require('jsdom');const documentHTML='';global.document=jsdom.jsdom(documentHTML)之后,我将添加任何我想要的内容到文档中,并在测试中使用它。实际上,这里的问题是,jsdom非常简单,没有webcomponents API。总之,根据我的回答,暂时解决了这个问题。是的,但它的用例非常简单……在webcomponents.js中,我们有大量的API相互连接。模拟它们是一项非常艰巨的任务…但是在你的情况下,你到底需要模拟什么?我试图通过在对象中提供它们来模拟
document.referer
document.URL
。运气不好。属性仍然在test runner中显示为它们的常规值。@theUtherSide我注意到此解决方案在某些版本的Node中工作,而在其他版本中不工作。也许可以安装NVM并玩不同版本的游戏谢谢你的提示!我要和诺德玩