3 changed files with 118 additions and 4 deletions
@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' |
||||
import nostrArchivesApi, { isArchivesApiCircuitFailure } from '@/services/nostr-archives-api.service' |
||||
|
||||
vi.mock('@/services/local-storage.service', () => ({ |
||||
default: { |
||||
getUseNostrArchivesApi: () => true |
||||
} |
||||
})) |
||||
|
||||
const EVENT_ID = '3047103e518909910b1fc10ca1f4cb0122e6e28f497fa2ad1f41e6e7e7adf3cf' |
||||
|
||||
describe('isArchivesApiCircuitFailure', () => { |
||||
it('treats 404 as healthy API (missing data)', () => { |
||||
expect(isArchivesApiCircuitFailure('http', 404)).toBe(false) |
||||
}) |
||||
|
||||
it('treats 5xx and network/parse as service failures', () => { |
||||
expect(isArchivesApiCircuitFailure('http', 500)).toBe(true) |
||||
expect(isArchivesApiCircuitFailure('http', 503)).toBe(true) |
||||
expect(isArchivesApiCircuitFailure('network')).toBe(true) |
||||
expect(isArchivesApiCircuitFailure('parse')).toBe(true) |
||||
}) |
||||
|
||||
it('does not trip circuit on other 4xx', () => { |
||||
expect(isArchivesApiCircuitFailure('http', 400)).toBe(false) |
||||
expect(isArchivesApiCircuitFailure('http', 403)).toBe(false) |
||||
}) |
||||
}) |
||||
|
||||
describe('NostrArchivesApiService circuit breaker', () => { |
||||
beforeEach(() => { |
||||
nostrArchivesApi.resetForTests() |
||||
}) |
||||
|
||||
afterEach(() => { |
||||
vi.unstubAllGlobals() |
||||
nostrArchivesApi.resetForTests() |
||||
}) |
||||
|
||||
it('returns not_found for 404 without opening the circuit', async () => { |
||||
vi.stubGlobal( |
||||
'fetch', |
||||
vi.fn(async () => new Response('not found', { status: 404 })) |
||||
) |
||||
|
||||
const first = await nostrArchivesApi.getEventById(EVENT_ID) |
||||
const second = await nostrArchivesApi.getEventById(EVENT_ID) |
||||
|
||||
expect(first).toEqual({ ok: false, reason: 'not_found', status: 404 }) |
||||
expect(second).toEqual({ ok: false, reason: 'not_found', status: 404 }) |
||||
expect(nostrArchivesApi.isAvailable()).toBe(true) |
||||
}) |
||||
|
||||
it('opens circuit after repeated 5xx errors', async () => { |
||||
vi.stubGlobal( |
||||
'fetch', |
||||
vi.fn(async () => new Response('error', { status: 503 })) |
||||
) |
||||
|
||||
await nostrArchivesApi.getEventById(EVENT_ID) |
||||
await nostrArchivesApi.getEventById(EVENT_ID) |
||||
|
||||
expect(nostrArchivesApi.isAvailable()).toBe(false) |
||||
|
||||
const blocked = await nostrArchivesApi.getEventById(EVENT_ID) |
||||
expect(blocked).toEqual({ ok: false, reason: 'circuit_open' }) |
||||
}) |
||||
}) |
||||
Loading…
Reference in new issue