Add offline-first task-master TUI with tickets, board lists, and undo.
Charm-based CLI with JSON persistence, status/list filters, external editor editing, command-history undo/redo, and glamour markdown without AutoStyle OSC hangs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package command_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"task/internal/command"
|
||||
"task/internal/ticket"
|
||||
)
|
||||
|
||||
func TestHistoryUndoRedoCreateDelete(t *testing.T) {
|
||||
store := ticket.NewJSONStore(t.TempDir())
|
||||
h := command.NewHistory()
|
||||
|
||||
create := &command.CreateTicket{
|
||||
Store: store,
|
||||
Ticket: ticket.Ticket{
|
||||
Title: "A",
|
||||
ProjectID: "inbox",
|
||||
Status: ticket.StatusTodo,
|
||||
},
|
||||
}
|
||||
if err := h.Do(create); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
list, err := store.List("inbox")
|
||||
if err != nil || len(list) != 1 {
|
||||
t.Fatalf("after create: %v len=%d", err, len(list))
|
||||
}
|
||||
|
||||
if err := h.Undo(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
list, err = store.List("inbox")
|
||||
if err != nil || len(list) != 0 {
|
||||
t.Fatalf("after undo create: %v len=%d", err, len(list))
|
||||
}
|
||||
|
||||
if err := h.Redo(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
list, err = store.List("inbox")
|
||||
if err != nil || len(list) != 1 {
|
||||
t.Fatalf("after redo create: %v len=%d", err, len(list))
|
||||
}
|
||||
|
||||
del := &command.DeleteTicket{Store: store, Snapshot: list[0]}
|
||||
if err := h.Do(del); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
list, _ = store.List("inbox")
|
||||
if len(list) != 0 {
|
||||
t.Fatal("expected empty after delete")
|
||||
}
|
||||
if err := h.Undo(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
list, _ = store.List("inbox")
|
||||
if len(list) != 1 {
|
||||
t.Fatal("expected restored after undo delete")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistoryUpdateUndo(t *testing.T) {
|
||||
store := ticket.NewJSONStore(t.TempDir())
|
||||
created, err := store.Create(ticket.Ticket{
|
||||
Title: "A", ProjectID: "inbox", Status: ticket.StatusTodo,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
after := created
|
||||
after.Status = ticket.StatusDone
|
||||
after.Title = "B"
|
||||
|
||||
h := command.NewHistory()
|
||||
if err := h.Do(&command.UpdateTicket{Store: store, Before: created, After: after}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, _ := store.Get(created.ID)
|
||||
if got.Status != ticket.StatusDone || got.Title != "B" {
|
||||
t.Fatalf("got %+v", got)
|
||||
}
|
||||
if err := h.Undo(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, _ = store.Get(created.ID)
|
||||
if got.Status != ticket.StatusTodo || got.Title != "A" {
|
||||
t.Fatalf("undo got %+v", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user