b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
104 lines
3.3 KiB
TypeScript
104 lines
3.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
extractSbom,
|
|
presentSections,
|
|
sbomDownloadHref,
|
|
SECTION_ORDER,
|
|
} from "../../src/lib/api/registry";
|
|
|
|
describe("presentSections", () => {
|
|
it("returns nothing for a missing or non-object sections map", () => {
|
|
expect(presentSections(null)).toEqual([]);
|
|
expect(presentSections(undefined)).toEqual([]);
|
|
expect(presentSections({})).toEqual([]);
|
|
expect(presentSections({ sections: undefined })).toEqual([]);
|
|
expect(presentSections({ sections: "nope" })).toEqual([]);
|
|
});
|
|
|
|
it("keeps non-empty sections in SECTION_ORDER", () => {
|
|
const result = presentSections({
|
|
sections: {
|
|
// Deliberately out of display order to prove ordering is by SECTION_ORDER.
|
|
security: "Report issues to security@example.com",
|
|
description: "# Hello\n\nA plugin.",
|
|
installation: "Run `npm i`.",
|
|
},
|
|
});
|
|
expect(result.map((s) => s.key)).toEqual(["description", "installation", "security"]);
|
|
expect(result[0]!.markdown).toBe("# Hello\n\nA plugin.");
|
|
});
|
|
|
|
it("drops empty, whitespace-only, and non-string entries", () => {
|
|
const result = presentSections({
|
|
sections: {
|
|
description: "Real content",
|
|
installation: "",
|
|
faq: " \n\t ",
|
|
changelog: 42,
|
|
security: null,
|
|
},
|
|
});
|
|
expect(result.map((s) => s.key)).toEqual(["description"]);
|
|
});
|
|
|
|
it("ignores unrecognised section keys", () => {
|
|
const result = presentSections({
|
|
sections: { description: "ok", "x-custom": "should be ignored" },
|
|
});
|
|
expect(result.map((s) => s.key)).toEqual(["description"]);
|
|
});
|
|
|
|
it("covers every key in SECTION_ORDER when all are present", () => {
|
|
const sections = Object.fromEntries(SECTION_ORDER.map((k) => [k, `content for ${k}`]));
|
|
const result = presentSections({ sections });
|
|
expect(result.map((s) => s.key)).toEqual([...SECTION_ORDER]);
|
|
});
|
|
});
|
|
|
|
describe("extractSbom", () => {
|
|
it("returns null for non-object or fully-empty input", () => {
|
|
expect(extractSbom(undefined)).toBeNull();
|
|
expect(extractSbom(null)).toBeNull();
|
|
expect(extractSbom("nope")).toBeNull();
|
|
expect(extractSbom({})).toBeNull();
|
|
expect(extractSbom({ format: "", url: "" })).toBeNull();
|
|
expect(extractSbom({ checksum: "bafy..." })).toBeNull();
|
|
});
|
|
|
|
it("keeps a url with no format", () => {
|
|
expect(extractSbom({ url: "https://x/sbom.json" })).toEqual({ url: "https://x/sbom.json" });
|
|
});
|
|
|
|
it("extracts format, url, and checksum", () => {
|
|
expect(
|
|
extractSbom({
|
|
format: "cyclonedx",
|
|
url: "https://x/sbom.json",
|
|
checksum: "bafy...",
|
|
}),
|
|
).toEqual({ format: "cyclonedx", url: "https://x/sbom.json", checksum: "bafy..." });
|
|
});
|
|
|
|
it("keeps a format with no url", () => {
|
|
expect(extractSbom({ format: "spdx" })).toEqual({ format: "spdx" });
|
|
});
|
|
});
|
|
|
|
describe("sbomDownloadHref", () => {
|
|
it("accepts http(s) URLs", () => {
|
|
expect(sbomDownloadHref("https://x/sbom.json")).toBe("https://x/sbom.json");
|
|
expect(sbomDownloadHref("http://x/sbom.json")).toBe("http://x/sbom.json");
|
|
});
|
|
|
|
it("rejects non-http(s) schemes and garbage", () => {
|
|
expect(sbomDownloadHref("javascript:alert(1)")).toBeNull();
|
|
expect(sbomDownloadHref("data:text/html,<script>")).toBeNull();
|
|
expect(sbomDownloadHref("/relative/path")).toBeNull();
|
|
expect(sbomDownloadHref("not a url")).toBeNull();
|
|
expect(sbomDownloadHref("")).toBeNull();
|
|
expect(sbomDownloadHref(undefined)).toBeNull();
|
|
expect(sbomDownloadHref(123)).toBeNull();
|
|
});
|
|
});
|