Files
FlowPilot/tests/sidepanel-flow-source-registry.test.js
T
2026-05-18 00:34:51 +08:00

116 lines
3.5 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const sidepanelSource = fs.readFileSync('sidepanel/sidepanel.js', 'utf8');
const sidepanelHtml = fs.readFileSync('sidepanel/sidepanel.html', 'utf8');
function extractFunction(source, name) {
const asyncStart = source.indexOf(`async function ${name}`);
const normalStart = source.indexOf(`function ${name}`);
const start = asyncStart !== -1
? asyncStart
: normalStart;
if (start === -1) {
throw new Error(`Function ${name} not found`);
}
const signatureEnd = source.indexOf(')', start);
const bodyStart = source.indexOf('{', signatureEnd);
let depth = 0;
let end = bodyStart;
for (; end < source.length; end += 1) {
const char = source[end];
if (char === '{') {
depth += 1;
} else if (char === '}') {
depth -= 1;
if (depth === 0) {
end += 1;
break;
}
}
}
return source.slice(start, end);
}
test('sidepanel html exposes flow selector and kiro source fields', () => {
[
'id="select-flow"',
'id="label-source-selector"',
'id="row-kiro-rs-url"',
'id="row-kiro-rs-key"',
'id="row-kiro-region"',
'id="row-kiro-device-code"',
'id="row-kiro-login-url"',
'id="row-kiro-upload-status"',
].forEach((snippet) => {
assert.match(sidepanelHtml, new RegExp(snippet.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
});
});
test('sidepanel step definitions rerender when active flow changes even if plus/signup settings stay the same', () => {
const bundle = [
extractFunction(sidepanelSource, 'normalizeSignupMethod'),
extractFunction(sidepanelSource, 'normalizePlusPaymentMethod'),
extractFunction(sidepanelSource, 'getStepDefinitionsForMode'),
extractFunction(sidepanelSource, 'rebuildStepDefinitionState'),
extractFunction(sidepanelSource, 'syncStepDefinitionsForMode'),
].join('\n');
const api = new Function(`
const calls = [];
const window = {
MultiPageStepDefinitions: {
getSteps(options) {
calls.push({ type: 'getSteps', options });
return [{ id: options.activeFlowId === 'kiro' ? 88 : 6, order: 1, key: options.activeFlowId }];
},
},
};
let latestState = { activeFlowId: 'openai' };
let currentPlusModeEnabled = false;
let currentPlusPaymentMethod = 'paypal';
let currentSignupMethod = 'email';
let currentPhoneSignupReloginAfterBindEmailEnabled = false;
let currentStepDefinitionFlowId = 'openai';
const DEFAULT_ACTIVE_FLOW_ID = 'openai';
const DEFAULT_SIGNUP_METHOD = 'email';
const DEFAULT_PLUS_PAYMENT_METHOD = 'paypal';
let stepDefinitions = [{ id: 6, key: 'openai' }];
let STEP_IDS = [6];
let STEP_DEFAULT_STATUSES = { 6: 'pending' };
let SKIPPABLE_STEPS = new Set([6]);
function renderStepsList() {
calls.push({ type: 'render', stepIds: [...STEP_IDS] });
}
${bundle}
return {
calls,
syncStepDefinitionsForMode,
getStepIds: () => [...STEP_IDS],
getCurrentFlowId: () => currentStepDefinitionFlowId,
};
`)();
api.syncStepDefinitionsForMode(false, {
activeFlowId: 'kiro',
plusPaymentMethod: 'paypal',
signupMethod: 'email',
phoneSignupReloginAfterBindEmailEnabled: false,
});
assert.equal(api.getCurrentFlowId(), 'kiro');
assert.deepEqual(api.getStepIds(), [88]);
assert.deepEqual(api.calls[0], {
type: 'getSteps',
options: {
activeFlowId: 'kiro',
plusModeEnabled: false,
plusPaymentMethod: 'paypal',
signupMethod: 'email',
phoneSignupReloginAfterBindEmailEnabled: false,
},
});
assert.deepEqual(api.calls[1], { type: 'render', stepIds: [88] });
});