Files
FlowPilot/tests/yyds-mail-provider.test.js
T
2026-05-16 21:58:14 +08:00

186 lines
6.4 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const utils = require('../yyds-mail-utils.js');
require('../background/yyds-mail-provider.js');
function createProviderApi(options = {}) {
const {
state = {
yydsMailApiKey: 'AC-demo',
yydsMailBaseUrl: 'https://maliapi.215.im/v1',
currentYydsMailInbox: null,
email: '',
},
fetchImpl,
} = options;
let currentState = { ...state };
const logs = [];
const persistCalls = [];
const stateUpdates = [];
const calls = [];
const api = globalThis.MultiPageBackgroundYydsMailProvider.createYydsMailProvider({
addLog: async (message, level) => logs.push({ message, level }),
buildYydsMailHeaders: utils.buildYydsMailHeaders,
DEFAULT_YYDS_MAIL_BASE_URL: utils.DEFAULT_YYDS_MAIL_BASE_URL,
fetchImpl: fetchImpl || (async (url, request = {}) => {
calls.push({
url: String(url),
method: request.method,
headers: request.headers,
body: request.body ? JSON.parse(request.body) : undefined,
});
if (String(url).endsWith('/accounts')) {
return {
ok: true,
text: async () => JSON.stringify({
success: true,
data: {
id: 'inbox-1',
address: 'fresh@example.com',
token: 'temp-token',
expiresAt: '2026-03-15T12:00:00Z',
},
}),
};
}
if (String(url).includes('/messages/msg-1')) {
return {
ok: true,
text: async () => JSON.stringify({
success: true,
data: {
id: 'msg-1',
from: { address: 'noreply@tm.openai.com' },
subject: 'OpenAI verification code',
text: 'Your ChatGPT code is 987654.',
createdAt: '2026-03-14T12:30:00Z',
},
}),
};
}
if (String(url).includes('/messages')) {
return {
ok: true,
text: async () => JSON.stringify({
success: true,
data: {
messages: [{
id: 'msg-1',
from: { address: 'noreply@tm.openai.com' },
subject: 'OpenAI verification code',
createdAt: '2026-03-14T12:30:00Z',
}],
},
}),
};
}
throw new Error(`unexpected URL ${url}`);
}),
getState: async () => currentState,
joinYydsMailUrl: utils.joinYydsMailUrl,
normalizeYydsMailAddress: utils.normalizeYydsMailAddress,
normalizeYydsMailApiKey: utils.normalizeYydsMailApiKey,
normalizeYydsMailBaseUrl: utils.normalizeYydsMailBaseUrl,
normalizeYydsMailCurrentInbox: utils.normalizeYydsMailCurrentInbox,
normalizeYydsMailInbox: utils.normalizeYydsMailInbox,
normalizeYydsMailMessageDetail: utils.normalizeYydsMailMessageDetail,
normalizeYydsMailMessages: utils.normalizeYydsMailMessages,
persistRegistrationEmailState: async (callState, email, persistOptions) => {
persistCalls.push({ state: callState, email, options: persistOptions });
currentState = { ...currentState, email };
},
pickVerificationMessageWithTimeFallback: (messages) => {
const match = messages.find((message) => message.verification_code);
return match
? {
match: {
code: match.verification_code,
receivedAt: Date.parse(match.receivedDateTime),
message: match,
},
usedRelaxedFilters: false,
usedTimeFallback: false,
}
: { match: null, usedRelaxedFilters: false, usedTimeFallback: false };
},
setState: async (updates) => {
stateUpdates.push(updates);
currentState = { ...currentState, ...updates };
},
sleepWithStop: async () => {},
throwIfStopped: () => {},
YYDS_MAIL_PROVIDER: utils.YYDS_MAIL_PROVIDER,
});
return {
...api,
snapshot() {
return { calls, currentState, logs, persistCalls, stateUpdates };
},
};
}
test('fetchYydsMailAddress creates an inbox with localPart only and stores the returned address/token', async () => {
const api = createProviderApi();
const email = await api.fetchYydsMailAddress(null, { localPart: 'fresh' });
const snapshot = api.snapshot();
assert.equal(email, 'fresh@example.com');
assert.equal(snapshot.calls[0].url, 'https://maliapi.215.im/v1/accounts');
assert.equal(snapshot.calls[0].method, 'POST');
assert.deepEqual(snapshot.calls[0].body, { localPart: 'fresh' });
assert.equal(snapshot.calls[0].headers['X-API-Key'], 'AC-demo');
assert.equal(snapshot.calls[0].headers.Authorization, undefined);
assert.equal(snapshot.currentState.currentYydsMailInbox.address, 'fresh@example.com');
assert.equal(snapshot.currentState.currentYydsMailInbox.token, 'temp-token');
assert.equal(snapshot.persistCalls[0].email, 'fresh@example.com');
});
test('pollYydsMailVerificationCode lists messages with temp token and reads detail before matching code', async () => {
const api = createProviderApi({
state: {
yydsMailApiKey: 'AC-demo',
yydsMailBaseUrl: 'https://maliapi.215.im/v1',
currentYydsMailInbox: {
id: 'inbox-1',
address: 'fresh@example.com',
token: 'temp-token',
},
email: 'fresh@example.com',
},
});
const result = await api.pollYydsMailVerificationCode(4, null, {
maxAttempts: 1,
intervalMs: 1,
senderFilters: ['openai'],
subjectFilters: ['code'],
});
const snapshot = api.snapshot();
const listCall = snapshot.calls.find((call) => call.url.includes('/messages?'));
const detailCall = snapshot.calls.find((call) => call.url.includes('/messages/msg-1'));
assert.equal(result.code, '987654');
assert.equal(listCall.headers.Authorization, 'Bearer temp-token');
assert.equal(listCall.headers['X-API-Key'], undefined);
assert.match(listCall.url, /address=fresh%40example\.com/);
assert.equal(detailCall.headers.Authorization, 'Bearer temp-token');
});
test('clearYydsMailRuntimeState clears current inbox and optionally current email', async () => {
const api = createProviderApi({
state: {
currentYydsMailInbox: { address: 'fresh@example.com', token: 'temp-token' },
email: 'fresh@example.com',
},
});
await api.clearYydsMailRuntimeState({ clearEmail: true });
assert.deepEqual(api.snapshot().stateUpdates.at(-1), {
currentYydsMailInbox: null,
email: null,
});
});