Cypress 从元素列表获取文本

huangapple go评论52阅读模式
英文:

Cypress get text from list of elements

问题

以下是您要翻译的部分:

I have seen a bunch of people asking a similar question, but the answers are not working for me.

Here is the html:

<!-- 省略部分HTML代码 -->

I need to get the list of products for a specific investor and return it, since I use this in multiple places, I was trying to make a method that I could call to:

  • first check if a product for a specific investor was already added
  • add it if not and verify it's now present.

Here is my method code:

/**
 * Returns a list of products for the investor passed
 * @param {string} investor 
 * @return {array} list of products
 */
getListofProductsAlreadyPresent(investor) {
    // 省略部分JavaScript代码
}

And the call to the method:

// 省略部分JavaScript代码

and after the product gets added:

// 省略部分JavaScript代码

My code above doesn't work. It would be very easy to do this with Xpath, since one Xpath would get the list of elements, but I'd rather not have to use the xpath module unless that's the only solution.
What would be the best way to do this?

英文:

I have seen a bunch of people asking a similar question, but the answers are not working for me.

Here is the html:

&lt;tr role=&quot;row&quot; aria-rowindex=&quot;2&quot; class=&quot;&quot;&gt;&lt;td aria-colindex=&quot;1&quot; role=&quot;cell&quot; class=&quot;&quot;&gt;&lt;div class=&quot;d-flex&quot;&gt;
          Investor1
        &lt;/div&gt;&lt;/td&gt;&lt;td aria-colindex=&quot;2&quot; role=&quot;cell&quot; class=&quot;&quot;&gt;
        Product1
      &lt;/td&gt;&lt;td aria-colindex=&quot;3&quot; role=&quot;cell&quot; class=&quot;mr-0 pr-0 text-right&quot;&gt;&lt;button class=&quot;ml-auto minus-icon mr-1&quot;&gt;&lt;/button&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr role=&quot;row&quot; aria-rowindex=&quot;2&quot; class=&quot;&quot;&gt;&lt;td aria-colindex=&quot;1&quot; role=&quot;cell&quot; class=&quot;&quot;&gt;&lt;div class=&quot;d-flex&quot;&gt;
          Investor1
        &lt;/div&gt;&lt;/td&gt;&lt;td aria-colindex=&quot;2&quot; role=&quot;cell&quot; class=&quot;&quot;&gt;
        Product2
      &lt;/td&gt;&lt;td aria-colindex=&quot;3&quot; role=&quot;cell&quot; class=&quot;mr-0 pr-0 text-right&quot;&gt;&lt;button class=&quot;ml-auto minus-icon mr-1&quot;&gt;&lt;/button&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr role=&quot;row&quot; aria-rowindex=&quot;2&quot; class=&quot;&quot;&gt;&lt;td aria-colindex=&quot;1&quot; role=&quot;cell&quot; class=&quot;&quot;&gt;&lt;div class=&quot;d-flex&quot;&gt;
          Investor2
        &lt;/div&gt;&lt;/td&gt;&lt;td aria-colindex=&quot;2&quot; role=&quot;cell&quot; class=&quot;&quot;&gt;
        Product1
      &lt;/td&gt;&lt;td aria-colindex=&quot;3&quot; role=&quot;cell&quot; class=&quot;mr-0 pr-0 text-right&quot;&gt;&lt;button class=&quot;ml-auto minus-icon mr-1&quot;&gt;&lt;/button&gt;&lt;/td&gt;&lt;/tr&gt;

I need to get the list of products for an specific investor and return it, since I use this in multiple places, I was trying to make a method that I could call to:

  • first check if a product for a specific investor was already added
  • add it if not and verify it's now present.

Here is my method code:

/**
     * Returns a list of products for the investor passed
     * @param {string} investor 
     * @return {array} list of products
     */
    getListOfProductsAlreadyPresent(investor) {
        this.elements.sourceProductTableProduct().filter(`:contains(${investor})`).as(&#39;listForInvestor&#39;);
        cy.get(&#39;@listForInvestor&#39;).then(($els) =&gt; {
            return (Cypress.$.makeArray($els).map((element) =&gt; {
                cy.wrap(element).parent(&#39;td&#39;).next(&#39;td&#39;).invoke(&#39;text&#39;);
            })
            );
        });

And the call to the method:

 this.getListOfProductsAlreadyPresent(investor).as(&#39;productList&#39;);
 cy.wrap(&#39;@productList&#39;).then((list) =&gt; {
     if (!list.includes(sourceProduct)) {
        this.setSourceProductIfNotPresent(investor, sourceProduct, true);
     }
});          

and after the product gets added:

this.getListOfProductsAlreadyPresent(investor).as(&#39;productList&#39;);
cy.wrap(&#39;@productList&#39;).then((list) =&gt; {
     if (!list.includes(sourceProduct)) {
        throw new Error(`Source product ${sourceProduct} did not get added successfully for investor ${investor}`);
     }
});          

My code above doesn't work. It would be very easy to do this with Xpath, since one Xpath would get the list of elements, but I'd rather not have to use the xpath module unless that's the only solution.
What would be the best way to do this?

答案1

得分: 3

我可以给你一个更干净的示例

问题的HTML可以用以下方式表示。我已经在文本周围添加了一些空格,因为这似乎也是你的问题。

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;

      one
    
    &lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;
      
      two
    
    &lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

您可以检索行并基于:contains伪选择器应用过滤器。

如果文本是"three"(不在HTML中),found为false。

cy.get(&#39;tr&#39;).then($rows =&gt; {
  const result = $rows.filter(&#39;:contains(three)&#39;)
  const found = !!result.length
  expect(found).to.eq(false)
})

如果文本是"two"(在HTML中),found为true。

cy.get(&#39;tr&#39;).then($rows =&gt; {
  const result = $rows.filter(&#39;:contains(two)&#39;)
  const found = !!result.length
  expect(found).to.eq(true)
})


<details>
<summary>英文:</summary>

I can give you a cleaner example

The problem HTML can be represented by this. I&#39;ve added some white-space around the text, as that seems to be an issue for you as well.

```html
&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;

      one
    
    &lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;
      
      two
    
    &lt;/td&gt;&lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

You can retrieve the rows and apply a filter based on the :contains pseudo-selector.

If the text is "three" (not in the HTML), found is false.

cy.get(&#39;tr&#39;).then($rows =&gt; {
  const result = $rows.filter(&#39;:contains(three)&#39;)
  const found = !!result.length
  expect(found).to.eq(false)
})

If the text is "two" (which is in the HTML), found is true.

cy.get(&#39;tr&#39;).then($rows =&gt; {
  const result = $rows.filter(&#39;:contains(two)&#39;)
  const found = !!result.length
  expect(found).to.eq(true)
})

答案2

得分: 0

我最终为这两种情况实施如下,它有效,但是否有办法将其封装为一个方法,以便不必重复两次代码?

this.elements.sourceProductTableInvestorProduct().then(($els) => {
    let found = false;
    for (const element of $els) {
        const innerText = `${element.innerText.split(/\r?\n/)[0].trim()} ${element.innerText.split(/\r?\n/)[1].trim()}`;
        cy.log(`InnerText: ${innerText} and investor: ${investor} and product: ${sourceProduct}`);
        if (innerText.includes(investor) && innerText.includes(sourceProduct)) {
            found = true;
        }
    }
    if (!found) {
        ....
    }
});
英文:

So I ended up implementing it as follow for both cases, which works, but is there a way to make a method out of it so I don't have to repeat the code twice?

this.elements.sourceProductTableInvestorProduct().then(($els) =&gt; {
            let found = false;
            for (const element of $els) {
                const innerText = `${element.innerText.split(/\r?\n/)[0].trim()} ${element.innerText.split(/\r?\n/)[1].trim()}`;
                cy.log(`InnerText: ${innerText} and investor: ${investor} and product: ${sourceProduct}`);
                if (innerText.includes(investor) &amp;&amp; innerText.includes(sourceProduct)) {
                    found = true;
                }
            }
            if (!found) {
                ....
            }
        });

huangapple
  • 本文由 发表于 2023年2月27日 01:19:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75573737.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定