From be3172df63941c6e10f899260fe378a4eef36024 Mon Sep 17 00:00:00 2001 From: QLHazyCoder <2825305047@qq.com> Date: Fri, 17 Apr 2026 09:43:39 +0800 Subject: [PATCH] Implement structure for code changes tracking --- background/verification-flow.js | 28 ++- content/signup-page.js | 24 ++- tests/step3-direct-complete.test.js | 158 ++++++++++++++ tests/verification-flow-polling.test.js | 124 +++++++++++ 项目完整链路说明.md | 5 +- 项目文件结构说明.md | 261 ++++++++++++------------ 6 files changed, 453 insertions(+), 147 deletions(-) create mode 100644 tests/step3-direct-complete.test.js diff --git a/background/verification-flow.js b/background/verification-flow.js index b630669..6ad59ee 100644 --- a/background/verification-flow.js +++ b/background/verification-flow.js @@ -113,6 +113,9 @@ await addLog(`步骤 ${step}:已请求新的${getVerificationCodeLabel(step)}验证码。`, 'warn'); const requestedAt = Date.now(); + if (step === 4) { + await setState({ signupVerificationRequestedAt: requestedAt }); + } if (step === 7) { await setState({ loginVerificationRequestedAt: requestedAt }); } @@ -387,15 +390,17 @@ const resendIntervalMs = Math.max(0, Number(options.resendIntervalMs) || 0); let lastResendAt = Number(options.lastResendAt) || 0; - const updateFilterAfterTimestampForStep7 = async (requestedAt) => { - if (step !== 7 || !requestedAt) { + const updateFilterAfterTimestampForVerificationStep = async (requestedAt) => { + if ((step !== 4 && step !== 7) || !requestedAt) { return nextFilterAfterTimestamp; } if (mail.provider === HOTMAIL_PROVIDER) { - nextFilterAfterTimestamp = getHotmailVerificationRequestTimestamp(7, { + nextFilterAfterTimestamp = getHotmailVerificationRequestTimestamp(step, { ...state, - loginVerificationRequestedAt: requestedAt, + ...(step === 4 + ? { signupVerificationRequestedAt: requestedAt } + : { loginVerificationRequestedAt: requestedAt }), }); } else { nextFilterAfterTimestamp = Math.max(0, Number(requestedAt) - 60000); @@ -407,7 +412,7 @@ if (requestFreshCodeFirst) { try { lastResendAt = await requestVerificationCodeResend(step); - await updateFilterAfterTimestampForStep7(lastResendAt); + await updateFilterAfterTimestampForVerificationStep(lastResendAt); await addLog(`步骤 ${step}:已先请求一封新的${getVerificationCodeLabel(step)}验证码,再开始轮询邮箱。`, 'warn'); } catch (err) { if (isStopError(err)) { @@ -426,13 +431,16 @@ } for (let attempt = 1; attempt <= maxSubmitAttempts; attempt++) { - const result = await pollFreshVerificationCode(step, state, mail, { + const pollOptions = { excludeCodes: [...rejectedCodes], - filterAfterTimestamp: nextFilterAfterTimestamp ?? undefined, resendIntervalMs, lastResendAt, - onResendRequestedAt: updateFilterAfterTimestampForStep7, - }); + onResendRequestedAt: updateFilterAfterTimestampForVerificationStep, + }; + if (nextFilterAfterTimestamp !== null && nextFilterAfterTimestamp !== undefined) { + pollOptions.filterAfterTimestamp = nextFilterAfterTimestamp; + } + const result = await pollFreshVerificationCode(step, state, mail, pollOptions); lastResendAt = Number(result?.lastResendAt) || lastResendAt; throwIfStopped(); @@ -468,7 +476,7 @@ } lastResendAt = await requestVerificationCodeResend(step); - await updateFilterAfterTimestampForStep7(lastResendAt); + await updateFilterAfterTimestampForVerificationStep(lastResendAt); await addLog(`步骤 ${step}:提交失败后已请求新验证码(${attempt + 1}/${maxSubmitAttempts})...`, 'warn'); continue; } diff --git a/content/signup-page.js b/content/signup-page.js index bf82642..d55903a 100644 --- a/content/signup-page.js +++ b/content/signup-page.js @@ -537,15 +537,27 @@ async function step3_fillEmailPassword(payload) { // Report complete BEFORE submit, because submit causes page navigation // which kills the content script connection const signupVerificationRequestedAt = submitBtn ? Date.now() : null; - reportComplete(3, { email, signupVerificationRequestedAt }); + const completionPayload = { + email, + signupVerificationRequestedAt, + deferredSubmit: Boolean(submitBtn), + }; + reportComplete(3, completionPayload); - // Submit the form (page will navigate away after this) - await sleep(500); if (submitBtn) { - await humanPause(500, 1300); - simulateClick(submitBtn); - log('步骤 3:表单已提交'); + window.setTimeout(async () => { + try { + await sleep(500); + await humanPause(500, 1300); + simulateClick(submitBtn); + log('步骤 3:表单已提交'); + } catch (error) { + console.error('[MultiPage:signup-page] deferred step 3 submit failed:', error?.message || error); + } + }, 120); } + + return completionPayload; } // ============================================================ diff --git a/tests/step3-direct-complete.test.js b/tests/step3-direct-complete.test.js new file mode 100644 index 0000000..0ce56e9 --- /dev/null +++ b/tests/step3-direct-complete.test.js @@ -0,0 +1,158 @@ +const test = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('node:fs'); + +const source = fs.readFileSync('content/signup-page.js', 'utf8'); + +function extractFunction(name) { + const markers = [`async function ${name}(`, `function ${name}(`]; + const start = markers + .map((marker) => source.indexOf(marker)) + .find((index) => index >= 0); + if (start < 0) { + throw new Error(`missing function ${name}`); + } + + let parenDepth = 0; + let signatureEnded = false; + let braceStart = -1; + for (let i = start; i < source.length; i += 1) { + const ch = source[i]; + if (ch === '(') { + parenDepth += 1; + } else if (ch === ')') { + parenDepth -= 1; + if (parenDepth === 0) { + signatureEnded = true; + } + } else if (ch === '{' && signatureEnded) { + braceStart = i; + break; + } + } + if (braceStart < 0) { + throw new Error(`missing body for function ${name}`); + } + + let depth = 0; + let end = braceStart; + for (; end < source.length; end += 1) { + const ch = source[end]; + if (ch === '{') depth += 1; + if (ch === '}') { + depth -= 1; + if (depth === 0) { + end += 1; + break; + } + } + } + + return source.slice(start, end); +} + +test('step 3 reports completion before deferred submit click', async () => { + const api = new Function(` +const logs = []; +const completions = []; +const clicks = []; +const scheduled = []; + +const snapshot = { + state: 'password_page', + passwordInput: { value: '', hidden: false }, + submitButton: { textContent: 'Continue', hidden: false }, + displayedEmail: 'user@example.com', +}; + +const window = { + setTimeout(fn) { + scheduled.push(fn); + return scheduled.length; + }, +}; + +const location = { + href: 'https://auth.openai.com/create-account/password', +}; + +function inspectSignupEntryState() { + return snapshot; +} + +async function ensureSignupPasswordPageReady() { + return { ready: true }; +} + +function getSignupPasswordSubmitButton() { + return snapshot.submitButton; +} + +async function waitForElementByText() { + return null; +} + +function fillInput(input, value) { + input.value = value; +} + +async function humanPause() {} +async function sleep() {} + +function log(message, level = 'info') { + logs.push({ message, level }); +} + +function reportComplete(step, payload) { + completions.push({ step, payload }); +} + +function simulateClick(target) { + clicks.push(target.textContent || 'button'); +} + +${extractFunction('step3_fillEmailPassword')} + +return { + async run(payload) { + return step3_fillEmailPassword(payload); + }, + async flushDeferredSubmit() { + if (!scheduled.length) { + throw new Error('missing deferred submit'); + } + await scheduled[0](); + }, + snapshot() { + return { + logs, + completions, + clicks, + passwordValue: snapshot.passwordInput.value, + scheduledCount: scheduled.length, + }; + }, +}; +`)(); + + const result = await api.run({ + email: 'user@example.com', + password: 'Secret123!', + }); + + const beforeSubmit = api.snapshot(); + assert.equal(beforeSubmit.passwordValue, 'Secret123!'); + assert.equal(beforeSubmit.scheduledCount, 1); + assert.deepStrictEqual(beforeSubmit.clicks, []); + assert.equal(beforeSubmit.completions.length, 1); + assert.equal(beforeSubmit.completions[0].step, 3); + assert.deepStrictEqual(result, beforeSubmit.completions[0].payload); + assert.equal(result.email, 'user@example.com'); + assert.equal(result.deferredSubmit, true); + assert.equal(typeof result.signupVerificationRequestedAt, 'number'); + + await api.flushDeferredSubmit(); + + const afterSubmit = api.snapshot(); + assert.deepStrictEqual(afterSubmit.clicks, ['Continue']); +}); diff --git a/tests/verification-flow-polling.test.js b/tests/verification-flow-polling.test.js index 37f104e..23a5391 100644 --- a/tests/verification-flow-polling.test.js +++ b/tests/verification-flow-polling.test.js @@ -108,3 +108,127 @@ test('verification flow runs beforeSubmit hook before filling the code', async ( ['complete', '654321'], ]); }); + +test('verification flow keeps Hotmail request timestamp filtering on the first poll', async () => { + const pollPayloads = []; + + const helpers = api.createVerificationFlowHelpers({ + addLog: async () => {}, + chrome: { tabs: { update: async () => {} } }, + CLOUDFLARE_TEMP_EMAIL_PROVIDER: 'cloudflare-temp-email', + completeStepFromBackground: async () => {}, + confirmCustomVerificationStepBypassRequest: async () => ({ confirmed: true }), + getHotmailVerificationPollConfig: () => ({}), + getHotmailVerificationRequestTimestamp: () => 87654, + getState: async () => ({}), + getTabId: async () => 1, + HOTMAIL_PROVIDER: 'hotmail-api', + isStopError: () => false, + LUCKMAIL_PROVIDER: 'luckmail-api', + MAIL_2925_VERIFICATION_INTERVAL_MS: 15000, + MAIL_2925_VERIFICATION_MAX_ATTEMPTS: 15, + pollCloudflareTempEmailVerificationCode: async () => ({}), + pollHotmailVerificationCode: async (_step, _state, payload) => { + pollPayloads.push(payload); + return { code: '654321', emailTimestamp: 123 }; + }, + pollLuckmailVerificationCode: async () => ({}), + sendToContentScript: async (_source, message) => { + if (message.type === 'FILL_CODE') { + return {}; + } + return {}; + }, + sendToMailContentScriptResilient: async () => ({}), + setState: async () => {}, + setStepStatus: async () => {}, + sleepWithStop: async () => {}, + throwIfStopped: () => {}, + VERIFICATION_POLL_MAX_ROUNDS: 5, + }); + + await helpers.resolveVerificationStep( + 7, + { + email: 'user@example.com', + loginVerificationRequestedAt: 100000, + lastLoginCode: null, + }, + { provider: 'hotmail-api', label: 'Hotmail' }, + {} + ); + + assert.equal(pollPayloads.length, 1); + assert.equal(pollPayloads[0].filterAfterTimestamp, 87654); +}); + +test('verification flow refreshes Hotmail signup filter timestamp after step 4 resend', async () => { + const pollPayloads = []; + const realDateNow = Date.now; + Date.now = () => 200000; + + let submitCount = 0; + + const helpers = api.createVerificationFlowHelpers({ + addLog: async () => {}, + chrome: { tabs: { update: async () => {} } }, + CLOUDFLARE_TEMP_EMAIL_PROVIDER: 'cloudflare-temp-email', + completeStepFromBackground: async () => {}, + confirmCustomVerificationStepBypassRequest: async () => ({ confirmed: true }), + getHotmailVerificationPollConfig: () => ({}), + getHotmailVerificationRequestTimestamp: (_step, state) => Math.max(0, Number(state.signupVerificationRequestedAt || 0) - 15000), + getState: async () => ({}), + getTabId: async () => 1, + HOTMAIL_PROVIDER: 'hotmail-api', + isStopError: () => false, + LUCKMAIL_PROVIDER: 'luckmail-api', + MAIL_2925_VERIFICATION_INTERVAL_MS: 15000, + MAIL_2925_VERIFICATION_MAX_ATTEMPTS: 15, + pollCloudflareTempEmailVerificationCode: async () => ({}), + pollHotmailVerificationCode: async (_step, _state, payload) => { + pollPayloads.push(payload); + return { + code: pollPayloads.length === 1 ? '111111' : '222222', + emailTimestamp: pollPayloads.length, + }; + }, + pollLuckmailVerificationCode: async () => ({}), + sendToContentScript: async (_source, message) => { + if (message.type === 'FILL_CODE') { + submitCount += 1; + return submitCount === 1 + ? { invalidCode: true, errorText: '旧验证码' } + : {}; + } + if (message.type === 'RESEND_VERIFICATION_CODE') { + return {}; + } + return {}; + }, + sendToMailContentScriptResilient: async () => ({}), + setState: async () => {}, + setStepStatus: async () => {}, + sleepWithStop: async () => {}, + throwIfStopped: () => {}, + VERIFICATION_POLL_MAX_ROUNDS: 5, + }); + + try { + await helpers.resolveVerificationStep( + 4, + { + email: 'user@example.com', + signupVerificationRequestedAt: 100000, + lastSignupCode: null, + }, + { provider: 'hotmail-api', label: 'Hotmail' }, + {} + ); + } finally { + Date.now = realDateNow; + } + + assert.equal(pollPayloads.length, 2); + assert.equal(pollPayloads[0].filterAfterTimestamp, 85000); + assert.equal(pollPayloads[1].filterAfterTimestamp, 185000); +}); diff --git a/项目完整链路说明.md b/项目完整链路说明.md index 3dd3846..56c563c 100644 --- a/项目完整链路说明.md +++ b/项目完整链路说明.md @@ -221,7 +221,9 @@ 1. 生成或读取密码 2. 更新运行态密码 3. 记录账号快照 -4. 让内容脚本填写密码并继续 +4. 让内容脚本填写密码 +5. 内容脚本先上报 Step 3 完成信号 +6. 上报完成后再异步点击提交,避免页面跳转打断响应通道 ### Step 4 / Step 7 @@ -243,6 +245,7 @@ 补充行为: - `2925` provider 会拉长单轮轮询窗口,并关闭 Step 4 / 7 的自动重发间隔,减少因邮件延迟过早判负。 +- Hotmail 在 Step 4 / 7 首轮轮询时会优先使用最近一次验证码请求时间作为时间窗口;如果中途触发重发,轮询窗口也会同步前移,避免旧邮件反复命中。 - CPA 模式下,Step 7 在真正回填登录验证码前,会先刷新最新 OAuth 地址并快速重走一次 Step 6,降低验证码等待过久导致 OAuth 过期的概率。 ### Step 5 diff --git a/项目文件结构说明.md b/项目文件结构说明.md index c1d639e..90a1a24 100644 --- a/项目文件结构说明.md +++ b/项目文件结构说明.md @@ -1,8 +1,8 @@ -# 项目文件结构说明 +# 椤圭洰鏂囦欢缁撴瀯璇存槑 -本文档列出当前仓库中所有“非忽略文件”,并说明每个文件的作用。 +鏈枃妗e垪鍑哄綋鍓嶄粨搴撲腑鎵€鏈夆€滈潪蹇界暐鏂囦欢鈥濓紝骞惰鏄庢瘡涓枃浠剁殑浣滅敤銆? -不纳入本清单的忽略目录: +涓嶇撼鍏ユ湰娓呭崟鐨勫拷鐣ョ洰褰曪細 - `.github/` - `_metadata/` @@ -10,160 +10,161 @@ - `.vscode/` - `.git/` -更新规则: +鏇存柊瑙勫垯锛? -- 新增、删除、重命名非忽略文件后,必须同步更新本文件。 -- 如果文件职责发生明显变化,也必须同步更新本文件中的说明。 +- 鏂板銆佸垹闄ゃ€侀噸鍛藉悕闈炲拷鐣ユ枃浠跺悗锛屽繀椤诲悓姝ユ洿鏂版湰鏂囦欢銆? +- 濡傛灉鏂囦欢鑱岃矗鍙戠敓鏄庢樉鍙樺寲锛屼篃蹇呴』鍚屾鏇存柊鏈枃浠朵腑鐨勮鏄庛€? -## 根目录 +## 鏍圭洰褰? -- `.gitignore`:定义仓库忽略规则,当前忽略 `docs/md/`、`.github/`、`_metadata/`、`.vscode/` 等目录。 -- `LICENSE`:项目许可证文件。 -- `README.md`:面向使用者的项目介绍、安装说明、能力清单与操作指引。 -- `background.js`:扩展后台 Service Worker 入口壳,负责模块装配、初始化、全局常量、少量保留的领域函数与运行入口。 -- `cloudflare-temp-email-utils.js`:Cloudflare Temp Email 相关的纯工具函数,负责 URL、域名、邮件内容与 MIME 数据归一化。 -- `hotmail-utils.js`:Hotmail 账号与验证码提取相关的纯工具函数,负责账号筛选、验证码匹配、第三方接口数据归一化。 -- `icloud-utils.js`:iCloud 隐私邮箱相关的纯工具函数,负责 host、别名列表、保留状态、已用状态等归一化。 -- `luckmail-utils.js`:LuckMail 相关的纯工具函数,负责邮箱购买记录、标签、邮件 cursor、验证码匹配等归一化。 -- `manifest.json`:Chrome 扩展清单,声明权限、背景脚本、侧边栏、内容脚本与规则集。 -- `microsoft-email.js`:Microsoft Graph / Outlook 邮件读取辅助模块,负责刷新令牌换 token、邮箱夹轮询和验证码提取。 -- `package.json`:仓库最小 Node 包配置,目前主要提供测试脚本定义。 -- `rules.json`:静态 DNR 规则,主要处理 iCloud 相关请求头。 -- `start-hotmail-helper.bat`:Windows 下启动本地 helper 的脚本;当前既服务于 Hotmail 本地收信,也服务于账号运行历史文本留档。 -- `start-hotmail-helper.command`:macOS 下启动本地 helper 的脚本;当前既服务于 Hotmail 本地收信,也服务于账号运行历史文本留档。 -- `开发者AI开发与PR提交流程.md`:仓库现有的 AI 开发与 PR 提交流程说明。 -- `项目文件结构说明.md`:当前文件,维护整个仓库非忽略文件的结构与职责索引。 -- `项目完整链路说明.md`:面向 AI/开发者的完整功能链路说明,用于快速理解系统整体运行过程。 -- `项目开发规范(AI协作).md`:面向 AI/开发者的项目开发规范、约束与变更检查清单。 +- `.gitignore`锛氬畾涔変粨搴撳拷鐣ヨ鍒欙紝褰撳墠蹇界暐 `docs/md/`銆乣.github/`銆乣_metadata/`銆乣.vscode/` 绛夌洰褰曘€? +- `LICENSE`锛氶」鐩鍙瘉鏂囦欢銆? +- `README.md`锛氶潰鍚戜娇鐢ㄨ€呯殑椤圭洰浠嬬粛銆佸畨瑁呰鏄庛€佽兘鍔涙竻鍗曚笌鎿嶄綔鎸囧紩銆? +- `background.js`锛氭墿灞曞悗鍙?Service Worker 鍏ュ彛澹筹紝璐熻矗妯″潡瑁呴厤銆佸垵濮嬪寲銆佸叏灞€甯搁噺銆佸皯閲忎繚鐣欑殑棰嗗煙鍑芥暟涓庤繍琛屽叆鍙c€? +- `cloudflare-temp-email-utils.js`锛欳loudflare Temp Email 鐩稿叧鐨勭函宸ュ叿鍑芥暟锛岃礋璐?URL銆佸煙鍚嶃€侀偖浠跺唴瀹逛笌 MIME 鏁版嵁褰掍竴鍖栥€? +- `hotmail-utils.js`锛欻otmail 璐﹀彿涓庨獙璇佺爜鎻愬彇鐩稿叧鐨勭函宸ュ叿鍑芥暟锛岃礋璐h处鍙风瓫閫夈€侀獙璇佺爜鍖归厤銆佺涓夋柟鎺ュ彛鏁版嵁褰掍竴鍖栥€? +- `icloud-utils.js`锛歩Cloud 闅愮閭鐩稿叧鐨勭函宸ュ叿鍑芥暟锛岃礋璐?host銆佸埆鍚嶅垪琛ㄣ€佷繚鐣欑姸鎬併€佸凡鐢ㄧ姸鎬佺瓑褰掍竴鍖栥€? +- `luckmail-utils.js`锛歀uckMail 鐩稿叧鐨勭函宸ュ叿鍑芥暟锛岃礋璐i偖绠辫喘涔拌褰曘€佹爣绛俱€侀偖浠?cursor銆侀獙璇佺爜鍖归厤绛夊綊涓€鍖栥€? +- `manifest.json`锛欳hrome 鎵╁睍娓呭崟锛屽0鏄庢潈闄愩€佽儗鏅剼鏈€佷晶杈规爮銆佸唴瀹硅剼鏈笌瑙勫垯闆嗐€? +- `microsoft-email.js`锛歁icrosoft Graph / Outlook 閭欢璇诲彇杈呭姪妯″潡锛岃礋璐e埛鏂颁护鐗屾崲 token銆侀偖绠卞す杞鍜岄獙璇佺爜鎻愬彇銆? +- `package.json`锛氫粨搴撴渶灏?Node 鍖呴厤缃紝鐩墠涓昏鎻愪緵娴嬭瘯鑴氭湰瀹氫箟銆? +- `rules.json`锛氶潤鎬?DNR 瑙勫垯锛屼富瑕佸鐞?iCloud 鐩稿叧璇锋眰澶淬€? +- `start-hotmail-helper.bat`锛歐indows 涓嬪惎鍔ㄦ湰鍦?helper 鐨勮剼鏈紱褰撳墠鏃㈡湇鍔′簬 Hotmail 鏈湴鏀朵俊锛屼篃鏈嶅姟浜庤处鍙疯繍琛屽巻鍙叉枃鏈暀妗c€? +- `start-hotmail-helper.command`锛歮acOS 涓嬪惎鍔ㄦ湰鍦?helper 鐨勮剼鏈紱褰撳墠鏃㈡湇鍔′簬 Hotmail 鏈湴鏀朵俊锛屼篃鏈嶅姟浜庤处鍙疯繍琛屽巻鍙叉枃鏈暀妗c€? +- `寮€鍙戣€匒I寮€鍙戜笌PR鎻愪氦娴佺▼.md`锛氫粨搴撶幇鏈夌殑 AI 寮€鍙戜笌 PR 鎻愪氦娴佺▼璇存槑銆? +- `椤圭洰鏂囦欢缁撴瀯璇存槑.md`锛氬綋鍓嶆枃浠讹紝缁存姢鏁翠釜浠撳簱闈炲拷鐣ユ枃浠剁殑缁撴瀯涓庤亴璐g储寮曘€? +- `椤圭洰瀹屾暣閾捐矾璇存槑.md`锛氶潰鍚?AI/寮€鍙戣€呯殑瀹屾暣鍔熻兘閾捐矾璇存槑锛岀敤浜庡揩閫熺悊瑙g郴缁熸暣浣撹繍琛岃繃绋嬨€? +- `椤圭洰寮€鍙戣鑼冿紙AI鍗忎綔锛?md`锛氶潰鍚?AI/寮€鍙戣€呯殑椤圭洰寮€鍙戣鑼冦€佺害鏉熶笌鍙樻洿妫€鏌ユ竻鍗曘€? ## `background/` -- `background/account-run-history.js`:账号运行历史模块,负责将成功/失败/停止结果持久化到 `chrome.storage.local`,并在启用独立的本地 txt 留档配置后追加写入文本日志。 -- `background/auto-run-controller.js`:自动运行主控制器,封装多轮执行、重试、轮次摘要、线程间隔与倒计时恢复逻辑。 -- `background/generated-email-helpers.js`:生成邮箱辅助层,封装 Duck、Cloudflare、Cloudflare Temp Email、iCloud 隐私邮箱的获取逻辑。 -- `background/logging-status.js`:后台日志、步骤状态、错误信息和若干状态判断的公共工具层。 -- `background/message-router.js`:后台消息路由层,负责处理 `chrome.runtime.onMessage` 进入的所有业务消息。 -- `background/navigation-utils.js`:导航与 URL 判断工具层,负责 callback、入口页、CPA/SUB2API 地址、步骤跳转相关判断。 -- `background/panel-bridge.js`:CPA / SUB2API 面板桥接层,封装 OAuth 地址获取所需的页面打开、脚本注入和通信。 -- `background/signup-flow-helpers.js`:注册页辅助层,负责打开注册入口、等待密码页以及解析当前流程所用邮箱。 -- `background/tab-runtime.js`:标签页与内容脚本运行时基础设施,封装标签注册、冲突清理、消息超时、注入重试与队列。 -- `background/verification-flow.js`:注册/登录验证码共享流程层,封装重发、轮询、提交、失败回退、自定义邮箱跳过以及 2925 长轮询参数。 +- `background/account-run-history.js`锛氳处鍙疯繍琛屽巻鍙叉ā鍧楋紝璐熻矗灏嗘垚鍔?澶辫触/鍋滄缁撴灉鎸佷箙鍖栧埌 `chrome.storage.local`锛屽苟鍦ㄥ惎鐢ㄧ嫭绔嬬殑鏈湴 txt 鐣欐。閰嶇疆鍚庤拷鍔犲啓鍏ユ枃鏈棩蹇椼€? +- `background/auto-run-controller.js`锛氳嚜鍔ㄨ繍琛屼富鎺у埗鍣紝灏佽澶氳疆鎵ц銆侀噸璇曘€佽疆娆℃憳瑕併€佺嚎绋嬮棿闅斾笌鍊掕鏃舵仮澶嶉€昏緫銆? +- `background/generated-email-helpers.js`锛氱敓鎴愰偖绠辫緟鍔╁眰锛屽皝瑁?Duck銆丆loudflare銆丆loudflare Temp Email銆乮Cloud 闅愮閭鐨勮幏鍙栭€昏緫銆? +- `background/logging-status.js`锛氬悗鍙版棩蹇椼€佹楠ょ姸鎬併€侀敊璇俊鎭拰鑻ュ共鐘舵€佸垽鏂殑鍏叡宸ュ叿灞傘€? +- `background/message-router.js`锛氬悗鍙版秷鎭矾鐢卞眰锛岃礋璐e鐞?`chrome.runtime.onMessage` 杩涘叆鐨勬墍鏈変笟鍔℃秷鎭€? +- `background/navigation-utils.js`锛氬鑸笌 URL 鍒ゆ柇宸ュ叿灞傦紝璐熻矗 callback銆佸叆鍙i〉銆丆PA/SUB2API 鍦板潃銆佹楠よ烦杞浉鍏冲垽鏂€? +- `background/panel-bridge.js`锛欳PA / SUB2API 闈㈡澘妗ユ帴灞傦紝灏佽 OAuth 鍦板潃鑾峰彇鎵€闇€鐨勯〉闈㈡墦寮€銆佽剼鏈敞鍏ュ拰閫氫俊銆? +- `background/signup-flow-helpers.js`锛氭敞鍐岄〉杈呭姪灞傦紝璐熻矗鎵撳紑娉ㄥ唽鍏ュ彛銆佺瓑寰呭瘑鐮侀〉浠ュ強瑙f瀽褰撳墠娴佺▼鎵€鐢ㄩ偖绠便€? +- `background/tab-runtime.js`锛氭爣绛鹃〉涓庡唴瀹硅剼鏈繍琛屾椂鍩虹璁炬柦锛屽皝瑁呮爣绛炬敞鍐屻€佸啿绐佹竻鐞嗐€佹秷鎭秴鏃躲€佹敞鍏ラ噸璇曚笌闃熷垪銆? +- `background/verification-flow.js`锛氭敞鍐?鐧诲綍楠岃瘉鐮佸叡浜祦绋嬪眰锛屽皝瑁呴噸鍙戙€佽疆璇€佹彁浜ゃ€佸け璐ュ洖閫€銆佽嚜瀹氫箟閭璺宠繃浠ュ強 2925 闀胯疆璇㈠弬鏁般€? ## `background/steps/` -- `background/steps/confirm-oauth.js`:步骤 8 实现,负责 OAuth 同意页按钮定位、点击、localhost 回调监听与回调完成。 -- `background/steps/fetch-login-code.js`:步骤 7 实现,负责登录验证码阶段的邮箱轮询与回退控制。 -- `background/steps/fetch-signup-code.js`:步骤 4 实现,负责注册验证码阶段的页面准备与验证码流程入口。 -- `background/steps/fill-password.js`:步骤 3 实现,负责密码生成、保存、回填与提交。 -- `background/steps/fill-profile.js`:步骤 5 实现,负责姓名、生日填写并把资料提交给注册页内容脚本。 -- `background/steps/oauth-login.js`:步骤 6 实现,负责刷新 OAuth 链接、登录和确保进入验证码页。 -- `background/steps/open-chatgpt.js`:步骤 1 实现,负责打开 ChatGPT 官网并确认入口就绪。 -- `background/steps/platform-verify.js`:步骤 9 实现,负责 CPA / SUB2API 回调验证。 -- `background/steps/registry.js`:步骤注册表工厂,负责用稳定的步骤元数据映射到执行器。 -- `background/steps/submit-signup-email.js`:步骤 2 实现,负责注册入口点击、邮箱提交与提交后落地页分支判断。 +- `background/steps/confirm-oauth.js`锛氭楠?8 瀹炵幇锛岃礋璐?OAuth 鍚屾剰椤垫寜閽畾浣嶃€佺偣鍑汇€乴ocalhost 鍥炶皟鐩戝惉涓庡洖璋冨畬鎴愩€? +- `background/steps/fetch-login-code.js`锛氭楠?7 瀹炵幇锛岃礋璐g櫥褰曢獙璇佺爜闃舵鐨勯偖绠辫疆璇笌鍥為€€鎺у埗銆? +- `background/steps/fetch-signup-code.js`锛氭楠?4 瀹炵幇锛岃礋璐f敞鍐岄獙璇佺爜闃舵鐨勯〉闈㈠噯澶囦笌楠岃瘉鐮佹祦绋嬪叆鍙c€? +- `background/steps/fill-password.js`锛氭楠?3 瀹炵幇锛岃礋璐e瘑鐮佺敓鎴愩€佷繚瀛樸€佸洖濉笌鎻愪氦銆? +- `background/steps/fill-profile.js`锛氭楠?5 瀹炵幇锛岃礋璐e鍚嶃€佺敓鏃ュ~鍐欏苟鎶婅祫鏂欐彁浜ょ粰娉ㄥ唽椤靛唴瀹硅剼鏈€? +- `background/steps/oauth-login.js`锛氭楠?6 瀹炵幇锛岃礋璐e埛鏂?OAuth 閾炬帴銆佺櫥褰曞拰纭繚杩涘叆楠岃瘉鐮侀〉銆? +- `background/steps/open-chatgpt.js`锛氭楠?1 瀹炵幇锛岃礋璐f墦寮€ ChatGPT 瀹樼綉骞剁‘璁ゅ叆鍙e氨缁€? +- `background/steps/platform-verify.js`锛氭楠?9 瀹炵幇锛岃礋璐?CPA / SUB2API 鍥炶皟楠岃瘉銆? +- `background/steps/registry.js`锛氭楠ゆ敞鍐岃〃宸ュ巶锛岃礋璐g敤绋冲畾鐨勬楠ゅ厓鏁版嵁鏄犲皠鍒版墽琛屽櫒銆? +- `background/steps/submit-signup-email.js`锛氭楠?2 瀹炵幇锛岃礋璐f敞鍐屽叆鍙g偣鍑汇€侀偖绠辨彁浜や笌鎻愪氦鍚庤惤鍦伴〉鍒嗘敮鍒ゆ柇銆? ## `content/` -- `content/activation-utils.js`:内容脚本通用激活策略工具,负责按钮点击方式判断与 Step 9 可恢复失败文案判断。 -- `content/duck-mail.js`:DuckDuckGo Email Protection 页面脚本,负责生成或读取 `@duck.com` 地址。 -- `content/gmail-mail.js`:Gmail 邮箱轮询脚本,负责在 Gmail 页面中匹配验证码邮件。 -- `content/icloud-mail.js`:iCloud 邮箱页面脚本,负责在 iCloud Mail 页面中读取邮件详情和验证码。 -- `content/inbucket-mail.js`:Inbucket 邮箱轮询脚本,负责在 Inbucket 页面中读取/删除验证码邮件。 -- `content/mail-163.js`:163 / 163 VIP 邮箱轮询脚本,负责网页邮箱验证码读取和邮件清理。 -- `content/mail-2925.js`:2925 邮箱页面脚本,负责 2925 邮箱收件轮询与验证码匹配。 -- `content/qq-mail.js`:QQ 邮箱轮询脚本,负责网页邮箱验证码读取。 -- `content/signup-page.js`:注册/登录/授权主内容脚本,负责 OpenAI / ChatGPT 页面上的步骤执行。 -- `content/sub2api-panel.js`:SUB2API 后台内容脚本,负责获取 OAuth 地址和提交 localhost 回调。 -- `content/utils.js`:内容脚本公共工具层,负责日志、READY/COMPLETE/ERROR 上报、元素等待、输入与点击。 -- `content/vps-panel.js`:CPA 面板内容脚本,负责获取 OAuth 地址、提交回调 URL,并基于精确成功徽标与错误态做 Step 9 判定。 +- `content/activation-utils.js`锛氬唴瀹硅剼鏈€氱敤婵€娲荤瓥鐣ュ伐鍏凤紝璐熻矗鎸夐挳鐐瑰嚮鏂瑰紡鍒ゆ柇涓?Step 9 鍙仮澶嶅け璐ユ枃妗堝垽鏂€? +- `content/duck-mail.js`锛欴uckDuckGo Email Protection 椤甸潰鑴氭湰锛岃礋璐g敓鎴愭垨璇诲彇 `@duck.com` 鍦板潃銆? +- `content/gmail-mail.js`锛欸mail 閭杞鑴氭湰锛岃礋璐e湪 Gmail 椤甸潰涓尮閰嶉獙璇佺爜閭欢銆? +- `content/icloud-mail.js`锛歩Cloud 閭椤甸潰鑴氭湰锛岃礋璐e湪 iCloud Mail 椤甸潰涓鍙栭偖浠惰鎯呭拰楠岃瘉鐮併€? +- `content/inbucket-mail.js`锛欼nbucket 閭杞鑴氭湰锛岃礋璐e湪 Inbucket 椤甸潰涓鍙?鍒犻櫎楠岃瘉鐮侀偖浠躲€? +- `content/mail-163.js`锛?63 / 163 VIP 閭杞鑴氭湰锛岃礋璐g綉椤甸偖绠遍獙璇佺爜璇诲彇鍜岄偖浠舵竻鐞嗐€? +- `content/mail-2925.js`锛?925 閭椤甸潰鑴氭湰锛岃礋璐?2925 閭鏀朵欢杞涓庨獙璇佺爜鍖归厤銆? +- `content/qq-mail.js`锛歈Q 閭杞鑴氭湰锛岃礋璐g綉椤甸偖绠遍獙璇佺爜璇诲彇銆? +- `content/signup-page.js`锛氭敞鍐?鐧诲綍/鎺堟潈涓诲唴瀹硅剼鏈紝璐熻矗 OpenAI / ChatGPT 椤甸潰涓婄殑姝ラ鎵ц銆? +- `content/sub2api-panel.js`锛歋UB2API 鍚庡彴鍐呭鑴氭湰锛岃礋璐h幏鍙?OAuth 鍦板潃鍜屾彁浜?localhost 鍥炶皟銆? +- `content/utils.js`锛氬唴瀹硅剼鏈叕鍏卞伐鍏峰眰锛岃礋璐f棩蹇椼€丷EADY/COMPLETE/ERROR 涓婃姤銆佸厓绱犵瓑寰呫€佽緭鍏ヤ笌鐐瑰嚮銆? +- `content/vps-panel.js`锛欳PA 闈㈡澘鍐呭鑴氭湰锛岃礋璐h幏鍙?OAuth 鍦板潃銆佹彁浜ゅ洖璋?URL锛屽苟鍩轰簬绮剧‘鎴愬姛寰芥爣涓庨敊璇€佸仛 Step 9 鍒ゅ畾銆? ## `data/` -- `data/names.js`:随机姓名、生日等测试数据源。 -- `data/step-definitions.js`:共享步骤元数据,前后台共同使用,用于动态渲染和步骤注册。 +- `data/names.js`锛氶殢鏈哄鍚嶃€佺敓鏃ョ瓑娴嬭瘯鏁版嵁婧愩€? +- `data/step-definitions.js`锛氬叡浜楠ゅ厓鏁版嵁锛屽墠鍚庡彴鍏卞悓浣跨敤锛岀敤浜庡姩鎬佹覆鏌撳拰姝ラ娉ㄥ唽銆? ## `docs/` -- `docs/Hotmail双模式适配开发方案及开发记录.md`:Hotmail 双模式接入的历史方案和开发记录。 -- `docs/仓库协作者AI分析PR与合并标准流程.md`:仓库协作者进行 AI 分析 PR 与合并时的流程说明。 -- `docs/images/交流群.jpg`:README 中展示的交流群图片资源。 -- `docs/images/十轮自动.png`:README 中展示的自动运行效果图。 -- `docs/images/微信.png`:README 中展示的微信收款码图片。 -- `docs/images/支付宝.jpg`:README 中展示的支付宝收款码图片。 -- `docs/refactor/2026-04-16-architecture-refactor-plan.md`:本轮重构阶段的结构设计与迁移计划记录。 -- `docs/superpowers/plans/2026-04-10-hotmail-oauth-mail-pool.md`:Hotmail OAuth 邮箱池实现计划文档。 -- `docs/superpowers/specs/2026-04-10-hotmail-oauth-design.md`:Hotmail OAuth + Graph Mail 的设计规格文档。 +- `docs/Hotmail鍙屾ā寮忛€傞厤寮€鍙戞柟妗堝強寮€鍙戣褰?md`锛欻otmail 鍙屾ā寮忔帴鍏ョ殑鍘嗗彶鏂规鍜屽紑鍙戣褰曘€? +- `docs/浠撳簱鍗忎綔鑰匒I鍒嗘瀽PR涓庡悎骞舵爣鍑嗘祦绋?md`锛氫粨搴撳崗浣滆€呰繘琛?AI 鍒嗘瀽 PR 涓庡悎骞舵椂鐨勬祦绋嬭鏄庛€? +- `docs/images/浜ゆ祦缇?jpg`锛歊EADME 涓睍绀虹殑浜ゆ祦缇ゅ浘鐗囪祫婧愩€? +- `docs/images/鍗佽疆鑷姩.png`锛歊EADME 涓睍绀虹殑鑷姩杩愯鏁堟灉鍥俱€? +- `docs/images/寰俊.png`锛歊EADME 涓睍绀虹殑寰俊鏀舵鐮佸浘鐗囥€? +- `docs/images/鏀粯瀹?jpg`锛歊EADME 涓睍绀虹殑鏀粯瀹濇敹娆剧爜鍥剧墖銆? +- `docs/refactor/2026-04-16-architecture-refactor-plan.md`锛氭湰杞噸鏋勯樁娈电殑缁撴瀯璁捐涓庤縼绉昏鍒掕褰曘€? +- `docs/superpowers/plans/2026-04-10-hotmail-oauth-mail-pool.md`锛欻otmail OAuth 閭姹犲疄鐜拌鍒掓枃妗c€? +- `docs/superpowers/specs/2026-04-10-hotmail-oauth-design.md`锛欻otmail OAuth + Graph Mail 鐨勮璁¤鏍兼枃妗c€? ## `icons/` -- `icons/icon128.png`:扩展 128 像素图标。 -- `icons/icon16.png`:扩展 16 像素图标。 -- `icons/icon48.png`:扩展 48 像素图标。 +- `icons/icon128.png`锛氭墿灞?128 鍍忕礌鍥炬爣銆? +- `icons/icon16.png`锛氭墿灞?16 鍍忕礌鍥炬爣銆? +- `icons/icon48.png`锛氭墿灞?48 鍍忕礌鍥炬爣銆? ## `scripts/` -- `scripts/hotmail_helper.py`:本地 helper 服务,负责通过本地接口协助 Hotmail 获取邮件和验证码,并提供账号运行历史文本追加接口。 +- `scripts/hotmail_helper.py`锛氭湰鍦?helper 鏈嶅姟锛岃礋璐i€氳繃鏈湴鎺ュ彛鍗忓姪 Hotmail 鑾峰彇閭欢鍜岄獙璇佺爜锛屽苟鎻愪緵璐﹀彿杩愯鍘嗗彶鏂囨湰杩藉姞鎺ュ彛銆? ## `sidepanel/` -- `sidepanel/hotmail-manager.js`:侧边栏 Hotmail 账号池管理器,负责列表、导入、验证、测试收信和批量操作。 -- `sidepanel/icloud-manager.js`:侧边栏 iCloud 隐私邮箱管理器,负责列表、筛选、保留、删除和批量操作。 -- `sidepanel/luckmail-manager.js`:侧边栏 LuckMail 管理器,负责邮箱列表、筛选、启停、保留与批量操作。 -- `sidepanel/sidepanel.css`:侧边栏样式文件。 -- `sidepanel/sidepanel.html`:侧边栏页面结构,当前步骤列表已改为动态容器,并在日志区标题下方预留账号运行历史摘要条带。 -- `sidepanel/sidepanel.js`:侧边栏主入口脚本,负责 UI 状态同步、动态步骤渲染、按钮交互、账号运行历史摘要渲染、独立 txt 留档配置与广播接收。 -- `sidepanel/update-service.js`:侧边栏更新检查服务,负责 GitHub Releases 查询与版本展示。 +- `sidepanel/hotmail-manager.js`锛氫晶杈规爮 Hotmail 璐﹀彿姹犵鐞嗗櫒锛岃礋璐e垪琛ㄣ€佸鍏ャ€侀獙璇併€佹祴璇曟敹淇″拰鎵归噺鎿嶄綔銆? +- `sidepanel/icloud-manager.js`锛氫晶杈规爮 iCloud 闅愮閭绠$悊鍣紝璐熻矗鍒楄〃銆佺瓫閫夈€佷繚鐣欍€佸垹闄ゅ拰鎵归噺鎿嶄綔銆? +- `sidepanel/luckmail-manager.js`锛氫晶杈规爮 LuckMail 绠$悊鍣紝璐熻矗閭鍒楄〃銆佺瓫閫夈€佸惎鍋溿€佷繚鐣欎笌鎵归噺鎿嶄綔銆? +- `sidepanel/sidepanel.css`锛氫晶杈规爮鏍峰紡鏂囦欢銆? +- `sidepanel/sidepanel.html`锛氫晶杈规爮椤甸潰缁撴瀯锛屽綋鍓嶆楠ゅ垪琛ㄥ凡鏀逛负鍔ㄦ€佸鍣紝骞跺湪鏃ュ織鍖烘爣棰樹笅鏂归鐣欒处鍙疯繍琛屽巻鍙叉憳瑕佹潯甯︺€? +- `sidepanel/sidepanel.js`锛氫晶杈规爮涓诲叆鍙h剼鏈紝璐熻矗 UI 鐘舵€佸悓姝ャ€佸姩鎬佹楠ゆ覆鏌撱€佹寜閽氦浜掋€佽处鍙疯繍琛屽巻鍙叉憳瑕佹覆鏌撱€佺嫭绔?txt 鐣欐。閰嶇疆涓庡箍鎾帴鏀躲€? +- `sidepanel/update-service.js`锛氫晶杈规爮鏇存柊妫€鏌ユ湇鍔★紝璐熻矗 GitHub Releases 鏌ヨ涓庣増鏈睍绀恒€? ## `tests/` -- `tests/activation-utils.test.js`:测试内容脚本激活策略与 Step 9 可恢复错误判断。 -- `tests/auto-run-fresh-attempt-reset.test.js`:测试自动运行在新一轮开始前会重置旧运行时上下文。 -- `tests/auto-run-step6-restart.test.js`:测试自动运行在步骤 6 之后遇错时会回到步骤 6 重开,并在命中 add-phone 时停止重开。 -- `tests/auto-step-random-delay.test.js`:测试自动运行步间延迟与旧配置键兼容解析。 -- `tests/background-auto-run-module.test.js`:测试自动运行控制器模块已接入且导出工厂。 -- `tests/background-account-run-history-module.test.js`:测试账号运行历史模块已接入、导出工厂,并能在不启用本地 helper 时正确持久化记录。 -- `tests/background-account-history-settings.test.js`:测试账号运行历史的独立配置项归一化,不再复用 Hotmail 模式作为启停条件。 -- `tests/background-generated-email-module.test.js`:测试生成邮箱辅助模块已接入且导出工厂。 -- `tests/background-icloud.test.js`:测试 iCloud 相关后台纯函数与别名收尾逻辑。 -- `tests/background-icloud-mail-provider.test.js`:测试 iCloud 邮箱 provider 配置解析。 -- `tests/background-logging-status-module.test.js`:测试日志/状态模块已接入且导出工厂。 -- `tests/background-luckmail.test.js`:测试 LuckMail 相关后台逻辑,如购买、复用、标记已用与重置。 -- `tests/background-message-router-module.test.js`:测试消息路由模块已接入且导出工厂。 -- `tests/background-message-router-step2-skip.test.js`:测试步骤 2 直接落到验证码页时的跳步与状态保护逻辑。 -- `tests/background-navigation-utils-module.test.js`:测试导航工具模块已接入且导出工厂。 -- `tests/background-panel-bridge-module.test.js`:测试面板桥接模块已接入且导出工厂。 -- `tests/background-signup-flow-module.test.js`:测试注册页辅助模块已接入且导出工厂。 -- `tests/background-step-modules.test.js`:测试步骤模块文件都已由后台入口加载。 -- `tests/background-step5-submit-short-circuit.test.js`:测试 Step 5 会把生成好的资料直接转发给内容脚本,并依赖完成信号收尾。 -- `tests/background-step6-retry-limit.test.js`:测试 Step 6 的有限重试上限,以及 Step 7 回放时可跳过登录前 Cookie 清理。 -- `tests/background-step7-recovery.test.js`:测试 Step 7 在 CPA 模式下会先回放 Step 6 再提交登录验证码,并为 2925 关闭重发间隔。 -- `tests/background-step-registry.test.js`:测试后台步骤注册表和共享步骤定义已接入。 -- `tests/background-tab-runtime-module.test.js`:测试标签运行时模块已接入且导出工厂。 -- `tests/background-verification-flow-module.test.js`:测试验证码流程模块已接入且导出工厂。 -- `tests/cloudflare-temp-email-provider.test.js`:测试 Cloudflare Temp Email provider 的轮询与目标邮箱选择逻辑。 -- `tests/cloudflare-temp-email-utils.test.js`:测试 Cloudflare Temp Email 工具层的 URL、域名、邮件解析逻辑。 -- `tests/hotmail-api-mode.test.js`:测试 Hotmail API 模式相关文案和集成方式。 -- `tests/hotmail-cors-headers.test.js`:测试 Microsoft token 请求相关 DNR 配置。 -- `tests/hotmail-utils.test.js`:测试 Hotmail 工具层的账号筛选、验证码提取和消息匹配逻辑。 -- `tests/icloud-mail-content.test.js`:测试 iCloud Mail 内容脚本读取邮件正文和选中状态逻辑。 -- `tests/icloud-utils.test.js`:测试 iCloud 工具层的 host、别名列表、保留状态与筛选逻辑。 -- `tests/luckmail-utils.test.js`:测试 LuckMail 工具层的购买记录、邮件、游标和验证码匹配逻辑。 -- `tests/microsoft-email.test.js`:测试 Microsoft 邮件拉取与验证码提取逻辑。 -- `tests/sidepanel-hotmail-manager.test.js`:测试侧边栏 Hotmail 管理器模块接线与空态渲染。 -- `tests/sidepanel-account-run-history.test.js`:测试侧边栏日志区下方的账号运行历史条带结构、独立留档配置控件与状态分类摘要逻辑。 -- `tests/sidepanel-icloud-manager.test.js`:测试侧边栏 iCloud 管理器模块接线与空态渲染。 -- `tests/sidepanel-icloud-provider.test.js`:测试侧边栏 iCloud 登录地址解析逻辑。 -- `tests/sidepanel-luckmail-manager.test.js`:测试侧边栏 LuckMail 管理器模块接线与空态渲染。 -- `tests/signup-page-tab-cleanup.test.js`:测试注册页来源标签的冲突清理逻辑。 -- `tests/step-definitions-module.test.js`:测试共享步骤定义模块及侧边栏脚本加载顺序。 -- `tests/step5-direct-complete.test.js`:测试 Step 5 在资料页点击提交后立即完成当前步骤。 -- `tests/step6-login-state.test.js`:测试 Step 6 登录状态判断逻辑。 -- `tests/step8-callback-handling.test.js`:测试 Step 8 回调地址捕获逻辑。 -- `tests/step8-debugger-stop.test.js`:测试 Step 8 调试器点击在 Stop 场景下的中止行为。 -- `tests/step8-state-timeout-retry.test.js`:测试 Step 8 通信错误是否可判定为可重试。 -- `tests/step8-stop-cleanup.test.js`:测试 Step 8 在 Stop 后能正确清理监听器与挂起状态。 -- `tests/step9-cpa-mode.test.js`:测试本地 CPA Step 9 策略判断。 -- `tests/step9-localhost-cleanup-scope.test.js`:测试 Step 9 仅清理精确命中的 localhost callback 和路径前缀残留页。 -- `tests/step9-status-diagnostics.test.js`:测试 Step 9 精确成功判定、红色错误态过滤,以及成功徽标与失败提示并存时的优先级。 -- `tests/verification-stop-propagation.test.js`:测试验证码流程在 Stop 场景下的错误传播与不中途降级。 -- `tests/verification-flow-polling.test.js`:测试 2925 长轮询参数,以及验证码提交流程中的 `beforeSubmit` 钩子执行顺序。 +- `tests/activation-utils.test.js`锛氭祴璇曞唴瀹硅剼鏈縺娲荤瓥鐣ヤ笌 Step 9 鍙仮澶嶉敊璇垽鏂€? +- `tests/auto-run-fresh-attempt-reset.test.js`锛氭祴璇曡嚜鍔ㄨ繍琛屽湪鏂颁竴杞紑濮嬪墠浼氶噸缃棫杩愯鏃朵笂涓嬫枃銆? +- `tests/auto-run-step6-restart.test.js`锛氭祴璇曡嚜鍔ㄨ繍琛屽湪姝ラ 6 涔嬪悗閬囬敊鏃朵細鍥炲埌姝ラ 6 閲嶅紑锛屽苟鍦ㄥ懡涓?add-phone 鏃跺仠姝㈤噸寮€銆? +- `tests/auto-step-random-delay.test.js`锛氭祴璇曡嚜鍔ㄨ繍琛屾闂村欢杩熶笌鏃ч厤缃敭鍏煎瑙f瀽銆? +- `tests/background-auto-run-module.test.js`锛氭祴璇曡嚜鍔ㄨ繍琛屾帶鍒跺櫒妯″潡宸叉帴鍏ヤ笖瀵煎嚭宸ュ巶銆? +- `tests/background-account-run-history-module.test.js`锛氭祴璇曡处鍙疯繍琛屽巻鍙叉ā鍧楀凡鎺ュ叆銆佸鍑哄伐鍘傦紝骞惰兘鍦ㄤ笉鍚敤鏈湴 helper 鏃舵纭寔涔呭寲璁板綍銆? +- `tests/background-account-history-settings.test.js`锛氭祴璇曡处鍙疯繍琛屽巻鍙茬殑鐙珛閰嶇疆椤瑰綊涓€鍖栵紝涓嶅啀澶嶇敤 Hotmail 妯″紡浣滀负鍚仠鏉′欢銆? +- `tests/background-generated-email-module.test.js`锛氭祴璇曠敓鎴愰偖绠辫緟鍔╂ā鍧楀凡鎺ュ叆涓斿鍑哄伐鍘傘€? +- `tests/background-icloud.test.js`锛氭祴璇?iCloud 鐩稿叧鍚庡彴绾嚱鏁颁笌鍒悕鏀跺熬閫昏緫銆? +- `tests/background-icloud-mail-provider.test.js`锛氭祴璇?iCloud 閭 provider 閰嶇疆瑙f瀽銆? +- `tests/background-logging-status-module.test.js`锛氭祴璇曟棩蹇?鐘舵€佹ā鍧楀凡鎺ュ叆涓斿鍑哄伐鍘傘€? +- `tests/background-luckmail.test.js`锛氭祴璇?LuckMail 鐩稿叧鍚庡彴閫昏緫锛屽璐拱銆佸鐢ㄣ€佹爣璁板凡鐢ㄤ笌閲嶇疆銆? +- `tests/background-message-router-module.test.js`锛氭祴璇曟秷鎭矾鐢辨ā鍧楀凡鎺ュ叆涓斿鍑哄伐鍘傘€? +- `tests/background-message-router-step2-skip.test.js`锛氭祴璇曟楠?2 鐩存帴钀藉埌楠岃瘉鐮侀〉鏃剁殑璺虫涓庣姸鎬佷繚鎶ら€昏緫銆? +- `tests/background-navigation-utils-module.test.js`锛氭祴璇曞鑸伐鍏锋ā鍧楀凡鎺ュ叆涓斿鍑哄伐鍘傘€? +- `tests/background-panel-bridge-module.test.js`锛氭祴璇曢潰鏉挎ˉ鎺ユā鍧楀凡鎺ュ叆涓斿鍑哄伐鍘傘€? +- `tests/background-signup-flow-module.test.js`锛氭祴璇曟敞鍐岄〉杈呭姪妯″潡宸叉帴鍏ヤ笖瀵煎嚭宸ュ巶銆? +- `tests/background-step-modules.test.js`锛氭祴璇曟楠ゆā鍧楁枃浠堕兘宸茬敱鍚庡彴鍏ュ彛鍔犺浇銆? +- `tests/background-step5-submit-short-circuit.test.js`锛氭祴璇?Step 5 浼氭妸鐢熸垚濂界殑璧勬枡鐩存帴杞彂缁欏唴瀹硅剼鏈紝骞朵緷璧栧畬鎴愪俊鍙锋敹灏俱€? +- `tests/step3-direct-complete.test.js`:测试 Step 3 会先回传完成载荷,再异步触发表单提交,避免页面跳转卡住主流程。 +- `tests/background-step6-retry-limit.test.js`锛氭祴璇?Step 6 鐨勬湁闄愰噸璇曚笂闄愶紝浠ュ強 Step 7 鍥炴斁鏃跺彲璺宠繃鐧诲綍鍓?Cookie 娓呯悊銆? +- `tests/background-step7-recovery.test.js`锛氭祴璇?Step 7 鍦?CPA 妯″紡涓嬩細鍏堝洖鏀?Step 6 鍐嶆彁浜ょ櫥褰曢獙璇佺爜锛屽苟涓?2925 鍏抽棴閲嶅彂闂撮殧銆? +- `tests/background-step-registry.test.js`锛氭祴璇曞悗鍙版楠ゆ敞鍐岃〃鍜屽叡浜楠ゅ畾涔夊凡鎺ュ叆銆? +- `tests/background-tab-runtime-module.test.js`锛氭祴璇曟爣绛捐繍琛屾椂妯″潡宸叉帴鍏ヤ笖瀵煎嚭宸ュ巶銆? +- `tests/background-verification-flow-module.test.js`锛氭祴璇曢獙璇佺爜娴佺▼妯″潡宸叉帴鍏ヤ笖瀵煎嚭宸ュ巶銆? +- `tests/cloudflare-temp-email-provider.test.js`锛氭祴璇?Cloudflare Temp Email provider 鐨勮疆璇笌鐩爣閭閫夋嫨閫昏緫銆? +- `tests/cloudflare-temp-email-utils.test.js`锛氭祴璇?Cloudflare Temp Email 宸ュ叿灞傜殑 URL銆佸煙鍚嶃€侀偖浠惰В鏋愰€昏緫銆? +- `tests/hotmail-api-mode.test.js`锛氭祴璇?Hotmail API 妯″紡鐩稿叧鏂囨鍜岄泦鎴愭柟寮忋€? +- `tests/hotmail-cors-headers.test.js`锛氭祴璇?Microsoft token 璇锋眰鐩稿叧 DNR 閰嶇疆銆? +- `tests/hotmail-utils.test.js`锛氭祴璇?Hotmail 宸ュ叿灞傜殑璐﹀彿绛涢€夈€侀獙璇佺爜鎻愬彇鍜屾秷鎭尮閰嶉€昏緫銆? +- `tests/icloud-mail-content.test.js`锛氭祴璇?iCloud Mail 鍐呭鑴氭湰璇诲彇閭欢姝f枃鍜岄€変腑鐘舵€侀€昏緫銆? +- `tests/icloud-utils.test.js`锛氭祴璇?iCloud 宸ュ叿灞傜殑 host銆佸埆鍚嶅垪琛ㄣ€佷繚鐣欑姸鎬佷笌绛涢€夐€昏緫銆? +- `tests/luckmail-utils.test.js`锛氭祴璇?LuckMail 宸ュ叿灞傜殑璐拱璁板綍銆侀偖浠躲€佹父鏍囧拰楠岃瘉鐮佸尮閰嶉€昏緫銆? +- `tests/microsoft-email.test.js`锛氭祴璇?Microsoft 閭欢鎷夊彇涓庨獙璇佺爜鎻愬彇閫昏緫銆? +- `tests/sidepanel-hotmail-manager.test.js`锛氭祴璇曚晶杈规爮 Hotmail 绠$悊鍣ㄦā鍧楁帴绾夸笌绌烘€佹覆鏌撱€? +- `tests/sidepanel-account-run-history.test.js`锛氭祴璇曚晶杈规爮鏃ュ織鍖轰笅鏂圭殑璐﹀彿杩愯鍘嗗彶鏉″甫缁撴瀯銆佺嫭绔嬬暀妗i厤缃帶浠朵笌鐘舵€佸垎绫绘憳瑕侀€昏緫銆? +- `tests/sidepanel-icloud-manager.test.js`锛氭祴璇曚晶杈规爮 iCloud 绠$悊鍣ㄦā鍧楁帴绾夸笌绌烘€佹覆鏌撱€? +- `tests/sidepanel-icloud-provider.test.js`锛氭祴璇曚晶杈规爮 iCloud 鐧诲綍鍦板潃瑙f瀽閫昏緫銆? +- `tests/sidepanel-luckmail-manager.test.js`锛氭祴璇曚晶杈规爮 LuckMail 绠$悊鍣ㄦā鍧楁帴绾夸笌绌烘€佹覆鏌撱€? +- `tests/signup-page-tab-cleanup.test.js`锛氭祴璇曟敞鍐岄〉鏉ユ簮鏍囩鐨勫啿绐佹竻鐞嗛€昏緫銆? +- `tests/step-definitions-module.test.js`锛氭祴璇曞叡浜楠ゅ畾涔夋ā鍧楀強渚ц竟鏍忚剼鏈姞杞介『搴忋€? +- `tests/step5-direct-complete.test.js`锛氭祴璇?Step 5 鍦ㄨ祫鏂欓〉鐐瑰嚮鎻愪氦鍚庣珛鍗冲畬鎴愬綋鍓嶆楠ゃ€? +- `tests/step6-login-state.test.js`锛氭祴璇?Step 6 鐧诲綍鐘舵€佸垽鏂€昏緫銆? +- `tests/step8-callback-handling.test.js`锛氭祴璇?Step 8 鍥炶皟鍦板潃鎹曡幏閫昏緫銆? +- `tests/step8-debugger-stop.test.js`锛氭祴璇?Step 8 璋冭瘯鍣ㄧ偣鍑诲湪 Stop 鍦烘櫙涓嬬殑涓琛屼负銆? +- `tests/step8-state-timeout-retry.test.js`锛氭祴璇?Step 8 閫氫俊閿欒鏄惁鍙垽瀹氫负鍙噸璇曘€? +- `tests/step8-stop-cleanup.test.js`锛氭祴璇?Step 8 鍦?Stop 鍚庤兘姝g‘娓呯悊鐩戝惉鍣ㄤ笌鎸傝捣鐘舵€併€? +- `tests/step9-cpa-mode.test.js`锛氭祴璇曟湰鍦?CPA Step 9 绛栫暐鍒ゆ柇銆? +- `tests/step9-localhost-cleanup-scope.test.js`锛氭祴璇?Step 9 浠呮竻鐞嗙簿纭懡涓殑 localhost callback 鍜岃矾寰勫墠缂€娈嬬暀椤点€? +- `tests/step9-status-diagnostics.test.js`锛氭祴璇?Step 9 绮剧‘鎴愬姛鍒ゅ畾銆佺孩鑹查敊璇€佽繃婊わ紝浠ュ強鎴愬姛寰芥爣涓庡け璐ユ彁绀哄苟瀛樻椂鐨勪紭鍏堢骇銆? +- `tests/verification-stop-propagation.test.js`锛氭祴璇曢獙璇佺爜娴佺▼鍦?Stop 鍦烘櫙涓嬬殑閿欒浼犳挱涓庝笉涓€旈檷绾с€? +- `tests/verification-flow-polling.test.js`锛氭祴璇?2925 闀胯疆璇㈠弬鏁帮紝浠ュ強楠岃瘉鐮佹彁浜ゆ祦绋嬩腑鐨?`beforeSubmit` 閽╁瓙鎵ц椤哄簭銆?