// @ts-ignore Node strip-types runtime requires explicit .ts extension in ESM imports. import { downloadDocumentContentMarkdown, downloadDocumentFile, getCurrentAuthSession, getDocumentPreviewBlob, getDocumentThumbnailBlob, getRuntimeApiToken, loginWithPassword, logoutCurrentSession, setRuntimeApiToken, updateDocumentMetadata, } from './api.ts'; /** * Throws when a test condition is false. */ function assert(condition: boolean, message: string): void { if (!condition) { throw new Error(message); } } /** * Verifies that async functions reject with an expected message fragment. */ async function assertRejects(action: () => Promise, expectedMessage: string): Promise { try { await action(); } catch (error) { const message = error instanceof Error ? error.message : String(error); assert(message.includes(expectedMessage), `Expected error containing "${expectedMessage}" but received "${message}"`); return; } throw new Error(`Expected rejection containing "${expectedMessage}"`); } /** * Converts fetch inputs into a URL string for assertions. */ function toRequestUrl(input: RequestInfo | URL): string { if (typeof input === 'string') { return input; } if (input instanceof URL) { return input.toString(); } return input.url; } /** * Runs API helper tests for authenticated media and auth session workflows. */ async function runApiTests(): Promise { const originalFetch = globalThis.fetch; try { setRuntimeApiToken(null); const requestUrls: string[] = []; const requestAuthHeaders: Array = []; globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit): Promise => { requestUrls.push(toRequestUrl(input)); requestAuthHeaders.push(new Headers(init?.headers).get('Authorization')); return new Response('preview-bytes', { status: 200 }); }) as typeof fetch; const thumbnail = await getDocumentThumbnailBlob('doc-1'); const preview = await getDocumentPreviewBlob('doc-1'); assert(await thumbnail.text() === 'preview-bytes', 'Thumbnail blob bytes mismatch'); assert(await preview.text() === 'preview-bytes', 'Preview blob bytes mismatch'); assert( requestUrls[0] === 'http://localhost:8000/api/v1/documents/doc-1/thumbnail', `Unexpected thumbnail URL ${requestUrls[0]}`, ); assert( requestUrls[1] === 'http://localhost:8000/api/v1/documents/doc-1/preview', `Unexpected preview URL ${requestUrls[1]}`, ); assert(requestAuthHeaders[0] === null, `Expected no auth header for thumbnail request, got "${requestAuthHeaders[0]}"`); assert(requestAuthHeaders[1] === null, `Expected no auth header for preview request, got "${requestAuthHeaders[1]}"`); setRuntimeApiToken('session-user-token'); assert(getRuntimeApiToken() === 'session-user-token', 'Expected runtime token readback to match active token'); globalThis.fetch = (async (_input: RequestInfo | URL, init?: RequestInit): Promise => { const authHeader = new Headers(init?.headers).get('Authorization'); assert(authHeader === 'Bearer session-user-token', `Expected session token auth header, got "${authHeader}"`); return new Response('preview-bytes', { status: 200 }); }) as typeof fetch; await getDocumentPreviewBlob('doc-session-auth'); let mergedContentType: string | null = null; let mergedAuthorization: string | null = null; globalThis.fetch = (async (_input: RequestInfo | URL, init?: RequestInit): Promise => { const headers = new Headers(init?.headers); mergedContentType = headers.get('Content-Type'); mergedAuthorization = headers.get('Authorization'); return new Response('{}', { status: 200 }); }) as typeof fetch; await updateDocumentMetadata('doc-headers', { original_filename: 'renamed.pdf' }); assert(mergedContentType === 'application/json', `Expected JSON content type to be preserved, got "${mergedContentType}"`); assert(mergedAuthorization === 'Bearer session-user-token', `Expected auth header, got "${mergedAuthorization}"`); globalThis.fetch = (async (): Promise => { return new Response( JSON.stringify({ access_token: 'issued-session-token', token_type: 'bearer', expires_at: '2026-03-01T10:30:00Z', user: { id: '3a42f5e0-b1ad-4f68-b2f4-3fa8c2fb31c9', username: 'admin', role: 'admin', }, }), { status: 200, headers: { 'Content-Type': 'application/json' } }, ); }) as typeof fetch; const loginPayload = await loginWithPassword('admin', 'password'); assert(loginPayload.access_token === 'issued-session-token', 'Unexpected issued session token in login payload'); assert(loginPayload.user.username === 'admin', 'Unexpected login user payload'); globalThis.fetch = (async (): Promise => { return new Response( JSON.stringify({ expires_at: '2026-03-01T10:30:00Z', user: { id: '3a42f5e0-b1ad-4f68-b2f4-3fa8c2fb31c9', username: 'admin', role: 'admin', }, }), { status: 200, headers: { 'Content-Type': 'application/json' } }, ); }) as typeof fetch; const sessionPayload = await getCurrentAuthSession(); assert(sessionPayload.user.role === 'admin', 'Expected admin role from auth session payload'); globalThis.fetch = (async (): Promise => { return new Response('{}', { status: 200, headers: { 'Content-Type': 'application/json' } }); }) as typeof fetch; await logoutCurrentSession(); globalThis.fetch = (async (): Promise => { return new Response('file-bytes', { status: 200, headers: { 'content-disposition': 'attachment; filename="invoice.pdf"', }, }); }) as typeof fetch; const fileResult = await downloadDocumentFile('doc-2'); assert(fileResult.filename === 'invoice.pdf', `Unexpected download filename ${fileResult.filename}`); assert((await fileResult.blob.text()) === 'file-bytes', 'Original download bytes mismatch'); globalThis.fetch = (async (): Promise => { return new Response('# markdown', { status: 200 }); }) as typeof fetch; const markdownResult = await downloadDocumentContentMarkdown('doc-3'); assert(markdownResult.filename === 'document-content.md', `Unexpected markdown filename ${markdownResult.filename}`); assert((await markdownResult.blob.text()) === '# markdown', 'Markdown bytes mismatch'); globalThis.fetch = (async (): Promise => { return new Response('forbidden', { status: 401 }); }) as typeof fetch; await assertRejects(async () => downloadDocumentContentMarkdown('doc-4'), 'Failed to download document markdown'); } finally { setRuntimeApiToken(null); globalThis.fetch = originalFetch; } } await runApiTests();