Files
go_bt/tests/problem_reason_classification.test.js
T

161 lines
7.5 KiB
JavaScript

const assert = require('assert');
const {
classifyFailure,
getFailureLabel,
isOAuthWait7DaysOutcome,
resolveFailureOutcome,
} = require('../src/utils/error_classifier');
const { detectOAuthReauthProblem } = require('../src/services/ag_verify_service');
function codeFor(message, url = '') {
return classifyFailure({ message, url }).code;
}
assert.strictEqual(codeFor('密码错误'), 'PASSWORD_WRONG');
assert.strictEqual(codeFor('Your password was changed 10 days ago'), 'PASSWORD_CHANGED_RECENTLY');
assert.strictEqual(codeFor('需要 2FA 验证但未提供密钥'), 'TOTP_KEY_INVALID');
assert.strictEqual(codeFor('Wrong code. Try again.'), 'TOTP_KEY_INCORRECT');
assert.strictEqual(codeFor('2fa密钥不正确'), 'TOTP_KEY_INCORRECT');
assert.strictEqual(codeFor('触发人机认证'), 'CAPTCHA');
assert.strictEqual(codeFor('Please try again later'), 'UNKNOWN', '普通 try again 不得误归2FA错误');
assert.strictEqual(codeFor('密码近期已更改'), 'PASSWORD_CHANGED_RECENTLY');
assert.strictEqual(codeFor('OAuth 暂无2FA认证选项'), 'OAUTH_WAIT_7_DAYS');
assert.strictEqual(codeFor('验证方式列表中没有 Google Authenticator 选项'), 'TOTP_OPTION_UNAVAILABLE');
assert.strictEqual(codeFor('需要辅助邮箱验证但未提供'), 'RECOVERY_EMAIL_REQUIRED');
assert.strictEqual(codeFor('需要备用码验证,且页面无法切换到 Google Authenticator'), 'BACKUP_CODE_REQUIRED');
assert.strictEqual(codeFor('Google拒绝本次登录', 'https://accounts.google.com/signin/rejected'), 'SIGNIN_REJECTED');
assert.strictEqual(
classifyFailure({ url: 'https://accounts.google.com/signin/rejected', message: 'Google拒绝本次登录' }).shouldRotateProxy,
true,
'signin/rejected 应触发自动更换代理后重试',
);
// 账号列表统一使用处理结论,避免同一类问题出现多种可见文案。
assert.strictEqual(classifyFailure({ message: '密码错误' }).label, '密码错误');
assert.strictEqual(classifyFailure({ message: 'Your password was changed 10 days ago' }).label, '密码已被修改');
assert.strictEqual(classifyFailure({ message: 'Your password was changed 10 days ago' }).shouldKeepOpen, false);
assert.strictEqual(classifyFailure({ message: 'Your password was changed 10 days ago' }).shouldRotateProxy, false);
assert.strictEqual(classifyFailure({ message: 'Wrong code. Try again.' }).label, '2fa密钥不正确');
assert.strictEqual(classifyFailure({ message: 'Wrong code. Try again.' }).shouldKeepOpen, false);
assert.strictEqual(classifyFailure({ message: 'Wrong code. Try again.' }).shouldRotateProxy, false);
assert.strictEqual(classifyFailure({ message: "Confirm you're not a robot" }).label, '人机验证');
assert.strictEqual(getFailureLabel('CAPTCHA'), '人机验证');
assert.strictEqual(getFailureLabel('PHONE_TABLET_VERIFY'), '要等7天');
assert.strictEqual(getFailureLabel('CHATGPT_ACCOUNT_DEACTIVATED'), '账号已删除/停用');
assert.strictEqual(
classifyFailure({ message: 'You do not have an account because it has been deleted or deactivated.' }).label,
'账号已删除/停用',
);
assert.strictEqual(
classifyFailure({ message: '需手机/平板验证' }).code,
'PHONE_TABLET_VERIFY',
);
assert.strictEqual(
classifyFailure({ message: '需手机/平板验证' }).label,
'要等7天',
);
assert.strictEqual(isOAuthWait7DaysOutcome('PHONE_TABLET_VERIFY'), true);
assert.strictEqual(classifyFailure({ message: '检测到风险登录,无法登录' }).label, '无法登录');
assert.strictEqual(classifyFailure({ message: 'net::ERR_CONNECTION_TIMED_OUT' }).label, '切换ip重试');
assert.strictEqual(classifyFailure({ message: '测速失败' }).label, '切换ip重试');
assert.strictEqual(
classifyFailure({ message: 'OAuth身份验证页面无法切换到其它方式:/v3/signin/challenge/dp' }).label,
'要等7天',
'OAuth 验证方式卡在 dp challenge 时应直接归入等待7天',
);
assert.strictEqual(
codeFor('OAuth身份验证页面无法切换到其它方式:/v3/signin/challenge/dp'),
'OAUTH_CHALLENGE_STUCK',
);
assert.strictEqual(getFailureLabel('OAUTH_CHALLENGE_STUCK'), '要等7天');
assert.strictEqual(getFailureLabel('GCP_NO_PERMISSION'), '无权限');
assert.strictEqual(getFailureLabel('GOOGLE_UNDER_18'), '未满18岁');
assert.strictEqual(classifyFailure({ message: 'OAuth授权超时' }).label, '要等7天');
assert.strictEqual(isOAuthWait7DaysOutcome('OAUTH_NO_AUTHENTICATOR'), true);
assert.strictEqual(isOAuthWait7DaysOutcome('OAUTH_CHALLENGE_STUCK'), true);
assert.strictEqual(isOAuthWait7DaysOutcome('OAUTH_TIMEOUT'), true);
assert.strictEqual(isOAuthWait7DaysOutcome('NETWORK_PROXY'), false);
assert.strictEqual(
isOAuthWait7DaysOutcome('TOKEN_EXCHANGE_FAILED', { message: 'network timeout' }),
false,
'Token 网络失败不得误进等待7天分组',
);
assert.strictEqual(classifyFailure({ message: 'OAuth token exchange network error' }).label, '切换ip重试');
assert.strictEqual(
resolveFailureOutcome({
code: 'OAUTH_CHALLENGE_STUCK',
message: 'OAuth身份验证页面无法切换到其它方式:/v3/signin/challenge/dp',
}).displayMessage,
'要等7天',
);
function fakeOAuthPage({ url = 'https://accounts.google.com/signin/challenge/pwd', body = '', frameBox = null, frameBoxes = null } = {}) {
const boxes = frameBoxes || (frameBox ? [frameBox] : []);
return {
url: () => url,
locator: selector => {
if (selector === 'body') {
return { innerText: async () => body };
}
return {
count: async () => boxes.length,
nth: index => ({
isVisible: async () => !!boxes[index],
boundingBox: async () => boxes[index] || null,
}),
};
},
};
}
(async () => {
let result = await detectOAuthReauthProblem(fakeOAuthPage({ body: 'Wrong password. Try again.' }), {
passwordSubmitted: false,
});
assert.strictEqual(result, null, '提交前不得只凭页面文字判密码错误');
result = await detectOAuthReauthProblem(fakeOAuthPage({ body: 'Wrong password. Try again.' }), {
passwordSubmitted: true,
});
assert.deepStrictEqual(result, { reasonCode: 'PASSWORD_WRONG', msg: '密码错误' });
result = await detectOAuthReauthProblem(fakeOAuthPage({ body: 'Forgot password? Please try again.' }), {
passwordSubmitted: true,
});
assert.strictEqual(result, null, '普通忘记密码/重试文字不得误判');
result = await detectOAuthReauthProblem(fakeOAuthPage({
url: 'https://accounts.google.com/o/oauth2/auth',
body: 'This site is protected by reCAPTCHA and the Google Privacy Policy.',
frameBox: { width: 70, height: 60 },
}));
assert.strictEqual(result, null, '正常 reCAPTCHA 条款和小徽标不得误报人机验证');
result = await detectOAuthReauthProblem(fakeOAuthPage({
url: 'https://accounts.google.com/o/oauth2/auth',
frameBoxes: [{ width: 70, height: 60 }, { width: 320, height: 120 }],
}));
assert.deepStrictEqual(
result,
{ reasonCode: 'CAPTCHA', msg: '触发人机验证' },
'小徽标之后的真挑战框不得被漏掉',
);
result = await detectOAuthReauthProblem(fakeOAuthPage({
url: 'https://accounts.google.com/o/oauth2/auth',
body: 'Verify you are not a robot',
}));
assert.deepStrictEqual(result, { reasonCode: 'CAPTCHA', msg: '触发人机验证' });
result = await detectOAuthReauthProblem(fakeOAuthPage({
url: 'https://accounts.google.com/signin/challenge/recaptcha',
}));
assert.deepStrictEqual(result, { reasonCode: 'CAPTCHA', msg: '触发人机验证' });
console.log('problem_reason_classification.test.js: PASS');
})().catch(error => {
console.error(error);
process.exitCode = 1;
});