'use strict'; const assert = require('assert'); const { checkNeedPassword, handleIdentityVerification } = require('../src/services/common_auth'); function passwordInputs(visibleCount) { return { count: async () => visibleCount, nth: () => ({ isVisible: async () => true }), }; } (async () => { const logs = []; const page = { waitForLoadState: async () => {}, url: () => 'https://myaccount.google.com/signinoptions/password?rapt=test', locator: selector => { assert.strictEqual(selector, 'input[type="password"]'); return passwordInputs(2); }, }; assert.strictEqual(await checkNeedPassword(page, message => logs.push(message)), false); assert(logs.some(message => message.includes('双输入框')), '两栏新密码表单应明确跳过旧密码验证'); const authenticatorLogs = []; let networkIdleWaited = false; const authenticatorPage = { waitForLoadState: async () => { networkIdleWaited = true; }, url: () => 'https://myaccount.google.com/two-step-verification/authenticator?utm_source=test', locator: () => { throw new Error('设置页快速路径不应扫描密码输入框'); }, }; assert.strictEqual( await checkNeedPassword(authenticatorPage, message => authenticatorLogs.push(message)), false, ); assert.strictEqual(networkIdleWaited, false, 'Authenticator 设置页不应等待 networkidle'); assert(authenticatorLogs.some(message => message.includes('Authenticator 设置页')), '日志应说明命中了设置页快速路径'); // 真实回归:reCAPTCHA 页面在初次密码检测结束后才跳到 challenge/pwd。 // 身份验证循环必须重新识别并提交密码,不能把它当成未知 challenge 空等。 { let currentUrl = 'https://accounts.google.com/v3/signin/challenge/recaptcha'; const fills = []; let submitCount = 0; const missing = () => ({ first() { return this; }, nth() { return this; }, or(other) { return other; }, count: async () => 0, waitFor: async () => { throw new Error('not visible'); }, isVisible: async () => false, textContent: async () => '', innerText: async () => '', }); const visiblePassword = () => ({ first() { return this; }, nth() { return this; }, or() { return this; }, count: async () => 1, waitFor: async () => {}, isVisible: async () => true, fill: async value => { fills.push(value); }, press: async () => { submitCount++; currentUrl = 'https://myaccount.google.com/'; }, }); const visibleSubmit = () => ({ first() { return this; }, nth() { return this; }, or() { return this; }, count: async () => 1, waitFor: async () => {}, isVisible: async () => true, evaluate: async () => { submitCount++; currentUrl = 'https://myaccount.google.com/'; }, }); const page = { url: () => currentUrl, waitForLoadState: async () => {}, waitForTimeout: async () => { if (currentUrl.includes('/recaptcha')) { currentUrl = 'https://accounts.google.com/v3/signin/challenge/pwd'; } }, locator: selector => { if (selector === 'body') return { ...missing(), innerText: async () => '' }; if (selector === 'input[type="password"]' && currentUrl.includes('/pwd')) { return visiblePassword(); } if (selector === 'button:has-text("Next")' && currentUrl.includes('/pwd')) { return visibleSubmit(); } return missing(); }, }; const delayedLogs = []; const result = await handleIdentityVerification( page, { password: 'correct-password' }, message => delayedLogs.push(message), ); assert.deepStrictEqual(result, [true, null]); assert.deepStrictEqual(fills, ['', 'correct-password']); assert.strictEqual(submitCount, 1, '延迟密码页只能提交一次'); assert(delayedLogs.some(message => message.includes('延迟出现的密码验证页')), '日志应明确记录异步出现的密码页恢复路径'); } console.log('common_auth_password_change_form.test.js: PASS'); })().catch(error => { console.error(error); process.exitCode = 1; });