Files
EpicNext-Cms/src/lib/services/furniture-source-assets.test.ts
T
Simo 159b1f7d1b
CI / check (push) Failing after 19s
CI / deploy (push) Skipped
CI / e2e (push) Skipped
fix(catalog): check source assets and offer reachable import alternatives
2026-09-05 14:56:04 +02:00

100 lines
2.8 KiB
TypeScript

// @vitest-environment node
import { afterEach, describe, expect, it, vi } from "vitest";
import {
relatedFurniture,
type SourceAssetItem,
} from "@/lib/furni/source-assets";
import { inspectSourceAssets, probeAsset } from "./furniture-source-assets";
const source: SourceAssetItem = {
id: 1,
classname: "h25_monkeybzn_pole",
name: "Jungle flags",
description: "Flags",
type: "flooritem",
revision: 73253,
category: "other",
};
const alternative = {
...source,
id: 2,
classname: "br_c25_monkeybzn_pole",
revision: 73257,
};
afterEach(() => vi.unstubAllGlobals());
describe("source asset preflight", () => {
it("suggests reachable alternatives for unavailable source files", async () => {
const fetchMock = vi.fn(
async (url: string) =>
new Response(null, { status: url.includes("/73257/") ? 200 : 404 }),
);
vi.stubGlobal("fetch", fetchMock);
const result = await inspectSourceAssets(source, [source, alternative]);
expect(result.state).toBe("missing");
expect(result.alternatives).toEqual([alternative]);
});
it("does not describe blocked or unreachable servers as missing files", async () => {
vi.stubGlobal(
"fetch",
vi.fn(async () => new Response(null, { status: 403 })),
);
const result = await inspectSourceAssets(
{ ...source, classname: "blocked_test" },
[alternative],
);
expect(result.state).toBe("unknown");
expect(result.alternatives).toEqual([]);
});
it("accepts an available configured Nitro source", async () => {
vi.stubGlobal(
"fetch",
vi.fn(
async (url: string) =>
new Response(null, { status: url.endsWith(".nitro") ? 200 : 404 }),
),
);
const result = await inspectSourceAssets(
{ ...source, classname: "custom_test" },
[],
{
id: "custom",
name: "Custom",
hotel: "",
furnidataUrl: "https://source.example/data.json",
nitroBaseUrl: "https://source.example/furniture",
iconBaseUrl: "",
},
);
expect(result.state).toBe("available");
});
it("bounds suggestions and excludes different furniture types", () => {
expect(
relatedFurniture(source, [source, { ...alternative, type: "wallitem" }]),
).toEqual([]);
expect(
relatedFurniture(
source,
Array.from({ length: 20 }, (_, id) => ({
...alternative,
id,
classname: `f${id}_monkeybzn_pole`,
})),
),
).toHaveLength(5);
});
it("handles unnamed source entries while finding related assets", () => {
expect(
relatedFurniture(source, [
{ ...alternative, name: null as unknown as string },
]),
).toHaveLength(1);
});
it("caches a probe to avoid repeating CDN requests", async () => {
const fetchMock = vi.fn(async () => new Response(null, { status: 200 }));
vi.stubGlobal("fetch", fetchMock);
await probeAsset("https://example.test/cache.nitro");
await probeAsset("https://example.test/cache.nitro");
expect(fetchMock).toHaveBeenCalledTimes(1);
});
});