Cypress - iframe - 无法定位第二个字段,测试挂起然后超时

Cypress - iframes - Unable to target second field, the test hangs then times out

我遇到了一个问题,一旦我的测试卡号被输入到第一个 iframe 中,测试就会尝试以第二个 iframe (CVC) 为目标,并且在尝试以该元素为目标时超时。所有信息都列在下面。感谢您对失败原因的任何帮助!

使用的自定义命令:

    // Make the iframe command return the body contents once it’s loaded
    Cypress.Commands.add("iframe", { prevSubject: "element" }, ($iframe) => {
    return new Cypress.Promise((resolve) => {
       $iframe.on("load", () => {
         resolve($iframe.contents().find("body"));
      });
     });
    });

针对来宾用户的卡号和 CVC 的命令

    // Checkout Add Card New Customer Card Number

    Cypress.Commands.add(
      "addCardNewCustomerCybersourceCardNumber",
      ({ cardNumber, expiry }) => {
      // Card number iFrame
      cy.get("#cardNumber-container > iframe")
         .iframe()
         .find('input[name="number"]')
         .should("be.visible")
         .should("have.attr", "placeholder", "Enter card number")
         .type(cardNumber);
       // Expiry date is not an iframe
      cy.get("[data-cy=expiryDate]").type(expiry);
     }
    );

     // Checkout Add Card New Customer CVC

     Cypress.Commands.add("addCardNewCustomerCybersourceCVC", ({ cvc }) => {
       // CVC iFrame
     cy.get("#cvc-container > iframe")
        .iframe()
        .find('input[name="securityCode"]')
        .should("be.visible")
        .should("have.attr", "placeholder", "•••")
        .type(cvc);
     });

这是来自测试的 'it' 个语句:

        it("User adds new AMEX card for payment - Card number", () => {
           cy.addCardNewCustomerCybersourceCardNumber({
               cardNumber: "370000000000002",
               expiry: "0330",
         });
      });
        it("User adds new AMEX card for payment - CVC", () => {
           cy.addCardNewCustomerCybersourceCVC({
               cvc: "7373",
         });
      });

这是显示测试正在做什么的屏幕截图。它成功找到卡输入并填写,但 CVC 失败。

然后超时,测试无法完成:

注意它试图找到的选择器是正确的。

仅在不需要卡号的不同场景中尝试定位 CVC 字段时,这也适用。

用于此的代码与有问题的命令相同。

// Select Existing Card Cybersource
  Cypress.Commands.add("selectExistingCardCybersource", ({ cvc }) => {
// CVC iFrame
   cy.get("#cvc-container > iframe")
       .iframe()
       .find('input[name="securityCode"]')
       .should("be.visible")
       .should("have.attr", "placeholder", "•••")
       .type(cvc);
   });

知道出了什么问题吗?这是一个很大的阻碍。

已编辑以包含完整内容 HTML。

<div class="tab-content">
    <div>
        <div class="row">
            <div class="col-sm-12">
                <div class="sc-bYoBSM efbeJM">
                    <div class="sc-ezbkAF jQjguY">
                        <div class="sc-dJjYzT hFgVEy">Name on card</div><input class="sc-kLwhqv hfTyyh card-name"
                            placeholder="Your name" data-cy="cardName">
                    </div>
                    <div class="sc-ezbkAF jQjguY">
                        <div class="sc-dJjYzT hFgVEy">Card number</div>
                        <div id="cardNumber-container" class="sc-ikJyIC gvVat flex-microform flex-microform-valid">
                            <iframe hspace="0" vspace="0" frameborder="0" scrolling="no" allowtransparency="true"
                                marginwidth="0" marginheight="0"
                                src="https://testflex.cybersource.com/cybersource/assets/microform/0.11.5/iframe.html?keyId=081ZqeqNTRWxPWy3gLgtSt7reOnfdz2l#{&quot;microformId&quot;:&quot;e01efa2c-96b6-43ae-a038-e81de8a9ae17&quot;,&quot;fieldId&quot;:&quot;58666f5e-2c66-4d7a-9dae-a549dd7e8ea6&quot;,&quot;jwt&quot;:&quot;eyJraWQiOiJ6dSIsImFsZyI6IlJTMjU2In0.eyJmbHgiOnsicGF0aCI6Ii9mbGV4L3YyL3Rva2VucyIsImRhdGEiOiJuSWloUXg4ekdmOTZ0NnpkMDdKSTN4QUFFSUczSEl5WXUxMzZMT0ZtdHFOZE4yOFplUTRTY2FuNWJsbmllUGl4SEZkM0Vxa1BlUVAySStZNGVWYlV2bE9EcGI4VEFxbi9DeWNBam1xK0c2S0MwRlIyamthR2VNa05pQ3hRbTZSUGpGblciLCJvcmlnaW4iOiJodHRwczovL3Rlc3RmbGV4LmN5YmVyc291cmNlLmNvbSIsImp3ayI6eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsInVzZSI6ImVuYyIsIm4iOiI0ZHpNdFpWLXRjYU1KYTVfOUZtUm5wMDFZWGJ0VFNYWTV0enh4LWdldlR4Nm9ZZURuZnBiWnFPVllIZFZHX2dOY0dJb0NuX0lFSWhkaHZURHBwU1VIUHdiVlhKMWJfbDNuWHFUT09vNW9hWW5aeW45VVRUQzJLelIzQzFuVFBZOFJ6SjB2YkpWeXJuaG1OcTI0NHVxcy1zMnJOX24xdlpDdXFyX0xFSHBRY2F0Ynd6Ti1KMlFDOXY4dGo5dlBXVF9jNFg3U3Q5S2Y2Qm02djVzcGo0eGVBWFV5V3laa2dHVkpueTNMTWJiS0hfalZEMkMydW9UODJmcmVUVGNjV09JZWZJTTJSVnFxbEk0ZGZfcXJKdHdWTTltNU8tQklSYzBwZmplLWptMW8xMzAzUDB2ZGFTMXZmV2hoYXFjNlAtTmZ1X2pEbXZ1RGlnY24wSGUxV3daTHciLCJraWQiOiIwODFacWVxTlRSV3hQV3kzZ0xndFN0N3JlT25mZHoybCJ9fSwiY3R4IjpbeyJkYXRhIjp7InRhcmdldE9yaWdpbnMiOlsiaHR0cHM6Ly93ZWJkZXYwMDEubGFpdGh3YWl0ZXMuY28udWs6OTE5MCJdLCJtZk9yaWdpbiI6Imh0dHBzOi8vdGVzdGZsZXguY3liZXJzb3VyY2UuY29tIn0sInR5cGUiOiJtZi0wLjExLjAifV0sImlzcyI6IkZsZXggQVBJIiwiZXhwIjoxNjQ2MTQ5MTk4LCJpYXQiOjE2NDYxNDgyOTgsImp0aSI6IjdPc3JDZ1VkbFhoYVdLb2MifQ.MtWDbBZfK6YBK6RE9mwBEgZ249jbFgIDrmCjDC4lyAGQRgL3JMBPVsrnj5CNLk3QKamnMF4za25FouGsaAWBEq8MHssNaXLxEspwEM702THodpTQ0-2NZ1nAx5trtx2LvoDjIAUliKHHrgvMcvAQS04IfsWKZwehm9hLmRilnVi6NNq2eyEPLpcbeoQx55cJyKA2lvsWZxDwqVyo5q_LqwqeCrcxvIQzXRbn8_zJXwymROgYKZGgQ-lGoxwns2EJDgVM1kg2f2-SZTza4aoN7SDBVljL-JpsAV_dS9thXLWJ2ov3tgIezMRDPPNDuTwCZDPHY5Ai4kCC2_t_70fM2w&quot;,&quot;microformConfig&quot;:{&quot;styles&quot;:{&quot;input&quot;:{&quot;font-size&quot;:&quot;16px&quot;,&quot;font-family&quot;:&quot;Roboto, sans-serif&quot;}}},&quot;config&quot;:{&quot;placeholder&quot;:&quot;Enter card number&quot;},&quot;fieldType&quot;:&quot;number&quot;}"
                                style="overflow: hidden; position: relative; border: none; width: 100%; height: 100%;"></iframe>
                        </div>
                    </div>
                    <div class="sc-ezbkAF jQjguY">
                        <div class="sc-dJjYzT hFgVEy">Expiry date*</div><input name="expiryDate"
                            aria-label="Expiry date in format MM YY" autocomplete="cc-exp" id="expiryDate"
                            placeholder="MM/YY" type="tel" data-cy="expiryDate"
                            class="sc-kLwhqv hfTyyh expiry-date null" value="">
                    </div>
                    <div class="sc-ezbkAF jQjguY">
                        <div class="row">
                            <div class="col-sm-12">
                                <div class="sc-dJjYzT hFgVEy">Security code*</div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-sm-4">
                                <div id="cvc-container" class="sc-jJoQJp ewxrAe flex-microform"><iframe hspace="0"
                                        vspace="0" frameborder="0" scrolling="no" allowtransparency="true"
                                        marginwidth="0" marginheight="0"
                                        src="https://testflex.cybersource.com/cybersource/assets/microform/0.11.5/iframe.html?keyId=081ZqeqNTRWxPWy3gLgtSt7reOnfdz2l#{&quot;microformId&quot;:&quot;e01efa2c-96b6-43ae-a038-e81de8a9ae17&quot;,&quot;fieldId&quot;:&quot;dce7c4ce-d302-47ae-9d0b-f7b2be73dbad&quot;,&quot;jwt&quot;:&quot;eyJraWQiOiJ6dSIsImFsZyI6IlJTMjU2In0.eyJmbHgiOnsicGF0aCI6Ii9mbGV4L3YyL3Rva2VucyIsImRhdGEiOiJuSWloUXg4ekdmOTZ0NnpkMDdKSTN4QUFFSUczSEl5WXUxMzZMT0ZtdHFOZE4yOFplUTRTY2FuNWJsbmllUGl4SEZkM0Vxa1BlUVAySStZNGVWYlV2bE9EcGI4VEFxbi9DeWNBam1xK0c2S0MwRlIyamthR2VNa05pQ3hRbTZSUGpGblciLCJvcmlnaW4iOiJodHRwczovL3Rlc3RmbGV4LmN5YmVyc291cmNlLmNvbSIsImp3ayI6eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsInVzZSI6ImVuYyIsIm4iOiI0ZHpNdFpWLXRjYU1KYTVfOUZtUm5wMDFZWGJ0VFNYWTV0enh4LWdldlR4Nm9ZZURuZnBiWnFPVllIZFZHX2dOY0dJb0NuX0lFSWhkaHZURHBwU1VIUHdiVlhKMWJfbDNuWHFUT09vNW9hWW5aeW45VVRUQzJLelIzQzFuVFBZOFJ6SjB2YkpWeXJuaG1OcTI0NHVxcy1zMnJOX24xdlpDdXFyX0xFSHBRY2F0Ynd6Ti1KMlFDOXY4dGo5dlBXVF9jNFg3U3Q5S2Y2Qm02djVzcGo0eGVBWFV5V3laa2dHVkpueTNMTWJiS0hfalZEMkMydW9UODJmcmVUVGNjV09JZWZJTTJSVnFxbEk0ZGZfcXJKdHdWTTltNU8tQklSYzBwZmplLWptMW8xMzAzUDB2ZGFTMXZmV2hoYXFjNlAtTmZ1X2pEbXZ1RGlnY24wSGUxV3daTHciLCJraWQiOiIwODFacWVxTlRSV3hQV3kzZ0xndFN0N3JlT25mZHoybCJ9fSwiY3R4IjpbeyJkYXRhIjp7InRhcmdldE9yaWdpbnMiOlsiaHR0cHM6Ly93ZWJkZXYwMDEubGFpdGh3YWl0ZXMuY28udWs6OTE5MCJdLCJtZk9yaWdpbiI6Imh0dHBzOi8vdGVzdGZsZXguY3liZXJzb3VyY2UuY29tIn0sInR5cGUiOiJtZi0wLjExLjAifV0sImlzcyI6IkZsZXggQVBJIiwiZXhwIjoxNjQ2MTQ5MTk4LCJpYXQiOjE2NDYxNDgyOTgsImp0aSI6IjdPc3JDZ1VkbFhoYVdLb2MifQ.MtWDbBZfK6YBK6RE9mwBEgZ249jbFgIDrmCjDC4lyAGQRgL3JMBPVsrnj5CNLk3QKamnMF4za25FouGsaAWBEq8MHssNaXLxEspwEM702THodpTQ0-2NZ1nAx5trtx2LvoDjIAUliKHHrgvMcvAQS04IfsWKZwehm9hLmRilnVi6NNq2eyEPLpcbeoQx55cJyKA2lvsWZxDwqVyo5q_LqwqeCrcxvIQzXRbn8_zJXwymROgYKZGgQ-lGoxwns2EJDgVM1kg2f2-SZTza4aoN7SDBVljL-JpsAV_dS9thXLWJ2ov3tgIezMRDPPNDuTwCZDPHY5Ai4kCC2_t_70fM2w&quot;,&quot;microformConfig&quot;:{&quot;styles&quot;:{&quot;input&quot;:{&quot;font-size&quot;:&quot;16px&quot;,&quot;font-family&quot;:&quot;Roboto, sans-serif&quot;}}},&quot;config&quot;:{&quot;placeholder&quot;:&quot;•••&quot;},&quot;fieldType&quot;:&quot;securityCode&quot;}"
                                        style="overflow: hidden; position: relative; border: none; width: 100%; height: 100%;"></iframe>
                                </div>
                            </div>
                            <div class="cvc col-sm-8">The last 3 digits on the back of your Credit or Debit card
                                (Amex 4 digits on the front).</div>
                        </div>
                    </div>
                    <div class="sc-gWXbKe bZJPUc"><label class="sc-eCImPb caZvFZ checkbox"><input
                                name="saveCreditCard" type="checkbox" class="sc-iqseJM gIJDbg" value="false">
                            <div class="sc-pVTFL imLlDI"><svg viewBox="0 0 24 24" class="sc-gKclnd dZWWmA">
                                    <polyline points="20 6 9 17 4 12"></polyline>
                                </svg></div>Add this card to my wallet
                        </label></div>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col"><button type="button" data-cy="useExistingCard" class="sc-crHmcD jOSMtb gotoCard link"
                    style="margin-bottom: 10px;">Cancel and return</button></div>
        </div>
    </div>
    <div class="sc-iIUQWv gaphzu">
        <div class="col-sm-6"><button data-cy="payCard" type="submit" id="confirmAndPay"
                class="sc-crHmcD jOSMtb block">Pay Now</button></div>
    </div>
</div>

我也添加了.focus() 这个成功进入了CVC字段但是type命令超时还是失败了

@BillBaily 谢谢,但我正在寻找更大的 HTML,涵盖两个 iframe。

但另一个建议 - 我在另一个使用 WorldPay 的项目上看到 nested iframe,所以你需要像

这样的东西

// Checkout Add Card New Customer CVC

Cypress.Commands.add("addCardNewCustomerCybersourceCVC", ({ cvc }) => { // CVC iFrame

  cy.get("#cardNumber-container > iframe")
    .iframe()
    .within(() => {

      cy.get("#cvc-container > iframe")
        .iframe()
        .find('input[name="securityCode"]')
        .should("be.visible")
        .should("have.attr", "placeholder", "•••")
        .type(cvc)
    })
 })

但是不需要卡号的测试与这个理论相矛盾,但值得一提的是,以防两种情况下页面结构不同。

(顺便说一句,正在使用什么支付库?)


我刚刚注意到,在最后一张截图中,CVC 字段确实获得了焦点,但名称和有效期为空。

这看起来像是验证可能会阻止在字段中输入任何内容。您可以通过手动尝试只输入 CVC 来检查。

试试这个进行测试

it("User adds new AMEX card for payment - CVC", () => {

  cy.addCardNewCustomerCybersourceCardNumber({
    cardNumber: "370000000000002",
    expiry: "0330",
  })

  // May need a name as well

  cy.addCardNewCustomerCybersourceCVC({
    cvc: "7373",
  })
})

或者(作为最后的手段)在 addCardNewCustomerCybersourceCVC 中使用 .type(cvc, {force:true})

我已经通过改变处理 CVC 领域的方式解决了这个问题。

使用以下命令解决了我的问题。

// Checkout Add Card New Customer CVC
Cypress.Commands.add("addCardNewCustomerCybersourceCVC", ({ cvc }) => {
  cy.get("#cvc-container > iframe").then(($element) => {
    const $body = $element.contents().find("body");
    let cvcField = cy.wrap($body);
    cvcField = cy.wrap($body);
    cvcField
      .find('input[name="securityCode"]')
      .should("be.visible")
      .should("have.attr", "placeholder", "•••")
      .click()
      .type(cvc);
  });
});

谢谢大家的帮助!