package api
import (
"context"
"errors"
"path/filepath"
"testing"
"craftdesign.group/quarry/internal/artifact"
"craftdesign.group/quarry/internal/index"
"craftdesign.group/quarry/internal/oltp"
"craftdesign.group/quarry/internal/ops"
)
// TestTicketGetDigitsAreANumberNeverAPrefix: a short run of digits that
// names no ticket is not found, even when a ticket's hex id starts with
// those digits (#417). The same ticket is still reached by its number
// and by a prefix that is not all digits.
func TestTicketGetDigitsAreANumberNeverAPrefix(t *testing.T) {
ix, err := index.Open(filepath.Join(t.TempDir(), "i.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { ix.Close() })
id := "1234abcd00000000000000000000000000000000000000000000000000000001"
if err := ix.FoldNow([]index.Parsed{{Hash: id, Art: &artifact.Artifact{Type: artifact.Ticket, TicketID: id,
Date: "2026-09-01T10:00:00", User: "dan",
Fields: []artifact.Field{{Name: "title", Value: "only"}, {Name: "status", Value: "Open"}}}}}); err != nil {
t.Fatal(err)
}
db, err := oltp.Open(filepath.Join(t.TempDir(), "o.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { db.Close() })
r := ops.NewRegistry()
if err := RegisterAll(r, Deps{Version: "v", Repos: NewRepos(map[string]*Repo{"q": {Index: ix}}),
Local: db, Idem: db, Numbers: db, Mirrors: memMirrors{}}); err != nil {
t.Fatal(err)
}
ctx := ops.WithUser(context.Background(), "dan")
if _, err := r.Invoke(ctx, "ticket.get", ticketGetIn{Repo: "q", ID: "1234"}); !errors.Is(err, ops.ErrNotFound) {
t.Errorf("FAIL: digits naming no ticket: err = %v, want not found", err)
}
for _, ref := range []string{"1", "1234abcd", id} {
got, err := r.Invoke(ctx, "ticket.get", ticketGetIn{Repo: "q", ID: ref})
if err != nil {
t.Errorf("FAIL: ticket.get %q: %v", ref, err)
continue
}
if got.(ticketGetOut).Ticket.ID != id {
t.Errorf("FAIL: ticket.get %q opened %q", ref, got.(ticketGetOut).Ticket.ID)
}
}
t.Log("ok")
}
// TestRepoListDeletableIsForTheCaller: an anonymous caller is never
// told a repository can be deleted (#418); a signed-in one still is.
func TestRepoListDeletableIsForTheCaller(t *testing.T) {
ix := wikiIndex(t)
r := ops.NewRegistry()
if err := RegisterAll(r, Deps{Version: "v", Repos: NewRepos(map[string]*Repo{"alpha": {Index: ix}}),
Deletable: func(string) bool { return true }}); err != nil {
t.Fatal(err)
}
for _, c := range []struct {
ctx context.Context
want bool
}{{context.Background(), false}, {ops.WithUser(context.Background(), "dan"), true}} {
got, err := r.Invoke(c.ctx, "repo.list", repoListIn{})
if err != nil {
t.Fatal(err)
}
if d := got.(repoListOut).Repos[0].Deletable; d != c.want {
t.Errorf("FAIL: caller %q: deletable = %v, want %v", ops.User(c.ctx), d, c.want)
}
}
t.Log("ok")
}