Files
HiveGrid-Wireframes/hivegrid-cloud/scripts/verify-licenses.test.mjs
T

135 lines
3.9 KiB
JavaScript

import { describe, it, expect } from "vitest";
import {
ALLOWED_LICENSES,
BLOCKED_LICENSE_PATTERNS,
classifyLicense,
isReviewed,
parseLicenseField,
splitSpdxExpression,
} from "./verify-licenses.mjs";
describe("parseLicenseField", () => {
it("reads a plain string license", () => {
expect(parseLicenseField({ license: "MIT" })).toBe("MIT");
});
it("reads the legacy { type } object form", () => {
expect(parseLicenseField({ license: { type: "Apache-2.0", url: "x" } })).toBe(
"Apache-2.0",
);
});
it("collapses a multi-entry `licenses` array into an SPDX OR expression", () => {
expect(
parseLicenseField({
licenses: [{ type: "MIT" }, { type: "Apache-2.0" }],
}),
).toBe("(MIT OR Apache-2.0)");
});
it("returns null for an empty package", () => {
expect(parseLicenseField({})).toBeNull();
expect(parseLicenseField({ license: "" })).toBeNull();
});
});
describe("splitSpdxExpression", () => {
it("returns single-atom expressions untouched", () => {
expect(splitSpdxExpression("MIT")).toEqual(["MIT"]);
});
it("splits parenthesised OR expressions", () => {
expect(splitSpdxExpression("(MIT OR Apache-2.0)")).toEqual([
"MIT",
"Apache-2.0",
]);
});
it("is case-insensitive on the OR conjunction", () => {
expect(splitSpdxExpression("MIT or BSD-3-Clause")).toEqual([
"MIT",
"BSD-3-Clause",
]);
});
});
describe("classifyLicense — allowlist", () => {
it.each([...ALLOWED_LICENSES])("accepts %s", (lic) => {
expect(classifyLicense(lic)).toBe("allowed");
});
it("treats an OR expression with one allowed atom as allowed", () => {
expect(classifyLicense("(MIT OR FooLicense-1.0)")).toBe("allowed");
});
});
describe("classifyLicense — blocklist", () => {
it.each([
"GPL-2.0",
"GPL-3.0-or-later",
"AGPL-3.0",
"SSPL-1.0",
"MIT AND Commons-Clause",
"LGPL-2.1",
])("blocks %s", (lic) => {
expect(classifyLicense(lic)).toBe("blocked");
});
it("blocks an OR expression that contains a blocked atom", () => {
expect(classifyLicense("(MIT OR GPL-3.0)")).toBe("blocked");
});
it("uses the configured pattern list, not the hardcoded one", () => {
expect(
classifyLicense("MIT", {
allowed: new Set(),
blockedPatterns: [/^MIT$/],
}),
).toBe("blocked");
});
});
describe("classifyLicense — unknown", () => {
it("returns 'unknown' for a missing license", () => {
expect(classifyLicense(null)).toBe("unknown");
});
it("returns 'unknown' for a license string we have no opinion on", () => {
expect(classifyLicense("Some-Bespoke-License-1.0")).toBe("unknown");
});
it("does not treat a partial blocklist match as blocked", () => {
// "NotGPL" must not match /^GPL-/
expect(classifyLicense("NotGPL-Public-1.0")).toBe("unknown");
});
});
describe("baseline allowlist", () => {
it("recognises an entry by exact name@version key", () => {
const baseline = { "moment@2.29.4": "legacy MIT shim, reviewed" };
expect(isReviewed(baseline, "moment", "2.29.4")).toBe(true);
expect(isReviewed(baseline, "moment", "2.29.5")).toBe(false);
});
it("ignores unrelated metadata keys without throwing", () => {
const baseline = { __doc__: "header", "react@19.2.3": "ok" };
expect(isReviewed(baseline, "react", "19.2.3")).toBe(true);
expect(isReviewed(baseline, "anything-else", "1.0.0")).toBe(false);
});
it("treats an empty/missing baseline as no exceptions", () => {
expect(isReviewed({}, "react", "19.2.3")).toBe(false);
expect(isReviewed(null, "react", "19.2.3")).toBe(false);
});
});
describe("BLOCKED_LICENSE_PATTERNS export", () => {
it("contains the headline copyleft families", () => {
const blob = BLOCKED_LICENSE_PATTERNS.map(String).join("|");
expect(blob).toMatch(/GPL/);
expect(blob).toMatch(/AGPL/);
expect(blob).toMatch(/SSPL/);
expect(blob).toMatch(/Commons-Clause/);
});
});