'use strict'; const assert = require('assert'); const fs = require('fs'); const path = require('path'); const { _private } = require('../src/services/aistudio_api_key_service'); (async () => { const accessBlock = _private.classifyAistudioAccessBlock( 'https://ai.google.dev/gemini-api/docs/available-regions', 'Available regions for Google AI Studio and Gemini API\nRegional restrictions\nAge requirements\nAccount verification', ); assert(accessBlock, 'Available regions 跳转必须被识别为 AI Studio 访问受限'); assert.strictEqual(accessBlock.code, 'AI_STUDIO_ACCESS_RESTRICTED'); assert.strictEqual( _private.classifyAistudioAccessBlock('https://aistudio.google.com/api-keys', 'API keys'), null, '正常 API Keys 页不能被误判为访问受限', ); const source = fs.readFileSync( path.join(__dirname, '..', 'src', 'services', 'aistudio_api_key_service.js'), 'utf8', ); const readyStart = source.indexOf('async function waitForApiKeysReady'); const readyEnd = source.indexOf('\n/** 定位工具栏', readyStart); const readySource = source.slice(readyStart, readyEnd); assert( readySource.indexOf('classifyAistudioAccessBlock(') < readySource.indexOf('findCreateApiKeyButton(page)'), '必须先识别 Available regions 受限页,再匹配通用按钮,避免把 Dismiss 当成创建按钮', ); const processStart = source.indexOf('async function processAistudioApiKey'); const processEnd = source.indexOf('\nmodule.exports', processStart); const processSource = source.slice(processStart, processEnd); assert( processSource.indexOf('const postConsentSnapshot = await pageSnapshot(page)') > processSource.indexOf('const consentHandled = await dismissWelcomeConsent(page, log)'), '首次条款提交后必须再次识别 Available regions 重定向', ); let evaluateCalls = 0; const page = { evaluate: async () => { evaluateCalls++; return true; // 模拟 suspicious / Failed to generate API key toast 已出现 }, }; const startedAt = Date.now(); const generated = await _private.waitKeyGenerated(page, 20000); const elapsed = Date.now() - startedAt; assert.strictEqual(generated, false); assert.strictEqual(evaluateCalls, 1); assert(elapsed < 200, '明确失败提示出现后不应继续空等 20 秒'); let rpcEvaluateCalls = 0; const rpcRejectedPage = { __aistudioGenerateKeyResponse: { status: 403, at: Date.now() }, evaluate: async () => { rpcEvaluateCalls++; return false; }, }; assert.strictEqual(await _private.waitKeyGenerated(rpcRejectedPage, 20000), false); assert.strictEqual(rpcEvaluateCalls, 0, '已捕获 GenerateCloudApiKey 403 时应在读取 DOM 前立即失败'); console.log('aistudio_fast_rejection.test.js: PASS'); })().catch(error => { console.error(error); process.exitCode = 1; });