138 lines
5.1 KiB
JavaScript
138 lines
5.1 KiB
JavaScript
const assert = require('assert');
|
|
|
|
const { shouldRotateProxyForFailure } = require('../src/services/proxy_recovery_service');
|
|
const { classifyFailure } = require('../src/utils/error_classifier');
|
|
const {
|
|
MAX_CHATGPT_BROWSER_ATTEMPTS,
|
|
MAX_CHATGPT_LOGIN_WITH_STUCK_BROWSER_ATTEMPTS,
|
|
MAX_OPENAI_PHONE_BROWSER_ATTEMPTS,
|
|
isChatGPTRouteError,
|
|
shouldRestartChatGPTBrowser,
|
|
buildChatGPTBrowserRetryMessage,
|
|
} = require('../src/services/chatgpt_restart_policy');
|
|
|
|
assert.strictEqual(
|
|
shouldRotateProxyForFailure({ code: 'SIGNIN_REJECTED', shouldRotateProxy: true }, 'SIGNIN_REJECTED'),
|
|
true,
|
|
);
|
|
assert.strictEqual(
|
|
shouldRotateProxyForFailure(null, 'SIGNIN_REJECTED'),
|
|
true,
|
|
'即使页面元数据丢失,明确的signin/rejected结果也应换代理',
|
|
);
|
|
assert.strictEqual(shouldRotateProxyForFailure(null, 'NETWORK_PROXY'), true);
|
|
for (const navigationError of [
|
|
'page.goto: net::ERR_FAILED at https://mail.google.com/mail/u/0/#inbox',
|
|
'page.goto: net::ERR_ABORTED at https://mail.google.com/mail/u/0/#inbox',
|
|
'page.goto: net::ERR_CONNECTION_CLOSED at https://mail.google.com/mail/u/0/#inbox',
|
|
'page.reload: net::ERR_ABORTED',
|
|
]) {
|
|
const navigationFailure = classifyFailure({ message: navigationError, taskType: 'refund_query' });
|
|
assert.strictEqual(navigationFailure.code, 'NETWORK_PROXY');
|
|
assert.strictEqual(
|
|
shouldRotateProxyForFailure(navigationFailure, navigationFailure.code),
|
|
true,
|
|
`${navigationError} 应在退款查询最终失败后自动换代理`,
|
|
);
|
|
}
|
|
assert.strictEqual(shouldRotateProxyForFailure(null, 'PASSWORD_WRONG'), false);
|
|
assert.strictEqual(shouldRotateProxyForFailure(null, 'PASSWORD_CHANGED_RECENTLY'), false);
|
|
assert.strictEqual(shouldRotateProxyForFailure(null, 'TOTP_CODE_WRONG'), false);
|
|
assert.strictEqual(shouldRotateProxyForFailure(null, 'TOTP_KEY_INCORRECT'), false);
|
|
assert.strictEqual(shouldRotateProxyForFailure(null, 'PHONE_VERIFY'), false);
|
|
assert.strictEqual(
|
|
shouldRotateProxyForFailure({ code: 'CHATGPT_ROUTE_ERROR', restartBrowser: true }, 'CHATGPT_ROUTE_ERROR'),
|
|
false,
|
|
'ChatGPT Route Error 不能触发代理轮换',
|
|
);
|
|
assert.strictEqual(
|
|
shouldRotateProxyForFailure(null, 'CHATGPT_LOGIN_WITH_STUCK'),
|
|
true,
|
|
'Google 登录中转页在同代理重开一次后应允许换代理',
|
|
);
|
|
assert.strictEqual(
|
|
shouldRotateProxyForFailure(null, 'CHATGPT_AGE_SUBMIT_STUCK'),
|
|
true,
|
|
'年龄表单多次提交仍无进展时应允许换代理重试',
|
|
);
|
|
for (const code of [
|
|
'CHATGPT_SESSION_CF_HTML',
|
|
'CHATGPT_SESSION_HTTP_403',
|
|
'CHATGPT_SESSION_HTTP_429',
|
|
'CHATGPT_SESSION_HTTP_5XX',
|
|
]) {
|
|
assert.strictEqual(
|
|
shouldRotateProxyForFailure(null, code),
|
|
true,
|
|
`${code} 应允许换代理重试`,
|
|
);
|
|
}
|
|
assert.deepStrictEqual(
|
|
classifyFailure({ message: 'ChatGPT Route Error 400', taskType: 'chatgpt_register' }).code,
|
|
'CHATGPT_ROUTE_ERROR',
|
|
);
|
|
assert.strictEqual(isChatGPTRouteError('login', { code: 'CHATGPT_ROUTE_ERROR', restartBrowser: true }), false);
|
|
assert.strictEqual(isChatGPTRouteError('chatgpt_register', { code: 'CAPTCHA' }), false);
|
|
|
|
let browserAttempt = 1;
|
|
let totalRuns = 0;
|
|
while (true) {
|
|
totalRuns++;
|
|
const failure = { code: 'CHATGPT_ROUTE_ERROR', restartBrowser: true };
|
|
if (!shouldRestartChatGPTBrowser('chatgpt_register', failure, browserAttempt)) break;
|
|
browserAttempt++;
|
|
}
|
|
assert.strictEqual(MAX_CHATGPT_BROWSER_ATTEMPTS, 3);
|
|
assert.strictEqual(totalRuns, 3, 'Route Error 总登录次数必须为初次加两次重启');
|
|
|
|
browserAttempt = 1;
|
|
totalRuns = 0;
|
|
const phoneFailure = { code: 'OPENAI_PHONE_REQUIRED' };
|
|
while (true) {
|
|
totalRuns++;
|
|
if (!shouldRestartChatGPTBrowser('openai_get_auth', phoneFailure, browserAttempt)) break;
|
|
browserAttempt++;
|
|
}
|
|
assert.strictEqual(MAX_OPENAI_PHONE_BROWSER_ATTEMPTS, 3);
|
|
assert.strictEqual(totalRuns, 3, '手机号要求总授权次数必须为初次加两次重启');
|
|
assert.match(
|
|
buildChatGPTBrowserRetryMessage('openai_get_auth', phoneFailure, 2),
|
|
/补充手机号.*第2\/3次/,
|
|
);
|
|
|
|
browserAttempt = 1;
|
|
totalRuns = 0;
|
|
const stuckFailure = { code: 'CHATGPT_LOGIN_WITH_STUCK' };
|
|
while (true) {
|
|
totalRuns++;
|
|
if (!shouldRestartChatGPTBrowser('chatgpt_register', stuckFailure, browserAttempt)) break;
|
|
browserAttempt++;
|
|
}
|
|
assert.strictEqual(MAX_CHATGPT_LOGIN_WITH_STUCK_BROWSER_ATTEMPTS, 2);
|
|
assert.strictEqual(totalRuns, 2, '登录中转页卡住时,同一代理只能重开浏览器一次');
|
|
assert.strictEqual(
|
|
shouldRestartChatGPTBrowser('security_chatgpt', stuckFailure, 1),
|
|
false,
|
|
'非独立ChatGPT任务不得触发ChatGPT专用浏览器重开',
|
|
);
|
|
|
|
const stuckRetryMessage = buildChatGPTBrowserRetryMessage(
|
|
'chatgpt_register',
|
|
stuckFailure,
|
|
2,
|
|
);
|
|
assert.match(stuckRetryMessage, /Google 登录中转页卡住/);
|
|
assert.match(stuckRetryMessage, /当前代理/);
|
|
assert.match(stuckRetryMessage, /第2\/2次/);
|
|
assert.doesNotMatch(stuckRetryMessage, /Route Error/);
|
|
|
|
const routeRetryMessage = buildChatGPTBrowserRetryMessage(
|
|
'chatgpt_register',
|
|
{ code: 'CHATGPT_ROUTE_ERROR', restartBrowser: true },
|
|
2,
|
|
);
|
|
assert.match(routeRetryMessage, /Route Error/);
|
|
assert.match(routeRetryMessage, /第2\/3次/);
|
|
|
|
console.log('proxy_retry_policy.test.js: PASS');
|