Skip to content
quarry Artifact [52ce63eee2]
Login

Artifact [52ce63eee2]

Artifact 52ce63eee207ef513b02f1d0db6f40705be7fb46774d0b3b7401b0831d7ce67f:


package index

import (
	"strings"
	"testing"

	"craftdesign.group/quarry/internal/artifact"
)

// There is no verb that reports a tracker's schema: `zit ticket` takes
// field=value pairs and asks no questions. What the tickets CARRY is
// the schema as far as anything outside the store can know, and it has
// the right failure mode — a field nobody ever set is a field no form
// needs to offer.
func TestTheFieldNamesAreWhatTheTicketsCarry(t *testing.T) {
	ix := openIndex(t)
	tkt := func(n byte, fields ...artifact.Field) Parsed {
		id := strings.Repeat(string([]byte{'a', n}), 20)
		return Parsed{Hash: strings.Repeat(string([]byte{'c', n}), 20),
			Art: &artifact.Artifact{Type: artifact.Ticket, TicketID: id,
				Date: "2026-08-15T10:00:00", User: "dan", Fields: fields}}
	}
	if err := ix.FoldNow([]Parsed{
		tkt('1', artifact.Field{Name: "title", Value: "one"},
			artifact.Field{Name: "status", Value: "Open"},
			artifact.Field{Name: "assignee", Value: "dan"}),
		tkt('2', artifact.Field{Name: "title", Value: "two"},
			artifact.Field{Name: "status", Value: "Open"},
			artifact.Field{Name: "assignee", Value: "lou"}),
		tkt('3', artifact.Field{Name: "title", Value: "three"},
			artifact.Field{Name: "status", Value: "Open"},
			artifact.Field{Name: "assigne", Value: "typo"}),
	}); err != nil {
		t.Fatal(err)
	}
	uses, err := ix.TicketFieldNames()
	if err != nil {
		t.Fatal(err)
	}
	count := map[string]int{}
	for _, u := range uses {
		count[u.Name] = u.Tickets
	}
	if count["assignee"] != 2 {
		t.Errorf("FAIL: assignee on %d tickets, want 2 (%+v)", count["assignee"], uses)
	}
	// Counted so a caller can tell a column from a typo: one ticket with
	// "assigne" is not a field the tracker defines.
	if count["assigne"] != 1 {
		t.Errorf("FAIL: the typo field counted %d, want 1", count["assigne"])
	}
	// Most-used first, so a form offers the real columns before the
	// accidents.
	if len(uses) == 0 || uses[0].Tickets < uses[len(uses)-1].Tickets {
		t.Errorf("FAIL: not ordered most-used first: %+v", uses)
	}
}

// A field set to nothing is not a field the tracker uses. Counting
// cleared values would keep a column alive forever after the last
// ticket dropped it.
func TestAClearedFieldIsNotCounted(t *testing.T) {
	ix := openIndex(t)
	id := strings.Repeat("b1", 20)
	if err := ix.FoldNow([]Parsed{{Hash: strings.Repeat("c1", 20),
		Art: &artifact.Artifact{Type: artifact.Ticket, TicketID: id,
			Date: "2026-08-15T10:00:00", User: "dan", Fields: []artifact.Field{
				{Name: "title", Value: "t"}, {Name: "status", Value: "Open"},
				{Name: "assignee", Value: ""}}}}}); err != nil {
		t.Fatal(err)
	}
	uses, err := ix.TicketFieldNames()
	if err != nil {
		t.Fatal(err)
	}
	for _, u := range uses {
		if u.Name == "assignee" {
			t.Errorf("FAIL: a cleared field is counted as used: %+v", u)
		}
	}
}