Files
task-master/internal/sqlite/ticketkeys_test.go
T
skrueckenandCursor efeb4a74a8 Assign readable ticket keys from project code and sequence.
Replace UUID-looking sync labels in TUI and web with keys like TAS-1,
while keeping the remote UUID for task-master matching.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-28 00:09:14 +01:00

125 lines
3.1 KiB
Go

package sqlite
import (
"path/filepath"
"testing"
"task/internal/ticket"
)
func TestTicketKeysSequential(t *testing.T) {
db, err := Open(filepath.Join(t.TempDir(), "keys.db"), []byte("test-secret"))
if err != nil {
t.Fatal(err)
}
defer db.Close()
ps := NewProjectStore(db)
p, err := ps.Create("", "Task Master")
if err != nil {
t.Fatal(err)
}
if p.Code != "TAS" {
t.Fatalf("code=%q want TAS", p.Code)
}
ts := NewTicketStore(db)
a, err := ts.Create(ticket.Ticket{Title: "One", ProjectID: p.ID})
if err != nil {
t.Fatal(err)
}
b, err := ts.Create(ticket.Ticket{Title: "Two", ProjectID: p.ID})
if err != nil {
t.Fatal(err)
}
if a.Key != "TAS-1" || a.Number != 1 {
t.Fatalf("first=%+v", a)
}
if b.Key != "TAS-2" || b.Number != 2 {
t.Fatalf("second=%+v", b)
}
got, err := ts.Get(a.ID)
if err != nil || got.Key != "TAS-1" {
t.Fatalf("get=%+v err=%v", got, err)
}
// Update must preserve key.
got.Title = "One*"
if err := ts.Update(got); err != nil {
t.Fatal(err)
}
got, _ = ts.Get(a.ID)
if got.Key != "TAS-1" || got.Title != "One*" {
t.Fatalf("after update=%+v", got)
}
}
func TestTicketKeyBackfill(t *testing.T) {
path := filepath.Join(t.TempDir(), "backfill.db")
db, err := Open(path, []byte("test-secret"))
if err != nil {
t.Fatal(err)
}
// Insert legacy-shaped rows as if pre-migration (columns exist after Open).
_, err = db.SQL.Exec(`INSERT INTO projects(id, name, code, ticket_seq, created_at, updated_at)
VALUES('p1', 'Inbox', '', 0, '2020-01-01T00:00:00Z', '2020-01-01T00:00:00Z')`)
if err != nil {
t.Fatal(err)
}
_, err = db.SQL.Exec(`INSERT INTO tickets(id, title, description, status, project_id, created_at, updated_at, source, external_id, external_url, synced_at, number, key)
VALUES('t1', 'Old', '', 'todo', 'p1', '2020-01-02T00:00:00Z', '2020-01-02T00:00:00Z', '', '', '', '', NULL, '')`)
if err != nil {
t.Fatal(err)
}
if err := db.backfillTicketKeys(); err != nil {
t.Fatal(err)
}
var code string
var seq int
if err := db.SQL.QueryRow(`SELECT code, ticket_seq FROM projects WHERE id='p1'`).Scan(&code, &seq); err != nil {
t.Fatal(err)
}
if code != "INB" || seq != 1 {
t.Fatalf("project code=%q seq=%d", code, seq)
}
var key string
var num int
if err := db.SQL.QueryRow(`SELECT key, number FROM tickets WHERE id='t1'`).Scan(&key, &num); err != nil {
t.Fatal(err)
}
if key != "INB-1" || num != 1 {
t.Fatalf("ticket key=%q num=%d", key, num)
}
_ = db.Close()
}
func TestMoveReassignsKey(t *testing.T) {
db, err := Open(filepath.Join(t.TempDir(), "move.db"), []byte("test-secret"))
if err != nil {
t.Fatal(err)
}
defer db.Close()
ps := NewProjectStore(db)
a, err := ps.Create("", "Alpha")
if err != nil {
t.Fatal(err)
}
b, err := ps.Create("", "Beta")
if err != nil {
t.Fatal(err)
}
ts := NewTicketStore(db)
tk, err := ts.Create(ticket.Ticket{Title: "Move me", ProjectID: a.ID})
if err != nil {
t.Fatal(err)
}
moved, err := ts.Move(tk.ID, b.ID)
if err != nil {
t.Fatal(err)
}
if moved.ProjectID != b.ID || moved.Key != b.Code+"-1" {
t.Fatalf("moved=%+v betaCode=%s", moved, b.Code)
}
}