const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const mail2925Utils = require('../mail2925-utils.js'); test('background mail2925 session module exposes a factory', () => { const source = fs.readFileSync('background/mail-2925-session.js', 'utf8'); const globalScope = {}; const api = new Function('self', `${source}; return self.MultiPageBackgroundMail2925Session;`)(globalScope); assert.equal(typeof api?.createMail2925SessionManager, 'function'); }); test('handleMail2925LimitReachedError disables current account and switches to the next one', async () => { const source = fs.readFileSync('background/mail-2925-session.js', 'utf8'); const globalScope = {}; const api = new Function('self', `${source}; return self.MultiPageBackgroundMail2925Session;`)(globalScope); let currentState = { mail2925Accounts: mail2925Utils.normalizeMail2925Accounts([ { id: 'current', email: 'current@2925.com', password: 'p1', enabled: true, lastUsedAt: 10 }, { id: 'next', email: 'next@2925.com', password: 'p2', enabled: true, lastUsedAt: 20 }, ]), currentMail2925AccountId: 'current', }; const events = { logs: [], dataUpdates: [], tabOpens: 0, sessionChecks: 0, }; const manager = api.createMail2925SessionManager({ addLog: async (message, level = 'info') => { events.logs.push({ message, level }); }, broadcastDataUpdate: (payload) => { events.dataUpdates.push(payload); }, chrome: { cookies: { getAll: async () => [], remove: async () => ({ ok: true }), }, browsingData: { removeCookies: async () => {}, }, }, findMail2925Account: mail2925Utils.findMail2925Account, getMail2925AccountStatus: mail2925Utils.getMail2925AccountStatus, getState: async () => currentState, isMail2925AccountAvailable: mail2925Utils.isMail2925AccountAvailable, MAIL2925_LIMIT_COOLDOWN_MS: mail2925Utils.MAIL2925_LIMIT_COOLDOWN_MS, normalizeMail2925Account: mail2925Utils.normalizeMail2925Account, normalizeMail2925Accounts: mail2925Utils.normalizeMail2925Accounts, pickMail2925AccountForRun: mail2925Utils.pickMail2925AccountForRun, reuseOrCreateTab: async () => { events.tabOpens += 1; return 1; }, sendToMailContentScriptResilient: async () => { events.sessionChecks += 1; return { loggedIn: true }; }, setPersistentSettings: async (payload) => { currentState = { ...currentState, ...payload, }; }, setState: async (updates) => { currentState = { ...currentState, ...updates, }; }, throwIfStopped: () => {}, upsertMail2925AccountInList: mail2925Utils.upsertMail2925AccountInList, }); const error = await manager.handleMail2925LimitReachedError( 4, new Error('MAIL2925_LIMIT_REACHED::子邮箱已达上限邮箱') ); assert.match(error.message, /^MAIL2925_THREAD_TERMINATED::/); assert.equal(currentState.currentMail2925AccountId, 'next'); assert.ok(events.tabOpens >= 1); assert.ok(events.sessionChecks >= 1); const currentAccount = currentState.mail2925Accounts.find((account) => account.id === 'current'); assert.equal(currentAccount.lastError, '子邮箱已达上限邮箱'); assert.ok(currentAccount.disabledUntil > Date.now()); });