174 lines
6.8 KiB
JavaScript
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;
|
|
});
|