Refactor multi-flow mail capability boundaries

This commit is contained in:
QLHazyCoder
2026-05-13 06:35:43 +08:00
parent a85ed0ce89
commit d93cdfff9e
33 changed files with 2035 additions and 198 deletions
@@ -196,6 +196,107 @@ test('startAutoRunFromCurrentSettings freezes run count before async settings sy
assert.equal(events[3].message.payload.totalRuns, 20);
});
test('startAutoRunFromCurrentSettings blocks when shared flow capability validation fails', async () => {
const bundle = [
extractFunction('normalizePendingAutoRunStartRunCount'),
extractFunction('registerPendingAutoRunStartRunCount'),
extractFunction('clearPendingAutoRunStartRunCount'),
extractFunction('startAutoRunFromCurrentSettings'),
].join('\n');
const api = new Function(`
const events = [];
const latestState = {
activeFlowId: 'site-a',
panelMode: 'cpa',
signupMethod: 'phone',
contributionMode: false,
phoneVerificationEnabled: true,
};
const inputAutoSkipFailures = { checked: false };
const inputContributionNickname = { value: 'tester' };
const inputContributionQq = { value: '123456' };
const inputAutoSkipFailuresThreadIntervalMinutes = { value: '5' };
const inputAutoDelayEnabled = { checked: false };
const inputAutoDelayMinutes = { value: '30' };
const btnAutoRun = { disabled: false, innerHTML: '' };
const inputRunCount = { disabled: false, value: '1' };
const inputPhoneVerificationEnabled = { checked: true };
const inputPlusModeEnabled = { checked: false };
let runCountValue = 1;
let pendingAutoRunStartTotalRuns = 0;
let pendingAutoRunStartExpiresAt = 0;
const chrome = {
runtime: {
async sendMessage(message) {
events.push({ type: 'send', message });
return { ok: true };
},
},
};
const console = {
warn(...args) {
events.push({ type: 'warn', args });
},
};
const window = {
MultiPageFlowCapabilities: {
createFlowCapabilityRegistry() {
return {
validateAutoRunStart() {
return {
ok: false,
errors: [{ message: '当前 flow 不支持手机号注册。' }],
};
},
};
},
},
};
async function sendSidepanelMessage(message) {
return chrome.runtime.sendMessage(message);
}
async function persistCurrentSettingsForAction() {
events.push({ type: 'sync-settings' });
}
function getRunCountValue() { return Math.max(1, Number(runCountValue) || 1); }
function normalizeAutoRunThreadIntervalMinutes(value) { return Number(value) || 0; }
function shouldOfferAutoModeChoice() { return false; }
async function openAutoStartChoiceDialog() { throw new Error('should not be called'); }
function getFirstUnfinishedStep() { return 1; }
function getRunningSteps() { return []; }
function shouldWarnAutoRunFallbackRisk() { return false; }
function isAutoRunFallbackRiskPromptDismissed() { return false; }
async function openAutoRunFallbackRiskConfirmModal() { throw new Error('should not be called'); }
function setAutoRunFallbackRiskPromptDismissed() {}
function normalizeAutoDelayMinutes(value) { return Number(value) || 30; }
async function refreshContributionContentHint() {
events.push({ type: 'refresh' });
return null;
}
async function ensureGpcApiKeyReadyForStart() {
return true;
}
${bundle}
return {
startAutoRunFromCurrentSettings,
getEvents() {
return events;
},
};
`)();
await assert.rejects(
() => api.startAutoRunFromCurrentSettings(),
/当前 flow 不支持手机号注册。/
);
assert.deepEqual(
api.getEvents().map((entry) => entry.type),
['refresh', 'sync-settings']
);
});
test('persistCurrentSettingsForAction forces a silent save even when settings are not marked dirty', async () => {
const bundle = [
extractFunction('waitForSettingsSaveIdle'),