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>
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user