mirror of
https://github.com/tale/headplane.git
synced 2026-07-26 07:48:14 +00:00
0512565f8e
Apparently I didn't use my brain cells and rely on the /version endpoint that Headscale has exposed since 0.26 (our lowest supported version). Switching to that significantly simplifies the API surface.
111 lines
3.6 KiB
TypeScript
111 lines
3.6 KiB
TypeScript
import { describe, expect, test } from "vitest";
|
|
|
|
import { capabilitiesFor } from "~/server/headscale/api/capabilities";
|
|
import {
|
|
formatServerVersion,
|
|
gte,
|
|
parseServerVersion,
|
|
} from "~/server/headscale/api/server-version";
|
|
|
|
describe("parseServerVersion", () => {
|
|
test("parses release versions with and without a leading v", () => {
|
|
expect(parseServerVersion("0.28.0")).toMatchObject({
|
|
major: 0,
|
|
minor: 28,
|
|
patch: 0,
|
|
prerelease: undefined,
|
|
unknown: false,
|
|
});
|
|
expect(parseServerVersion("v0.27.1")).toMatchObject({
|
|
major: 0,
|
|
minor: 27,
|
|
patch: 1,
|
|
unknown: false,
|
|
});
|
|
});
|
|
|
|
test("captures prerelease and build metadata", () => {
|
|
const v = parseServerVersion("v0.28.0-beta.1+abcdef");
|
|
expect(v.major).toBe(0);
|
|
expect(v.minor).toBe(28);
|
|
expect(v.patch).toBe(0);
|
|
expect(v.prerelease).toBe("beta.1");
|
|
expect(v.build).toBe("abcdef");
|
|
expect(v.unknown).toBe(false);
|
|
});
|
|
|
|
test("flags unparseable versions (e.g. dev builds)", () => {
|
|
const v = parseServerVersion("dev");
|
|
expect(v.unknown).toBe(true);
|
|
expect(v.raw).toBe("dev");
|
|
});
|
|
});
|
|
|
|
describe("gte", () => {
|
|
test("compares plain versions correctly", () => {
|
|
const v = parseServerVersion("0.28.0");
|
|
expect(gte(v, "0.27.0")).toBe(true);
|
|
expect(gte(v, "0.28.0")).toBe(true);
|
|
expect(gte(v, "0.29.0")).toBe(false);
|
|
});
|
|
|
|
test("ignores prerelease tags so betas get modern capabilities", () => {
|
|
// 0.28.0-beta.1 ships every wire format change that 0.28.0 does, so
|
|
// strict semver (where 0.28.0-beta.1 < 0.28.0) would lock beta users
|
|
// out of features their server actually supports.
|
|
const beta = parseServerVersion("0.28.0-beta.1");
|
|
expect(gte(beta, "0.28.0")).toBe(true);
|
|
expect(gte(beta, "0.27.0")).toBe(true);
|
|
});
|
|
|
|
test("unknown versions are treated as the newest known release", () => {
|
|
const dev = parseServerVersion("dev");
|
|
expect(gte(dev, "9.9.9")).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("formatServerVersion", () => {
|
|
test("renders release and prerelease versions without a leading v", () => {
|
|
expect(formatServerVersion(parseServerVersion("v0.28.0"))).toBe("0.28.0");
|
|
expect(formatServerVersion(parseServerVersion("0.28.0-beta.1"))).toBe("0.28.0-beta.1");
|
|
});
|
|
|
|
test("falls back to the raw string for unknown versions", () => {
|
|
expect(formatServerVersion(parseServerVersion("dev"))).toBe("dev");
|
|
});
|
|
});
|
|
|
|
describe("capabilitiesFor", () => {
|
|
test("0.28.0 enables every modern flag", () => {
|
|
const caps = capabilitiesFor(parseServerVersion("0.28.0"));
|
|
expect(caps).toEqual({
|
|
preAuthKeysHaveStableIds: true,
|
|
nodeTagsAreFlat: true,
|
|
nodeOwnerIsImmutable: true,
|
|
policyErrorsUseModernFormat: true,
|
|
});
|
|
});
|
|
|
|
test("0.28.0-beta.1 matches 0.28.0 capabilities (prerelease gating)", () => {
|
|
expect(capabilitiesFor(parseServerVersion("0.28.0-beta.1"))).toEqual(
|
|
capabilitiesFor(parseServerVersion("0.28.0")),
|
|
);
|
|
});
|
|
|
|
test("0.27.1 only has the policy-error format flag", () => {
|
|
const caps = capabilitiesFor(parseServerVersion("0.27.1"));
|
|
expect(caps.preAuthKeysHaveStableIds).toBe(false);
|
|
expect(caps.nodeTagsAreFlat).toBe(false);
|
|
expect(caps.nodeOwnerIsImmutable).toBe(false);
|
|
expect(caps.policyErrorsUseModernFormat).toBe(true);
|
|
});
|
|
|
|
test("0.26.1 has none of the modern capabilities", () => {
|
|
const caps = capabilitiesFor(parseServerVersion("0.26.1"));
|
|
expect(caps.preAuthKeysHaveStableIds).toBe(false);
|
|
expect(caps.nodeTagsAreFlat).toBe(false);
|
|
expect(caps.nodeOwnerIsImmutable).toBe(false);
|
|
expect(caps.policyErrorsUseModernFormat).toBe(false);
|
|
});
|
|
});
|