Cypress测试中localhost多Origin登录流程异常排查
环境信息
- 应用与OAuth服务器均运行在Docker容器,端口映射至localhost:
- 应用baseUrl:
https://localhost:8888 - OAuth服务器地址:
http://localhost:9081
- 应用baseUrl:
- 二者属于localhost下的不同Origin
- 环境版本:Cypress 11.0.1,Chrome 107(无头模式),Node.js v18.6.0
问题场景
应用所有页面均为私有,访问后直接重定向至OAuth服务器完成登录。
第一次尝试:无cy.origin的测试代码
cy.visit('/mysecuredpage'); // 重定向至http://localhost:9081 cy.contains('Please log in'); cy.get('input#username').type('user1'); cy.get('input#password').type('password1'); cy.get('button#password-submit').click();
错误信息:
The command was expected to run against origin
http://localhost:9081but the application is at originhttps://localhost:8888.
第二次尝试:使用cy.origin的测试代码
cy.visit('/mysecuredpage'); // 重定向至http://localhost:9081 cy.origin('http://localhost:9081', () => { cy.contains('Please log in'); cy.get('input#username').type('user1'); cy.get('input#password').type('password1'); cy.get('button#password-submit').click(); });
错误信息:
CypressError:
cy.origin()requires the first argument to be a different domain than top. You passedhttp://localhost:9081to the origin command, while top is athttp://localhost:9081.Either the intended page was not visited prior to running the cy.origin block or the cy.origin block may not be needed at all.
疑问
不确定是操作有误,还是遇到了Cypress针对localhost多Origin的已知限制,或是私有页面直接重定向的模式导致的问题。
解决方案
核心问题分析
- 第一次报错:Cypress默认不允许跨Origin操作,
cy.visit后页面重定向到OAuth服务器,但测试上下文仍停留在应用的Origin,后续命令与当前页面Origin冲突。 - 第二次报错:
cy.visit完成重定向后,当前页面Origin已经是OAuth服务器,而cy.origin()要求传入不同的Origin,因此触发错误。
方法一:直接访问OAuth登录页(推荐)
跳过应用的重定向流程,直接访问OAuth登录页面完成操作,再处理回调后的应用页面:
// 直接访问OAuth登录页(替换为实际登录路径) cy.visit('http://localhost:9081/login'); // 当前页面已在OAuth Origin,直接执行登录操作 cy.contains('Please log in'); cy.get('input#username').type('user1'); cy.get('input#password').type('password1'); cy.get('button#password-submit').click(); // 登录后重定向回应用,切换到应用Origin验证 cy.origin('https://localhost:8888', () => { cy.contains('Welcome, user1'); // 验证是否进入受保护页面 });
方法二:等待重定向完成后执行操作
如果必须从应用私有页面开始测试,需等待重定向完成后再执行登录:
cy.visit('/mysecuredpage'); // 等待页面重定向到OAuth服务器,确认当前URL cy.url().should('include', 'http://localhost:9081'); // 当前页面已在OAuth Origin,直接执行登录(无需cy.origin) cy.contains('Please log in'); cy.get('input#username').type('user1'); cy.get('input#password').type('password1'); cy.get('button#password-submit').click(); // 登录完成后重定向回应用,继续验证 cy.url().should('include', 'https://localhost:8888'); cy.contains('Welcome, user1');
方法三:临时关闭跨Origin保护(不推荐)
仅用于临时测试,在cypress.config.ts中关闭实验性的Session和Origin功能:
export default defineConfig({ e2e: { experimentalSessionAndOrigin: false, baseUrl: 'https://localhost:8888', }, });
此方法会带来测试稳定性风险,不建议用于正式测试流程。
内容的提问来源于stack exchange,提问作者Lesiak

