skip to Main Content

I am testing a payment screen in Cypress. We have two third-party payment systems, and when the user pays, they will go from my site to the payment provider and then back to my site. For the purposes of this example, the payment provider hosts can be regarded as https://demo.paymentprovider1.com and https://demo.paymentprovider2.com.

A complication is that currently the system can go to either provider in a way that I cannot predict. I will change this in the future, but currently I plan to work around it. I understand the well-meaning warnings in the manual but I intend to ignore them in the short term (this would, after all, be easy in Selenium).

Normally if one knew which card provider I would land on, I would do this:

it.only('Makes a Visa/Mastercard payment', () => {
    clickPaymentTypeRadioButtonAndSubmit(0);
    cy.url().should('not.contain', 'test.myapp.com');

    cy.origin(
        'https://demo.paymentprovider1.com',
        () => {
            cy
                .get('body', {timeout: 5000})
                .should('contain.text', 'Select payment method');
        }
    );

});

However if I get that wrong, because the other provider is chosen, the test will fail with this:

CypressError: Timed out retrying after 5000ms: The command was expected to run against origin demo.paymentprovider1.com but the application is at origin demo.paymentprovider2.com.

This commonly happens when you have either not navigated to the expected origin or have navigated away unexpectedly.

I would like to capture this case, so that I have this arrangement:

  • If the get() inside the origin() succeeds then I do the tests for the first payment provider
  • If it fails I do another origin() on the other domain, and if that succeeds, do the tests for the second provider

Update

I’ve tried getting the location using the below code:

cy.window().then((win) => {
    const l = win.location;
    cy.task('log', `Location: ${l}`);
});

However that fails due to this error:

SecurityError: Permission denied to access property Symbol.toPrimitive on cross-origin object

Update

I have found that I can reset chromeWebSecurity, which might fix the above error, but I am using Firefox, and don’t especially want to swap browsers just to fix this one tiny thing.

Update

I have tried various approaches using location() and url() to run tests conditionally, but those have not yielded successful results either. What can I try next?

2

Answers


  1. How about you act AFTER you got to the payment provider and you know which one it is instead of assuming and then falling back to the next one. Something along the lines:

    it.only('Handles multiple payment providers', () => {
    
    
        clickPaymentTypeRadioButtonAndSubmit(0);
    
        cy.url().should('not.contain', 'test.myapp.com');
    
        // Handle redirected URL!
        cy.url().then((currentUrl) => {
            if (currentUrl.includes('demo.paymentprovider1.com')) {
                // Handle Payment Provider 1
                cy.origin('https://demo.paymentprovider1.com', () => {
                    cy.get('body', { timeout: 5000 }).should('contain.text', 'Select payment method');
                    // Additional assertions for provider 1
                });
            } else if (currentUrl.includes('demo.paymentprovider2.com')) {
                // Handle Payment Provider 2
                cy.origin('https://demo.paymentprovider2.com', () => {
                    cy.get('body', { timeout: 5000 }).should('contain.text', 'Choose your payment method');
                    // Additional assertions for provider 2
                });
            } else {
                throw new Error(`Unexpected URL: ${currentUrl}`);
            }
        });
    });
    

    NOTE!

    For Chrome, chromeWebSecurity needs to be disabled. In Firefox this should work without altering.

    Also worth mentioning, you need to have actual URLs and partials written correctly instead of what seem like placeholders to me.

    Login or Signup to reply.
  2. It would perhaps be better to use cy.location() as this has an origin property.

    You can of course pass the variable directly into the cy.origin() command.

    clickPaymentTypeRadioButtonAndSubmit(0);
    
    cy.location('origin')
      .then(currentOrigin => {
    
        cy.origin(currentOrigin, () => {
          ...
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search