Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

61 lines · 2.9 KBRaw History
1import { describe, expect, it } from "vitest";
2import { compareVersions, credentialInput, dedupe, matches, nextLink, repoNameFrom, repoRef, type RepoJson } from "../src/util";
3
4
5const S = "https://diffinery.com";
6const repo = (full: string, description: string | null = null): RepoJson => ({
7 full_name: full,
8 name: full.split("/")[1]!,
9 owner: { login: full.split("/")[0]! },
10 description,
11 private: true,
12 clone_url: `${S}/${full}.git`,
13 html_url: `${S}/${full}`,
14});
15
16describe("repositories", () => {
17 it("reads owner/repo from names and URLs on this server only", () => {
18 expect(repoRef(S, "codician/diffinery")).toEqual({ owner: "codician", repo: "diffinery" });
19 expect(repoRef(S, "https://diffinery.com/codician/diffinery.git")).toEqual({ owner: "codician", repo: "diffinery" });
20 expect(repoRef(S, "https://diffinery.com/codician/diffinery/tree/main/src")).toEqual({ owner: "codician", repo: "diffinery" });
21 expect(repoRef(S, "https://github.com/codician/diffinery")).toBeNull();
22 expect(repoRef(S, "diffinery")).toBeNull();
23 expect(repoRef(S, "a/b/c")).toBeNull();
24 expect(repoRef(S, "a b/c")).toBeNull();
25 expect(repoRef("http://localhost:8787", "http://localhost:8787/ada/x.git")).toEqual({ owner: "ada", repo: "x" });
26 });
27
28 it("matches every word, merges without duplicates", () => {
29 const a = repo("codician/diffinery", "A git forge for agents");
30 const b = repo("acme/website", "Marketing site");
31 expect(matches(a, "forge DIFF")).toBe(true);
32 expect(matches(b, "forge")).toBe(false);
33 expect(dedupe([a], [b, repo("Codician/Diffinery")]).map((r) => r.full_name)).toEqual(["codician/diffinery", "acme/website"]);
34 });
35
36 it("follows Link headers", () => {
37 expect(nextLink('<https://diffinery.com/api/v3/user/repos?page=2>; rel="next", <https://diffinery.com/api/v3/user/repos?page=5>; rel="last"')).toBe("https://diffinery.com/api/v3/user/repos?page=2");
38 expect(nextLink('<https://x/?page=1>; rel="prev"')).toBeNull();
39 expect(nextLink(null)).toBeNull();
40 });
41
42 it("names a repository after a folder", () => {
43 expect(repoNameFrom("My Project (old)")).toBe("My-Project-old");
44 expect(repoNameFrom("...")).toBe("repository");
45 });
46});
47
48describe("updates and Git", () => {
49 it("compares versions", () => {
50 expect(compareVersions("0.2.0", "0.1.9")).toBe(1);
51 expect(compareVersions("0.1.0", "0.1.0")).toBe(0);
52 expect(compareVersions("0.1.0", "0.1.10")).toBe(-1);
53 expect(compareVersions("1.0.0-beta", "1.0.0")).toBe(-1);
54 });
55
56 it("writes what git credential approve reads", () => {
57 expect(credentialInput(S, "ada", "dfy_x", 1_800_000_000_500)).toBe("protocol=https\nhost=diffinery.com\nusername=ada\npassword=dfy_x\npassword_expiry_utc=1800000000\n\n");
58 expect(credentialInput("http://localhost:8787", "ada", "t")).toBe("protocol=http\nhost=localhost:8787\nusername=ada\npassword=t\n\n");
59 expect(() => credentialInput(S, "ada\nhost=evil", "t")).toThrow();
60 });
61});