【问题标题】:Cypress conditional testing code suggestionsCypress 条件测试代码建议
【发布时间】:2020-07-20 00:45:15
【问题描述】:

我不知道如何使用赛普拉斯实现 if & else 自动化。我是 Cypress & JS 的新手,正在努力解决这个问题。

我有问题页面,有时是 3,有时是 4。不一致。我只是想处理柏树点击否的情况,如果它发现 4 个“否”按钮。最后的 CTA 按钮也会发生变化,如果出现第 4 个问题,CTA 的文本也会发生变化。

赛普拉斯中“应该”的问题在于它断言然后失败。我想要类似 IsDisplayed in selenium 的东西。

我知道不建议进行条件测试,但我现在没有选择。请帮我解决这个问题。

这是我的代码:

    //cy.get(`button[name="cosmeticDamage"][value="${cosmetic}"]`).then($a => {
    cy.get('div span.MultiScreenForm__content').then($a => {
      if ($a.attr('name', `[name="cosmeticDamage"][value="${cosmetic}"]`).length > 0) {
        cy.log('Cosmetic Damage Button does exist: ==>');
        cy.get(`button[name="cosmeticDamage"][value="${cosmetic}"]`).click();
      } else {
        cy.log('Cosmetic Damage Button does not exist, do Nothing');
      }
    });
  }

【问题讨论】:

  • 你的代码输出了什么?
  • @KaranSharma 当按钮不存在时它会失败。所以我不确定代码是否工作正常。即使按钮不存在,它也会进入 if 条件循环。

标签: javascript cypress


【解决方案1】:

我知道不建议进行条件测试,但我现在没有选择。

是的,您确实可以选择。我先道歉,这不是一个快速,简单的答案。 cypress 中的条件测试可能很棘手,但是,当您了解它时,您的测试会更好。你确实有更好的选择,我会尽力解释,所以就这样吧。

对于这种情况,您必须调整处理问题的方式。目前,您的条件基于 UI 元素,as Cypress documentation states 会导致小猫爆炸。没有人想要爆炸的小猫。相反,您想要做的是将您的条件所基于的事实来源从使用 UI 元素更改为将您的条件基于更稳定的东西,例如服务器响应。

就我个人而言,要想在实践中真正做到这一点非常困难,所以我会尽力解释。

所以,目前,您正在执行以下操作:

  • 发出请求(#of 个问题)并根据响应设置页面加载和视图。
  • 如果 UI 元素在页面上(第 4 个问题),则测试按钮

你想要的是:

  • 已提出请求(有多少问题?)
  • 使用cy.route("someAlias")cy.wait('@someAlias') 从请求中捕获响应
  • 来自服务器的响应是您的 UI 元素构建自身的信息。 请以此为基础。(请参阅Routes & Aliases

所以你的情况会是这样的:

if questions returned in response > 3 then test button.

这里的理论是,您的服务器是可靠的事实来源,其中包含您需要的所有信息,就在前面。 DOM(UI 元素)不是因为它没有预先提供您需要的所有信息,并且在您的情况下无法保证它会解决您继续进行所需的内容。

如果您的服务器回答的问题超过 3 个,那里应该有一个按钮。在这里切换逻辑使您的测试更加稳定,并且您实际上正在测试您想要测试的东西。 当你有超过 3 个问题时,你应该有一个按钮如果 UI 元素超过三个,那么您应该有一个按钮。 无法保证在满足 UI 元素条件时您的按钮已经解析。您的服务器响应应该是您的真实来源,而不是 UI 元素。

我不知道您提出请求的逻辑,因此我的回答并不准确,但是,让我们假设在页面加载时,有一个对/questions 的请求以您提出的问题作出回应'重新谈论(3或4)。您的代码将如下所示:

// setup the route to wait for
cy.server();
cy.route("/questions").as("questions");
// do whatever you do that sends that request
cy.visit("/pageOfQuestions");
// wait for request and grab response using route alias
cy.wait("@questions").then(function(xhr) {
  // find your path (I'm guessing here) to the info you need and test condition
  // the condition and the path to the info will vary based on what your response 
  // actually contains
  if(xhr.response.questions.length > 3) {
    // test your button-y stuff here
    cy.get(`button[name="cosmeticDamage"][value="${cosmetic}"]`).click();
  } else {
    cy.log("nothing to test");
}

不同之处在于,当您将条件(事实来源)基于 UI 元素时,DOM 并不总是以您期望的方式自行解析。当您达到条件时(在本例中为问题 UI 元素),其他事情仍未自行解决(按钮 UI 元素)。您必须等待 DOM 中的两个元素对齐 -> 您的事实来源(条件)和要测试的 UI 元素(按钮)。通常,一个没有加载而另一个加载,你不能依赖它们始终加载,这就是为什么 cypress 建议不要基于 UI 元素的条件,除非你喜欢爆炸的小猫。

换一种说法,假设 DOM 有 10 个资源要加载。你对柏树说: if resource #7 looks like this then play with resource #1

Cypress 等待资源 7。当它准备好时,它会检查条件是否满足,然后尝试使用资源 1... DOM 可能尚未解决。实际上,有时它可以被加载,但你永远无法保证它会导致不稳定的测试。

当您基于服务器响应的事实来源时,您只需等待和测试一个 UI 元素,cypress 内置超时可以成功等待该元素加载而不依赖于另一个。 On page load, did the server give us more than 4 things? Then play with UI element

如果有什么我可以澄清的,尽管问。

参考:

【讨论】:

    【解决方案2】:

    我从你的描述和你提供的片段中了解到[name="cosmeticDamage"] 总是存在几个元素,所以我不太确定.length 是如何使[name="cosmeticDamage"][value="${cosmetic}"] 增值的,这可能意味着你的情况总是真的。

    我建议使用find,因为它会过滤匹配的后代 DOM 元素:

        cy.get('div span.MultiScreenForm__content').then($form => {
            if ($form.find(`[name="cosmeticDamage"][value="${cosmetic}"]`).is(':visible')) {
                cy.get(`button[name="cosmeticDamage"][value="${cosmetic}"]`).click();        
            } else {
                cy.log('Cosmetic Damage Button does not exist, do Nothing');
            }
        });
    

    【讨论】:

      猜你喜欢
      • 2022-09-30
      • 2019-12-27
      • 1970-01-01
      • 2022-12-16
      • 2022-01-14
      • 1970-01-01
      • 1970-01-01
      • 2020-06-05
      • 1970-01-01
      相关资源
      最近更新 更多