【问题标题】:How to trigger change event on slate.js when testing with Selenium or Cypress使用 Selenium 或 Cypress 进行测试时如何在 slate.js 上触发更改事件
【发布时间】:2019-05-05 00:35:03
【问题描述】:

我正在尝试找到一种方法来在进行 E2E 测试(使用 selenium 或 cypress)和 slate.js 时模拟“更改”事件

在我们的 UI 中,当用户点击一个词时,我们会弹出一个模态框(与该词相关)。我无法做到这一点,因为我无法触发更改事件

【问题讨论】:

    标签: selenium cypress slate.js


    【解决方案1】:

    Cypress 可以显式触发事件:https://docs.cypress.io/api/commands/trigger.html#Syntax

    这可能对你有用:

    cy.get(#element).trigger("change")
    

    【讨论】:

    • 可能是点击事件。你能展示一些代码来说明测试逻辑吗?
    【解决方案2】:

    找到解决办法:

    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)
    

    【讨论】:

      【解决方案3】:

      赛普拉斯输入命令(例如 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 下缺少链接;)
      猜你喜欢
      • 2017-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-11
      • 1970-01-01
      • 2022-12-16
      • 2014-06-29
      相关资源
      最近更新 更多