Spaces:
Sleeping
Sleeping
Download frontend/src/api/__tests__/client.test.ts from orakzai-io/Rednote: direct link, hf CLI and curl.
- Browser
- Download file 4.62 kB
-
https://huggingface.co/spaces/orakzai-io/Rednote/resolve/main/frontend/src/api/__tests__/client.test.ts
- Command line
-
hf download hf://spaces/orakzai-io/Rednote/frontend/src/api/__tests__/client.test.ts
-
curl -L -o client.test.ts https://huggingface.co/spaces/orakzai-io/Rednote/resolve/main/frontend/src/api/__tests__/client.test.ts
4.62 kB
| import { describe, it, expect, vi, beforeEach } from 'vitest'; | |
| const mockFetch = vi.fn(); | |
| global.fetch = mockFetch; | |
| // Set VITE_API_URL for tests | |
| import.meta.env.VITE_API_URL = 'http://localhost:8000'; | |
| import { | |
| fetchDocuments, | |
| uploadDocument, | |
| deleteDocument, | |
| streamChat, | |
| } from '../client'; | |
| // Mock auth headers | |
| vi.mock('../../lib/auth', () => ({ | |
| getAuthHeaders: vi.fn(() => ({ Authorization: 'Bearer test-token' })), | |
| })); | |
| describe('API client', () => { | |
| beforeEach(() => { | |
| vi.clearAllMocks(); | |
| mockFetch.mockReset(); | |
| }); | |
| // ββ fetchDocuments ββ | |
| describe('fetchDocuments', () => { | |
| it('fetches documents list with auth header', async () => { | |
| const docs = [ | |
| { id: '1', user_id: 'u1', filename: 'doc1.pdf', status: 'ready', created_at: '2025-01-01' }, | |
| ]; | |
| mockFetch.mockResolvedValueOnce({ | |
| ok: true, | |
| json: async () => docs, | |
| }); | |
| const result = await fetchDocuments(); | |
| expect(result).toEqual(docs); | |
| expect(mockFetch).toHaveBeenCalledWith( | |
| 'http://localhost:8000/documents', | |
| expect.objectContaining({ | |
| headers: expect.objectContaining({ Authorization: 'Bearer test-token' }), | |
| }) | |
| ); | |
| }); | |
| it('throws on fetch failure', async () => { | |
| mockFetch.mockResolvedValueOnce({ ok: false, json: async () => ({ detail: 'Failed' }) }); | |
| await expect(fetchDocuments()).rejects.toThrow('Failed to fetch documents'); | |
| }); | |
| }); | |
| // ββ uploadDocument ββ | |
| describe('uploadDocument', () => { | |
| it('uploads a file as FormData', async () => { | |
| const file = new File(['test content'], 'test.txt', { type: 'text/plain' }); | |
| mockFetch.mockResolvedValueOnce({ | |
| ok: true, | |
| json: async () => ({ id: '1', filename: 'test.txt', status: 'ready' }), | |
| }); | |
| await uploadDocument(file); | |
| expect(mockFetch).toHaveBeenCalledWith( | |
| 'http://localhost:8000/documents/upload', | |
| expect.objectContaining({ | |
| method: 'POST', | |
| headers: expect.not.objectContaining({ 'Content-Type': 'application/json' }), | |
| }) | |
| ); | |
| }); | |
| it('throws on upload failure with detail', async () => { | |
| const file = new File(['bad'], 'bad.txt', { type: 'text/plain' }); | |
| mockFetch.mockResolvedValueOnce({ | |
| ok: false, | |
| json: async () => ({ detail: 'Unsupported file' }), | |
| }); | |
| await expect(uploadDocument(file)).rejects.toThrow('Unsupported file'); | |
| }); | |
| }); | |
| // ββ deleteDocument ββ | |
| describe('deleteDocument', () => { | |
| it('sends DELETE request', async () => { | |
| mockFetch.mockResolvedValueOnce({ ok: true }); | |
| await deleteDocument('doc-123'); | |
| expect(mockFetch).toHaveBeenCalledWith( | |
| 'http://localhost:8000/documents/doc-123', | |
| expect.objectContaining({ method: 'DELETE' }) | |
| ); | |
| }); | |
| it('throws on delete failure', async () => { | |
| mockFetch.mockResolvedValueOnce({ ok: false }); | |
| await expect(deleteDocument('doc-123')).rejects.toThrow('Failed to delete document'); | |
| }); | |
| }); | |
| // ββ streamChat ββ | |
| describe('streamChat', () => { | |
| function createMockStream(chunks: string[]): ReadableStream { | |
| const encoder = new TextEncoder(); | |
| return new ReadableStream({ | |
| async start(controller) { | |
| for (const chunk of chunks) { | |
| controller.enqueue(encoder.encode(chunk)); | |
| } | |
| controller.close(); | |
| }, | |
| }); | |
| } | |
| it('calls onChunk with streamed content', async () => { | |
| const mockBody = createMockStream(['Hello', ' world']); | |
| mockFetch.mockResolvedValueOnce({ | |
| ok: true, | |
| body: mockBody, | |
| }); | |
| const onChunk = vi.fn(); | |
| const onError = vi.fn(); | |
| await streamChat( | |
| { messages: [{ role: 'user', content: 'Hi' }], document_id: null }, | |
| { onChunk, onError }, | |
| ); | |
| expect(onChunk).toHaveBeenCalled(); | |
| expect(onError).not.toHaveBeenCalled(); | |
| }); | |
| it('calls onError when request fails', async () => { | |
| mockFetch.mockResolvedValueOnce({ | |
| ok: false, | |
| json: async () => ({ detail: 'Chat error' }), | |
| }); | |
| const onChunk = vi.fn(); | |
| const onError = vi.fn(); | |
| await streamChat( | |
| { messages: [{ role: 'user', content: 'Hi' }], document_id: null }, | |
| { onChunk, onError }, | |
| ); | |
| expect(onError).toHaveBeenCalledWith('Chat error'); | |
| }); | |
| }); | |
| }); |