基于Playwright复刻Cypress的Microsoft登录流程遇阻求助
解决Playwright复刻Microsoft SSO登录流程的问题
问题背景
已有可正常运行的Cypress脚本,用于SAP系统的Microsoft单点登录(SSO)流程。使用Playwright复刻该流程时,点击「Login with Single Sign On」按钮后,新窗口打开Microsoft登录页,但脚本无法正确识别并操作该窗口,导致测试失败。
可用的Cypress脚本
beforeEach(() => { cy.visit('https://backoffice.iqos.com/backoffice/login.zul', { failOnStatusCode: false, timeout: 30000 }).then(() => { cy.log('Visited the URL successfully'); }).wait(1000); }); it('should test the replacement matrix', () => { cy.get('div.singlesignon_login_cell') .contains('Login with Single Sign On') .should('exist') .click({ force: true }) .wait(20000); cy.origin('https://login.microsoftonline.com', () => { cy.get('#i0116.form-control.ltr_override.input.ext-input.text-box.ext-text-box', { timeout: 10000 }) .should('have.attr', 'placeholder', 'Email address, phone number or Skype') .type("EMAIL HERE") .wait(1000); cy.get('.win-button.button_primary.high-contrast-overrides.button.ext-button.primary.ext-primary') .contains('Next') .should('exist') .click({ force: true }) .wait(5000); cy.get('#i0118.form-control.input.ext-input.text-box.ext-text-box', { timeout: 10000 }) .should('exist') .type("PASSWORD HERE") .wait(1000); cy.get('input#idSIButton9.win-button.button_primary.high-contrast-overrides.button.ext-button.primary.ext-primary') .should('exist') .click({ force: true }) .wait(30000); }); });
存在问题的Playwright脚本
问题核心:手动新建页面跳转至Microsoft登录页,未正确捕获点击按钮后打开的新窗口,导致流程断裂。
test.describe('Replacement Matrix test', () => { test('should test the replacement matrix', async ({ page, context }) => { await page.goto('https://backoffice.iqos.com/backoffice/login.zul', { waitUntil: 'load', timeout: 30000 }); console.log('Visited the URL successfully'); await page.waitForTimeout(1000); // Click the 'Login with Single Sign On' button await page.locator('div.singlesignon_login_cell', { hasText: 'Login with Single Sign On' }).click({ force: true }); await page.waitForTimeout(20000); // Interact with the Microsoft login page const microsoftPage = await context.newPage(); await microsoftPage.goto('https://login.microsoftonline.com'); // Enter email const emailInput = await microsoftPage.waitForSelector('#i0116.form-control.ltr_override.input.ext-input.text-box.ext-text-box', { timeout: 10000 }); await expect(emailInput).toHaveAttribute('placeholder', 'Email address, phone number or Skype'); await emailInput.fill('EMAIL HERE'); await microsoftPage.waitForTimeout(1000); // Click 'Next' const nextButton = await microsoftPage.locator('.win-button.button_primary.high-contrast-overrides.button.ext-button.primary.ext-primary', { hasText: 'Next' }); await expect(nextButton).toBeVisible(); await nextButton.click({ force: true }); await microsoftPage.waitForTimeout(5000); // Enter password const passwordInput = await microsoftPage.waitForSelector('#i0118.form-control.input.ext-input.text-box.ext-text-box', { timeout: 10000 }); await expect(passwordInput).toBeVisible(); await passwordInput.fill('PASSWORD HERE'); await microsoftPage.waitForTimeout(1000); // Click 'Sign in' const signInButton = await microsoftPage.waitForSelector('input#idSIButton9.win-button.button_primary.high-contrast-overrides.button.ext-button.primary.ext-primary'); await expect(signInButton).toBeVisible(); await signInButton.click({ force: true }); await microsoftPage.waitForTimeout(30000); }); });
修复后的Playwright脚本
核心修复点:
- 通过
page.waitForEvent('popup')捕获点击按钮后打开的新窗口,而非手动创建页面 - 移除不必要的固定等待,改用Playwright自动等待机制
- 优化元素定位逻辑,提升稳定性
test.describe('Replacement Matrix test', () => { test('should complete Microsoft SSO login', async ({ page, context }) => { // 1. 打开SAP登录页 await page.goto('https://backoffice.iqos.com/backoffice/login.zul', { waitUntil: 'domcontentloaded', timeout: 30000 }); // 2. 点击单点登录按钮,同时监听新窗口弹出 const popupPromise = page.waitForEvent('popup'); await page.locator('div.singlesignon_login_cell', { hasText: 'Login with Single Sign On' }).click({ force: true }); const microsoftPage = await popupPromise; // 3. 等待Microsoft登录页加载完成 await microsoftPage.waitForLoadState('domcontentloaded', { timeout: 10000 }); // 4. 输入邮箱并点击下一步 const emailInput = microsoftPage.locator('#i0116'); await expect(emailInput).toHaveAttribute('placeholder', 'Email address, phone number or Skype'); await emailInput.fill('EMAIL HERE'); await microsoftPage.locator('.win-button.button_primary', { hasText: 'Next' }).click({ force: true }); // 5. 输入密码并点击登录 const passwordInput = microsoftPage.locator('#i0118'); await expect(passwordInput).toBeVisible({ timeout: 10000 }); await passwordInput.fill('PASSWORD HERE'); await microsoftPage.locator('#idSIButton9').click({ force: true }); // 6. 等待登录完成并跳转回原系统 await page.waitForLoadState('domcontentloaded', { timeout: 30000 }); }); });
额外说明
- 尽量避免使用
waitForTimeout,Playwright的自动等待会根据元素状态智能等待,提升测试稳定性 - 元素定位可简化(如直接用
#i0116而非完整类名),减少因类名变化导致的测试失败 - 登录完成后需等待原页面加载状态,确认跳转成功
内容的提问来源于stack exchange,提问作者No Tools No Craft
相关产品推荐
相关产品推荐

