Files
go_bt/tests/openai_plan_feature.test.js
T

174 lines
6.8 KiB
JavaScript

'use strict';
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const vm = require('vm');
(async () => {
const root = path.join(__dirname, '..');
const oauthPath = require.resolve('../src/services/openai_oauth_service');
const stepPath = require.resolve('../src/pipeline/steps/openai_query_plan');
const originalOauthCache = require.cache[oauthPath];
const originalStepCache = require.cache[stepPath];
const enrichedAuth = {
access_token: 'access-new',
refresh_token: 'refresh-old',
plan_type: 'plus',
subscription_expires_at: '2027-02-01T00:00:00.000Z',
usage: { rate_limit: { primary_window: { used_percent: 37.5 } } },
};
const queryCalls = [];
require.cache[oauthPath] = {
id: oauthPath,
filename: oauthPath,
loaded: true,
exports: {
queryAndEnrichOpenAIAuthJsonDirect: async (_authJson, proxyIp, _log, options) => {
queryCalls.push({ authJson: _authJson, proxyIp, options });
return {
success: true,
authJson: { ...enrichedAuth, tested_proxy: proxyIp, tested_mode: options.connectionMode },
sessionText: options.sessionText,
details: { errors: [] },
error: null,
};
},
},
};
delete require.cache[stepPath];
const queryPlanStep = require(stepPath);
const writes = [];
const ctx = {
account: { email: 'plan@example.com' },
page: {},
params: { connectionMode: 'direct' },
log: () => {},
results: {},
dbWrite: async (fn, args) => {
writes.push({ fn, args });
if (fn === 'getAccount') {
return {
email: 'plan@example.com',
proxy_ip: 'proxy.example.com:1080:user:pass',
openai_auth_json: JSON.stringify({ access_token: 'old' }),
};
}
return true;
},
};
await queryPlanStep(ctx);
const saved = writes.find(call => call.fn === 'updateAccountOpenAIPlan');
assert(saved, '独立套餐任务应保存套餐结果');
assert.deepStrictEqual(saved.args.slice(0, 5), [
'plan@example.com', '查询成功', 'plus', 37.5, '2027-02-01T00:00:00.000Z',
]);
assert.strictEqual(JSON.parse(saved.args[5]).access_token, 'access-new');
assert.strictEqual(JSON.parse(saved.args[5]).tested_proxy, 'proxy.example.com:1080:user:pass');
assert.strictEqual(JSON.parse(saved.args[5]).tested_mode, 'direct');
assert.strictEqual(ctx.results.openaiPlan.success, true);
const sessionOnlyWrites = [];
const sessionOnlyCtx = {
...ctx,
account: { email: 'session-only@gmail.com' },
results: {},
dbWrite: async (fn, args) => {
sessionOnlyWrites.push({ fn, args });
if (fn === 'getAccount') {
return {
email: 'session-only@gmail.com',
proxy_ip: '',
openai_auth_json: null,
chatgpt_session: JSON.stringify({ accessToken: 'session-access', sessionToken: 'session-token' }),
};
}
return true;
},
};
await queryPlanStep(sessionOnlyCtx);
assert.strictEqual(sessionOnlyCtx.results.openaiPlan.success, true);
assert.strictEqual(queryCalls.at(-1).options.expectedEmail, 'session-only@gmail.com');
assert.match(queryCalls.at(-1).options.sessionText, /session-token/);
assert(sessionOnlyWrites.some(call => call.fn === 'updateAccountOpenAIPlan'),
'没有授权 JSON、但有 Session 时不得跳过套餐查询');
const { openAIPlanFailureStatus } = queryPlanStep._private;
assert.strictEqual(
openAIPlanFailureStatus({ code: 'OPENAI_ACCOUNT_QUERY_UNAUTHORIZED', message: 'Request failed' }),
'Token失效(401)',
);
assert.strictEqual(
openAIPlanFailureStatus({ code: 'OPENAI_PLAN_PROXY_AUTH_FAILED', message: 'User was rejected' }),
'代理认证失败',
);
assert.strictEqual(
openAIPlanFailureStatus({ code: 'OPENAI_PLAN_PROXY_CONNECTION_FAILED', message: 'connect timeout' }),
'代理连接失败',
);
assert.strictEqual(
openAIPlanFailureStatus({ code: 'OPENAI_PLAN_DIRECT_CONNECTION_FAILED', message: 'connect timeout' }),
'直连失败',
);
assert.strictEqual(
openAIPlanFailureStatus({ code: 'UNEXPECTED', message: 'unexpected response body' }),
'套餐查询异常:unexpected response body',
);
if (originalOauthCache) require.cache[oauthPath] = originalOauthCache;
else delete require.cache[oauthPath];
if (originalStepCache) require.cache[stepPath] = originalStepCache;
else delete require.cache[stepPath];
const recipesPath = require.resolve('../src/pipeline/recipes');
delete require.cache[recipesPath];
const { RECIPES } = require(recipesPath);
assert.strictEqual(RECIPES.openai_get_auth.length, 1);
assert.strictEqual(RECIPES.openai_query_plan.length, 1);
assert.notStrictEqual(
RECIPES.openai_get_auth[0],
RECIPES.openai_query_plan[0],
'提取授权JSON和查询套餐必须是两个独立步骤',
);
const appSource = fs.readFileSync(path.join(root, 'public', 'app.js'), 'utf8');
const context = vm.createContext({
console, Set, Map, Date, JSON, Math, String, Number, Object, Array, RegExp, Promise,
setTimeout, clearTimeout,
});
vm.runInContext(`${appSource}\nthis.__geminiApp = geminiApp;`, context, { filename: 'public/app.js' });
const app = context.__geminiApp();
let launchedTask = '';
let launchedParams = null;
app.runTask = (taskType, params) => { launchedTask = taskType; launchedParams = params; };
app.runOpenAIQueryPlan();
assert.strictEqual(app.showOpenAIPlanRunModal, true);
assert.strictEqual(app.openAIPlanConnectionMode, 'browser_proxy');
app.openAIPlanConnectionMode = 'direct';
app.confirmOpenAIQueryPlan();
assert.strictEqual(launchedTask, 'openai_query_plan');
assert.strictEqual(launchedParams.connectionMode, 'direct');
assert.strictEqual(app.showOpenAIPlanRunModal, false);
assert.strictEqual(app.formatOpenAIPlanCell({ openai_plan_type: 'plus' }), 'Plus');
assert.strictEqual(app.formatOpenAIUsagePercent(37.5), '37.5%');
assert.strictEqual(app.statusClass('Token失效(401)'), 'status-登录失败');
assert.strictEqual(app.statusClass('代理认证失败'), 'status-登录失败');
assert.strictEqual(app.statusClass('套餐查询异常:unexpected response body'), 'status-登录失败');
assert(app.accountFilterFields.some(field => field.value === 'openai_plan_type'));
const oauthSource = fs.readFileSync(path.join(root, 'src', 'services', 'openai_oauth_service.js'), 'utf8');
const extractionTail = oauthSource.slice(oauthSource.indexOf('async function extractOpenAIAuthJson'));
assert.match(extractionTail, /return buildAuthJson\(callback\.code, tokens\);/);
assert.doesNotMatch(
extractionTail.slice(0, extractionTail.indexOf('module.exports')),
/queryAndEnrichOpenAIAuthJson(?:Direct)?|enrichOpenAIAuthJson/,
'提取授权 JSON 不得再自动查询套餐',
);
console.log('openai_plan_feature.test.js: PASS');
})().catch(error => {
console.error(error);
process.exitCode = 1;
});