Cypress重定向测试问题:外部跳转后空白页解决方案咨询
Hey there, let's tackle this common Cypress issue head-on. The blank page happens because of Cypress' default same-origin policy restrictions—once you jump to an external domain, Cypress loses control of the browser context, leaving you stuck with a blank screen. Let's break down solutions based on whether you have control over the external login site or not.
If You Control the External Login Site (e.g., Internal SSO)
Option 1: Skip the UI Login (Fastest & Most Reliable)
Instead of going through the external site's login UI, directly call the login API to grab auth credentials, then inject them into your original site's browser context. This avoids cross-domain headaches entirely.
Here's a code example:
// In your test file beforeEach(() => { // Send a POST request to the external login API cy.request({ method: 'POST', url: 'https://your-external-login-site.com/api/login', body: { username: Cypress.env('TEST_USER'), // Store these in cypress.env.json password: Cypress.env('TEST_PASS') } }).then(response => { // Set the auth cookie/token on your original site's domain cy.setCookie('auth_session', response.body.session_token, { domain: 'your-original-site.com' }); }); // Directly navigate to the connections page—you're already authenticated! cy.visit('/connections'); }); it('verifies connections are visible', () => { cy.get('[data-testid="connections-container"]').should('be.visible'); });
Pro tip: Storing credentials in cypress.env.json keeps them out of your codebase—just add the file to .gitignore.
Option 2: Enable Cypress' Cross-Domain Support
Cypress has an experimental (but stable in v12+) feature to handle cross-origin navigation. Enable it in your config, then use cy.origin() to interact with the external site.
First, update cypress.config.js:
const { defineConfig } = require('cypress'); module.exports = defineConfig({ e2e: { experimentalSessionAndOrigin: true, // Enable cross-origin support // Your other config options... } });
Then write the test to handle the full flow:
it('navigates to external login, authenticates, and returns to connections', () => { cy.visit('/'); // Click the redirect button to the external login site cy.get('[data-testid="external-login-btn"]').click(); // Use cy.origin() to target the external domain cy.origin('https://your-external-login-site.com', () => { cy.get('#username-input').type(Cypress.env('TEST_USER')); cy.get('#password-input').type(Cypress.env('TEST_PASS')); cy.get('#submit-login').click(); }); // After redirecting back, verify the connections page loads cy.url().should('include', '/connections'); cy.get('[data-testid="connections-list"]').should('have.length.greaterThan', 0); });
If You Don't Control the External Login Site (e.g., Third-Party OAuth)
Third-party sites like Google or Facebook often have anti-automation measures (captchas, rate limits) that make UI-based testing tricky. Here are your best alternatives:
Option 1: Save & Reuse Authentication State
Manually complete the login flow once, save the browser's auth state (cookies, localStorage), then reuse it in your tests. You'll need the cypress-localstorage-commands plugin for this.
- Install the plugin:
npm install cypress-localstorage-commands --save-dev
- Add it to
cypress/support/e2e.js:
import 'cypress-localstorage-commands';
- Write the test to save/restore state:
beforeEach(() => { cy.restoreLocalStorage(); // Restore any auth cookies if needed cy.setCookie('third-party-auth-token', Cypress.env('SAVED_AUTH_TOKEN'), { domain: 'your-original-site.com' }); cy.visit('/connections'); }); afterEach(() => { cy.saveLocalStorage(); }); it('loads connections using saved auth state', () => { cy.get('[data-testid="connections-container"]').should('be.visible'); });
Note: You'll need to manually grab the auth token/cookie once and store it in cypress.env.json.
Option 2: Simulate the OAuth Flow via API
If the third-party provider supports OAuth 2.0, you can simulate the authorization code flow directly via cy.request() to avoid the UI entirely. This requires knowing the provider's API endpoints and having valid client credentials.
Example code outline:
it('simulates OAuth authorization to access connections', () => { // Step 1: Get the authorization code (bypass the login UI) cy.request({ method: 'GET', url: 'https://third-party-provider.com/oauth/authorize', qs: { client_id: Cypress.env('OAUTH_CLIENT_ID'), redirect_uri: 'https://your-original-site.com/oauth/callback', response_type: 'code', scope: 'openid profile' }, followRedirect: false // Don't follow the redirect, grab the code from the header }).then(authRes => { const authCode = authRes.headers.location.match(/code=([^&]+)/)[1]; // Step 2: Exchange the code for an access token return cy.request({ method: 'POST', url: 'https://third-party-provider.com/oauth/token', body: { client_id: Cypress.env('OAUTH_CLIENT_ID'), client_secret: Cypress.env('OAUTH_CLIENT_SECRET'), code: authCode, grant_type: 'authorization_code', redirect_uri: 'https://your-original-site.com/oauth/callback' } }); }).then(tokenRes => { // Step 3: Set the token in your site's context cy.setCookie('access_token', tokenRes.body.access_token, { domain: 'your-original-site.com' }); cy.visit('/connections'); cy.get('[data-testid="connections-list"]').should('be.visible'); }); });
Caveat: Some third-party providers block this kind of direct API access or require additional security checks (like PKCE), so test this first.
内容的提问来源于stack exchange,提问作者ITguy

