【问题标题】:How to read data value for Cypress?如何读取赛普拉斯的数据值?
【发布时间】:2019-10-14 00:53:20
【问题描述】:

我正在尝试从 API 响应中读取数据。 Chrome Inspect 中的 html 显示了值,但是数字变为 4 或 5。我需要 Cypress 读取数据,并根据该值,做一定的条件。

html

<p _ngcontent-wvl-c5="" class="availablelicenses"> 5 </p>

柏树

it("number of licences", function(){
    cy.get('p[class="availablelicenses"]').as("avc");
    cy.get('p[class="totallicenses"]').as("ls");
    if (avc == ls){
      cy.get('button[id="cyAdd"]').click()
      cy.get('p[class="add-user"]').contains('All licenses are already assigned')
    }
    else {
      cy.get('button[id="cyAdd"]').click()
      cy.get('[data-cy=cyFirst').type('testName')
      cy.get('[data-cy=cyLast').type('testLast')
      cy.get('[data-cy=cyEmail').type('testEmail@mailinator.com')
    }
  });

【问题讨论】:

  • 不确定在您的场景中是否可行,但您应该设计测试,以便知道许可证数量是多少,然后创建两个测试,一个用于 4 个许可证,另一个用于 5 个许可证。也许您可以使用cy.route() 对 API 进行存根,以使每个测试都看到适当的数字。

标签: javascript angular cypress


【解决方案1】:

最简单的方法是先获取文本,如下所示:

const licensesOne = document.querySelector('p[class="availablelicenses"]').innerText;
const licensesTwo = document.querySelector('p[class="totallicenses"]').innerText;

if (licensesOne === licensesTwo) {
  // Checks to run if texts are equal
} else {
  // Checks to run if texts are different
}

请注意,.innerText.querySelector(…) 一次只能处理一个元素。如果您有多个元素,则可能需要使用循环。此外,.innerText 可能在不同浏览器中的工作方式不一致。

除此之外,正如@eric99 正确指出的那样,document.querySelector 根本不会等待元素更新/出现。因此,如果您在 API 调用后立即运行此测试,您可能更喜欢使用下面介绍的方法。

还有一种替代方式,涉及程度更高proposed by Cypress。应用于您的案例,它看起来像这样:

// Gets text of element and passes it to "then" callback
cy.get(`p[class="availablelicenses"]`).invoke('text').then(
  availableLicensesText => {
    //Gets text of second element & passes it to "then" callback
    cy.get(`p[class="totallicenses"]`).invoke(`text`).then(totalLicensesText => {
      if( availableLicensesText ===  totalLicensesText){
        // Checks to run if texts are equal
      } else {
        // Checks to run if texts are different
      }
    });
  }
);

【讨论】:

  • 第一行看起来不对 - cy.get() 返回一个链接器,而不是像 document.querySelector() 这样的元素。你测试过这段代码吗?
  • @eric99 我刚刚做了,你是对的,它返回了一个链接器。感谢您指出,我刚刚更新了答案。
  • 看起来不错。另一件事是,由于许可证计数是从 API document.querySelector() 返回的,因此无需等待,因此该语句可能会在 fetch 完成时运行。赛普拉斯的cy.get() 有一个内置等待,但如果p[class="availablelicenses"] 是静态的(即在获取之前在Angular 模板上),它也会返回太快。将.should() 替换为.then() 可能会更幸运,因为应该将超时应用于内部检查(您的评论行)。
  • @eric99 谢谢,我又更新了答案:)
【解决方案2】:

如果可能,我建议放弃 if 语句,并执行两个测试。通过确保两条路径都经过测试,这将为您提供更好的覆盖范围。

context("number of licences", function() {

  it('when max licences not assigned, should allow licence entry', () => {

    cy.server();

    // Stubbed with mock response of same shape as real response
    cy.route('api/path/to/licence/count', {
      assigned: 4,   
      total: 5
    })

    cy.contains('p[class="availablelicenses"]', '4'); // confirms stubbed response used 
    cy.contains('p[class="totallicenses"]', '5');     

    cy.get('button[id="cyAdd"]').click()
    cy.get('[data-cy=cyFirst').type('testName')
    cy.get('[data-cy=cyLast').type('testLast')
    cy.get('[data-cy=cyEmail').type('testEmail@mailinator.com')
  });

  it('when max licences assigned, should not allow licence entry', () => {

    cy.server();

    // Stubbed with mock response of same shape as real response
    cy.route('api/path/to/licence/count', {
      assigned: 5,   
      total: 5
    })

    cy.contains('p[class="availablelicenses"]', '5'); // confirms stubbed response used 
    cy.contains('p[class="totallicenses"]', '5');     

    cy.get('button[id="cyAdd"]').click()
    cy.get('p[class="add-user"]').contains('All licenses are already assigned')
  });

});

如果你不能存根 API,你可以使用类似于 Igor 的最后一个建议的东西,但我会远离 document.querySelector('p[class="availablelicenses"]'),因为它会很脆弱,请参阅文档的这一部分 Retry-ability

另外,出于同样的原因,请使用should() 而不是.then()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-12
    • 2020-12-23
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多