Files
Agent-System-Frontend/test/auth.test.ts
T
weichen 09310cb753 Clear stale API-key credentials when a password session begins
Why: the auth middleware prefers Bearer keys over the session cookie, so a stale key left in localStorage shadows valid cookie sessions and every request after password login returns 401 (observed at http://192.168.3.2:8788 on 2026-10-11).
Evidence: modules/frontend vitest 19 files / 88 tests green; auth.test.ts covers beginSession clearing the stored Bearer before any fetch.
Impact: password logins switch to the HttpOnly cookie session cleanly; API-key logins unchanged.
Refs: task card feature-login-clear-stale-key in Agent-System-Dev.
2026-10-11 13:53:27 +00:00

55 lines
2.2 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.
// 认证模块行为测试:密钥存取(无 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()
})
})