package tui import ( "strings" "testing" tea "github.com/charmbracelet/bubbletea" "github.com/lukaszkasprzak/lectio/internal/bible" "github.com/lukaszkasprzak/lectio/internal/config" ) func enReader(t *testing.T) ReaderModel { t.Helper() tbl, err := bible.LoadBookTable(nil) if err != nil { t.Fatal(err) } cfg := config.Default() cfg.UILanguage = "en" cfg.SiglaStyle = "english" cfg.Versions = []string{"bt", "wuj", "vul", "grb", "drb"} return NewReader(cfg, tbl) } func key(m ReaderModel, k tea.KeyMsg) ReaderModel { nm, _ := m.Update(k) return nm.(ReaderModel) } func runes(s string) tea.KeyMsg { return tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune(s)} } func TestReaderInit(t *testing.T) { m := enReader(t) if m.mode != modePick { t.Errorf("mode = %v want modePick", m.mode) } if len(m.matches) != len(m.books) || len(m.books) != 73 { t.Errorf("matches=%d books=%d", len(m.matches), len(m.books)) } if len(m.versions) == 0 || m.versions[0] == "bt" { t.Errorf("versions = %v (bt must be excluded, non-empty)", m.versions) } } func TestReaderFilterAndOpen(t *testing.T) { m := enReader(t) nm, _ := m.Update(tea.WindowSizeMsg{Width: 80, Height: 24}) m = nm.(ReaderModel) m = key(m, runes("jn")) if len(m.matches) == 0 || m.books[m.matches[0]].Canonical != "John" { t.Fatalf("filter 'jn' top = %v", m.books[m.matches[m.pickSel]]) } m = key(m, tea.KeyMsg{Type: tea.KeyEnter}) if m.mode != modeRead { t.Fatalf("did not enter read mode") } if m.books[m.bookIdx].Canonical != "John" || len(m.verses) == 0 { t.Errorf("opened book=%q verses=%d", m.books[m.bookIdx].Canonical, len(m.verses)) } if !strings.Contains(m.View(), "1") { // chapter 1 header t.Errorf("read view missing chapter:\n%s", m.View()) } } func TestReaderChapterAndVersion(t *testing.T) { m := enReader(t) nm, _ := m.Update(tea.WindowSizeMsg{Width: 80, Height: 24}) m = nm.(ReaderModel) m = key(m, runes("jn")) m = key(m, tea.KeyMsg{Type: tea.KeyEnter}) firstChap := m.chapters[m.chapPos] m = key(m, tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("n")}) // next chapter if m.chapters[m.chapPos] <= firstChap { t.Errorf("chapter did not advance: %d -> %d", firstChap, m.chapters[m.chapPos]) } v0 := m.verIdx m = key(m, tea.KeyMsg{Type: tea.KeyTab}) if m.verIdx == v0 { t.Errorf("version did not cycle") } // esc returns to picker m = key(m, tea.KeyMsg{Type: tea.KeyEsc}) if m.mode != modePick { t.Errorf("esc did not return to picker") } } func TestReaderFuzzyScore(t *testing.T) { if s, ok := fuzzyScore("gen", "Gen Genesis"); !ok || s < 500 { t.Errorf("substring score = %d,%v", s, ok) } if _, ok := fuzzyScore("xyz", "Gen Genesis"); ok { t.Error("xyz should not match Genesis") } // subsequence: g..s..s across the string if _, ok := fuzzyScore("gss", "Gen Genesis"); !ok { t.Error("gss should subsequence-match") } }