| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- const test = require('node:test');
- const assert = require('node:assert/strict');
- const fs = require('node:fs');
- const vm = require('node:vm');
- function createJsonResponse(payload, status = 200) {
- return {
- ok: status >= 200 && status < 300,
- status,
- text: async () => JSON.stringify(payload),
- };
- }
- function createSub2ApiPanelContext(fetchCalls = []) {
- const storage = new Map();
- const documentElement = {
- attrs: new Map(),
- getAttribute(name) {
- return this.attrs.get(name) || null;
- },
- setAttribute(name, value) {
- this.attrs.set(name, String(value));
- },
- };
- const context = {
- URL,
- console: { log() {} },
- setTimeout() {},
- document: { documentElement },
- location: {
- href: 'https://sub.example/admin/accounts',
- origin: 'https://sub.example',
- pathname: '/admin/accounts',
- replace() {},
- },
- chrome: {
- runtime: {
- onMessage: { addListener() {} },
- sendMessage: async () => ({
- email: 'flow@example.com',
- sub2apiDefaultProxyName: 'shadowrocket',
- }),
- },
- },
- localStorage: {
- setItem(key, value) { storage.set(`local:${key}`, String(value)); },
- removeItem(key) { storage.delete(`local:${key}`); },
- },
- sessionStorage: {
- removeItem(key) { storage.delete(`session:${key}`); },
- },
- log() {},
- reportComplete(step, payload) {
- context.completed.push({ step, payload });
- },
- reportReady() {},
- reportError() {},
- resetStopState() {},
- throwIfStopped() {},
- isStopError() { return false; },
- completed: [],
- fetch: async (url, options = {}) => {
- const parsed = new URL(url);
- const body = options.body ? JSON.parse(options.body) : null;
- fetchCalls.push({ path: parsed.pathname, search: parsed.search, method: options.method || 'GET', body });
- if (parsed.pathname === '/api/v1/auth/login') {
- return createJsonResponse({
- code: 0,
- data: {
- access_token: 'admin-token',
- refresh_token: 'refresh-admin',
- expires_in: 3600,
- user: { id: 1 },
- },
- });
- }
- if (parsed.pathname === '/api/v1/admin/groups/all') {
- return createJsonResponse({
- code: 0,
- data: [{ id: 5, name: 'codex', platform: 'openai' }],
- });
- }
- if (parsed.pathname === '/api/v1/admin/proxies/all') {
- return createJsonResponse({
- code: 0,
- data: [{
- id: 7,
- name: 'shadowrocket',
- protocol: 'socks5',
- host: '127.0.0.1',
- port: 1080,
- status: 'active',
- }],
- });
- }
- if (parsed.pathname === '/api/v1/admin/openai/generate-auth-url') {
- return createJsonResponse({
- code: 0,
- data: {
- auth_url: 'https://auth.openai.com/oauth?state=oauth-state',
- session_id: 'session-1',
- state: 'oauth-state',
- },
- });
- }
- if (parsed.pathname === '/api/v1/admin/openai/exchange-code') {
- return createJsonResponse({
- code: 0,
- data: {
- access_token: 'openai-access',
- refresh_token: 'openai-refresh',
- expires_at: 1770000000,
- email: 'flow@example.com',
- },
- });
- }
- if (parsed.pathname === '/api/v1/admin/accounts') {
- return createJsonResponse({
- code: 0,
- data: { id: 11 },
- });
- }
- return createJsonResponse({ code: 1, message: `unexpected path ${parsed.pathname}` }, 404);
- },
- };
- vm.createContext(context);
- vm.runInContext(fs.readFileSync('content/sub2api-panel.js', 'utf8'), context);
- return context;
- }
- test('SUB2API step 1 selects the configured default proxy before generating OAuth URL', async () => {
- const fetchCalls = [];
- const context = createSub2ApiPanelContext(fetchCalls);
- const result = await vm.runInContext(`
- step1_generateOpenAiAuthUrl({
- sub2apiEmail: 'admin@example.com',
- sub2apiPassword: 'secret',
- sub2apiGroupName: 'codex',
- sub2apiDefaultProxyName: 'shadowrocket'
- }, { report: false })
- `, context);
- const generateCall = fetchCalls.find((call) => call.path === '/api/v1/admin/openai/generate-auth-url');
- assert.equal(result.sub2apiProxyId, 7);
- assert.equal(generateCall.body.proxy_id, 7);
- });
- test('SUB2API step 10 uses the same proxy for code exchange and account creation', async () => {
- const fetchCalls = [];
- const context = createSub2ApiPanelContext(fetchCalls);
- await vm.runInContext(`
- step9_submitOpenAiCallback({
- localhostUrl: 'http://localhost:1455/auth/callback?code=callback-code&state=oauth-state',
- sub2apiUrl: 'https://sub.example/admin/accounts',
- sub2apiEmail: 'admin@example.com',
- sub2apiPassword: 'secret',
- sub2apiGroupName: 'codex',
- sub2apiSessionId: 'session-1',
- sub2apiOAuthState: 'oauth-state',
- sub2apiGroupId: 5,
- sub2apiProxyId: 7
- })
- `, context);
- const exchangeCall = fetchCalls.find((call) => call.path === '/api/v1/admin/openai/exchange-code');
- const createCall = fetchCalls.find((call) => call.path === '/api/v1/admin/accounts');
- assert.equal(exchangeCall.body.proxy_id, 7);
- assert.equal(createCall.body.proxy_id, 7);
- assert.equal(createCall.body.group_ids[0], 5);
- assert.equal(context.completed[0].step, 10);
- });
|