首页 文章

嘲笑`文件`开玩笑

提问于
浏览
14

我'm trying to write tests for my web components projects in jest. I already use babel with es2015 preset. I'm在加载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

Update: 根据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();
  });
});

但没有运气

Update: 我在没有 __dev__ 的情况下尝试了上面的代码 . 还可以将文档设置为全局 .

6 回答

  • 1

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

    在Jest配置中设置setupFiles,例如:

    "setupFiles": ["<rootDir>/browserMock.js"]
    
    
    // browserMock.js
    Object.defineProperty(document, 'currentScript', {
      value: document.createElement('script'),
    });
    

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

  • 9

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

    mocks/client.js

    import { JSDOM } from "jsdom"
    const dom = new JSDOM()
    global.document = dom.window.document
    global.window = dom.window
    

    然后在你的jest配置中:

    "setupFiles": [
      "./__mocks__/client.js"
    ],
    
  • 0

    我可以使用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

    如果像我一样你想要将文档模拟为未定义(例如,对于服务器端/客户端测试),我可以在我的测试套件中使用object.defineProperty而无需使用setupFiles

    例:

    beforeAll(() => {
      Object.defineProperty(global, 'document', {});
    })
    
  • 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

  • 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()
    });
    

相关问题