测试直接更改 DOM 的库
Posted
技术标签:
【中文标题】测试直接更改 DOM 的库【英文标题】:Testing a library that changes DOM directly 【发布时间】:2018-07-26 14:10:36 【问题描述】:我编写了一个直接操作 DOM 的小型库,使用 window
和 document
来搜索和更改 DOM。现在我正在尝试弄清楚如何对其进行测试。
到目前为止,我已经尝试了jest + jsdom 的组合:
const jsdom = require('jsdom');
const JSDOM = jsdom;
const dom = new JSDOM('<!DOCTYPE html><p>Hello world</p>');
// these two lines do not seem to do anything useful:
global.window = dom.window;
global.document = dom.window.document;
test('can globally access and search the DOM', () =>
// this doesn't work
expect(global.document.querySelectorAll('p').length).toBe(1);
);
我在这里做错了什么,还是我的测试方法完全错了?如果是这样,进行此类测试的正确方法是什么?
我觉得有点迷失在所谓的 e2e 测试和单元测试之间,因为在我的情况下,这似乎是介于两者之间的东西。
理想情况下,我希望最终对这个东西进行针对多个浏览器的测试,并获得某种测试覆盖率。但这更像是下一步。现在我根本无法让它工作。
我知道网络世界的发展速度有多快,所以如果我完全错了,如果你能指出今天的正确方法,我将不胜感激。
更新
这是我的完整代码,经过 @duxfox 的一些建议,因为使用这种方法,我的库现在缺少事件 DOMContentLoaded
,它应该触发其 DOM 处理。
const jsdom = require('jsdom');
const JSDOM = jsdom;
const document = (new JSDOM('<!DOCTYPE html><p>Hello world</p>')).window;
global.document = document;
global.window = document.defaultView;
window.console = global.console;
Object.keys(document.defaultView).forEach((property) =>
if (typeof global[property] === 'undefined')
global[property] = document.defaultView[property];
);
global.navigator =
userAgent: 'node.js'
;
// Here I'm trying to follow a suggestion from Luis:
// https://***.com/questions/36803733/jsdom-dispatchevent-addeventlistener-doesnt-seem-to-work
window.addEventListener('DOMContentLoaded', function (ev)
console.log('DOMContentLoaded called!'); // this is not called.
/*
console.log('window click', ev.target.constructor.name,
ev.currentTarget.constructor.name);*/
);
// loading my library here:
// const root = require('../src');
test('something', () =>
// This now works, but my library is missing
// event DOMContentLoaded to start processing the DOM
expect(document.querySelectorAll('p').length).toBe(1);
);
【问题讨论】:
手动触发 domContentLoaded 事件会起作用吗? ***.com/questions/9153314/… 等一下,对不起,你已经这样做了 或者这个:gist.github.com/chad3814/5059671 @duxfox——我不明白,使用那段代码我得到错误TypeError: jsdom.env is not a function
。我正在使用jsdom
版本11.11.0
。
@duxfox-- 哈哈,刚刚看到最后一条评论:Would you please redo the example using the new API? jsdom.env is deprecated as of jsdom v10.
。所以,这行不通。那么最新的jsdom的正确方法是什么? :)
lol idk,我也看到了,只是在查找它
【参考方案1】:
下面是我与mocha/chai/jsdom/enzyme
一起使用的jsdom设置脚本
看起来global.window
应该设置为
dom.window.document.defaultView
而不是
dom.window
完整脚本,添加其他全局属性:
var jsdom = require('jsdom');
const JSDOM = jsdom;
const document = (new JSDOM('')).window;
global.document = document;
global.window = document.defaultView;
window.console = global.console;
Object.keys(document.defaultView).forEach((property) =>
if (typeof global[property] === 'undefined')
global[property] = document.defaultView[property];
);
global.navigator =
userAgent: 'node.js'
;
【讨论】:
这似乎在表面上起作用。现在它对我来说失败了,因为在库内部它仅在初始化后解析 DOM:document.addEventListener('DOMContentLoaded', function () /* process the DOM */);
。任何建议如何解决这个问题?
不确定您的意思 - 您粘贴的 addEventListener
代码的意义是什么?这是一个测试用例还是什么?
看到这个问题:***.com/questions/36803733/…
document.addEventListener('DOMContentLoaded', function ()
是在文档加载完成后开始处理 DOM。但在我们的案例中,这发生在包含库之前。如果我首先包含该库,那么它将无法工作,因为尚未设置全局变量。所以这就像一场比赛。
我开始感觉到什么应该是正确的方法,但我还没有尝试管理它。我认为,最好的方法可能是使用JSDOM.fromFile
加载一个包含所有库用例的 HTML 文件,但最重要的是 - 从其中包含我的库。然后,理论上,一切都应该正常工作。这就是我现在正在尝试做的事情......以上是关于测试直接更改 DOM 的库的主要内容,如果未能解决你的问题,请参考以下文章