import { beforeEach, describe, expect, it, vi } from 'vitest' import { ArchivableCrudApi } from './ArchivableCrudApi' import type { ApiClient } from './ApiClient' // ── Test types ─────────────────────────────────────────────────────── type Item = { id: string; name: string; archivedAt: string | null } type CreateItem = { name: string } type UpdateItem = { name?: string; archivedAt?: string | null } // ── Mock client factory ────────────────────────────────────────────── function createMockClient(): ApiClient { return { setAccessToken: vi.fn().mockReturnThis(), request: vi.fn(), get: vi.fn(), post: vi.fn(), put: vi.fn(), patch: vi.fn(), delete: vi.fn(), } } // ── Tests ──────────────────────────────────────────────────────────── describe('ArchivableCrudApi', () => { let client: ReturnType let api: ArchivableCrudApi beforeEach(() => { client = createMockClient() api = new ArchivableCrudApi(client, '/items') }) it('inherits BaseCrudApi behavior (deleteById)', async () => { vi.mocked(client.delete).mockResolvedValue({ id: '1', name: 'x', archivedAt: null }) await api.deleteById('1') expect(client.delete).toHaveBeenCalledWith('/items/1', undefined) }) describe('archive', () => { it('PUTs basePath/id with an archivedAt timestamp', async () => { const archived: Item = { id: 'abc', name: 'x', archivedAt: '2026-01-01T00:00:00.000Z' } vi.mocked(client.put).mockResolvedValue(archived) const result = await api.archive('abc') const [path, body, headers] = vi.mocked(client.put).mock.calls.at(0) ?? [] expect(path).toBe('/items/abc') expect(typeof (body as { archivedAt?: unknown }).archivedAt).toBe('string') expect(headers).toBeUndefined() expect(result).toEqual(archived) }) it('forwards custom headers', async () => { vi.mocked(client.put).mockResolvedValue({ id: '1', name: 'x', archivedAt: null }) const headers = { 'X-Reason': 'cleanup' } await api.archive('1', headers) expect(vi.mocked(client.put).mock.calls.at(0)?.at(2)).toEqual(headers) }) }) describe('unarchive', () => { it('PUTs basePath/id with archivedAt null', async () => { const restored: Item = { id: 'abc', name: 'x', archivedAt: null } vi.mocked(client.put).mockResolvedValue(restored) const result = await api.unarchive('abc') expect(client.put).toHaveBeenCalledWith('/items/abc', { archivedAt: null }, undefined) expect(result).toEqual(restored) }) }) it('archive/unarchive stay bound when destructured', async () => { vi.mocked(client.put).mockResolvedValue({ id: '1', name: 'x', archivedAt: null }) const { archive, unarchive } = api await archive('1') await unarchive('1') expect(client.put).toHaveBeenCalledTimes(2) }) })