121 lines
5.8 KiB
JavaScript
121 lines
5.8 KiB
JavaScript
'use strict';
|
||
|
||
const assert = require('assert');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const { chromium } = require('playwright');
|
||
const { _private } = require('../src/services/aistudio_api_key_service');
|
||
|
||
(async () => {
|
||
const browser = await chromium.launch({ headless: true });
|
||
try {
|
||
const page = await browser.newPage({ viewport: { width: 1200, height: 800 } });
|
||
page.__osDisabled = true;
|
||
|
||
await page.setContent(`
|
||
<ms-api-key-creation-dialog style="display:block;width:500px;height:300px">
|
||
<h2>Create API key</h2>
|
||
<input id="api-key-name-input" value="Gemini API Key">
|
||
<div role="combobox">Gemini Project</div>
|
||
<button id="create-key" class="ms-button-primary">Create key</button>
|
||
</ms-api-key-creation-dialog>
|
||
<div id="project-dialog" role="dialog" style="position:fixed;left:300px;top:100px;width:500px;height:260px;background:white">
|
||
<h2>Create a new project</h2>
|
||
<input value="Gemini Project">
|
||
<button aria-label="Close" style="width:32px;height:32px">×</button>
|
||
<button class="ms-button-primary">Create</button>
|
||
<div class="spinner-container">Loading</div>
|
||
</div>
|
||
<script>
|
||
window.createKeyClicks = 0;
|
||
document.getElementById('create-key').addEventListener('click', () => window.createKeyClicks++);
|
||
</script>
|
||
`);
|
||
|
||
assert.strictEqual(await _private.hasBlockingProjectCreationDialog(page), true,
|
||
'新建项目弹窗仍在时必须阻止底层 Create key');
|
||
assert.strictEqual(await _private.isCreateKeyDisabled(page), true,
|
||
'项目弹窗转圈期间 Create key 应视为不可点');
|
||
assert.strictEqual(await _private.clickCreateKeyButton(page, () => {}), false,
|
||
'不能把新建项目弹窗的关闭按钮当成 Create key');
|
||
assert.strictEqual(await page.evaluate(() => window.createKeyClicks), 0);
|
||
|
||
const stalled = await _private.createProject(page, () => {}, 'Gemini Project', 600);
|
||
assert.strictEqual(stalled.ok, false, '新建项目弹窗一直转圈不能误报成功');
|
||
assert(/持续加载超时/.test(stalled.msg), '转圈超时应触发 Cloud Console 兜底');
|
||
|
||
await page.locator('#project-dialog').evaluate(element => element.remove());
|
||
assert.strictEqual(await _private.clickCreateKeyButton(page, () => {}), true,
|
||
'项目弹窗关闭后应能精确点击 Create key');
|
||
assert.strictEqual(await page.evaluate(() => window.createKeyClicks), 1);
|
||
|
||
await page.setContent(`
|
||
<ms-api-key-creation-dialog style="display:block;width:500px;height:300px">
|
||
<h2>Create API key</h2>
|
||
<input id="api-key-name-input" value="Gemini API Key">
|
||
<div role="combobox">Gemini Project</div>
|
||
<button>Create key</button>
|
||
</ms-api-key-creation-dialog>
|
||
<table><tbody><tr role="row"><td class="cdk-column-Key">...AbCd</td><td><button><svg></svg></button></td></tr></tbody></table>
|
||
`);
|
||
assert.strictEqual(await _private.countRowMenuButtons(page), 1,
|
||
'无 more_vert/aria-haspopup 的新版 Key 行也必须被识别');
|
||
assert.strictEqual(await _private.waitCreationFormReady(page, 1000), 'late_existing',
|
||
'列表晚到时应立即切回先删除旧 Key 的路径');
|
||
|
||
await page.setContent('<main id="late-table"></main>');
|
||
await page.evaluate(() => {
|
||
setTimeout(() => {
|
||
document.getElementById('late-table').innerHTML = `
|
||
<table><tbody><tr role="row"><td class="cdk-column-Key">...Late</td><td><button><svg></svg></button></td></tr></tbody></table>`;
|
||
}, 500);
|
||
});
|
||
assert.strictEqual(await _private.waitForLateExistingRows(page, 2000), 1,
|
||
'刷新瞬间读到 0 后应继续轮询,并识别延迟出现的旧 Key');
|
||
|
||
await page.setContent(`
|
||
<button id="toolbar-menu"><mat-icon>more_vert</mat-icon></button>
|
||
<ms-api-key-creation-dialog style="display:block;width:500px;height:300px">
|
||
<h2>Create API key</h2>
|
||
<input id="api-key-name-input" value="Gemini API Key">
|
||
<div role="combobox">Gemini Project</div>
|
||
<button>Create key</button>
|
||
</ms-api-key-creation-dialog>
|
||
`);
|
||
assert.strictEqual(await _private.countRowMenuButtons(page), 0,
|
||
'工具栏 more_vert 不能被误计为已有 Key 行');
|
||
assert.strictEqual(await _private.waitCreationFormReady(page, 1000), 'ready',
|
||
'无 Key 时创建表单应正常继续,不能误报 late_existing');
|
||
|
||
await page.setContent(`
|
||
<ms-api-key-creation-dialog style="display:block;width:500px;height:300px">
|
||
<h2>Create API key</h2>
|
||
<input id="api-key-name-input" value="Gemini API Key">
|
||
<div role="combobox">Gemini Project</div>
|
||
</ms-api-key-creation-dialog>
|
||
<div role="dialog" style="position:fixed;left:300px;top:100px;width:500px;height:300px;background:white">
|
||
<p>Go Further. Build Smarter. Gemini API Additional Terms of Service and Google Privacy Policy.</p>
|
||
<button>Continue</button>
|
||
</div>
|
||
`);
|
||
assert.strictEqual(await _private.waitCreationFormReady(page, 1000), 'consent_required',
|
||
'第二层附加条款必须优先处理,不能误报项目选择控件缺失');
|
||
|
||
const source = fs.readFileSync(
|
||
path.join(__dirname, '..', 'src', 'services', 'aistudio_api_key_service.js'),
|
||
'utf8',
|
||
);
|
||
const onceStart = source.indexOf('async function createKeyOnce');
|
||
const onceSource = source.slice(onceStart, source.indexOf('\n/**', onceStart + 30));
|
||
assert(onceSource.includes('postProjectFormState = await waitCreationFormReady(page, 15000)'),
|
||
'导入/新建项目后必须再等创建表单 spinner 消失,不能直接点 Create key');
|
||
|
||
console.log('aistudio_dialog_state_regression.test.js: PASS');
|
||
} finally {
|
||
await browser.close();
|
||
}
|
||
})().catch(error => {
|
||
console.error(error);
|
||
process.exitCode = 1;
|
||
});
|