【问题标题】:Do something "if an element with some text is not present"做一些“如果不存在带有某些文本的元素”
【发布时间】:2022-07-31 18:05:29
【问题描述】:

这基本上是针对 ReactSelect 元素(行为类似于启用多选的Select2 element),我试图在该元素上选择一些尚未选择的值。

如果选择了一个选项,那么 DOM 中将有一个如下所示的元素

<div class="select__multi-value__label">option1</div>

因此该选项不会出现在列表中。因此,click()“选项”的任何代码都会失败。

有没有办法检查具有某些特定文本的元素是否在 DOM 中可用?

类似的,

options = ['option1','option2','option3'];
options.forEach(option =>{
   cy.get('[test-id="react-select"]').then(reactSelect =>{
      if(reactSelect.find('[class="select__multi-value__label"]').contains(option).length == 0){
      //code to select that option
        cy.get('div.select__menu-list > div[role="option"]').contains(option).click();
     }
   })
})

这个 find().contains() 部分不起作用。 我怎样才能做到这一点?

感谢您的帮助。

编辑


除了下面给出的解决方案之外,我可以得到一个完全匹配的选择器——比如使用正则表达式吗?

let r = new RegExp("^" + option + "$");
 ...........
const selector = `div.select__multi-value__label:contains(${r})`;

这在某种程度上是行不通的。找到一个帖子推荐using filter(),但是不知道怎么用。

有可能吗?

【问题讨论】:

    标签: cypress


    【解决方案1】:

    您可以通过在选择器内移动contains() 来实现,

    options = ['option1','option2','option3'];
    options.forEach(option =>{
      cy.get('[test-id="react-select"]').then(reactSelect =>{
    
          const selector = `[class="select__multi-value__label"]:contains(${option})`
    
          if(reactSelect.find(selector).length == 0){
            //code to select that option
            cy.get('div.select__menu-list > div[role="option"]')
              .contains(option)
              .click();
         }
       })
    })
    

    您代码中的.find().contains() 部分使用了与赛普拉斯.contains() 不同的.contains()

    它正在调用具有不同目的的jQuery .contains()

    说明:检查一个 DOM 元素是否是另一个 DOM 元素的后代。


    我想您也可以直接选择选项并对其进行迭代

    options = ['option1','option2','option3'];
    
    cy.get('div.select__menu-list > div[role="option"]')
      .each(option =>{
        if (options.includes(option.text()) {
          option.click();
        }
      })
    

    完全匹配

    options = ['option1','option2','option3'];
    options.forEach(option =>{
      cy.get('[test-id="react-select"]').then(reactSelect =>{
    
        const matchedOptions = reactSelect
          .find('[class="select__multi-value__label"]')
          .filter((index, el) => el.innerText === option)   // exact
    
        if(matchedOptions.length === 0){
            //code to select that option
            cy.get('div.select__menu-list > div[role="option"]')
              .contains(option)
              .click();
         }
       })
    })
    

    【讨论】:

    • 感谢您的代码。我不得不使用div.select__multi-value__label 选择器。
    • 编辑了原始问题以包含一个具有完全文本匹配的选择器。请检查。
    • 正则表达式是个好主意,但不幸的是它不适用于:contains()。正如你所提到的,它可以与`.filter() 中的string.match(r) 表达式一起使用-我将在上面添加我认为应该起作用的内容。
    【解决方案2】:

    您应该避免在测试中使用条件,因为它违反了最佳实践。

    在这种情况下,遵循良好做法的解决方案是模拟来自 API 的响应,以便您根据需要处理请求,这样您就可以准确地知道屏幕上何时会出现特定文本,而不是成为随机行为,你不必做条件。

    您可以在此处阅读有关模拟的更多信息:https://docs.cypress.io/api/commands/intercept#Stubbing-a-response

    但我也建议您阅读有关使用条件进行测试的赛普拉斯文档:https://docs.cypress.io/guides/core-concepts/conditional-testing#What-you-ll-learn

    【讨论】:

    • 谢谢。我的要求是测试应用程序并通过 UI 插入一些默认数据。如果没有任何内容,测试将按预期运行,但如果之前的运行出现错误,那么这些运行添加的数据会导致问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-02
    • 2018-02-27
    • 2021-02-02
    • 2010-12-26
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多