Files
Genarrative/apps/ai-game-creator-shell/tests/clientAuthStorage.test.ts
T
kdletters e3682fd06f
Project CI / AI game creator shell Rust shard 4/4 (push) Successful in 7m31s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 7m32s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 7m33s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 7m40s
Project CI / AI game creator shell Rust smoke (push) Successful in 2m21s
Project CI / AI game creator shell Rust crates (push) Successful in 3m11s
Project CI / Native shell tests (push) Successful in 16m15s
Project CI / Frontend tests (push) Successful in 14m57s
Project CI / Repository checks (push) Successful in 14m48s
Project CI / Backend tests (push) Successful in 20m7s
Project CI / AI game creator shell web tests (push) Successful in 6m20s
固定客户端dev服务并支持官网多平台下载
移除服务器选择并按来源隔离登录凭据
新增官网客户端下载入口和匿名平台聚合接口
根据发布清单自动展示Windows与macOS首装包
补齐Mac首装元数据和上传顺序校验
同步定向测试与下载发布规范
2026-09-19 16:19:28 +08:00

122 lines
4.3 KiB
TypeScript

/** @vitest-environment jsdom */
import { afterEach, describe, expect, it, vi } from 'vitest';
import {
getStoredAuthAccessToken as getApiAccessToken,
requestClientApi,
} from '../src/services/clientApi';
import {
clearStoredAuthAccessToken,
getStoredAuthAccessToken,
setStoredAuthAccessToken,
} from '../src/services/clientAuth';
import { AGC_DEVELOPMENT_API_BASE_URL } from '../src/services/clientHttp';
vi.mock('@tauri-apps/plugin-http', () => ({ fetch: vi.fn() }));
vi.mock('../src/services/errorReporting', () => ({
captureClientError: vi.fn(),
}));
const tokenKey = 'genarrative.auth.access-token.v1';
const originKey = 'genarrative.auth.access-token-origin.v1';
const selectionKey = 'genarrative.client.server-selection.v1';
describe('AGC platform credential origin', () => {
afterEach(() => {
window.localStorage.clear();
vi.restoreAllMocks();
vi.unstubAllEnvs();
});
it('preserves a credential already marked as dev', () => {
window.localStorage.setItem(tokenKey, 'existing-dev-token');
window.localStorage.setItem(originKey, AGC_DEVELOPMENT_API_BASE_URL);
expect(getStoredAuthAccessToken()).toBe('existing-dev-token');
expect(getApiAccessToken()).toBe('existing-dev-token');
expect(window.localStorage.getItem(originKey)).toBe(
AGC_DEVELOPMENT_API_BASE_URL,
);
});
it.each([
JSON.stringify({ preset: 'dev', customBaseUrl: '' }),
JSON.stringify({
preset: 'custom',
customBaseUrl: `${AGC_DEVELOPMENT_API_BASE_URL}/`,
}),
JSON.stringify({ preset: 'release', customBaseUrl: '' }),
JSON.stringify({ preset: 'custom', customBaseUrl: 'https://example.com' }),
JSON.stringify({
preset: 'custom',
customBaseUrl: 'http://localhost:8082',
}),
JSON.stringify({ preset: 'unknown', customBaseUrl: '' }),
'invalid-json',
'null',
])(
'never infers a legacy credential origin from a saved preference: %s',
async (selection) => {
window.localStorage.setItem(tokenKey, 'other-server-token');
window.localStorage.setItem(selectionKey, selection);
vi.stubEnv('MODE', 'production');
const fetchMock = vi
.spyOn(globalThis, 'fetch')
.mockResolvedValue(
new Response(JSON.stringify({ result: true }), { status: 200 }),
);
await requestClientApi('/api/profile/dashboard', {}, '读取失败');
expect(fetchMock).toHaveBeenCalledTimes(1);
const [url, init] = fetchMock.mock.calls[0];
expect(url).toBe(`${AGC_DEVELOPMENT_API_BASE_URL}/api/profile/dashboard`);
expect(new Headers(init?.headers).get('Authorization')).toBeNull();
expect(window.localStorage.getItem(tokenKey)).toBeNull();
},
);
it.each([true, false])(
'clears an unmarked credential without a preference (development=%s)',
(development) => {
// Vitest 0.34 stores stubbed env values as strings; use a falsy value for DEV=false.
vi.stubEnv('DEV', development ? 'true' : '');
window.localStorage.setItem(tokenKey, 'legacy-token');
expect(getStoredAuthAccessToken()).toBe('');
},
);
it('does not relabel a credential that already belongs to another origin', () => {
window.localStorage.setItem(tokenKey, 'other-origin-token');
window.localStorage.setItem(originKey, 'https://www.genarrative.world');
window.localStorage.setItem(
selectionKey,
JSON.stringify({ preset: 'dev' }),
);
expect(getApiAccessToken()).toBe('');
expect(window.localStorage.getItem(tokenKey)).toBeNull();
expect(window.localStorage.getItem(originKey)).toBeNull();
});
it('stores new dev credentials with their origin and ignores old preferences', () => {
vi.stubEnv('DEV', false);
setStoredAuthAccessToken('new-token');
window.localStorage.setItem(
selectionKey,
JSON.stringify({ preset: 'release' }),
);
expect(getApiAccessToken()).toBe('new-token');
expect(getStoredAuthAccessToken('https://www.genarrative.world')).toBe('');
expect(() =>
setStoredAuthAccessToken('wrong-token', 'https://example.com'),
).toThrow('固定的 dev 服务');
expect(getStoredAuthAccessToken()).toBe('new-token');
clearStoredAuthAccessToken();
expect(window.localStorage.getItem(tokenKey)).toBeNull();
expect(window.localStorage.getItem(originKey)).toBeNull();
});
});