没有直接撬 Step 1~9 的核心状态机,而是先把最适合独立的管理器和桥接层拆出来
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
test('background imports generated email helper module', () => {
|
||||
const source = fs.readFileSync('background.js', 'utf8');
|
||||
assert.match(source, /importScripts\([\s\S]*'background\/generated-email-helpers\.js'/);
|
||||
});
|
||||
|
||||
test('generated email helper module exposes a factory', () => {
|
||||
const source = fs.readFileSync('background/generated-email-helpers.js', 'utf8');
|
||||
const globalScope = {};
|
||||
|
||||
const api = new Function('self', `${source}; return self.MultiPageGeneratedEmailHelpers;`)(globalScope);
|
||||
|
||||
assert.equal(typeof api?.createGeneratedEmailHelpers, 'function');
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
test('background imports panel bridge module', () => {
|
||||
const source = fs.readFileSync('background.js', 'utf8');
|
||||
assert.match(source, /importScripts\([\s\S]*'background\/panel-bridge\.js'/);
|
||||
});
|
||||
|
||||
test('panel bridge module exposes a factory', () => {
|
||||
const source = fs.readFileSync('background/panel-bridge.js', 'utf8');
|
||||
const globalScope = {};
|
||||
|
||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundPanelBridge;`)(globalScope);
|
||||
|
||||
assert.equal(typeof api?.createPanelBridge, 'function');
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
test('background imports signup flow helper module', () => {
|
||||
const source = fs.readFileSync('background.js', 'utf8');
|
||||
assert.match(source, /importScripts\([\s\S]*'background\/signup-flow-helpers\.js'/);
|
||||
});
|
||||
|
||||
test('signup flow helper module exposes a factory', () => {
|
||||
const source = fs.readFileSync('background/signup-flow-helpers.js', 'utf8');
|
||||
const globalScope = {};
|
||||
|
||||
const api = new Function('self', `${source}; return self.MultiPageSignupFlowHelpers;`)(globalScope);
|
||||
|
||||
assert.equal(typeof api?.createSignupFlowHelpers, 'function');
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
test('sidepanel loads hotmail manager before sidepanel bootstrap', () => {
|
||||
const html = fs.readFileSync('sidepanel/sidepanel.html', 'utf8');
|
||||
const hotmailManagerIndex = html.indexOf('<script src="hotmail-manager.js"></script>');
|
||||
const sidepanelIndex = html.indexOf('<script src="sidepanel.js"></script>');
|
||||
|
||||
assert.notEqual(hotmailManagerIndex, -1);
|
||||
assert.notEqual(sidepanelIndex, -1);
|
||||
assert.ok(hotmailManagerIndex < sidepanelIndex);
|
||||
});
|
||||
|
||||
test('hotmail manager exposes a factory and renders empty state', () => {
|
||||
const source = fs.readFileSync('sidepanel/hotmail-manager.js', 'utf8');
|
||||
const windowObject = {};
|
||||
const localStorageMock = {
|
||||
getItem() {
|
||||
return null;
|
||||
},
|
||||
setItem() {},
|
||||
};
|
||||
|
||||
const api = new Function('window', 'localStorage', `${source}; return window.SidepanelHotmailManager;`)(
|
||||
windowObject,
|
||||
localStorageMock
|
||||
);
|
||||
|
||||
assert.equal(typeof api?.createHotmailManager, 'function');
|
||||
|
||||
const hotmailAccountsList = { innerHTML: '' };
|
||||
const toggleButton = {
|
||||
textContent: '',
|
||||
disabled: false,
|
||||
setAttribute() {},
|
||||
};
|
||||
const noopClassList = { toggle() {} };
|
||||
|
||||
const manager = api.createHotmailManager({
|
||||
state: {
|
||||
getLatestState: () => ({ currentHotmailAccountId: null }),
|
||||
syncLatestState() {},
|
||||
},
|
||||
dom: {
|
||||
btnClearUsedHotmailAccounts: { textContent: '', disabled: false },
|
||||
btnDeleteAllHotmailAccounts: { textContent: '', disabled: false },
|
||||
btnToggleHotmailList: toggleButton,
|
||||
hotmailAccountsList,
|
||||
hotmailListShell: { classList: noopClassList },
|
||||
selectMailProvider: { value: 'hotmail-api' },
|
||||
inputEmail: { value: '' },
|
||||
},
|
||||
helpers: {
|
||||
getHotmailAccounts: () => [],
|
||||
getCurrentHotmailEmail: () => '',
|
||||
escapeHtml: (value) => String(value || ''),
|
||||
showToast() {},
|
||||
openConfirmModal: async () => true,
|
||||
copyTextToClipboard: async () => {},
|
||||
},
|
||||
runtime: {
|
||||
sendMessage: async () => ({}),
|
||||
},
|
||||
constants: {
|
||||
copyIcon: '',
|
||||
displayTimeZone: 'Asia/Shanghai',
|
||||
expandedStorageKey: 'multipage-hotmail-list-expanded',
|
||||
},
|
||||
hotmailUtils: {},
|
||||
});
|
||||
|
||||
assert.equal(typeof manager.renderHotmailAccounts, 'function');
|
||||
assert.equal(typeof manager.bindHotmailEvents, 'function');
|
||||
assert.equal(typeof manager.initHotmailListExpandedState, 'function');
|
||||
|
||||
manager.renderHotmailAccounts();
|
||||
assert.match(hotmailAccountsList.innerHTML, /还没有 Hotmail 账号/);
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
test('sidepanel loads icloud manager before sidepanel bootstrap', () => {
|
||||
const html = fs.readFileSync('sidepanel/sidepanel.html', 'utf8');
|
||||
const icloudManagerIndex = html.indexOf('<script src="icloud-manager.js"></script>');
|
||||
const sidepanelIndex = html.indexOf('<script src="sidepanel.js"></script>');
|
||||
|
||||
assert.notEqual(icloudManagerIndex, -1);
|
||||
assert.notEqual(sidepanelIndex, -1);
|
||||
assert.ok(icloudManagerIndex < sidepanelIndex);
|
||||
});
|
||||
|
||||
test('icloud manager exposes a factory and renders empty state', () => {
|
||||
const source = fs.readFileSync('sidepanel/icloud-manager.js', 'utf8');
|
||||
const windowObject = {};
|
||||
|
||||
const api = new Function('window', `${source}; return window.SidepanelIcloudManager;`)(windowObject);
|
||||
|
||||
assert.equal(typeof api?.createIcloudManager, 'function');
|
||||
|
||||
const manager = api.createIcloudManager({
|
||||
dom: {
|
||||
btnIcloudBulkDelete: { disabled: false },
|
||||
btnIcloudBulkPreserve: { disabled: false },
|
||||
btnIcloudBulkUnpreserve: { disabled: false },
|
||||
btnIcloudBulkUnused: { disabled: false },
|
||||
btnIcloudBulkUsed: { disabled: false },
|
||||
btnIcloudDeleteUsed: { disabled: false },
|
||||
btnIcloudLoginDone: { disabled: false },
|
||||
btnIcloudRefresh: { disabled: false },
|
||||
checkboxIcloudSelectAll: { checked: false, indeterminate: false, disabled: false },
|
||||
icloudList: { innerHTML: '' },
|
||||
icloudLoginHelp: { style: { display: 'none' } },
|
||||
icloudLoginHelpText: { textContent: '' },
|
||||
icloudLoginHelpTitle: { textContent: '' },
|
||||
icloudSection: { style: { display: '' } },
|
||||
icloudSelectionSummary: { textContent: '' },
|
||||
icloudSummary: { textContent: '' },
|
||||
inputIcloudSearch: { value: '', disabled: false },
|
||||
selectIcloudFilter: { value: 'all', disabled: false },
|
||||
},
|
||||
helpers: {
|
||||
escapeHtml: (value) => String(value || ''),
|
||||
openConfirmModal: async () => true,
|
||||
showToast() {},
|
||||
},
|
||||
runtime: {
|
||||
sendMessage: async () => ({ aliases: [] }),
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(typeof manager.renderIcloudAliases, 'function');
|
||||
assert.equal(typeof manager.refreshIcloudAliases, 'function');
|
||||
assert.equal(typeof manager.queueIcloudAliasRefresh, 'function');
|
||||
assert.equal(typeof manager.reset, 'function');
|
||||
|
||||
manager.renderIcloudAliases([]);
|
||||
assert.equal(manager.hasDeletableUsedAliases(), false);
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
test('sidepanel loads luckmail manager before sidepanel bootstrap', () => {
|
||||
const html = fs.readFileSync('sidepanel/sidepanel.html', 'utf8');
|
||||
const luckmailManagerIndex = html.indexOf('<script src="luckmail-manager.js"></script>');
|
||||
const sidepanelIndex = html.indexOf('<script src="sidepanel.js"></script>');
|
||||
|
||||
assert.notEqual(luckmailManagerIndex, -1);
|
||||
assert.notEqual(sidepanelIndex, -1);
|
||||
assert.ok(luckmailManagerIndex < sidepanelIndex);
|
||||
});
|
||||
|
||||
test('luckmail manager exposes a factory and renders empty state', () => {
|
||||
const source = fs.readFileSync('sidepanel/luckmail-manager.js', 'utf8');
|
||||
const windowObject = {};
|
||||
|
||||
const api = new Function('window', `${source}; return window.SidepanelLuckmailManager;`)(windowObject);
|
||||
|
||||
assert.equal(typeof api?.createLuckmailManager, 'function');
|
||||
|
||||
const manager = api.createLuckmailManager({
|
||||
dom: {
|
||||
btnLuckmailBulkDisable: { disabled: false },
|
||||
btnLuckmailBulkEnable: { disabled: false },
|
||||
btnLuckmailBulkPreserve: { disabled: false },
|
||||
btnLuckmailBulkUnpreserve: { disabled: false },
|
||||
btnLuckmailBulkUnused: { disabled: false },
|
||||
btnLuckmailBulkUsed: { disabled: false },
|
||||
btnLuckmailDisableUsed: { disabled: false, textContent: '' },
|
||||
btnLuckmailRefresh: { disabled: false },
|
||||
checkboxLuckmailSelectAll: { checked: false, indeterminate: false, disabled: false },
|
||||
inputEmail: { value: '' },
|
||||
inputLuckmailSearch: { value: '', disabled: false },
|
||||
luckmailList: { innerHTML: '' },
|
||||
luckmailSection: { style: { display: '' } },
|
||||
luckmailSelectionSummary: { textContent: '' },
|
||||
luckmailSummary: { textContent: '' },
|
||||
selectLuckmailFilter: { value: 'all', disabled: false },
|
||||
},
|
||||
helpers: {
|
||||
copyTextToClipboard: async () => {},
|
||||
escapeHtml: (value) => String(value || ''),
|
||||
formatLuckmailDateTime: (value) => String(value || ''),
|
||||
getLuckmailPreserveTagName: () => '保留',
|
||||
normalizeLuckmailProjectName: (value) => String(value || '').trim().toLowerCase(),
|
||||
openConfirmModal: async () => true,
|
||||
showToast() {},
|
||||
},
|
||||
runtime: {
|
||||
sendMessage: async () => ({ purchases: [] }),
|
||||
},
|
||||
constants: {
|
||||
copyIcon: '',
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(typeof manager.renderLuckmailPurchases, 'function');
|
||||
assert.equal(typeof manager.refreshLuckmailPurchases, 'function');
|
||||
assert.equal(typeof manager.queueLuckmailPurchaseRefresh, 'function');
|
||||
assert.equal(typeof manager.reset, 'function');
|
||||
|
||||
manager.renderLuckmailPurchases([]);
|
||||
manager.reset();
|
||||
});
|
||||
Reference in New Issue
Block a user