package grid import ( "strings" "testing" tea "github.com/charmbracelet/bubbletea" "ticktock/internal/store" ) func loggedFixture() *fakeStore { return &fakeStore{entries: []store.Entry{{ Key: "2026-07-07-01", Start: at(8, 0), End: at(8, 30), Project: "ARCHER", Description: "standup", Duration: 30 * 60 * 1e9, }}} } // place cursor on the labeled row for the fixture (08:00 with default window). func onLoggedRow(m Model) Model { row := m.grid.RowOf(8 * 60) m.cursor = row m.col = ColLogged return m } func TestEnterOnLoggedOpensEditThenSafeReplace(t *testing.T) { f := loggedFixture() m := onLoggedRow(loaded(f)) nm, _ := m.Update(special(tea.KeyEnter)) mm := nm.(Model) if !mm.editing || mm.adding || mm.form == nil { t.Fatalf("enter on logged should open edit (not add) form") } if mm.editKey != "2026-07-07-01" || mm.fv.Desc != "standup" { t.Errorf("edit form not prefilled from session: key=%q desc=%q", mm.editKey, mm.fv.Desc) } mm.fv.Desc = "standup (edited)" nm, _ = mm.Update(special(tea.KeyCtrlS)) if len(f.repl) != 1 || f.repl[0].Description != "standup (edited)" { t.Fatalf("SafeReplace not called with edit: %+v", f.repl) } } func TestEnterOnEmptyLoggedRowDoesNothing(t *testing.T) { f := loggedFixture() m := loaded(f) m.cursor = 0 // 07:00, empty m.col = ColLogged nm, _ := m.Update(special(tea.KeyEnter)) if nm.(Model).editing { t.Errorf("enter on empty logged row should not open a form") } } func TestDeleteConfirmThenRemove(t *testing.T) { f := loggedFixture() m := onLoggedRow(loaded(f)) nm, _ := m.Update(key("d")) mm := nm.(Model) if !mm.confirmDelete || mm.confirmKey != "2026-07-07-01" { t.Fatalf("d should arm delete confirm for the session") } nm, _ = mm.Update(key("y")) if len(f.removed) != 1 || f.removed[0] != "2026-07-07-01" { t.Fatalf("y should confirm remove: %v", f.removed) } } func TestConfirmLabelDescribesSession(t *testing.T) { f := loggedFixture() m := onLoggedRow(loaded(f)) nm, _ := m.Update(key("d")) label := nm.(Model).confirmLabel() if !strings.Contains(label, "standup") || !strings.Contains(label, "08:00") { t.Errorf("confirm label should name the session and range, got %q", label) } } func TestDeleteConfirmCancel(t *testing.T) { f := loggedFixture() m := onLoggedRow(loaded(f)) nm, _ := m.Update(key("d")) nm, _ = nm.(Model).Update(key("n")) if nm.(Model).confirmDelete { t.Errorf("n should cancel the delete confirm") } if len(f.removed) != 0 { t.Errorf("cancel should not remove") } }