package harness
import (
"encoding/json"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"testing"
"craftdesign.group/quarry/internal/api"
"craftdesign.group/quarry/internal/ops"
)
// A record opened on a branch that has already landed is not a dead
// end: its page says accepting lands it on the branch the base went
// onto, and accepting does — retargeting it on the way, on the record —
// instead of handing back zit's "retarget it with ..." command line.
func TestARecordOnALandedBaseStillAccepts(t *testing.T) {
store := buildStore(t, "base")
srv := ingestAndServeAuth(t, map[string]string{"alpha": store}, t.TempDir(),
func(repo, user, pass string, need ops.Auth) api.Decision { return api.Allowed })
call := func(method, path, body string) (int, map[string]any) {
t.Helper()
req, _ := http.NewRequest(method, srv.URL+path, strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth("dan", "pw")
resp, err := srv.Client().Do(req)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
var out map[string]any
json.Unmarshal(b, &out)
if out == nil {
out = map[string]any{"raw": string(b)}
}
return resp.StatusCode, out
}
write := func(name, body string) {
if err := os.WriteFile(filepath.Join(store, name), []byte(body), 0o644); err != nil {
t.Fatal(err)
}
}
write("a.txt", "a\n")
zrun(t, store, "add", "a.txt")
zrun(t, store, "commit", "-m", "rung one", "--branch", "one", "--user", "dan")
_, opened := call("POST", "/api/v1/r/alpha/landing", `{"branch":"one","target":"trunk","message":"one"}`)
base := opened["id"].(string)
if code, out := call("POST", "/api/v1/r/alpha/landing/"+base[:12]+"/accept", `{}`); code != 200 {
t.Fatalf("accepting the base: %d %v", code, out)
}
// The next rung is opened AFTER its base landed, on the base's branch.
zrun(t, store, "update", "one")
write("b.txt", "b\n")
zrun(t, store, "add", "b.txt")
zrun(t, store, "commit", "-m", "rung two", "--branch", "two", "--user", "dan")
_, top := call("POST", "/api/v1/r/alpha/landing", `{"branch":"two","target":"one","message":"two"}`)
id := top["id"].(string)
_, before := call("GET", "/api/v1/r/alpha/landing/"+id[:12], "")
if before["landsOn"] != "trunk" {
t.Fatalf("FAIL: the record does not say it will land on trunk: landsOn=%v", before["landsOn"])
}
code, out := call("POST", "/api/v1/r/alpha/landing/"+id[:12]+"/accept", `{}`)
if code != 200 {
t.Fatalf("FAIL: accepting a record on a landed base answered %d %v", code, out)
}
_, after := call("GET", "/api/v1/r/alpha/landing/"+id[:12], "")
l := after["landing"].(map[string]any)
if l["state"] != "accepted" || l["target"] != "trunk" {
t.Fatalf("FAIL: after accept the record is %v on %v", l["state"], l["target"])
}
t.Log("ok: a record on a landed base says it lands on trunk, and accepting lands it there")
}