我有一个SVG对象,该对象使用d3-zoom来实现缩放和平移功能。它可以正常工作,但是当我开始使用Cypress.js进行集成测试时,问题就出现了。
我尝试在svg
元素上使用标准鼠标事件来模拟拖动行为:
cy.get('svg')
.trigger('mousedown', { which: 1, force: true })
.trigger('mousemove', { position: 'left' })
.trigger('mouseup', { position: 'left', force: true });
上面的示例取自赛普拉斯drag and drop recipe,它在 nodrag.js 文件中产生以下错误:
无法读取未定义的属性文档
下面您可以看到错误发生的位置(视图为undefined
):
__webpack_exports__["default"] = (function(view) {
var root = view.document.documentElement,
...
我花了很多时间试图以另一种方式触发事件,但是没有成功-就像使用svg
容器尝试上面的代码段一样。
请记住,我无法从赛普拉斯测试中访问任何d3.js软件包,因为它已作为NPM软件包导入到React应用程序中。
在此先感谢您的帮助!
答案 0 :(得分:3)
在不得不继续之前,我只能得到部分答案,但这也许可以帮助您或其他人找到最终的解决方案。
要纠正该错误,必须为view
提供mousedown
属性。像这样提供window
,就可以正确触发D3方法:
cy.get('svg')
.trigger('mousedown', { which: 1, force: true, view: window }) // <-- here
.trigger('mousemove', { position: 'left', view: window }) // <-- here
.trigger('mouseup', { position: 'left', force: true });
但是,在测试运行期间没有拖动或移动发生,其他问题也从那里出现。开始于...这是与事件一起发送的正确上下文吗?似乎是这样,因为window
似乎是D3预期具有属性链的唯一上下文:
view.document.documentElement
或者这是一种反模式...一种代码气味?
追逐这些后续问题得出的结论似乎具有重要意义。
第一个问题涉及D3如何处理鼠标和拖动事件。 D3具有大量的事件监听器和回调,可以覆盖标准事件及其各自的处理程序。
第二个原因是iframes
与赛普拉斯的测试跑步者一起玩。
可能是赛普拉斯的程序触发事件在赛普拉斯iframe中正确触发了,但是由于D3的激进事件处理,这些事件到应用程序iframe的转换丢失了吗?尤其是考虑到在测试视口中手动拖动圆圈效果很好。
再一次回到:
我在一个简单的Ember应用程序中选择了Zoomable Force Directed Graph作为我的D3主题,以研究这个问题。它完美地再现了所提到的错误,因此,它肯定是D3 + Cypress的挑战,并且与前端框架无关。
我希望这项工作会有所帮助。
续...
经过进一步的阅读– Cypress's Trade-offs,尤其是他们的公开拉取请求Support for Native Browser Events –似乎赛普拉斯在D3中的事件处理优先级尚未完全协调。像drag and drop example中详细介绍的那样,更简单的实现不会带来由D3之类的第三方库引入的事件处理挑战。但是,赛普拉斯团队似乎确实正在开发这种支持。
答案 1 :(得分:0)
我使用的代码与您的代码有些不同,因此您可以尝试
cy.get('svg')
.trigger('mousedown', { which: 1 })
.trigger('dragstart', {})
.trigger('drag', {});
答案 2 :(得分:0)
尝试一下:
cy.window().then(win => {
cy.get('svg')
.trigger('mousedown', {
which: 1,
force: true,
view: win,
})
.trigger('mousemove', {
clientX: 300,
clientY: 500,
force: true,
})
.trigger('mouseup', {
force: true,
view: win,
});
});
参考Jennifer Shehane's answer in this GitHub issue,对cannot read property document of undefined
部分的答案是将窗口对象插入触发选项中的view
中。在jacefarm的答案中提到的问题没有发生任何移动,似乎可以通过指定clientX
/ clientY
来解决,而不是使用相对于所选元素的位置来解决。