Download src/lib/__tests__/apiAdapter.test.ts from Esketch/CarboAny: direct link, hf CLI and curl.
- Browser
- Download file 5.29 kB
-
https://huggingface.co/spaces/Esketch/CarboAny/resolve/main/src/lib/__tests__/apiAdapter.test.ts
- Command line
-
hf download hf://spaces/Esketch/CarboAny/src/lib/__tests__/apiAdapter.test.ts
-
curl -L -o apiAdapter.test.ts https://huggingface.co/spaces/Esketch/CarboAny/resolve/main/src/lib/__tests__/apiAdapter.test.ts
5.29 kB
| import { describe, it, expect, vi, beforeEach } from 'vitest'; | |
| import { supabase } from '../supabase'; | |
| vi.mock('../supabase', () => { | |
| return { | |
| supabase: { | |
| functions: { | |
| invoke: vi.fn(), | |
| }, | |
| }, | |
| }; | |
| }); | |
| // Mock global fetch | |
| const mockFetch = vi.fn(); | |
| global.fetch = mockFetch; | |
| // Import code under test after mock definition | |
| import { invokeEdgeFunction, setUseGoGateway, setGoGatewayUrl } from '../apiAdapter'; | |
| type SupabaseInvokeResult = Awaited<ReturnType<typeof supabase.functions.invoke>>; | |
| type FetchResult = Pick<Response, 'ok' | 'json' | 'text'>; | |
| describe('apiAdapter - Go Gateway Strangler Pattern', () => { | |
| beforeEach(() => { | |
| vi.clearAllMocks(); | |
| setUseGoGateway('verify-receipt', false); // Reset switch | |
| setGoGatewayUrl('http://localhost:8080'); // Reset gateway url | |
| }); | |
| it('routes to Supabase Deno Edge Function when USE_GO_GATEWAY is false', async () => { | |
| // 1. Mock Deno successful response | |
| vi.mocked(supabase.functions.invoke).mockResolvedValue({ | |
| data: { | |
| success: true, | |
| co2Reduction: 21, | |
| confidence: 0.95, | |
| }, | |
| error: null, | |
| } as SupabaseInvokeResult); | |
| // 2. Act | |
| const res = await invokeEdgeFunction<{ text: string }, { success: boolean; co2Reduction: number }>('verify-receipt', { | |
| text: 'receipt-data', | |
| }); | |
| // 3. Assertions | |
| expect(supabase.functions.invoke).toHaveBeenCalledWith('verify-receipt', { | |
| body: { text: 'receipt-data' }, | |
| }); | |
| expect(mockFetch).not.toHaveBeenCalled(); | |
| expect(res.success).toBe(true); | |
| expect(res.co2Reduction).toBe(21); | |
| }); | |
| it('routes to Go Gateway via fetch when USE_GO_GATEWAY is true', async () => { | |
| // 1. Enable Go Gateway routing switch | |
| setUseGoGateway('verify-receipt', true); | |
| setGoGatewayUrl('https://gateway.carboany.com'); | |
| // 2. Mock global fetch to return successful response | |
| mockFetch.mockResolvedValue({ | |
| ok: true, | |
| json: vi.fn().mockResolvedValue({ | |
| data: { | |
| status: 'accepted', | |
| co2Reduction: 33, | |
| confidence: 0.88, | |
| }, | |
| meta: { | |
| traceId: 'e8838d21-f222-4777-a999-2999cb222ccc', | |
| source: 'go-gateway', | |
| audit: { | |
| ledgerTxId: null, | |
| integrity: true, | |
| }, | |
| }, | |
| error: null, | |
| }), | |
| } as FetchResult); | |
| // 3. Act | |
| const res = await invokeEdgeFunction<{ text: string }, { status: string; co2Reduction: number }>('verify-receipt', { | |
| text: 'receipt-data', | |
| }); | |
| // 4. Assertions | |
| expect(supabase.functions.invoke).not.toHaveBeenCalled(); | |
| expect(mockFetch).toHaveBeenCalledWith('https://gateway.carboany.com/api/v1/verify-receipt', expect.objectContaining({ | |
| method: 'POST', | |
| body: JSON.stringify({ text: 'receipt-data' }), | |
| })); | |
| expect(res.status).toBe('accepted'); | |
| expect(res.co2Reduction).toBe(33); | |
| }); | |
| it('routes receipt verification to the OpenAPI submission verification path when submissionId is present', async () => { | |
| setUseGoGateway('verify-receipt', true); | |
| setGoGatewayUrl('https://gateway.carboany.com'); | |
| mockFetch.mockResolvedValue({ | |
| ok: true, | |
| json: vi.fn().mockResolvedValue({ | |
| data: { | |
| status: 'verified', | |
| co2Reduction: 11, | |
| }, | |
| meta: { | |
| traceId: 'e8838d21-f222-4777-a999-2999cb222ccc', | |
| source: 'go-gateway', | |
| audit: { | |
| ledgerTxId: null, | |
| integrity: true, | |
| }, | |
| }, | |
| error: null, | |
| }), | |
| } as FetchResult); | |
| const res = await invokeEdgeFunction<{ submissionId: string }, { status: string; co2Reduction: number }>('verify-receipt', { | |
| submissionId: '4d7f90b8-a52c-4a3f-84b2-986d8bbf1070', | |
| }); | |
| expect(mockFetch).toHaveBeenCalledWith( | |
| 'https://gateway.carboany.com/api/v1/submissions/4d7f90b8-a52c-4a3f-84b2-986d8bbf1070/verify', | |
| expect.objectContaining({ | |
| method: 'POST', | |
| body: JSON.stringify({ submissionId: '4d7f90b8-a52c-4a3f-84b2-986d8bbf1070' }), | |
| }) | |
| ); | |
| expect(res.status).toBe('verified'); | |
| expect(res.co2Reduction).toBe(11); | |
| }); | |
| it('throws structured exception when response data contract is broken', async () => { | |
| // Enable Go Gateway routing switch | |
| setUseGoGateway('verify-receipt', true); | |
| // Mock global fetch to return broken schema (missing "co2Reduction" which is required) | |
| mockFetch.mockResolvedValue({ | |
| ok: true, | |
| json: vi.fn().mockResolvedValue({ | |
| data: { | |
| status: 'accepted', | |
| // missing co2Reduction | |
| confidence: 0.99, | |
| }, | |
| meta: { | |
| traceId: 'e8838d21-f222-4777-a999-2999cb222ccc', | |
| source: 'go-gateway', | |
| audit: { | |
| ledgerTxId: null, | |
| integrity: true, | |
| }, | |
| }, | |
| error: null, | |
| }), | |
| } as FetchResult); | |
| // Act & Assert (expecting Contract Validation error) | |
| await expect( | |
| invokeEdgeFunction<{ text: string }, { success: boolean; co2Reduction: number }>('verify-receipt', { | |
| text: 'receipt-data', | |
| }) | |
| ).rejects.toThrow( | |
| '[apiAdapter] API κ³μ½ κ²μ¦ μ€ν¨: verify-receipt μλ΅μ νμ νλ(co2Reduction)κ° λλ½λμμ΅λλ€.' | |
| ); | |
| }); | |
| }); | |