【问题标题】:How to get the value of an element only if another specific element is visible?仅当另一个特定元素可见时如何获取元素的值?
【发布时间】:2022-10-15 03:54:04
【问题描述】:

我正在使用什么:

<ul class="abc">
 <li class="xyz">
  <a href="www.something.com">
   <div>
    <h2>
     <div>
      <div class="theText">
       <div>Get this text</DIV>
      </div>
     </div>
    </h2>
   </div>
  </a> 
  <button aria-label="remove">...</button>
 </li>
 <li class="xyz">...Same stuff here as above li...</li>
 <li class="xyz">...Same stuff here as above li...</li>
 <li class="xyz">...Same stuff here as above li...</li>
</ul>

button 这里的aria-label 属性有两种状态,即删除(用于单击按钮时)和添加(用于尚未单击按钮时)。

我想要达到的目标:
我想获取&lt;a&gt; 标签中的值,在本例中为“获取此文本”,仅当同一 &lt;li&gt; 标记内的按钮设置为 aria-label="remove" 时。我还将存储我在一个数组中获得的值,以便稍后与另一个数组进行比较。

我试过的:

let myArray: any = []

cy.get('li[class="xyz"]').each(($element) => {
    cy.get('li[class="xyz"]').within(($element) => {
        cy.wrap($element)
            .find('button[aria-label="remove"]')
            .find('div[class="theText"]')
            .invoke('text').then(text => {
                myArray.push(text)
            })
    })
}).then(() => {
    cy.wrap(myArray).as('myArray')
})

使用上面的代码,我得到了这个Assertion Error from Cypress

【问题讨论】:

  • 没有用过柏树。但是,如果我理解但首先你为什么不做 cy.get('li.xyz')?此外,您正在查询所有特定的 li 项目,并且对于每个项目,您都试图找到另一个 .xyz 元素?但是,根据提供的标记,不存在其他 .xyz
  • @ManosKounelakis - 所有其他 &lt;li&gt; 标签都具有相同的 class="xyz"。让我更新帖子,谢谢。
  • 您可以删除 cy.get('li[class="xyz"]').within() 行,因为您正在包装 $element 并在其中使用 .find() - 并 find 做几乎相同的事情。

标签: javascript typescript cypress cypress-each


【解决方案1】:

如果你想使用:has() 伪选择器,你应该在.each() 循环的外部这样做。

但是,求求您谨防, :has() 伪选择器将失败如果已经点击了零个按钮。

let myArray: any = []

cy.get('li[class="xyz"]:has(button[aria-label="remove"])')  // implied filter
  .each($li => {
    // only element with remove attribute inside here
    cy.wrap($li)
      .find('div[class="theText"]')
      .invoke('text')
      .then(text => {
        myArray.push(text)
      })
  })
}).then(() => {
  cy.wrap(myArray).as('myArray')
})

【讨论】:

    【解决方案2】:

    使用cypress-if package

    let myArray: any = []
    
    cy.get('li[class="xyz"]').each(($element) => {
      cy.wrap($element).within(() => {    
    
        cy.get('button[aria-label="remove"]')
          .if()                                // chained commands only run 
                                               // if [aria-label="remove"] exists
                                               // but does not fail if not existing      
          .parent()                            // up to parent (avoids error)
          .find('div[class="theText"] div')
          .invoke('text').then(text => {
            myArray.push(text)
          })
      })
    }).then(() => {
      cy.wrap(myArray).as('myArray')
    })
    

    用于测试的示例 HTML

    <ul class="abc">
      <li class="xyz">
        <a href="www.something.com">
          <div>
            <h2>
              <div>
                <div class="theText">
                  <div>Get this text</DIV>
                </div>
              </div>
            </h2>
          </div>
        </a>
        <button aria-label="remove">...</button>
      </li>
      <li class="xyz">
        <a href="www.somethingelse.com">
          <div>
            <h2>
              <div>
                <div class="theText">
                  <div>Not this text</DIV>
                </div>
              </div>
            </h2>
          </div>
        </a>
        <button aria-label="add">...</button>
      </li>
    </ul>
    

    结果: ['获取此文本']


    笔记我在这里添加了额外的div .find('div[class="theText"] div') 以避免文本周围出现空格,但它不会改变条件检查。

    【讨论】:

    • 我试过了,测试仍然通过了所有没有[aria-label="remove"]&lt;button&gt; 元素。我也没有点击按钮就运行了这个,这样[aria-label="remove"] 就不会存在了。无论如何,测试仍然通过了所有&lt;button&gt; 元素。对此有何建议?
    • 你在某处有一个错误,它对我有用 - 将添加我测试过的样本。
    【解决方案3】:

    您可以在选择器中使用 has

    let myArray: any = []
    
    cy.get('li[class="xyz"]').each(($element) => {
        cy.get('li[class="xyz"]:has(button[aria-label="remove"])').within(($element) => {
            cy.wrap($element)
                .find('div[class="theText"]')
                .invoke('text').then(text => {
                    myArray.push(text)
                })
        })
    }).then(() => {
        cy.wrap(myArray).as('myArray')
    })
    

    或者您可以使用parentsUntil 找到与aria-label="remove" 相关的元素后返回父元素

    let myArray: any = []
    
    cy.get('li[class="xyz"]').each(($element) => {
        cy.get('li[class="xyz"]').within(($element) => {
            cy.wrap($element)
                .find('button[aria-label="remove"]')
                .parentsUntil('li[class="xyz"]')
                .find('div[class="theText"]')
                .invoke('text').then(text => {
                    myArray.push(text)
                })
        })
    }).then(() => {
        cy.wrap(myArray).as('myArray')
    })
    

    【讨论】:

      【解决方案4】:

      let myArray = []
      
      const buttonCheck = document.querySelector("button").getAttribute("aria-label");
          
      if(buttonCheck === "remove"){
         const aTagInnerText = document.querySelector("a").innerText;
         myArray.push(aTagInnerText.trim(" "));
      }
      
      console.log(myArray)
      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width">
      
      </head>
      <body>
      <ul class="abc">
       <li class="xyz">
        <a href="www.something.com">
         <div>
          <h2>
           <div>
            <div class="theText">
             <div>Get this text</DIV>
            </div>
           </div>
          </h2>
         </div>
        </a> 
        <button aria-label="remove">...</button>
       </li>
       <li>...Same stuff here as above li...</li>
       <li>...Same stuff here as above li...</li>
       <li>...Same stuff here as above li...</li>
      </ul>
      </body>
      
      </html>

      【讨论】:

        【解决方案5】:

        这是进行条件检查的“旧”方式,但.if() 命令更好,因为它在加载异步数据时具有内置的重试。

        let myArray: any = []
        
        cy.get('li[class="xyz"]').each(($element) => {
        
          // Use jquery to check the button has remove attribute
          const removeButton = $element.find('button[aria-label="remove"]')
          if (removeButton.length) {
        
            cy.wrap($element).find('div[class="theText"]')
              .invoke('text').then(text => {
                myArray.push(text)
              })
          }
        }).then(() => {
          cy.wrap(myArray).as('myArray')
        })
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-09-20
          • 2022-11-28
          • 1970-01-01
          • 2023-03-27
          • 2018-03-10
          • 2022-11-25
          • 1970-01-01
          相关资源
          最近更新 更多