Spaces:
Running
Running
File size: 4,301 Bytes
6c3af4e 4b4ae63 6c3af4e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | import type { ServerConfig } from "@shared/serverConfig";
import { beforeEach, describe, expect, it, vi } from "vitest";
const mockFetch = vi.fn();
vi.stubGlobal("fetch", mockFetch);
const serverConfig: ServerConfig = {
accessKeysEnabled: true,
accessKeyTimeoutHours: 24,
wllamaDefaultModelId: "some-model",
internalApiEnabled: true,
internalApiName: "Custom LLM",
defaultInferenceType: "internal",
searchToken: "a".repeat(64),
};
/** Imports a fresh copy of the module so its cache starts empty. */
async function importConfigModule() {
vi.resetModules();
return import("./config");
}
describe("Config Module", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("returns the config served by the endpoint", async () => {
const { getConfig } = await importConfigModule();
mockFetch.mockResolvedValue({
ok: true,
json: vi.fn().mockResolvedValue(serverConfig),
});
await expect(getConfig()).resolves.toEqual(serverConfig);
});
it("fetches only once across concurrent and repeated calls", async () => {
const { getConfig } = await importConfigModule();
mockFetch.mockResolvedValue({
ok: true,
json: vi.fn().mockResolvedValue(serverConfig),
});
await Promise.all([getConfig(), getConfig()]);
await getConfig();
expect(mockFetch).toHaveBeenCalledTimes(1);
});
// Resolving with defaults here would report `accessKeysEnabled: false` to the
// app shell, skipping the access key page whenever the endpoint hiccups.
it("rejects rather than reporting defaults when the endpoint fails", async () => {
const { getConfig } = await importConfigModule();
mockFetch.mockResolvedValue({ ok: false, status: 500 });
await expect(getConfig()).rejects.toThrow("500");
});
it("rejects when the request cannot be made at all", async () => {
const { getConfig } = await importConfigModule();
mockFetch.mockRejectedValue(new Error("Network error"));
await expect(getConfig()).rejects.toThrow("Network error");
});
// The search token is per-process, so a restart leaves this page holding one
// the server never issued; invalidating is how a loaded page gets the new one.
it("refetches after the cache is invalidated", async () => {
const { getConfig, invalidateConfig } = await importConfigModule();
mockFetch.mockResolvedValue({
ok: true,
json: vi.fn().mockResolvedValue(serverConfig),
});
await getConfig();
const rotatedConfig = { ...serverConfig, searchToken: "b".repeat(64) };
mockFetch.mockResolvedValue({
ok: true,
json: vi.fn().mockResolvedValue(rotatedConfig),
});
invalidateConfig();
await expect(getConfig()).resolves.toEqual(rotatedConfig);
expect(mockFetch).toHaveBeenCalledTimes(2);
});
// Otherwise the discarded response lands in the cache a moment after the
// invalidation, and the page goes back to hashing the token it just dropped.
it("does not let a fetch started before the invalidation repopulate the cache", async () => {
const { getConfig, invalidateConfig } = await importConfigModule();
let resolveFirstFetch: (config: ServerConfig) => void = () => {};
mockFetch.mockReturnValueOnce(
new Promise((resolve) => {
resolveFirstFetch = (config) =>
resolve({ ok: true, json: vi.fn().mockResolvedValue(config) });
}),
);
const firstCall = getConfig();
invalidateConfig();
resolveFirstFetch(serverConfig);
await expect(firstCall).resolves.toEqual(serverConfig);
const rotatedConfig = { ...serverConfig, searchToken: "b".repeat(64) };
mockFetch.mockResolvedValue({
ok: true,
json: vi.fn().mockResolvedValue(rotatedConfig),
});
await expect(getConfig()).resolves.toEqual(rotatedConfig);
expect(mockFetch).toHaveBeenCalledTimes(2);
});
it("retries after a failure instead of caching it", async () => {
const { getConfig } = await importConfigModule();
mockFetch.mockRejectedValueOnce(new Error("Network error"));
await expect(getConfig()).rejects.toThrow("Network error");
mockFetch.mockResolvedValue({
ok: true,
json: vi.fn().mockResolvedValue(serverConfig),
});
await expect(getConfig()).resolves.toEqual(serverConfig);
});
});
|