初始化提交:go比特版本精简

This commit is contained in:
2026-09-20 17:02:11 +08:00
commit f41a979462
213 changed files with 58288 additions and 0 deletions
+354
View File
@@ -0,0 +1,354 @@
'use strict';
const assert = require('assert');
const { _private: loginPrivate } = require('../src/services/login_service');
const { _private: chatgptPrivate } = require('../src/services/chatgpt_service');
const {
handleIdentityVerification,
handleChallengeSelection,
inputCurrent2fa,
_private: commonAuthPrivate,
} = require('../src/services/common_auth');
function emptyLocator() {
return {
count: async () => 0,
nth: () => { throw new Error('empty locator'); },
};
}
(async () => {
const securityCodeText = [
'Get a code to sign in',
'To get your security code, go to g.co/sc in a new browser window',
'Enter security code',
'Try another way',
].join('\n');
assert.strictEqual(loginPrivate.hasSecurityCodePageText(securityCodeText), true);
assert.strictEqual(commonAuthPrivate.hasSecurityCodePageText(securityCodeText), true);
assert.strictEqual(
loginPrivate.hasSecurityCodePageText('Get a verification code from the Google Authenticator app'),
false,
'Authenticator 页面不能被识别为 g.co 安全码页面',
);
const phoneTabletOnlyText = [
"Verify it's you",
'Choose a way to verify',
"Use your phone or tablet to get a security code (even if it's offline)",
].join('\n');
{
const page = {
url: () => 'https://accounts.google.com/v3/signin/challenge/selection',
locator: selector => selector === 'body'
? { innerText: async () => phoneTabletOnlyText }
: emptyLocator(),
};
assert.strictEqual(
await commonAuthPrivate.detectPhoneTabletOnlyChallenge(page),
true,
'只有手机/平板安全码时应立即识别',
);
assert.strictEqual(await loginPrivate.detectPhoneTabletOnlyChallenge(page), true);
}
{
let optionsSettled = false;
const makeMissing = () => ({
count: async () => 0,
nth() { return this; },
first() { return this; },
or() { return this; },
waitFor: async () => { throw new Error('not visible'); },
isVisible: async () => false,
textContent: async () => '',
});
const page = {
url: () => 'https://accounts.google.com/v3/signin/challenge/selection',
locator: selector => {
if (selector === 'body') {
return {
...makeMissing(),
innerText: async () => optionsSettled
? phoneTabletOnlyText
: "Verify it's you\nChoose a way to verify",
};
}
return makeMissing();
},
waitForLoadState: async () => {},
waitForTimeout: async () => { optionsSettled = true; },
};
const result = await handleIdentityVerification(page, {}, () => {});
assert.deepStrictEqual(
result,
[false, '需手机/平板验证', 'PHONE_TABLET_VERIFY'],
'selection 首次正文未稳定时,等待后必须复检唯一手机/平板方式',
);
}
{
const page = {
url: () => 'https://accounts.google.com/v3/signin/challenge/selection',
locator: selector => selector === 'body'
? { innerText: async () => `${phoneTabletOnlyText}\nGet a verification code from the Google Authenticator app` }
: emptyLocator(),
};
assert.strictEqual(
await commonAuthPrivate.detectPhoneTabletOnlyChallenge(page),
false,
'仍有Authenticator选项时不得误判为只能手机/平板验证',
);
}
{
const heading = {
first() { return this; },
textContent: async () => "Verify it's you",
};
const page = {
url: () => 'https://accounts.google.com/v3/signin/challenge/ootp',
locator: selector => {
if (selector === 'body') return { innerText: async () => phoneTabletOnlyText };
if (selector.startsWith('h1#headingText')) return heading;
return emptyLocator();
},
};
assert.strictEqual(await commonAuthPrivate.detectVerifyItsYouOotp(page), true);
assert.strictEqual(
await commonAuthPrivate.detectPhoneTabletOnlyChallenge(page),
true,
'OOTP 页面只剩手机/平板安全码时也应直接识别',
);
}
{
const makeMissing = () => ({
count: async () => 0,
nth() { return this; },
first() { return this; },
or() { return this; },
waitFor: async () => { throw new Error('not visible'); },
isVisible: async () => false,
textContent: async () => '',
});
const heading = {
...makeMissing(),
textContent: async () => "Verify it's you",
};
const page = {
url: () => 'https://accounts.google.com/v3/signin/challenge/ootp',
locator: selector => {
if (selector === 'body') return { ...makeMissing(), innerText: async () => phoneTabletOnlyText };
if (selector.startsWith('h1#headingText')) return heading;
return makeMissing();
},
waitForLoadState: async () => {},
waitForTimeout: async () => {},
};
const result = await handleIdentityVerification(page, {}, () => {});
assert.deepStrictEqual(
result,
[false, '需手机/平板验证', 'PHONE_TABLET_VERIFY'],
'Verify it’s you + 唯一手机/平板方式必须返回明确机器分类',
);
const oauthResult = await chatgptPrivate.handleGoogleOAuth(page, {}, () => {});
assert.strictEqual(oauthResult.code, 'PHONE_TABLET_VERIFY', 'ChatGPT OAuth 必须保留手机/平板分类');
}
{
const makeMissing = () => ({
count: async () => 0,
nth() { return this; },
first() { return this; },
or() { return this; },
waitFor: async () => { throw new Error('not visible'); },
isVisible: async () => false,
textContent: async () => '',
});
const heading = {
...makeMissing(),
textContent: async () => "Verify it's you",
};
const page = {
url: () => 'https://accounts.google.com/v3/signin/challenge/ootp',
locator: selector => {
if (selector === 'body') return { ...makeMissing(), innerText: async () => "Verify it's you" };
if (selector.startsWith('h1#headingText')) return heading;
return makeMissing();
},
waitForLoadState: async () => {},
waitForTimeout: async () => {},
};
const result = await handleIdentityVerification(page, {}, () => {});
assert.strictEqual(result[0], false);
assert.strictEqual(result[2], 'VERIFY_ITS_YOU');
assert.match(result[1], /Verify it.s you/);
}
{
const page = {
url: () => 'https://accounts.google.com/v3/signin/challenge/custom',
locator: selector => selector === 'body'
? { innerText: async () => securityCodeText }
: emptyLocator(),
};
assert.strictEqual(await loginPrivate.isSecurityCodeChallenge(page), true);
assert.strictEqual(await commonAuthPrivate.isSecurityCodeChallenge(page), true);
}
{
const page = {
url: () => 'https://accounts.google.com/signin/challenge/selection',
locator: selector => selector === 'body'
? { innerText: async () => `Choose how you want to sign in\n${securityCodeText}\nGoogle Authenticator` }
: emptyLocator(),
};
assert.strictEqual(
await loginPrivate.isSecurityCodeChallenge(page),
false,
'验证方式列表即使展示 g.co 选项,也不能被当作当前安全码页面',
);
assert.strictEqual(await commonAuthPrivate.isSecurityCodeChallenge(page), false);
}
{
let bodyText = securityCodeText;
const tryAnotherButton = {
isVisible: async () => true,
scrollIntoViewIfNeeded: async () => {},
click: async () => {
bodyText = 'Choose how you want to sign in\nGoogle Authenticator';
},
evaluate: async () => true,
};
const page = {
url: () => 'https://accounts.google.com/v3/signin/challenge/custom',
locator: selector => {
if (selector === 'body') return { innerText: async () => bodyText };
if (selector === 'text="Try another way"') {
return { count: async () => 1, nth: () => tryAnotherButton };
}
return emptyLocator();
},
waitForTimeout: async () => {},
};
const result = await loginPrivate.tryLeaveAlternateChallenge(page, () => {}, 50);
assert.strictEqual(result.clicked, true);
assert.strictEqual(result.moved, true, '同一 URL 内切换到验证方式列表也应视为成功离开');
}
{
const attemptedSelectors = [];
let currentUrl = 'https://accounts.google.com/signin/challenge/selection';
const authButton = {
isVisible: async () => true,
scrollIntoViewIfNeeded: async () => {},
click: async () => {
currentUrl = 'https://accounts.google.com/signin/challenge/totp';
},
evaluate: async () => true,
};
const page = {
url: () => currentUrl,
locator: selector => {
attemptedSelectors.push(selector);
if (selector === 'li:has-text("Get a verification code from the Google Authenticator app")') {
return { count: async () => 1, nth: () => authButton };
}
return emptyLocator();
},
waitForTimeout: async () => {},
waitForLoadState: async () => {},
};
assert.strictEqual(await handleChallengeSelection(page, () => {}), true);
assert.strictEqual(
attemptedSelectors.includes('div[data-challengetype="6"]'),
false,
'不稳定的 challenge type 不能再作为 Authenticator 兜底',
);
}
{
const invalidResult = await inputCurrent2fa(
{ url: () => 'https://accounts.google.com/signin/challenge/totp' },
'1//not-a-totp-secret',
() => {},
);
assert.strictEqual(invalidResult.ok, false);
assert.match(invalidResult.msg, /2FA密钥格式不正确|Base32/);
}
{
let filledCode = '';
const input = {
first() { return this; },
waitFor: async () => {},
fill: async value => { if (value) filledCode = value; },
press: async () => {},
};
const missingButton = {
first() { return this; },
waitFor: async () => { throw new Error('button unavailable'); },
};
const page = {
url: () => 'https://accounts.google.com/signin/challenge/totp',
locator: selector => selector.includes('input[id="totpPin"]') ? input : missingButton,
waitForLoadState: async () => {},
};
const result = await inputCurrent2fa(page, 'JBSWY3DPEHPK3PXP', () => {});
assert.strictEqual(result.ok, true, '页面只有totpPin输入框时也应能提交2FA');
assert.match(filledCode, /^\d{6}$/);
}
{
const alert = {
isVisible: async () => true,
innerText: async () => 'Wrong code. Try again.',
};
const page = {
locator: selector => {
if (selector.startsWith('[role="alert"]')) {
return { count: async () => 1, nth: () => alert };
}
if (selector === 'body') return { innerText: async () => 'Wrong code. Try again.' };
return emptyLocator();
},
};
assert.strictEqual(await commonAuthPrivate.detectTotpRejection(page), 'Wrong code. Try again.');
assert.strictEqual(await loginPrivate.detectTotpRejection(page), 'Wrong code. Try again.');
}
{
let secondClicked = false;
const failingButton = {
isVisible: async () => true,
scrollIntoViewIfNeeded: async () => {},
click: async () => { throw new Error('intercepted'); },
evaluate: async () => { throw new Error('intercepted'); },
};
const workingButton = {
isVisible: async () => true,
scrollIntoViewIfNeeded: async () => {},
click: async () => { secondClicked = true; },
evaluate: async () => true,
};
const page = {
locator: selector => {
if (selector === 'first') return { count: async () => 1, nth: () => failingButton };
if (selector === 'second') return { count: async () => 1, nth: () => workingButton };
return emptyLocator();
},
};
const selector = await commonAuthPrivate.clickFirstVisible(page, ['first', 'second'], 20);
assert.strictEqual(selector, 'second');
assert.strictEqual(secondClicked, true, '点击失败后必须继续尝试下一个可点击元素');
}
console.log('security_code_challenge.test.js: PASS');
})().catch(error => {
console.error(error);
process.exitCode = 1;
});