How to test stripe elements with Cypress in NextJs app without extra libs

Viewed 23

How can I test stripe elements with Cypress. I am trying to target the Cart Input, Cart Cvc and Cart Expiry. I found two article that I tried to follow - https://medium.com/swinginc/testing-stripe-integration-with-cypress-3f0d665cfef7 and one that comes from stripe - https://www.cypress.io/blog/2020/02/12/working-with-iframes-in-cypress maybe first the markup:

 <section className="w-full" data-testid="credit-card">
        <span className="relative flex items-center justify-between">
          <ChipIcon className="h-9 w-9 text-midnight" strokeWidth={1} />
          <RssIcon className="rotate-90 text-midnight" />
        </span>
        <span className="capitalize font-anonymous text-midnight text-xs">
          card number
        </span>
        <CardNumberElement
          onChange={({ complete }) => {
            mustCorrectError && setPaymentState({ type: "InitialState" });
            handleCardInputStateChange(complete, "cardNumber");
          }}
          className="border border-white text-white p-2"
          options={commonInputStyles}
        />
        <div className="flex justify-between items-end mt-2">
          <div>
            <span className="uppercase font-anonymous text-midnight text-xs">
              cvc
            </span>
            <CardCvcElement
              onChange={({ complete }) => {
                mustCorrectError && setPaymentState({ type: "InitialState" });
                handleCardInputStateChange(complete, "cvc");
              }}
              className="border border-white text-white p-2 w-12"
              options={{ ...commonInputStyles, placeholder: "CVC" }}
            />
          </div>
          <div>
            <span className="capitalize font-anonymous text-midnight text-xs">
              valid thru
            </span>
            <CardExpiryElement
              onChange={({ complete }) => {
                mustCorrectError && setPaymentState({ type: "InitialState" });
                handleCardInputStateChange(complete, "expiration");
              }}
              className="border border-white text-white p-2 w-20"
              options={{
                ...commonInputStyles,
                placeholder: "MM / YY",
              }}
            />
          </div>
          <EuroIcon className="text-midnight" />
        </div>
      </section>

here I have a component and in this component I have three Stripe Element Components - Card number, Cvc and Expiry and following the above mentioned artcile I have created custom command

Cypress.Commands.add("getStripeElement", (fieldName, index) => {
  if (Cypress.config("chromeWebSecurity")) {
    throw new Error(
      "To get stripe element `chromeWebSecurity` must be disabled"
    );
  }
  const selector = `input[data-elements-stable-field-name="${fieldName}"]`;
  cy.get("iframe")
    .eq(index)
    .its("0.contentDocument")
    .should("exist")
    .its("body")
    .should("not.be.undefined")
    .then(cy.wrap)
    .find(selector);
});

The only tweak I made is adding index to target the iframe I am after (because cypress finds 5, it should 3 however, when I increment index above 2 it changes the error from not finding nothing within iframes body to not finding body). Even if I look for the div#root which is the most outer wrapper within body it does not find it. This is my test:

it("User can successfully purchase after filling the form correctly",
      () => {
        cy.getByData("credit-card").getStripeElement("cardNumber", 2);
        // AssertionError
        // Timed out retrying after 4000ms: Expected to find element: input[data-elements-stable-field-name="cardNumber"], but never found it. Queried from element: <body>
      }
    );

Thanks

0 Answers
Related