【发布时间】:2019-05-05 00:35:03
【问题描述】:
我正在尝试找到一种方法来在进行 E2E 测试(使用 selenium 或 cypress)和 slate.js 时模拟“更改”事件
在我们的 UI 中,当用户点击一个词时,我们会弹出一个模态框(与该词相关)。我无法做到这一点,因为我无法触发更改事件
【问题讨论】:
我正在尝试找到一种方法来在进行 E2E 测试(使用 selenium 或 cypress)和 slate.js 时模拟“更改”事件
在我们的 UI 中,当用户点击一个词时,我们会弹出一个模态框(与该词相关)。我无法做到这一点,因为我无法触发更改事件
【问题讨论】:
Cypress 可以显式触发事件:https://docs.cypress.io/api/commands/trigger.html#Syntax
这可能对你有用:
cy.get(#element).trigger("change")
【讨论】:
找到解决办法:
1) 向编辑器添加引用
<Editor
ref={this.editor}
/>
2) 为自定义事件添加文档监听器
componentDidMount() {
document.addEventListener("Test_SelectWord", this.onTestSelectWord)
}
componentWillUnmount() {
document.removeEventListener("Test_SelectWord", this.onTestSelectWord)
}
3) 创建一个创建自定义选择事件的处理程序
onTestSelectWord(val: any) {
let slateEditor = val.detail.parentElement.parentElement.parentElement.parentElement
// Events are special, can't use spread or Object.keys
let selectEvent: any = {}
for (let key in val) {
if (key === 'currentTarget') {
selectEvent['currentTarget'] = slateEditor
}
else if (key === 'type') {
selectEvent['type'] = "select"
}
else {
selectEvent[key] = val[key]
}
}
// Make selection
let selection = window.getSelection();
let range = document.createRange();
range.selectNodeContents(val.detail);
selection.removeAllRanges();
selection.addRange(range)
// Fire select event
this.editor.current.onEvent("onSelect", selectEvent)
}
4) 在您的测试代码中使用以下内容:
arr = Array.from(document.querySelectorAll(".cl-token-node"))
text = arr.filter(element => element.children[0].innerText === "*WORD_YOU_ARE_SELECTING*")[0].children[0].children[0]
var event = new CustomEvent("Test_SelectWord", {detail: text})
document.dispatchEvent(event, text)
【讨论】:
赛普拉斯输入命令(例如 cy.type() 和 cy.clear())通过调度 input 和 change 事件来工作 - 在 cy.type() 的情况下,每个字符一个。这模仿了用户在键盘上键入时真实浏览器的行为,足以触发大多数应用程序 JavaScript 的行为。
但是,Slate 几乎完全依赖于 beforeinput 事件(请参阅此处 https://docs.slatejs.org/concepts/xx-migrating#beforeinput),这是一种新的浏览器技术,赛普拉斯输入命令无法模拟的事件。希望 Cypress 团队更新他们的输入命令以调度 beforeinput 事件,但在他们这样做之前,我已经创建了几个简单的自定义命令,它们将触发 Slate 的输入事件侦听器并使其响应。
// commands.js
Cypress.Commands.add('getEditor', (selector) => {
return cy.get(selector)
.click();
});
Cypress.Commands.add('typeInSlate', { prevSubject: true }, (subject, text) => {
return cy.wrap(subject)
.then(subject => {
subject[0].dispatchEvent(new InputEvent('beforeinput', { inputType: 'insertText', data: text }));
return subject;
})
});
Cypress.Commands.add('clearInSlate', { prevSubject: true }, (subject) => {
return cy.wrap(subject)
.then(subject => {
subject[0].dispatchEvent(new InputEvent('beforeinput', { inputType: 'deleteHardLineBackward' }))
return subject;
})
});
// slateEditor.spec.js
cy.getEditor('[data-testid=slateEditor1] [contenteditable]')
.typeInSlate('Some input text ');
cy.getEditor('[data-testid=slateEditor2] [contenteditable]')
.clearInSlate()
.typeInSlate('http://httpbin.org/status/409');
如果你需要支持其他的inputTypes,Slate支持的所有inputTypes都会列出in the source code for editable.tsx
【讨论】:
here 下缺少链接;)