Spaces:
Running
Running
Download server/statusEndpointServerHook.test.ts from Felladrin/MiniSearch: direct link, hf CLI and curl.
- Browser
- Download file 4.62 kB
-
https://huggingface.co/spaces/Felladrin/MiniSearch/resolve/main/server/statusEndpointServerHook.test.ts
- Command line
-
hf download hf://spaces/Felladrin/MiniSearch/server/statusEndpointServerHook.test.ts
-
curl -L -o statusEndpointServerHook.test.ts https://huggingface.co/spaces/Felladrin/MiniSearch/resolve/main/server/statusEndpointServerHook.test.ts
4.62 kB
| import type { IncomingMessage, ServerResponse } from "node:http"; | |
| import { describe, expect, it, vi } from "vitest"; | |
| import { getFallbackProviderStats } from "./fallbackSearchService.ts"; | |
| import { | |
| incrementSearchesFailedOnFallback, | |
| incrementSearchesServedByFallback, | |
| } from "./searchesSinceLastRestart.ts"; | |
| import { statusEndpointServerHook } from "./statusEndpointServerHook.ts"; | |
| // The health getters probe live services; this test is about the payload, | |
| // so they answer healthy without a network. | |
| vi.mock("./biEncoderService.ts", () => ({ | |
| getBiEncoderStatus: async () => true, | |
| })); | |
| vi.mock("./rerankerService.ts", () => ({ | |
| getRerankerStatus: async () => true, | |
| })); | |
| vi.mock("./webSearchService.ts", () => ({ | |
| getWebSearchServiceStatus: async () => "degraded", | |
| getSearchCircuitStats: () => ({ | |
| circuitState: "closed", | |
| circuitOpens: 0, | |
| }), | |
| })); | |
| type Handler = ( | |
| request: IncomingMessage, | |
| response: ServerResponse, | |
| next: () => void, | |
| ) => Promise<void>; | |
| type RecordedResponse = ServerResponse & { | |
| setHeader: ReturnType<typeof vi.fn>; | |
| end: ReturnType<typeof vi.fn>; | |
| }; | |
| function callStatus(): Promise<Record<string, unknown>> { | |
| const use = vi.fn(); | |
| // Vite sets VITE_BUILD_DATE_TIME for every serve (see vite.config.ts). | |
| statusEndpointServerHook({ | |
| middlewares: { use }, | |
| config: { define: { VITE_BUILD_DATE_TIME: new Date().toISOString() } }, | |
| } as unknown as Parameters<typeof statusEndpointServerHook>[0]); | |
| const response = { | |
| setHeader: vi.fn(), | |
| end: vi.fn(), | |
| } as unknown as RecordedResponse; | |
| const request = { | |
| url: "/status", | |
| headers: {}, | |
| } as unknown as IncomingMessage; | |
| return (use.mock.calls[0][0] as Handler)( | |
| request, | |
| response, | |
| () => undefined, | |
| ).then(() => JSON.parse(response.end.mock.calls[0][0])); | |
| } | |
| describe("statusEndpointServerHook", () => { | |
| it("publishes the web search verdict and the per-engine tally", async () => { | |
| const status = await callStatus(); | |
| // Passed through rather than recomputed: the hook used to derive this | |
| // field itself from a liveness probe, which reported an open circuit as | |
| // healthy. | |
| expect(status.webSearchServiceStatus).toBe("degraded"); | |
| expect(status.searches).toMatchObject({ | |
| degradedSearchTypes: [], | |
| unresponsiveEngines: {}, | |
| }); | |
| }); | |
| it("publishes the two fallback counters as plain counts", async () => { | |
| const before = await callStatus(); | |
| incrementSearchesServedByFallback(); | |
| incrementSearchesFailedOnFallback(); | |
| incrementSearchesFailedOnFallback(); | |
| const status = await callStatus(); | |
| // Exact values rather than expect.any(Number), which a pair of swapped | |
| // getters would satisfy too. The counters are module state that no test | |
| // here resets, so the deltas are what each getter moved. | |
| expect(status.searchesServedByFallback).toBe( | |
| (before.searchesServedByFallback as number) + 1, | |
| ); | |
| expect(status.searchesFailedOnFallback).toBe( | |
| (before.searchesFailedOnFallback as number) + 2, | |
| ); | |
| }); | |
| it("publishes the per-provider fallback counters under searches", async () => { | |
| const status = await callStatus(); | |
| expect(status.searches).toMatchObject({ | |
| fallbackProviders: getFallbackProviderStats(), | |
| }); | |
| expect( | |
| Object.keys( | |
| (status.searches as { fallbackProviders: object }).fallbackProviders, | |
| ), | |
| ).toEqual(["parallel", "youcom"]); | |
| }); | |
| it("publishes the page-read circuit count beside the outcome counters", async () => { | |
| const status = await callStatus(); | |
| // Counts and nothing else: the hosts the breaker boxes come from search | |
| // results, so naming one here would say something about a query. | |
| expect(status.pageReads).toMatchObject({ | |
| circuitOpens: expect.any(Number), | |
| skipped: { skippedByBreaker: expect.any(Number) }, | |
| }); | |
| }); | |
| it("keeps startedAt fixed at the restart while uptime advances", async () => { | |
| const first = await callStatus(); | |
| expect(typeof first.startedAt).toBe("string"); | |
| const startedAt = Date.parse(first.startedAt as string); | |
| expect(Number.isNaN(startedAt)).toBe(false); | |
| vi.useFakeTimers(); | |
| try { | |
| vi.setSystemTime(startedAt + 600_000); | |
| const later = await callStatus(); | |
| // The module captured its start once, on import: startedAt is the same | |
| // instant on every call while uptime advances. Replacing the capture | |
| // with a per-call Date.now() fails this. | |
| expect(later.startedAt).toBe(first.startedAt); | |
| expect(later.uptime).toBe("10 minutes"); | |
| } finally { | |
| vi.useRealTimers(); | |
| } | |
| }); | |
| }); | |