From 3af7f8e9a5400c9e72bf87321216995683698e31 Mon Sep 17 00:00:00 2001 From: Lzj37412 Date: Mon, 9 Nov 2026 23:25:32 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E5=BC=80=E5=8F=91=E6=9C=BA=E4=BB=A3?= =?UTF-8?q?=E7=90=86=E7=8E=AF=E5=A2=83=E6=B3=84=E6=BC=8F=E8=BF=9B=E3=80=8C?= =?UTF-8?q?=E6=97=A0=E7=BD=91=E7=BB=9C=E3=80=8D=E6=B5=8B=E8=AF=95=E7=9A=84?= =?UTF-8?q?=E9=9A=94=E7=A6=BB=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 两套 fetch-stub 测试在带代理的开发机上必挂(CI 无代理不暴露): fetchJsonRace 的 viaProxy 路径走 node:http/tls 原生模块直连代理服务器, 完全绕过 globalThis.fetch stub——shell 里的 https_proxy / HTTPS_PROXY / ALL_PROXY 让真网络请求闯进测试,探测结果被真实响应覆盖。 实测(Windows + https_proxy=http://localhost:7897 + zcode-net.json proxyFirst=true): - web-session-watch 3/4 挂,单测耗时 6-8s(真网络往返) - robustness-audit「200 但非 JSON」挂(同根因) - 摘掉代理变量后全部 <50ms 通过 修复(只动测试文件,产品代码零改动): 1. 两文件头部统一摘除 https_proxy/HTTPS_PROXY/http_proxy/HTTP_PROXY/ ALL_PROXY/all_proxy——「全部注入 fetch,无网络」的承诺靠这个兑现 2. seedQoder 补 id:缺 id 时 find(x.id === acc.id) 退化成「找第一个 undefined id 的账号」,多账号共存时永远命中第一个种子,断言到错的记录 3. store 投影测试改按精确 id 寻址(原模糊 find(x.meta?.qoderWebDead) 会被前面测试留下的死标记账号串位) --- test/robustness-audit.test.js | 5 +++++ test/web-session-watch.test.js | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/test/robustness-audit.test.js b/test/robustness-audit.test.js index a0ffc25..49ce6ea 100644 --- a/test/robustness-audit.test.js +++ b/test/robustness-audit.test.js @@ -13,6 +13,11 @@ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; +// 隔离代理:qoderClient 的 webReq → fetchJsonRace(preferProxy) 在配置了 +// https_proxy 时会走 node:http/tls 的 viaProxy 路径(不经 globalThis.fetch), +// 开发机 shell 带代理变量会让 stub 失效、真网络闯进「无网络」测试。 +for (const k of ['https_proxy', 'HTTPS_PROXY', 'http_proxy', 'HTTP_PROXY', 'ALL_PROXY', 'all_proxy']) delete process.env[k]; + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'creditdaddy-audit-')); process.env.CREDITDADDY_HOME = path.join(root, 'data'); diff --git a/test/web-session-watch.test.js b/test/web-session-watch.test.js index 9f56df2..85055d8 100644 --- a/test/web-session-watch.test.js +++ b/test/web-session-watch.test.js @@ -12,6 +12,12 @@ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; +// 隔离代理:fetchJsonRace 的 viaProxy 路径走 node:http/tls 原生模块(不经 +// globalThis.fetch),开发机 shell 里的 https_proxy / HTTPS_PROXY 会让它绕过 +// fetch stub 发真网络请求(6-8s 耗时、探测结果被真实响应覆盖)。本文件 +// 「全部注入 fetch,无网络」的承诺靠摘掉代理变量兑现。 +for (const k of ['https_proxy', 'HTTPS_PROXY', 'http_proxy', 'HTTP_PROXY', 'ALL_PROXY', 'all_proxy']) delete process.env[k]; + const HOME = fs.mkdtempSync(path.join(os.tmpdir(), 'ws-watch-test-')); process.env.CREDITDADDY_HOME = HOME; @@ -30,6 +36,10 @@ function stubFetch(handler) { async function seedQoder(overrides = {}) { const acc = { + // 必须带 id:产品代码与断言都按 id 精确寻址(withAccounts / find)。 + // 缺 id 时 find(x.id === acc.id) 退化成「第一个 undefined id 的账号」, + // 多账号共存时永远命中第一个种子,断言到错的记录上。 + id: 'acc-' + Math.random().toString(36).slice(2), name: '测试号', provider: 'qoder', token: 'tok-' + Math.random().toString(36).slice(2), @@ -67,10 +77,12 @@ test('保活监视:网络异常 → 保守不动标记(不误杀)', async }); test('store 投影:qoderWebDead 只回时间戳,qoderWebSession.cookie 永不回显', async () => { - await seedQoder({ meta: { qoderWebSession: { cookie: 'SECRET', capturedAt: '2026-10-15T00:00:00Z' }, qoderWebDead: { at: '2026-10-15T01:00:00Z' } } }); + // 按精确 id 找自己种入的账号:模糊 find(x.meta?.qoderWebDead)会被 + // 前面测试留下的死标记账号串位,断言到错的记录上 + const acc = await seedQoder({ meta: { qoderWebSession: { cookie: 'SECRET', capturedAt: '2026-10-15T00:00:00Z' }, qoderWebDead: { at: '2026-10-15T01:00:00Z' } } }); const accounts = await store.loadAccounts(); - const hit = accounts.find((x) => x.meta?.qoderWebDead); - assert.ok(hit); + const hit = accounts.find((x) => x.id === acc.id); + assert.ok(hit, '刚种入的账号必须能按 id 找到'); const panel = store.publicAccount(hit); assert.equal(panel.qoderWebDead, '2026-10-15T01:00:00Z'); assert.equal(panel.qoderWebCapturedAt, '2026-10-15T00:00:00Z');