276 lines
8.3 KiB
JavaScript
276 lines
8.3 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const {
|
|
DEFAULT_LUCKMAIL_BASE_URL,
|
|
DEFAULT_LUCKMAIL_EMAIL_TYPE,
|
|
DEFAULT_LUCKMAIL_PRESERVE_TAG_NAME,
|
|
buildLuckmailBaselineCursor,
|
|
buildLuckmailMailCursor,
|
|
extractLuckmailVerificationCode,
|
|
filterReusableLuckmailPurchases,
|
|
isLuckmailMailNewerThanCursor,
|
|
isLuckmailPurchaseForProject,
|
|
normalizeLuckmailBaseUrl,
|
|
normalizeLuckmailEmailType,
|
|
normalizeLuckmailProjectName,
|
|
normalizeLuckmailPurchaseListPage,
|
|
normalizeLuckmailTags,
|
|
normalizeLuckmailUsedPurchases,
|
|
normalizeTimestamp,
|
|
normalizeLuckmailTokenCode,
|
|
normalizeLuckmailTokenMail,
|
|
pickReusableLuckmailPurchase,
|
|
pickLuckmailVerificationMail,
|
|
} = require('../luckmail-utils.js');
|
|
|
|
test('normalizeLuckmailEmailType keeps supported values and falls back to ms_graph', () => {
|
|
assert.equal(normalizeLuckmailEmailType('self_built'), 'self_built');
|
|
assert.equal(normalizeLuckmailEmailType('ms_imap'), 'ms_imap');
|
|
assert.equal(normalizeLuckmailEmailType('ms_graph'), 'ms_graph');
|
|
assert.equal(normalizeLuckmailEmailType('google_variant'), 'google_variant');
|
|
assert.equal(normalizeLuckmailEmailType(''), DEFAULT_LUCKMAIL_EMAIL_TYPE);
|
|
assert.equal(normalizeLuckmailEmailType('unknown'), DEFAULT_LUCKMAIL_EMAIL_TYPE);
|
|
});
|
|
|
|
test('normalizeLuckmailBaseUrl trims invalid input to default base url', () => {
|
|
assert.equal(normalizeLuckmailBaseUrl(''), DEFAULT_LUCKMAIL_BASE_URL);
|
|
assert.equal(normalizeLuckmailBaseUrl('https://mails.luckyous.com/'), DEFAULT_LUCKMAIL_BASE_URL);
|
|
assert.equal(normalizeLuckmailBaseUrl('https://demo.example.com/api/'), 'https://demo.example.com/api');
|
|
assert.equal(normalizeLuckmailBaseUrl('notaurl'), DEFAULT_LUCKMAIL_BASE_URL);
|
|
});
|
|
|
|
test('normalizeLuckmailTokenCode and normalizeLuckmailTokenMail extract verification code', () => {
|
|
const tokenCode = normalizeLuckmailTokenCode({
|
|
email_address: 'demo@outlook.com',
|
|
project: 'openai',
|
|
has_new_mail: true,
|
|
verification_code: '123456',
|
|
mail: {
|
|
message_id: 'mail-1',
|
|
from: 'noreply@openai.com',
|
|
subject: 'Your ChatGPT code is 123456',
|
|
received_at: '2026-04-14T10:00:00Z',
|
|
},
|
|
});
|
|
|
|
assert.equal(tokenCode.verification_code, '123456');
|
|
assert.equal(tokenCode.mail.message_id, 'mail-1');
|
|
assert.equal(tokenCode.mail.verification_code, '123456');
|
|
|
|
const normalizedMail = normalizeLuckmailTokenMail({
|
|
message_id: 'mail-2',
|
|
from: 'noreply@openai.com',
|
|
subject: 'OpenAI security message',
|
|
body: 'Your verification code is 654321.',
|
|
received_at: '2026-04-14T10:01:00Z',
|
|
});
|
|
|
|
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', () => {
|
|
assert.equal(normalizeLuckmailProjectName(' OpenAi '), 'openai');
|
|
assert.equal(isLuckmailPurchaseForProject({
|
|
id: 1,
|
|
email_address: 'demo@outlook.com',
|
|
token: 'tok-1',
|
|
project_name: 'OpenAi',
|
|
}, 'openai'), true);
|
|
assert.equal(isLuckmailPurchaseForProject({
|
|
id: 2,
|
|
email_address: 'other@example.com',
|
|
token: 'tok-2',
|
|
project: 'OtherProject',
|
|
}, 'openai'), false);
|
|
});
|
|
|
|
test('normalizeLuckmailPurchaseListPage and normalizeLuckmailTags normalize list payloads', () => {
|
|
const page = normalizeLuckmailPurchaseListPage({
|
|
list: [{
|
|
id: 3,
|
|
email_address: 'demo@outlook.com',
|
|
token: 'tok-3',
|
|
project_name: 'OpenAi',
|
|
}],
|
|
total: 4,
|
|
page: 2,
|
|
page_size: 1,
|
|
});
|
|
assert.equal(page.total, 4);
|
|
assert.equal(page.page, 2);
|
|
assert.equal(page.page_size, 1);
|
|
assert.equal(page.list[0].project_code, 'openai');
|
|
|
|
const tags = normalizeLuckmailTags([{
|
|
id: 9,
|
|
name: DEFAULT_LUCKMAIL_PRESERVE_TAG_NAME,
|
|
limit_type: 0,
|
|
}]);
|
|
assert.deepEqual(tags[0], {
|
|
id: 9,
|
|
name: DEFAULT_LUCKMAIL_PRESERVE_TAG_NAME,
|
|
remark: '',
|
|
limit_type: 0,
|
|
purchase_count: 0,
|
|
created_at: null,
|
|
});
|
|
});
|
|
|
|
test('normalizeLuckmailUsedPurchases keeps positive numeric keys only', () => {
|
|
assert.deepEqual(normalizeLuckmailUsedPurchases({
|
|
1: true,
|
|
foo: true,
|
|
'-2': true,
|
|
3: false,
|
|
}), {
|
|
1: true,
|
|
3: false,
|
|
});
|
|
});
|
|
|
|
test('pickReusableLuckmailPurchase only returns reusable openai purchase', () => {
|
|
const purchases = [{
|
|
id: 10,
|
|
email_address: 'used@outlook.com',
|
|
token: 'tok-used',
|
|
project_name: 'openai',
|
|
}, {
|
|
id: 11,
|
|
email_address: 'preserved@outlook.com',
|
|
token: 'tok-preserved',
|
|
project_name: 'OpenAi',
|
|
tag_name: DEFAULT_LUCKMAIL_PRESERVE_TAG_NAME,
|
|
}, {
|
|
id: 12,
|
|
email_address: 'disabled@outlook.com',
|
|
token: 'tok-disabled',
|
|
project_name: 'openai',
|
|
user_disabled: 1,
|
|
}, {
|
|
id: 13,
|
|
email_address: 'expired@outlook.com',
|
|
token: 'tok-expired',
|
|
project_name: 'openai',
|
|
warranty_until: '2026-04-14T09:00:00Z',
|
|
}, {
|
|
id: 14,
|
|
email_address: 'other@example.com',
|
|
token: 'tok-other',
|
|
project_name: 'other',
|
|
}, {
|
|
id: 15,
|
|
email_address: 'ready@outlook.com',
|
|
token: 'tok-ready',
|
|
project_name: 'OpenAi',
|
|
warranty_until: '2026-04-15T09:00:00Z',
|
|
}];
|
|
|
|
const reusable = filterReusableLuckmailPurchases(purchases, {
|
|
projectCode: 'openai',
|
|
usedPurchases: { 10: true },
|
|
preserveTagName: DEFAULT_LUCKMAIL_PRESERVE_TAG_NAME,
|
|
now: Date.parse('2026-04-14T10:00:00Z'),
|
|
});
|
|
|
|
assert.deepEqual(reusable.map((purchase) => purchase.id), [15]);
|
|
assert.equal(pickReusableLuckmailPurchase(purchases, {
|
|
projectCode: 'openai',
|
|
usedPurchases: { 10: true },
|
|
preserveTagName: DEFAULT_LUCKMAIL_PRESERVE_TAG_NAME,
|
|
now: Date.parse('2026-04-14T10:00:00Z'),
|
|
}).id, 15);
|
|
});
|
|
|
|
test('pickLuckmailVerificationMail respects sender filters, time filters, and excluded codes', () => {
|
|
const match = pickLuckmailVerificationMail([
|
|
{
|
|
message_id: 'old-mail',
|
|
from: 'noreply@openai.com',
|
|
subject: 'Your code is 111111',
|
|
received_at: '2026-04-14T09:59:00Z',
|
|
},
|
|
{
|
|
message_id: 'new-mail',
|
|
from: 'noreply@openai.com',
|
|
subject: 'Your code is 222222',
|
|
received_at: '2026-04-14T10:05:00Z',
|
|
},
|
|
], {
|
|
senderFilters: ['openai'],
|
|
subjectFilters: ['code'],
|
|
excludeCodes: ['111111'],
|
|
afterTimestamp: Date.parse('2026-04-14T10:00:00Z'),
|
|
});
|
|
|
|
assert.equal(match.code, '222222');
|
|
assert.equal(match.mail.message_id, 'new-mail');
|
|
});
|
|
|
|
test('isLuckmailMailNewerThanCursor compares message id and timestamp safely', () => {
|
|
const cursor = buildLuckmailMailCursor({
|
|
message_id: 'mail-1',
|
|
received_at: '2026-04-14T10:00:00Z',
|
|
});
|
|
|
|
assert.equal(isLuckmailMailNewerThanCursor({
|
|
message_id: 'mail-1',
|
|
received_at: '2026-04-14T10:00:00Z',
|
|
}, cursor), false);
|
|
|
|
assert.equal(isLuckmailMailNewerThanCursor({
|
|
message_id: 'mail-2',
|
|
received_at: '2026-04-14T10:01:00Z',
|
|
}, cursor), true);
|
|
});
|
|
|
|
test('normalizeLuckmailMailCursor tolerates null cursor input', () => {
|
|
const { normalizeLuckmailMailCursor } = require('../luckmail-utils.js');
|
|
assert.deepEqual(normalizeLuckmailMailCursor(null), {
|
|
messageId: '',
|
|
receivedAt: '',
|
|
});
|
|
});
|
|
|
|
test('normalizeTimestamp treats LuckMail naive datetime strings as UTC', () => {
|
|
assert.equal(
|
|
normalizeTimestamp('2026-04-14 13:32:05'),
|
|
Date.UTC(2026, 3, 14, 13, 32, 5, 0)
|
|
);
|
|
});
|
|
|
|
test('buildLuckmailBaselineCursor tracks newest existing mail as baseline', () => {
|
|
const cursor = buildLuckmailBaselineCursor([
|
|
{
|
|
message_id: 'mail-old',
|
|
received_at: '2026-04-14 13:31:15',
|
|
subject: '你的 ChatGPT 代码为 111111',
|
|
},
|
|
{
|
|
message_id: 'mail-new',
|
|
received_at: '2026-04-14 13:32:05',
|
|
subject: '你的 ChatGPT 代码为 222222',
|
|
},
|
|
]);
|
|
|
|
assert.deepEqual(cursor, {
|
|
messageId: 'mail-new',
|
|
receivedAt: '2026-04-14 13:32:05',
|
|
});
|
|
});
|