import { describe, expect, test } from "vitest"; import { isPluginCompatibleWithHost } from "./version-check.js"; import type { PluginManifest } from "./manifest.js"; import type { PluginVersionConstraints } from "./version-check.js"; const hex64 = "0".repeat(64); const hex128 = "0".repeat(128); function manifest(overrides: PluginVersionConstraints = {}): PluginManifest & PluginVersionConstraints { return { schemaVersion: 1, id: "de.toolctrl.hello", version: "1.0.0", name: "Hello", entry: "plugin.wasm", wasmSha256: hex64, signature: hex128, signedBy: hex64, allowedHosts: [], capabilities: [], hooks: [{ name: "tenant.created", export: "onTenantCreated" }], ...overrides, }; } describe("isPluginCompatibleWithHost", () => { test("compatible when host equals minHostVersion exactly", () => { const result = isPluginCompatibleWithHost(manifest({ minHostVersion: "1.0.0" }), "1.0.0"); expect(result.compatible).toBe(true); }); test("host_below_min when host is a patch below minHostVersion", () => { const result = isPluginCompatibleWithHost(manifest({ minHostVersion: "1.0.1" }), "1.0.0"); expect(result.compatible).toBe(false); if (!result.compatible) { expect(result.reason).toBe("host_below_min"); expect(result.details).toContain("1.0.1"); } }); test("host_above_max when host is a patch above maxHostVersion", () => { const result = isPluginCompatibleWithHost(manifest({ maxHostVersion: "1.0.0" }), "1.0.1"); expect(result.compatible).toBe(false); if (!result.compatible) { expect(result.reason).toBe("host_above_max"); } }); test("invalid_host_version when hostVersion is malformed", () => { const result = isPluginCompatibleWithHost(manifest({ minHostVersion: "1.0.0" }), "not-a-version"); expect(result.compatible).toBe(false); if (!result.compatible) { expect(result.reason).toBe("invalid_host_version"); } }); test("invalid_plugin_range when minHostVersion is malformed", () => { const result = isPluginCompatibleWithHost(manifest({ minHostVersion: "v.bad" }), "1.0.0"); expect(result.compatible).toBe(false); if (!result.compatible) { expect(result.reason).toBe("invalid_plugin_range"); } }); test("invalid_plugin_range when maxHostVersion is malformed", () => { const result = isPluginCompatibleWithHost(manifest({ maxHostVersion: "garbage" }), "1.0.0"); expect(result.compatible).toBe(false); if (!result.compatible) { expect(result.reason).toBe("invalid_plugin_range"); } }); test("pre-release host satisfies stable minHostVersion via includePrerelease", () => { const result = isPluginCompatibleWithHost(manifest({ minHostVersion: "1.0.0" }), "1.0.0-rc.1"); // With includePrerelease, 1.0.0-rc.1 >= 1.0.0 evaluates as compatible // (in standard semver semantics 1.0.0-rc.1 < 1.0.0 by spec, but our // policy says RC hosts accept plugins authored against the GA). // We document this by requiring this case to be compatible. expect(result.compatible).toBe(true); }); test("returns compatible when neither min nor max declared (back-compat)", () => { const result = isPluginCompatibleWithHost(manifest(), "1.7.0"); expect(result.compatible).toBe(true); }); test("boundary: maxHostVersion inclusive — host equals max is compatible", () => { const result = isPluginCompatibleWithHost(manifest({ maxHostVersion: "2.0.0" }), "2.0.0"); expect(result.compatible).toBe(true); }); test("compatible when host sits inside [min, max]", () => { const result = isPluginCompatibleWithHost( manifest({ minHostVersion: "1.0.0", maxHostVersion: "2.0.0" }), "1.5.3", ); expect(result.compatible).toBe(true); }); test("host_above_max takes precedence over equal-max edge cases", () => { const result = isPluginCompatibleWithHost( manifest({ minHostVersion: "1.0.0", maxHostVersion: "1.0.0" }), "1.0.1", ); expect(result.compatible).toBe(false); if (!result.compatible) { expect(result.reason).toBe("host_above_max"); } }); });