import { describe, expect, test } from "bun:test";
import { conflictRef, decideRef, isMirroredRef, nextEventRunAt, stagingRef, EVENT_GAP_MS } from "./plan";
import type { PlanOptions, RefState } from "./plan";
import { keepOurs, oursResolutions } from "./resolve";
import { verifyMirrorHook } from "./hook-auth";
import { hmacSha256Hex } from "../crypto";
import { mergeRootTrees } from "../git/merge";
import { makeBlob, makeTree } from "../git/objects";
import type { RawObject } from "../git/objects";
const A = "a".repeat(40);
const B = "b".repeat(40);
const both: PlanOptions = { direction: "both", strategy: "merge", propagateDeletes: false };
function ref(partial: Partial<RefState>): RefState {
return { name: "refs/heads/main", local: A, remote: B, synced: null, relation: "diverged", ...partial };
}
describe("decideRef", () => {
test("fast-forwards flow in the allowed direction only", () => {
expect(decideRef(ref({ relation: "remote-ahead" }), both)).toEqual({ kind: "pull", force: false });
expect(decideRef(ref({ relation: "local-ahead" }), both)).toEqual({ kind: "push", force: false });
expect(decideRef(ref({ relation: "remote-ahead" }), { ...both, direction: "push" })).toEqual({ kind: "none" });
expect(decideRef(ref({ relation: "local-ahead" }), { ...both, direction: "pull" })).toEqual({ kind: "none" });
});
test("diverged branches merge when bidirectional", () => {
expect(decideRef(ref({}), both)).toEqual({ kind: "merge" });
});
test("one-way divergence overwrites only with the matching preference", () => {
const pull = { ...both, direction: "pull" as const };
expect(decideRef(ref({}), pull).kind).toBe("conflict");
expect(decideRef(ref({}), { ...pull, strategy: "prefer-remote" })).toEqual({ kind: "pull", force: true });
expect(decideRef(ref({}), { ...pull, strategy: "prefer-local" }).kind).toBe("conflict");
const push = { ...both, direction: "push" as const, strategy: "prefer-local" as const };
expect(decideRef(ref({}), push)).toEqual({ kind: "push", force: true });
});
test("unrelated histories never merge silently", () => {