Files
FlowPilot/tests/background-platform-verify-codex2api.test.js
T
initiatione f8b919e883 Add codex2api as a protocol-first OAuth source
This keeps the existing CPA, SUB2API, and contribution flows intact
while introducing codex2api as a separate source that plugs into
Step 7 and Step 10 through backend APIs instead of page DOM.

The sidepanel now exposes codex2api settings, preserves the built-in
local default through placeholder-only UI, and accepts user-provided
public admin URLs. Step 7 now treats missing or invalid management
secrets as terminal config errors so the flow stops instead of retrying
needlessly.

Constraint: New source must be additive and must not break existing CPA/SUB2API/contribution paths
Rejected: Drive codex2api through admin page button clicks | too brittle against frontend DOM changes
Rejected: Reuse contribution mode as a source surface | violates existing panelMode/runtime-mode boundary
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep codex2api on the protocol path unless its API becomes insufficient; do not add a panel content script without proving the protocol path cannot work
Tested: npm test; targeted codex2api/auth retry loops repeated 40 times; full suite repeated 5 times
Not-tested: Real browser run against a live codex2api instance with a real Admin Secret and OpenAI authorization
2026-04-22 13:57:21 +08:00

82 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const assert = require('node:assert/strict');
const fs = require('node:fs');
const test = require('node:test');
test('platform verify module supports codex2api protocol callback exchange', async () => {
const source = fs.readFileSync('background/steps/platform-verify.js', 'utf8');
const originalFetch = globalThis.fetch;
globalThis.fetch = async (url, options = {}) => {
assert.equal(url, 'http://localhost:8080/api/admin/oauth/exchange-code');
assert.equal(options.method, 'POST');
assert.equal(options.headers['X-Admin-Key'], 'admin-secret');
assert.deepStrictEqual(JSON.parse(options.body), {
session_id: 'session-123',
code: 'callback-code',
state: 'oauth-state',
});
return {
ok: true,
json: async () => ({
message: 'OAuth 账号 flow@example.com 添加成功',
id: 42,
email: 'flow@example.com',
plan_type: 'pro',
}),
};
};
try {
const api = new Function('self', `${source}; return self.MultiPageBackgroundStep10;`)({});
const completed = [];
const logs = [];
const executor = api.createStep10Executor({
addLog: async (message, level = 'info') => {
logs.push({ message, level });
},
chrome: {},
closeConflictingTabsForSource: async () => {},
completeStepFromBackground: async (step, payload) => {
completed.push({ step, payload });
},
ensureContentScriptReadyOnTab: async () => {},
getPanelMode: () => 'codex2api',
getTabId: async () => 0,
isLocalhostOAuthCallbackUrl: (value) => String(value || '').includes('/auth/callback?code='),
isTabAlive: async () => false,
normalizeCodex2ApiUrl: () => 'http://localhost:8080/admin/accounts',
normalizeSub2ApiUrl: (value) => value,
rememberSourceLastUrl: async () => {},
reuseOrCreateTab: async () => 0,
sendToContentScript: async () => ({}),
sendToContentScriptResilient: async () => ({}),
shouldBypassStep9ForLocalCpa: () => false,
SUB2API_STEP9_RESPONSE_TIMEOUT_MS: 120000,
});
await executor.executeStep10({
panelMode: 'codex2api',
localhostUrl: 'http://localhost:1455/auth/callback?code=callback-code&state=oauth-state',
codex2apiUrl: 'http://localhost:8080/admin/accounts',
codex2apiAdminKey: 'admin-secret',
codex2apiSessionId: 'session-123',
codex2apiOAuthState: 'oauth-state',
});
assert.deepStrictEqual(logs, [
{ message: '步骤 10:正在向 Codex2API 提交回调并创建账号...', level: 'info' },
{ message: '步骤 10OAuth 账号 flow@example.com 添加成功', level: 'ok' },
]);
assert.deepStrictEqual(completed, [
{
step: 10,
payload: {
localhostUrl: 'http://localhost:1455/auth/callback?code=callback-code&state=oauth-state',
verifiedStatus: 'OAuth 账号 flow@example.com 添加成功',
},
},
]);
} finally {
globalThis.fetch = originalFetch;
}
});