Files
Genarrative/apps/ai-game-creator-shell/tests/clientHttp.test.ts
T
k88936 594063a1e0 测试:修正 AGC 测试文件的类型错误
- 按 vitest 0.34 的参数元组口径改写 mock 泛型
- 修正 noUncheckedIndexedAccess 下的下标访问
- 补齐与当前类型脱节的测试桩字段
- 按 scripts/*.mjs 的运行时契约补局部类型声明
2026-10-03 17:41:30 +08:00

135 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// @vitest-environment node
/**
* 客户端服务器选择的边界。
*
* 正式包只跟随构建渠道(`VITE_AGC_PLATFORM_CHANNEL`),自定义地址只在本地 Vite debug 可用;
* 归一化必须拒绝把凭据、路径、查询、哈希或明文远程地址带进登录请求——这些值随后会作为
* origin 交给 Rust 与后端,渲染层这一层只负责即时反馈与内存投影。
*/
import { beforeEach, expect, test, vi } from 'vitest';
const { invoke, resolveTauriInvoke } = vi.hoisted(() => {
const invokeMock = vi.fn();
return {
invoke: invokeMock,
resolveTauriInvoke: vi.fn(() => invokeMock),
};
});
vi.mock('../src/app/tauri', () => ({ resolveTauriInvoke }));
async function loadClientHttp() {
return import('../src/services/clientHttp');
}
beforeEach(() => {
vi.resetModules();
vi.unstubAllEnvs();
invoke.mockReset();
resolveTauriInvoke.mockReturnValue(invoke);
});
test('非法服务器地址按原因逐条拒绝', async () => {
const { normalizeClientServerBaseUrl } = await loadClientHttp();
expect(() => normalizeClientServerBaseUrl('dev.genarrative.world')).toThrow(
'服务器地址无效',
);
expect(() => normalizeClientServerBaseUrl('ftp://example.com')).toThrow(
'服务器地址必须是纯 HTTP(S) 地址',
);
expect(() =>
normalizeClientServerBaseUrl('https://user:pass@example.com'),
).toThrow('服务器地址必须是纯 HTTP(S) 地址');
expect(() => normalizeClientServerBaseUrl('https://example.com/api')).toThrow(
'服务器地址必须是纯 HTTP(S) 地址',
);
expect(() =>
normalizeClientServerBaseUrl('https://example.com/?token=1'),
).toThrow('服务器地址必须是纯 HTTP(S) 地址');
expect(() =>
normalizeClientServerBaseUrl('https://example.com/#frag'),
).toThrow('服务器地址必须是纯 HTTP(S) 地址');
expect(() => normalizeClientServerBaseUrl('http://example.com')).toThrow(
'非本机服务器必须使用 HTTPS',
);
});
test('合法地址去掉尾部斜杠并保留回环端口', async () => {
const { normalizeClientServerBaseUrl } = await loadClientHttp();
expect(normalizeClientServerBaseUrl('https://dev.genarrative.world///')).toBe(
'https://dev.genarrative.world',
);
expect(normalizeClientServerBaseUrl(' http://127.0.0.1:10001/ ')).toBe(
'http://127.0.0.1:10001',
);
expect(normalizeClientServerBaseUrl('http://localhost:8080')).toBe(
'http://localhost:8080',
);
});
test('预设映射到渠道地址,自定义走归一化', async () => {
const mod = await loadClientHttp();
expect(
mod.getClientServerBaseUrl({ preset: 'release', customBaseUrl: '' }),
).toBe(mod.AGC_RELEASE_API_BASE_URL);
expect(mod.getClientServerBaseUrl({ preset: 'dev', customBaseUrl: '' })).toBe(
mod.AGC_DEVELOPMENT_API_BASE_URL,
);
expect(
mod.getClientServerBaseUrl({
preset: 'custom',
customBaseUrl: 'https://staging.example.com/',
}),
).toBe('https://staging.example.com');
expect(mod.isClientServerPreset('custom')).toBe(true);
expect(mod.isClientServerPreset('staging')).toBe(false);
});
test('开发态切换服务器会落盘并在内存中生效', async () => {
vi.stubEnv('DEV', 'true');
const mod = await loadClientHttp();
expect(mod.isClientServerSelectionEnabled()).toBe(true);
expect(
mod.setClientServerSelection({
preset: 'custom',
customBaseUrl: ' https://staging.example.com/ ',
}),
).toEqual({ preset: 'custom', customBaseUrl: 'https://staging.example.com' });
await Promise.resolve();
expect(invoke).toHaveBeenCalledWith('set_client_server_selection', {
preset: 'custom',
customBaseUrl: 'https://staging.example.com',
});
expect(mod.getClientServerBaseUrl()).toBe('https://staging.example.com');
});
test('开发态从 Rust 偏好恢复服务器选择', async () => {
vi.stubEnv('DEV', 'true');
const mod = await loadClientHttp();
invoke.mockResolvedValue({
clientServerSelection: {
preset: 'custom',
customBaseUrl: 'https://restored.example.com',
},
});
await expect(mod.hydrateClientServerSelection()).resolves.toEqual({
preset: 'custom',
customBaseUrl: 'https://restored.example.com',
});
expect(invoke).toHaveBeenCalledWith('read_workspace_preferences');
expect(mod.getClientServerSelection()).toEqual({
preset: 'custom',
customBaseUrl: 'https://restored.example.com',
});
});
// 「打包态不开放服务器切换」这条规则这里测不了:`import.meta.env.DEV` 在测试运行下恒为
// true,`vi.stubEnv('DEV', false)` 改不动它(Vite/Vitest 把它按构建期常量处理),因此
// `isClientServerSelectionEnabled()` 与 `getClientServerSelection()` 的打包分支只能在真实
// 发布构建里核对。本文件覆盖的是地址归一化、预设映射、开发态落盘与偏好恢复。