// 认证模块行为测试:密钥存取(无 DOM 回退内存)、凭证注入、资源 URL 追加 key。 import { describe, expect, it, vi, beforeEach } from 'vitest' import { auth } from '../src/auth' describe('auth 凭证模块', () => { beforeEach(() => { auth.clear() vi.unstubAllGlobals() }) it('未设置密钥时 fetch 透传(无 Authorization 头)', async () => { const spy = vi.fn().mockResolvedValue(new Response('{}')) vi.stubGlobal('fetch', spy) await auth.fetch('/api/projects') const [, init] = spy.mock.calls[0] as [string, RequestInit | undefined] const headers = new Headers(init?.headers ?? {}) expect(headers.get('Authorization')).toBeNull() }) it('设置密钥后 fetch 注入 Bearer 头', async () => { auth.setKey('ask_test123') const spy = vi.fn().mockResolvedValue(new Response('{}')) vi.stubGlobal('fetch', spy) await auth.fetch('/api/projects', { method: 'POST' }) const [, init] = spy.mock.calls[0] as [string, RequestInit] expect(new Headers(init.headers).get('Authorization')).toBe('Bearer ask_test123') expect(init.method).toBe('POST') // 原有 init 语义保留 }) it('withKey:无密钥不改 URL;有密钥按是否含 ? 选择连接符', () => { expect(auth.withKey('/api/artifacts/a/content')).toBe('/api/artifacts/a/content') auth.setKey('ask_k') expect(auth.withKey('/api/events?conversationId=c1')).toBe('/api/events?conversationId=c1&key=ask_k') expect(auth.withKey('/api/artifacts/a/content')).toBe('/api/artifacts/a/content?key=ask_k') }) it('clear 后恢复无凭证状态', () => { auth.setKey('ask_x') auth.clear() expect(auth.apiKey()).toBe('') expect(auth.withKey('/x')).toBe('/x') }) it('beginSession:密码会话生效后清残留 Bearer,fetch 不再带头', async () => { auth.setKey('ask_stale') auth.beginSession() expect(auth.apiKey()).toBe('') const spy = vi.fn().mockResolvedValue(new Response('{}')) vi.stubGlobal('fetch', spy) await auth.fetch('/api/me') const [, init] = spy.mock.calls[0] as [string, RequestInit | undefined] expect(new Headers(init?.headers ?? {}).get('Authorization')).toBeNull() }) })