feat: 完善 AI Studio Key 自动化流程

This commit is contained in:
2026-09-23 15:39:20 +08:00
parent f41a979462
commit 04309f60c7
45 changed files with 6600 additions and 119 deletions
@@ -0,0 +1,100 @@
'use strict';
const assert = require('assert');
const { _private } = require('../src/services/change_password_service');
function locator(overrides = {}) {
return {
scrollIntoViewIfNeeded: async () => {},
waitFor: async () => {},
isDisabled: async () => false,
isVisible: async () => true,
click: async () => {},
press: async () => {},
evaluate: async () => true,
inputValue: async () => '',
...overrides,
};
}
(async () => {
const calls = [];
const button = locator({
click: async (options) => calls.push(['click', options]),
evaluate: async () => { calls.push(['domClick']); return true; },
});
const confirm = locator({
press: async key => calls.push(['press', key]),
});
const log = () => {};
assert.strictEqual(await _private.submitPasswordForm({}, button, confirm, 1, log), true);
assert.deepStrictEqual(calls[0], ['click', { timeout: 10000, noWaitAfter: true }],
'首次提交必须使用正常点击且禁止 force');
assert.strictEqual(await _private.submitPasswordForm({}, button, confirm, 2, log), true);
assert.deepStrictEqual(calls[1], ['press', 'Enter'], '第二次必须复用原表单并按回车提交');
assert.strictEqual(await _private.submitPasswordForm({}, button, confirm, 3, log), true);
assert.deepStrictEqual(calls[2], ['domClick'], '第三次必须走 DOM 按钮点击兜底');
assert.strictEqual(await _private.canRetryPasswordSubmit(button, locator(), confirm), true);
assert.strictEqual(await _private.canRetryPasswordSubmit(
locator({ isDisabled: async () => true }),
locator(),
confirm,
), false, '按钮仍禁用时不得重复提交');
assert.strictEqual(_private.hasPasswordFieldsInUrl(
'https://myaccount.google.com/signinoptions/password?password=secret&confirmation_password=secret',
), true, '密码字段进入 URL 时必须触发安全保护');
assert.strictEqual(_private.hasPasswordFieldsInUrl(
'https://myaccount.google.com/signinoptions/password?rapt=token',
), false);
assert.strictEqual(_private.hasPasswordFieldsInUrl(
'https://myaccount.google.com/signinoptions/password?NEW_PASSWORD=secret',
), true, '敏感查询参数检查必须忽略大小写');
let passwordSelector = '';
const visibleInputs = await _private.pickVisiblePasswordInputs({
locator: (selector) => {
passwordSelector = selector;
return {
count: async () => 2,
nth: () => locator(),
};
},
});
assert.strictEqual(visibleInputs.length, 2);
assert(passwordSelector.includes('input[name="password"]'),
'显示密码后 type 可能变成 text,仍必须按 name 识别密码控件');
let dialogConfirmClicks = 0;
const makeDialog = (visible, hasConfirm) => ({
isVisible: async () => visible,
locator: () => ({ first: () => ({ isVisible: async () => true }) }),
getByRole: (_role, options) => {
const isConfirm = /Change password/.test(String(options.name));
if (!isConfirm) return { first: () => ({ isVisible: async () => true }) };
return {
count: async () => (hasConfirm ? 1 : 0),
nth: () => locator({ click: async () => { dialogConfirmClicks++; } }),
};
},
waitFor: async () => {},
});
const dialogs = [makeDialog(true, false), makeDialog(true, true)];
const dialogHandled = await _private.confirmPasswordChangeDialog({
locator: () => ({
count: async () => dialogs.length,
nth: index => dialogs[index],
}),
}, log);
assert.strictEqual(dialogHandled, true);
assert.strictEqual(dialogConfirmClicks, 1, '必须点击弹窗作用域内的确认按钮');
console.log('change_password_submit_fallback.test.js: PASS');
})().catch(error => {
console.error(error);
process.exitCode = 1;
});