Files
EasyCLIProxyAPI/tests/agent-backups-ui.cjs
T
lzt404 6b5d88cf9b fix: preserve legacy Claude alias sources during reconfiguration
Resolve model sources before replacing role aliases and support legacy
API and OAuth configurations that retain only aliased model entries.

Add regression coverage for source priority, disabled providers,
cross-role updates, and transaction rollback.
2026-09-11 16:25:14 +08:00

74 lines
5.7 KiB
JavaScript

// Run Vite on port 1421, then node tests/agent-backups-ui.cjs.
// PLAYWRIGHT_MODULE may point to an existing Playwright installation.
const { chromium } = require(process.env.PLAYWRIGHT_MODULE || 'playwright');
const assert = require('node:assert/strict');
(async () => {
const browser = await chromium.launch({ channel: 'msedge', headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1280, height: 900 } });
page.setDefaultTimeout(10000);
const errors = []; page.on('pageerror', e => errors.push(String(e)));
const calls = cmd => page.evaluate(cmd => window.fixtureCalls.filter(c => c.cmd === cmd), cmd);
const open = async query => { await page.goto('http://localhost:1421/tests/fixtures/agent-backups.html?' + query); await page.getByRole('button', { name: '手动备份', exact: true }).waitFor(); };
const backup = async () => { await page.getByRole('button', { name: '手动备份', exact: true }).click(); await page.getByText('已手动备份当前磁盘配置,未包含未保存的表单修改。', { exact: true }).waitFor(); };
const choose = async () => { await page.getByRole('button', { name: '恢复备份', exact: true }).click(); await page.locator('.agent-backup-columns nav button').first().click(); };
for (const query of ['fresh', 'embedded&fresh', 'client=pi']) {
await open(query);
if (!query.includes('pi')) {
await page.getByRole('button', { name: '一键接入', exact: true }).click();
await page.getByText('配置已更新。', { exact: true }).waitFor();
await page.getByRole('button', { name: '更新配置', exact: true }).click();
await page.getByText('配置已是最新,无需写入。', { exact: true }).waitFor();
}
assert.equal((await calls('create_agent_config_backup')).length, 0);
await backup();
assert.deepEqual((await calls('create_agent_config_backup'))[0].args, { client: query.includes('pi') ? 'pi' : 'codex' });
await page.getByRole('button', { name: '基础配置模板', exact: true }).click();
await page.getByRole('button', { name: '确认覆盖', exact: true }).waitFor();
assert.equal(await page.locator('.agent-template-files li').count(), 3);
assert.equal((await calls('apply_agent_config_template')).length, 0);
await page.getByRole('button', { name: '确认覆盖', exact: true }).click();
await page.getByRole('button', { name: '确认覆盖', exact: true }).waitFor({ state: 'detached' });
assert.equal((await calls('apply_agent_config_template'))[0].args.revision, 'template1');
assert.equal((await calls('create_agent_config_backup')).length, 1);
await choose();
await page.getByText('备份时不存在;恢复时删除', { exact: true }).waitFor();
assert.equal(await page.locator('.agent-backup-files li').count(), 3);
const updateCount = (await calls('update_agent_config')).length;
await page.getByRole('button', { name: '恢复此版本', exact: true }).click();
assert.equal((await calls('restore_agent_config_backup')).length, 0);
await page.getByRole('button', { name: '确认恢复', exact: true }).click();
await page.locator('.agent-backup-modal').waitFor({ state: 'detached' });
assert.equal((await calls('restore_agent_config_backup'))[0].args.revision, 'rev1');
assert.equal((await calls('update_agent_config')).length, updateCount);
await choose();
await page.getByRole('button', { name: '删除此版本', exact: true }).click();
assert.equal((await calls('delete_agent_config_backup')).length, 0);
await page.getByRole('button', { name: '确认删除', exact: true }).click();
await page.getByText('暂无手动备份。点击“手动备份”保存当前磁盘配置。', { exact: true }).waitFor();
assert.equal((await calls('restore_agent_config_backup')).length, 1);
assert.equal((await calls('create_agent_config_backup')).length, 1);
}
await open('state=invalid');
assert.ok(await page.getByRole('button', { name: '更新配置', exact: true }).isDisabled());
assert.ok(await page.getByRole('button', { name: '基础配置模板', exact: true }).isEnabled());
await backup(); await choose();
assert.ok(await page.getByRole('button', { name: '恢复此版本', exact: true }).isDisabled());
assert.ok(await page.getByRole('button', { name: '删除此版本', exact: true }).isEnabled());
await open('conflict'); await backup(); await choose();
await page.getByRole('button', { name: '恢复此版本', exact: true }).click();
await page.getByRole('button', { name: '确认恢复', exact: true }).click();
await page.getByText(/预览后配置或备份发生变化,请重新预览/).waitFor();
assert.ok(await page.getByRole('button', { name: '恢复此版本', exact: true }).isDisabled());
await page.setViewportSize({ width: 540, height: 820 });
assert.ok(await page.locator('.agent-backup-modal').isVisible());
assert.ok(await page.locator('.agent-backup-modal').evaluate(el => el.scrollWidth <= el.clientWidth));
await page.screenshot({ path: 'misc/agent-backups-narrow.png', fullPage: true });
await open('client=claude-desktop');
await page.getByText('没有可靠的 Claude Desktop 模型映射,请重新选择模型。', { exact: true }).waitFor();
assert.ok(await page.getByRole('button', { name: '更新配置', exact: true }).isDisabled());
assert.deepEqual(errors, []);
console.log('PASS: full/compact/Pi backup, disk-only payload, template preview, restore/delete confirmations, corrupt backups, conflict invalidation, narrow layout, missing Desktop mapping');
} finally { await browser.close(); }
})().catch(e => { console.error(e); process.exit(1); });