package web
import (
"net/http/httptest"
"path/filepath"
"strings"
"testing"
"craftdesign.group/quarry/internal/api"
"craftdesign.group/quarry/internal/index"
"craftdesign.group/quarry/internal/oltp"
"craftdesign.group/quarry/internal/ops"
)
type oneExternal struct{ subject string }
func (oneExternal) CheckReporterToken(string, string) bool { return true }
func (oneExternal) UpsertExternalCheck(string, oltp.ExternalCheck) error { return nil }
func (oneExternal) MintReporterToken(string, string) (string, error) { return "", nil }
func (oneExternal) ReporterTokens(string) ([]oltp.ReporterToken, error) { return nil, nil }
func (oneExternal) RevokeReporterToken(string, string) error { return nil }
func (o oneExternal) ExternalChecks(_, subject string) ([]oltp.ExternalCheck, error) {
if subject != o.subject {
return nil, nil
}
return []oltp.ExternalCheck{{Subject: subject, Context: "external/g65-probe", State: "success",
URL: "https://ci.example/1", Updated: "2026-01-01T01:00:00"}}, nil
}
// The check-in page draws every check on the check-in, external ones
// included, so a check reported on a commit with no open landing has
// a page (ab50b6dd, G-65). Asserted on the hook and the row's data,
// never on display text.
func TestTheCheckinPageDrawsItsExternalChecks(t *testing.T) {
const hash = "eb83336845e0eb83336845e0eb83336845e0eb83"
ix, err := index.Open(filepath.Join(t.TempDir(), "index.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { ix.Close() })
if err := ix.FoldCheckins([]index.CheckinRecord{{Hash: hash, Date: "2026-01-01T00:00:00", User: "jan", Comment: "g65 probe"}}); err != nil {
t.Fatal(err)
}
r := ops.NewRegistry()
if err := api.RegisterAll(r, api.Deps{Version: "v", Repos: api.NewRepos(map[string]*api.Repo{"test": {Index: ix}}),
External: oneExternal{subject: hash}}); err != nil {
t.Fatal(err)
}
rec := httptest.NewRecorder()
Handler(r, nil, nil).ServeHTTP(rec, httptest.NewRequest("GET", "/r/test/checkin/"+hash, nil))
if rec.Code != 200 {
t.Fatalf("status %d", rec.Code)
}
body := rec.Body.String()
if !strings.Contains(body, `data-hook="checkin-checks"`) {
t.Fatal("FAIL: the check-in page has no checks block")
}
if !strings.Contains(body, "https://ci.example/1") || !strings.Contains(body, "external/g65-probe") {
t.Fatal("FAIL: the external check's URL and context are not on the page")
}
t.Log("ok: the check-in page carries the external check with its link")
}
// refusedExternal holds a pipeline quarry refused to run, as the
// trigger records it: an error check with the reason and no link.
type refusedExternal struct{ oneExternal }
func (r refusedExternal) ExternalChecks(_, subject string) ([]oltp.ExternalCheck, error) {
if subject != r.subject {
return nil, nil
}
return []oltp.ExternalCheck{{Subject: subject, Context: "ci/pr.yml", State: "error",
Summary: `not run: ci/pr.yml: on: quarry emits no "pull_request" event`, Updated: "2026-01-01T01:00:00"}}, nil
}
// A REFUSED PIPELINE'S ROW SAYS WHY, NOT THAT A WORKER IS BUSY.
//
// jva (#1601): the check's summary reached no surface, and a row with
// no link and no run fell back to "the worker is full; it runs when a
// slot frees", about a workflow that will never run.
func TestARefusedPipelineSaysWhyOnTheCheckinPage(t *testing.T) {
const hash = "eb83336845e0eb83336845e0eb83336845e0eb83"
ix, err := index.Open(filepath.Join(t.TempDir(), "index.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { ix.Close() })
if err := ix.FoldCheckins([]index.CheckinRecord{{Hash: hash, Date: "2026-01-01T00:00:00", User: "jan", Comment: "pr probe"}}); err != nil {
t.Fatal(err)
}
r := ops.NewRegistry()
if err := api.RegisterAll(r, api.Deps{Version: "v", Repos: api.NewRepos(map[string]*api.Repo{"test": {Index: ix}}),
External: refusedExternal{oneExternal{subject: hash}}}); err != nil {
t.Fatal(err)
}
rec := httptest.NewRecorder()
Handler(r, nil, nil).ServeHTTP(rec, httptest.NewRequest("GET", "/r/test/checkin/"+hash, nil))
body := rec.Body.String()
if !strings.Contains(body, `data-hook="check-summary"`) || !strings.Contains(body, "quarry emits no "pull_request" event") {
t.Fatal("FAIL: the refused pipeline's row does not carry its reason")
}
if strings.Contains(body, "the worker is full") {
t.Fatal("FAIL: a refused pipeline reads as waiting for a worker")
}
t.Log("ok: the refusal's reason is on the row, and nothing claims a worker is busy")
}