const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); test('background imports message router module', () => { const source = fs.readFileSync('background.js', 'utf8'); assert.match(source, /background\/message-router\.js/); }); test('background defaults enable free phone reuse switches', () => { const source = fs.readFileSync('background.js', 'utf8'); const defaultsStart = source.indexOf('const PERSISTED_SETTING_DEFAULTS = {'); const defaultsEnd = source.indexOf('const PERSISTED_SETTING_KEYS = Object.keys(PERSISTED_SETTING_DEFAULTS);'); const defaultsBlock = source.slice(defaultsStart, defaultsEnd); assert.match(defaultsBlock, /freePhoneReuseEnabled:\s*true/); assert.match(defaultsBlock, /freePhoneReuseAutoEnabled:\s*true/); }); test('background free reusable phone setter does not depend on module-scoped phone flow constants', () => { const source = fs.readFileSync('background.js', 'utf8'); const setterStart = source.indexOf('async function setFreeReusablePhoneActivation'); const setterEnd = source.indexOf('// ============================================================\n// Tab Registry', setterStart); const setterBlock = source.slice(setterStart, setterEnd); assert.ok(setterStart >= 0, 'expected setFreeReusablePhoneActivation to exist'); assert.doesNotMatch(setterBlock, /DEFAULT_PHONE_NUMBER_MAX_USES/); assert.match(setterBlock, /maxUses:\s*Math\.max\(1,\s*Math\.floor\(Number\(record\.maxUses\)\s*\|\|\s*3\)\)/); }); test('background free reusable phone setter can recover local HeroSMS activation id by phone number', () => { const source = fs.readFileSync('background.js', 'utf8'); const setterStart = source.indexOf('async function setFreeReusablePhoneActivation'); const setterEnd = source.indexOf('// ============================================================\n// Tab Registry', setterStart); const setterBlock = source.slice(setterStart, setterEnd); assert.match(source, /function findLocalHeroSmsActivationForPhone\(/); assert.match(source, /state\.currentPhoneActivation/); assert.match(source, /state\.reusablePhoneActivation/); assert.match(source, /state\.signupPhoneActivation/); assert.match(source, /state\.signupPhoneCompletedActivation/); assert.match(source, /state\.phonePreferredActivation/); assert.match(source, /state\.phoneReusableActivationPool/); assert.match(setterBlock, /findLocalHeroSmsActivationForPhone\(state,\s*phoneNumber\)/); assert.match(setterBlock, /activationId = String\(\s*record\.activationId[\s\S]*localActivation\?\.activationId/); assert.match(setterBlock, /manualOnly:\s*!activationId/); }); test('background HeroSMS phone prefix inference covers built-in major countries', () => { const source = fs.readFileSync('background.js', 'utf8'); const supportedStart = source.indexOf('const HERO_SMS_SUPPORTED_COUNTRY_IDS = ['); const prefixStart = source.indexOf('const HERO_SMS_COUNTRY_BY_PHONE_PREFIX = Object.freeze(['); const prefixEnd = source.indexOf(']);', prefixStart); const supportedBlock = source.slice(supportedStart, source.indexOf('];', supportedStart)); const prefixBlock = source.slice(prefixStart, prefixEnd); assert.match(supportedBlock, /\[6,\s*52,\s*187,\s*16,\s*151,\s*43,\s*73,\s*10/); [ ['84', 10, 'Vietnam'], ['66', 52, 'Thailand'], ['62', 6, 'Indonesia'], ['44', 16, 'United Kingdom'], ['81', 151, 'Japan'], ['49', 43, 'Germany'], ['33', 73, 'France'], ['1', 187, 'USA'], ].forEach(([prefix, id, label]) => { assert.match(prefixBlock, new RegExp(`prefix:\\s*'${prefix}'[\\s\\S]*id:\\s*${id}[\\s\\S]*label:\\s*'${label}'`)); }); }); test('message router module exposes a factory', () => { const source = fs.readFileSync('background/message-router.js', 'utf8'); const globalScope = {}; const api = new Function('self', `${source}; return self.MultiPageBackgroundMessageRouter;`)(globalScope); assert.equal(typeof api?.createMessageRouter, 'function'); }); test('SAVE_SETTING broadcasts free phone reuse setting updates for realtime sidepanel sync', async () => { const source = fs.readFileSync('background/message-router.js', 'utf8'); const globalScope = { console }; const api = new Function('self', `${source}; return self.MultiPageBackgroundMessageRouter;`)(globalScope); const broadcasts = []; let state = { freePhoneReuseEnabled: false, freePhoneReuseAutoEnabled: false, plusModeEnabled: false, plusPaymentMethod: 'paypal', }; const router = api.createMessageRouter({ addLog: async () => {}, buildLuckmailSessionSettingsPayload: () => ({}), buildPersistentSettingsPayload: (input = {}) => { const updates = {}; if (Object.prototype.hasOwnProperty.call(input, 'freePhoneReuseEnabled')) { updates.freePhoneReuseEnabled = Boolean(input.freePhoneReuseEnabled); } if (Object.prototype.hasOwnProperty.call(input, 'freePhoneReuseAutoEnabled')) { updates.freePhoneReuseAutoEnabled = Boolean(input.freePhoneReuseAutoEnabled); } return updates; }, broadcastDataUpdate: (payload) => broadcasts.push(payload), getState: async () => ({ ...state }), setPersistentSettings: async () => {}, setState: async (updates) => { state = { ...state, ...updates }; }, }); const response = await router.handleMessage({ type: 'SAVE_SETTING', payload: { freePhoneReuseEnabled: true, freePhoneReuseAutoEnabled: true, }, }); assert.equal(response.ok, true); assert.equal(state.freePhoneReuseEnabled, true); assert.equal(state.freePhoneReuseAutoEnabled, true); assert.ok( broadcasts.some((payload) => ( payload.freePhoneReuseEnabled === true && payload.freePhoneReuseAutoEnabled === true )), 'expected SAVE_SETTING to broadcast free reuse switch updates' ); });