package api
import (
"path/filepath"
"testing"
"craftdesign.group/quarry/internal/artifact"
"craftdesign.group/quarry/internal/index"
)
type checksStub struct {
required []string
}
func (c checksStub) RequiredChecks(string, string) []string { return c.required }
type runsStub struct{ runs []CIRun }
func (r runsStub) CIRuns(string, int) ([]CIRun, error) { return r.runs, nil }
func (r runsStub) CIRunsPage(string, int, int) ([]CIRun, error) { return r.runs, nil }
func (r runsStub) CIRunsFor(string, string) ([]CIRun, error) { return r.runs, nil }
func (r runsStub) CIRunsForPair(string, string) ([]CIRun, error) { return r.runs, nil }
// openLandingIndex holds one check-in on branch, and one open landing
// from it, so the branch has a tip a landing can be judged at.
func openLandingIndex(t *testing.T, branch, tip string) *index.Index {
t.Helper()
ix, err := index.Open(filepath.Join(t.TempDir(), "index.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { ix.Close() })
if err := ix.FoldNow([]index.Parsed{
{Hash: "t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0t0", Art: &artifact.Artifact{Type: artifact.Manifest, Date: "2026-01-01T08:00:00", User: "ada", Comment: "trunk",
Tags: []artifact.Tag{{Name: "*branch", Target: "*", Value: "trunk"}}}},
{Hash: tip, Art: &artifact.Artifact{Type: artifact.Manifest, Date: "2026-01-01T09:00:00", User: "ada", Comment: "work",
Tags: []artifact.Tag{{Name: "*branch", Target: "*", Value: branch}}}},
{Hash: landingHash, Art: &artifact.Artifact{Type: artifact.Forum, ThreadTitle: "land it", Date: "2026-01-01T10:00:00", User: "ada",
Body: []byte("zit-landing: 1\nbranch: " + branch + "\ntarget: trunk\n\nready\n")}},
}); err != nil {
t.Fatal(err)
}
return ix
}
// A required check is named the way a person names a pipeline: its file
// stem. ci/race.json, registered on a shared engine under a scoped
// workflow name, answers a required check named "race", which is the
// string trunk's rule lists beside "quarry".
func TestARaceRunAnswersTheRequiredCheckNamedRace(t *testing.T) {
run := CIRun{Workflow: "quarry.race.1f2e3d", Pipeline: "ci/race.json", Status: "completed"}
if !CheckNameMatches("race", run.Workflow, run.Pipeline) {
t.Fatal(`FAIL: a ci/race.json run does not answer a check named "race"`)
}
if got := withoutVerdict([]string{"quarry", "race"}, []CIRun{run}, nil); len(got) != 1 || got[0] != "quarry" {
t.Errorf(`FAIL: with a race run, the checks without a verdict are %v; want only "quarry"`, got)
}
t.Log(`ok: ci/race.json answers the required check "race"`)
}