▍ humdrum codex / ticktock v0.0.2
license AGPL-3.0
2.5 KB raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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")
	}
}