Files
EasyCLIProxyAPI/tests/claude-code-model-inputs-ui.cjs
lzt404 259389f2b2 fix(claude-code): persist runtime settings and clean up managed configuration
- Persist auto-compaction preferences and allow reducing 1M windows
- Remove stale managed settings while preserving user changes
- Normalize Fable model comparisons
- Add regression tests and real Claude Code integration coverage
2026-10-08 18:36:58 +08:00

77 lines
5.0 KiB
JavaScript

const { chromium } = require(process.env.PLAYWRIGHT_MODULE || 'playwright');
const assert = require('node:assert/strict');
const path = require('node:path');
const os = require('node:os');
const base = process.env.AGENT_MODEL_INPUTS_TEST_URL || 'http://127.0.0.1:1421';
(async () => {
const browser = await chromium.launch({ channel: 'msedge', headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1280, height: 900 } });
page.setDefaultTimeout(10000);
await page.goto(`${base}/tests/fixtures/agent-backups.html?client=claude-code&reset-selections`);
const startup = page.getByRole('combobox', { name: '默认模型', exact: true });
const subagent = page.getByRole('combobox', { name: 'Subagent 模型', exact: true });
await startup.click();
await page.getByRole('option', { name: /^sonnet / }).click();
assert.equal(await startup.inputValue(), 'sonnet');
assert(await page.getByRole('button', { name: '更新配置', exact: true }).isDisabled());
for (const role of ['opus', 'haiku', 'fable']) {
await page.locator(`.claude-role-row[data-role=${role}] .agent-model-trigger`).click();
await page.getByRole('option', { name: /^gpt-one / }).click();
}
await page.locator('.claude-role-row .agent-model-trigger').first().click();
await page.getByRole('option', { name: /gpt-two/ }).click();
assert.equal(await page.locator('.claude-code-model-summary').count(), 0);
assert.equal(await startup.inputValue(), 'sonnet');
await startup.click();
await page.getByRole('option', { name: /^gpt-two / }).click();
await page.locator('.claude-code-context-settings summary').click();
const context = page.getByRole('switch', { name: '默认模型 1M', exact: true });
await context.check();
assert.equal(await startup.inputValue(), 'gpt-two[1m]');
assert.equal(await page.getByRole('spinbutton', { name: '全局窗口覆盖', exact: true }).inputValue(), '1000000');
await context.uncheck();
assert.equal(await page.getByRole('spinbutton', { name: '全局窗口覆盖', exact: true }).inputValue(), '200000');
assert.equal(await startup.inputValue(), 'gpt-two');
await page.locator('.claude-code-context-settings summary').click();
assert.equal(await page.locator('.claude-role-row input[type=checkbox]').count(), 4);
await subagent.fill('custom-worker');
await subagent.press('Enter');
assert.equal(await subagent.inputValue(), 'custom-worker');
await page.getByRole('button', { name: '更新配置', exact: true }).click();
await page.waitForFunction(() => window.fixtureCalls.some(c => c.args?.claudeCodeModelMappings?.startupModel === 'gpt-two' && c.args?.claudeCodeModelMappings?.subagentModel === 'custom-worker'));
await subagent.fill('unsaved-worker');
await subagent.press('Escape');
await page.evaluate(() => { window.fixtureFailedCommands = ['get_agent_models']; });
await page.locator('.claude-role-row .agent-model-trigger').first().click();
await page.locator('.agent-model-dropdown:visible button').filter({ has: page.locator('svg.lucide-refresh-cw') }).click();
await page.locator('.claude-code-model-error').waitFor();
assert.equal(await startup.inputValue(), 'gpt-two');
assert.equal(await subagent.inputValue(), 'unsaved-worker');
assert.match(await page.locator('.claude-role-row .agent-model-trigger').first().innerText(), /gpt-two/);
await subagent.press('Escape');
await page.evaluate(() => { window.fixtureFailedCommands = []; });
await page.locator('.claude-code-model-error button').click();
await page.locator('.claude-code-model-error').waitFor({ state: 'hidden' });
assert.equal(await subagent.inputValue(), 'unsaved-worker');
await startup.click();
await page.getByRole('option', { name: /^opus / }).click();
await subagent.click();
await page.getByRole('option', { name: '使用默认继承行为', exact: true }).click();
await page.getByRole('button', { name: '更新配置', exact: true }).click();
await page.waitForFunction(() => window.fixtureCalls.some(c => c.args?.claudeCodeModelMappings?.startupModel === 'opus' && c.args?.claudeCodeModelMappings?.subagentModel === ''));
await page.getByRole('switch', { name: 'fable 1M', exact: true }).check();
await page.getByRole('button', { name: '更新配置', exact: true }).click();
await page.waitForFunction(() => window.fixtureCalls.some(c => c.args?.claudeCodeModelMappings?.fable1m === true));
for (const width of [1280, 760]) {
await page.setViewportSize({ width, height: 1000 });
await page.screenshot({ path: path.join(os.tmpdir(), `claude-code-models-${width}.png`), fullPage: true });
for (const field of await page.locator('.claude-code-model-field').all()) {
assert(await field.evaluate(el => el.scrollWidth <= el.clientWidth + 1));
}
}
console.log('PASS: select, custom input, defaults, connection failure/retry, draft retention and responsive layout');
} finally { await browser.close(); }
})().catch(error => { console.error(error); process.exitCode = 1; });