import { describe, expect, it } from "vitest";
import {
atUriOf,
capabilityOf,
gitOidOf,
knotOf,
labelKeyOf,
proxyPathOf
} from "#lib/api/syntax.ts";
const rejects = (run: () => unknown, kind: string, value: string) =>
expect(run).toThrowError(new Error(`"${value}" is not a valid ${kind}.`));
describe("syntax atcute doesn't validate", () => {
it("accepts bare origins with ports and rejects every other spelling", () => {
expect(knotOf("knot.test")).toBe("knot.test");
expect(knotOf("knot.test:8443")).toBe("knot.test:8443");
rejects(() => knotOf("https://knot.test"), "knot origin", "https://knot.test");
rejects(() => knotOf("knot.test/repo"), "knot origin", "knot.test/repo");
});
it("accepts sha-1 and sha-256 hex git OIDs and rejects every other length", () => {
const oid = "0f1e2d3c9b8a7f6e5d4c3b2a1908877665544332";
const wide = "ab".repeat(32);
expect(gitOidOf(oid)).toBe(oid);
expect(gitOidOf(wide)).toBe(wide);
rejects(() => gitOidOf("0f1e"), "git OID", "0f1e");
rejects(() => gitOidOf(oid.toUpperCase()), "git OID", oid.toUpperCase());
});
it("rejects AT-URIs that aren't canonical record URIs", () => {
const uri = "at://did:plc:zaqarkey/org.tangled.track.ticket/3labc";
expect(atUriOf(uri)).toBe(uri);
expect(() => atUriOf("at://nel.test/org.tangled.track.ticket/3labc")).toThrow(
/invalid repo in canonical-at-uri/
);
expect(() => atUriOf(`${uri}#frag`)).toThrow(/invalid canonical-at-uri/);
expect(() => atUriOf("at://did:plc:zaqarkey/org.tangled.track.ticket")).toThrow(
/invalid rkey in canonical-at-uri/
);
});
it("accepts slug label keys and rejects DIDs and slugs with invalid chars", () => {
expect(labelKeyOf("good-first-issue")).toBe("good-first-issue");
expect(labelKeyOf("a.b_c~d-1")).toBe("a.b_c~d-1");
rejects(() => labelKeyOf("did:plc:zaqarkey"), "label key", "did:plc:zaqarkey");
rejects(() => labelKeyOf("has space"), "label key", "has space");
rejects(() => labelKeyOf(""), "label key", "");
});
it("accepts single-token caps and rejects spaced or empty ones", () => {
expect(capabilityOf("knot-social-writes")).toBe("knot-social-writes");
rejects(() => capabilityOf(""), "cap", "");
rejects(() => capabilityOf("two words"), "cap", "two words");
});
it("accepts underscore-prefixed proxy paths and rejects unprefixed NSIDs", () => {
expect(proxyPathOf("_delegation.listControlledAccounts")).toBe(
"_delegation.listControlledAccounts"
);
rejects(
() => proxyPathOf("org.tangled.repo.getRepo"),
"proxy path",
"org.tangled.repo.getRepo"
);
rejects(() => proxyPathOf("_has/slash"), "proxy path", "_has/slash");
});
});