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

I'm coming across an issue where once my test card number is typed into the first iframe the test tries to target the 2nd iframe (CVC) & it times out whilst trying to target the element. All info is listed below. Any help to why this is failing is appreciated!

Custom commands used:

    // 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"));
      });
     });
    });

Commands for targeting the card number & CVC for guest users

    // 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);
     });

This are the 'it' statements from the test:

        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",
         });
      });

Here's a screenshot showing what the test is doing. It successfully finds the card input & fills it in but it fails for the CVC.

enter image description here

It then times out and the test cannot complete:

enter image description here

NOTE The selector it's trying to find is correct.

enter image description here

This also works when only trying to target the CVC field in a different scenario where a card number is not needed.

enter image description here

The code used for this is identical to the command that is having issues.

// 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);
   });

Any idea what is going wrong? This is quite a big blocker.

EDITED TO INCLUDE THE FULL 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>

I've also added .focus() This successfully enters the CVC field but the type command still fails as it times out.

enter image description here



Solution 1:[1]

I've been able to solve this by changing the way I approach the CVC field.

Using the below command fixed my problems.

// 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);
  });
});

Thanks, everyone for your help with this!

Solution 2:[2]

@BillBaily Thanks but I was looking for a larger piece of HTML, covering both iframes.

But another suggestion - I have seen on another project that uses WorldPay has nested iframes, so you would need something like


// 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)
    })
 })

But the test where a card number is not needed contradicts this theory, but worth mentioning in case the page structure differs between the two scenarios.

(BTW what payment library is being used?)


I just noticed that in the last screenshot the CVC field has indeed got focus, but name and expiry are empty.

This looks like validation may be preventing anything from being typed into the field. You can check that out by manually trying to only enter the CVC.

Try this for the test

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",
  })
})

Or (as a last resort) use .type(cvc, {force:true}) in addCardNewCustomerCybersourceCVC.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Billy Bailey
Solution 2 Fody