This commit is contained in:
QLHazyCoder
2026-04-25 19:33:40 +08:00
28 changed files with 463 additions and 34 deletions
@@ -16,6 +16,26 @@ test('navigation utils module exposes a factory', () => {
assert.equal(typeof api?.createNavigationUtils, 'function');
});
test('navigation utils treat 126 mail hosts as part of the shared NetEase mail family', () => {
const source = fs.readFileSync('background/navigation-utils.js', 'utf8');
const globalScope = {};
const moduleApi = new Function('self', `${source}; return self.MultiPageBackgroundNavigationUtils;`)(globalScope);
const navigationUtils = moduleApi.createNavigationUtils({
DEFAULT_SUB2API_URL: 'https://example.com/admin/accounts',
normalizeLocalCpaStep9Mode: value => value,
});
assert.equal(navigationUtils.is163MailHost('mail.126.com'), true);
assert.equal(
navigationUtils.matchesSourceUrlFamily(
'mail-163',
'https://mail.126.com/js6/main.jsp',
'https://mail.163.com/js6/main.jsp'
),
true
);
});
test('navigation utils support codex2api mode and url normalization', () => {
const source = fs.readFileSync('background/navigation-utils.js', 'utf8');
const globalScope = {};
+82
View File
@@ -0,0 +1,82 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const source = fs.readFileSync('content/utils.js', 'utf8');
function extractFunction(name) {
const start = source.indexOf(`function ${name}(`);
if (start < 0) {
throw new Error(`missing function ${name}`);
}
let parenDepth = 0;
let signatureEnded = false;
let braceStart = -1;
for (let index = start; index < source.length; index += 1) {
const ch = source[index];
if (ch === '(') {
parenDepth += 1;
} else if (ch === ')') {
parenDepth -= 1;
if (parenDepth === 0) {
signatureEnded = true;
}
} else if (ch === '{' && signatureEnded) {
braceStart = index;
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('detectScriptSource maps 126 mail hosts to the shared 163 mail source', () => {
const bundle = [extractFunction('detectScriptSource')].join('\n');
const api = new Function(`
${bundle}
return { detectScriptSource };
`)();
assert.equal(
api.detectScriptSource({
url: 'https://mail.126.com/js6/main.jsp',
hostname: 'mail.126.com',
}),
'mail-163'
);
});
test('detectScriptSource maps 126 mail subdomains to the shared 163 mail source', () => {
const bundle = [extractFunction('detectScriptSource')].join('\n');
const api = new Function(`
${bundle}
return { detectScriptSource };
`)();
assert.equal(
api.detectScriptSource({
url: 'https://app.mail.126.com/js6/main.jsp',
hostname: 'app.mail.126.com',
}),
'mail-163'
);
});
+10
View File
@@ -181,6 +181,7 @@ test('shouldClearHotmailCurrentSelection returns true only when account becomes
test('extractVerificationCode returns first six-digit code from multilingual mail text', () => {
assert.equal(extractVerificationCode('你的 ChatGPT 验证码为 370794,请勿泄露。'), '370794');
assert.equal(extractVerificationCode('Your verification code is 654321.'), '654321');
assert.equal(extractVerificationCode('ChatGPT Log-in Code\nIf that was you, enter this code:\n\n982219'), '982219');
assert.equal(extractVerificationCode('No code here'), null);
});
@@ -202,6 +203,15 @@ test('extractVerificationCodeFromMessage reads code from the latest message subj
}),
'654321'
);
assert.equal(
extractVerificationCodeFromMessage({
subject: 'ChatGPT Log-in Code',
bodyPreview: 'We noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219',
from: { emailAddress: { address: 'noreply@openai.com' } },
}),
'982219'
);
});
test('getHotmailListToggleLabel reflects expanded state and account count', () => {
+14
View File
@@ -81,6 +81,20 @@ return { readOpenedMailBody, extractVerificationCode };
assert.equal(api.extractVerificationCode(bodyText), '731091');
});
test('extractVerificationCode matches the new suspicious log-in mail body', () => {
const bundle = [
extractFunction('extractVerificationCode'),
].join('\n');
const api = new Function(`
${bundle}
return { extractVerificationCode };
`)();
const bodyText = 'ChatGPT Log-in Code\nWe noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219';
assert.equal(api.extractVerificationCode(bodyText), '982219');
});
test('readOpenedMailBody ignores conversation list rows when no detail pane is open', () => {
const bundle = [
extractFunction('normalizeText'),
+14
View File
@@ -68,6 +68,20 @@ test('normalizeLuckmailTokenCode and normalizeLuckmailTokenMail extract verifica
assert.equal(normalizedMail.verification_code, '654321');
assert.equal(extractLuckmailVerificationCode('你的验证码为 778899'), '778899');
assert.equal(
extractLuckmailVerificationCode('ChatGPT Log-in Code\nIf that was you, enter this code:\n\n982219'),
'982219'
);
const suspiciousLoginMail = normalizeLuckmailTokenMail({
message_id: 'mail-3',
from: 'noreply@openai.com',
subject: 'ChatGPT Log-in Code',
body: 'We noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219',
received_at: '2026-04-14T10:02:00Z',
});
assert.equal(suspiciousLoginMail.verification_code, '982219');
});
test('normalizeLuckmailProjectName and isLuckmailPurchaseForProject match openai case-insensitively', () => {
+37 -1
View File
@@ -101,6 +101,23 @@ return { findMailItems };
assert.equal(rows.length, 1);
});
test('getNetEaseMailLabel returns the active NetEase mailbox brand', () => {
const bundle = [
extractFunction('getNetEaseMailLabel'),
].join('\n');
const api = new Function(`
${bundle}
return { getNetEaseMailLabel };
`)();
assert.equal(api.getNetEaseMailLabel('mail.126.com'), '126 邮箱');
assert.equal(api.getNetEaseMailLabel('app.mail.126.com'), '126 邮箱');
assert.equal(api.getNetEaseMailLabel('webmail.vip.163.com'), '163 VIP 邮箱');
assert.equal(api.getNetEaseMailLabel('mail.163.com'), '163 邮箱');
assert.equal(api.getNetEaseMailLabel('example.com'), '163 邮箱');
});
test('getMailTimestamp parses visible hh:mm text even when no title attribute exists', () => {
const bundle = [
extractFunction('normalizeText'),
@@ -340,14 +357,30 @@ return { openMailAndGetMessageText, mailItem };
assert.doesNotMatch(text, /111111/);
});
test('extractVerificationCode matches the new suspicious log-in mail body', () => {
const bundle = [
extractFunction('extractVerificationCode'),
].join('\n');
const api = new Function(`
${bundle}
return { extractVerificationCode };
`)();
const bodyText = 'ChatGPT Log-in Code\nWe noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219';
assert.equal(api.extractVerificationCode(bodyText), '982219');
});
test('handlePollEmail ignores same-minute old snapshot mail before fallback', async () => {
const bundle = [
extractFunction('normalizeText'),
extractFunction('normalizeMinuteTimestamp'),
extractFunction('getNetEaseMailLabel'),
extractFunction('handlePollEmail'),
].join('\n');
const api = new Function(`
const location = { hostname: 'mail.126.com' };
let currentItems = [{ id: 'old-mail' }];
const seenCodes = new Set();
@@ -405,7 +438,7 @@ return { handlePollEmail };
intervalMs: 1,
filterAfterTimestamp: new Date(2026, 3, 22, 22, 22, 40, 0).getTime(),
}),
/未在 163 邮箱中找到新的匹配邮件/
/未在 126 邮箱中找到新的匹配邮件/
);
});
@@ -413,6 +446,7 @@ test('handlePollEmail accepts a new same-minute mail that appears after the snap
const bundle = [
extractFunction('normalizeText'),
extractFunction('normalizeMinuteTimestamp'),
extractFunction('getNetEaseMailLabel'),
extractFunction('handlePollEmail'),
].join('\n');
@@ -505,6 +539,7 @@ test('handlePollEmail falls back to row text when the subject node is missing',
const bundle = [
extractFunction('normalizeText'),
extractFunction('normalizeMinuteTimestamp'),
extractFunction('getNetEaseMailLabel'),
extractFunction('handlePollEmail'),
].join('\n');
@@ -584,6 +619,7 @@ test('handlePollEmail opens matching mail body when preview has no code', async
const bundle = [
extractFunction('normalizeText'),
extractFunction('normalizeMinuteTimestamp'),
extractFunction('getNetEaseMailLabel'),
extractFunction('handlePollEmail'),
].join('\n');
+22
View File
@@ -0,0 +1,22 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
test('manifest 为网易邮箱内容脚本覆盖 126 子域名', () => {
const manifest = JSON.parse(fs.readFileSync('manifest.json', 'utf8'));
const mail163Script = manifest.content_scripts.find((script) => (
Array.isArray(script.js) && script.js.includes('content/mail-163.js')
));
assert.ok(mail163Script, '应存在 mail-163 内容脚本声明');
assert.equal(
mail163Script.matches.includes('https://mail.126.com/*'),
true,
'应覆盖 mail.126.com'
);
assert.equal(
mail163Script.matches.includes('https://*.mail.126.com/*'),
true,
'应覆盖 *.mail.126.com'
);
});
+15
View File
@@ -546,6 +546,21 @@ return {
]);
});
test('extractVerificationCode strict mode matches the new suspicious log-in mail body', () => {
const bundle = [
extractFunction('extractVerificationCode'),
].join('\n');
const api = new Function(`
${bundle}
return { extractVerificationCode };
`)();
const bodyText = 'ChatGPT Log-in Code\nWe noticed a suspicious log-in on your account. If that was you, enter this code:\n\n982219';
assert.equal(api.extractVerificationCode(bodyText, true), '982219');
assert.equal(api.extractVerificationCode(bodyText, false), '982219');
});
test('openMailAndGetMessageText always returns to inbox after opening a 2925 message', async () => {
const bundle = [
extractFunction('returnToInbox'),
+35
View File
@@ -0,0 +1,35 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const {
HOTMAIL_PROVIDER,
getMailProviderConfig,
normalizeMailProvider,
} = require('../mail-provider-utils.js');
test('normalizeMailProvider accepts 126 and falls back to 163', () => {
assert.equal(normalizeMailProvider('126'), '126');
assert.equal(normalizeMailProvider('163-vip'), '163-vip');
assert.equal(normalizeMailProvider('unknown-provider'), '163');
});
test('getMailProviderConfig returns the shared NetEase source for 126 mail', () => {
assert.deepEqual(
getMailProviderConfig({ mailProvider: '126' }),
{
source: 'mail-163',
url: 'https://mail.126.com/js6/main.jsp?df=mail163_letter#module=mbox.ListModule%7C%7B%22fid%22%3A1%2C%22order%22%3A%22date%22%2C%22desc%22%3Atrue%7D',
label: '126 邮箱',
}
);
});
test('getMailProviderConfig preserves the hotmail provider sentinel', () => {
assert.deepEqual(
getMailProviderConfig({ mailProvider: HOTMAIL_PROVIDER }),
{
provider: HOTMAIL_PROVIDER,
label: 'Hotmail(微软 Graph',
}
);
});
+6
View File
@@ -48,6 +48,7 @@ const helperBundle = [
extractFunction(helperSource, 'parseUrlSafely'),
extractFunction(helperSource, 'isSignupPageHost'),
extractFunction(helperSource, 'isSignupEntryHost'),
extractFunction(helperSource, 'is163MailHost'),
extractFunction(helperSource, 'matchesSourceUrlFamily'),
].join('\n');
@@ -153,6 +154,11 @@ return {
true,
'signup-page family should include legacy chat.openai.com'
);
assert.strictEqual(
api.matchesSourceUrlFamily('mail-163', 'https://mail.126.com/js6/main.jsp', 'https://mail.163.com/js6/main.jsp'),
true,
'mail-163 family should include mail.126.com'
);
api.reset({
tabs: [