14
votes

I have to call stripe.redirectToCheckout (https://stripe.com/docs/js/checkout/redirect_to_checkout) in js to take a customer to their stripe checkout page.

I want to use cypress to test the checkout process, but it is not able to handle the stripe redirect as the cypress frame is lost when stripe.redirectToCheckout navigates to the page on Stripe's domain.

I also want to test that Stripe redirects us back to the success or error URL.

  1. Is there any way to force cypress to "reattach" to the page once we've navigated to the Stripe checkout -or-
  2. Is there any way to get the URL for the Stripe checkout page so we can redirect manually or just know that it was at least called with the right parameters.

I know that testing external sites is considered an "anti-pattern" by the people at cypress (https://github.com/cypress-io/cypress/issues/1496). But how can a very standard web process, checkout, be tested (with a very popular and standard payment service, I will add) in that case? I don't buy that this is an "anti-pattern". This is an important step of the end-to-end test, and Stripe specifically gives us a testing sandbox for this kind of thing.

3
Did you end finding a solution? I had the same problem. I tried to catch the redirect with stubs but no luck. - denislexic
no. Just gave up on Cypress and used selenium derivatives - Salami
@denislexic I have added a bounty to this question - Norfeldt
@Norfeldt Awesome. I'm unfortunately unable to answer it still... - denislexic

3 Answers

2
votes

One common way to e2e test application with external dependencies like stripe is to make a simple mock version of it, that is then applied in e2e testing. The mock can also be applied during development, to speed things up.

0
votes

Would this help?

it(`check stripe redirection`, () => {
  cy.get('#payButton').click();
  
  cy.location('host', { timeout: 20 * 1000 }).should('eq', STRIPE_REDIRECT_URL);    

  // do some payment stuff here
  // ...
  // after paying return back to local
 

  cy.location({ timeout: 20 * 1000 }).should((location) => {
    expect(location.host).to.eq('localhost:8080')
    expect(location.pathname).to.eq('/')
  })

})

I've used this method to test keyCloak login. This is the actual code that worked.

describe('authentication', () => {
  
  beforeEach(() => cy.kcLogout());

  it('should login with correct credentials', () => {
    cy.visit('/');

    cy.location('host', { timeout: 20 * 1000 }).should('eq', 'keycloak.dev.mysite.com:8443');

    // This happens on https://keycloak.dev.mysite.com:8443/auth/dealm/...
    cy.fixture('userCredentials').then((user) => {
      cy.get('#username').type(user.email);
      cy.get('#password').type(user.password);

      cy.get('#kc-login').click();

      cy.location({ timeout: 20 * 1000 }).should((location) => {
        expect(location.host).to.eq('localhost:8080')
        expect(location.pathname).to.eq('/')
      })
    })
  });
0
votes

I'm giving it a try to use stripe elements instead since it does not redirect and gives me much more control over it.