cat / 012
clone

a spreadsheet for the terminal: lotus 1-2-3 looks, google sheets keys and formulas, one go binary

main
012 / internal / ui / assist_test.go
assist_test.go 3.9K
1package ui23import (4 "strings"5 "testing"67 tea "charm.land/bubbletea/v2"89 "src.rest/cat/012/internal/ui/suggest"10)1112func TestAutocompleteFunctions(t *testing.T) {13 m := newModel()14 press(t, m, "=su")15 list, _ := m.entry.assist.Shown(m.host())16 if len(list) == 0 || list[0].Name != "SUBSTITUTE" && list[0].Name != "SUM" {17 t.Fatalf("suggestions %v", list)18 }19 for _, s := range list {20 if !strings.HasPrefix(s.Name, "SU") && !strings.Contains(s.Name, "SU") {21 t.Errorf("unexpected %s", s.Name)22 }23 }24 scr := screen(m)25 if !strings.Contains(scr, "│ SUM ") || !strings.Contains(scr, "(value1, [value2, ...])") {26 t.Errorf("list not drawn:\n%s", scr)27 }28 if st := line(m, m.height-1); !strings.Contains(st, "Tab insert") {29 t.Errorf("status %q", st)30 }31 // Down moves the highlight rather than committing; Tab inserts.32 for list[m.entry.assist.Sel()].Name != "SUM" {33 press(t, m, "<down>")34 }35 press(t, m, "<tab>")36 if m.mode != modeEnter || m.line.Text() != "=SUM(" {37 t.Fatalf("mode %v buf %q", m.mode, m.line.Text())38 }39 if ctx := line(m, contextLine); !strings.HasPrefix(ctx, "SUM(value1, [value2, ...])") || !strings.Contains(ctx, "Sum of numbers") {40 t.Errorf("signature %q", ctx)41 }42 press(t, m, "1,")43 sig, _ := suggest.Signature(&m.th, m.line.Buf, m.line.Pos, ',')44 if !strings.Contains(sig, m.th.Argument.Render("[value2, ...]")) {45 t.Errorf("second argument not marked: %q", sig)46 }47 press(t, m, "2)", "<enter>")48 if input(m, "A1") != "=SUM(1,2)" || m.sheet.Value(addr("A1")).Num != 3 {49 t.Errorf("A1 %q", input(m, "A1"))50 }51}5253func TestAutocompleteKeys(t *testing.T) {54 m := newModel()55 // Enter inserts while the list shows, then commits when it doesn't.56 press(t, m, "=ab", "<enter>")57 if m.line.Text() != "=ABS(" {58 t.Fatalf("enter: %q", m.line.Text())59 }60 press(t, m, "-4)", "<enter>")61 if m.sheet.Value(addr("A1")).Num != 4 {62 t.Fatalf("A1 = %v", m.sheet.Value(addr("A1")))63 }64 // Esc hides the list, a second Esc cancels the entry.65 press(t, m, "=ro")66 press(t, m, "<esc>")67 if list, _ := m.entry.assist.Shown(m.host()); list != nil || m.mode != modeEnter {68 t.Fatalf("esc: %v %v", list, m.mode)69 }70 press(t, m, "<esc>")71 if m.mode != modeReady {72 t.Fatalf("second esc: %v", m.mode)73 }74 // Arrows after an operator still point.75 press(t, m, "=1+", "<up>")76 if m.mode != modePoint {77 t.Errorf("mode %v", m.mode)78 }79 press(t, m, "<esc>", "<esc>")80 // Moving the caret hides the list; a cell reference gets no list.81 press(t, m, "=co", "<left>")82 if list, _ := m.entry.assist.Shown(m.host()); list != nil {83 t.Error("list after moving the caret")84 }85 press(t, m, "<esc>", "=B2")86 if list, _ := m.entry.assist.Shown(m.host()); list != nil {87 t.Errorf("list for a reference: %v", list)88 }89 // Plain text gets no list.90 press(t, m, "<esc>", "su")91 if list, _ := m.entry.assist.Shown(m.host()); list != nil {92 t.Error("list for text")93 }94}9596func TestAutocompleteNamesAndMouse(t *testing.T) {97 m := tallModel()98 m.sheet.DefineName("Sales", rectOf("B1:B3"))99 press(t, m, "=SUM(sa")100 list, start := m.entry.assist.Shown(m.host())101 if list[0].Name != "Sales" || list[0].Fn {102 t.Fatalf("names first: %v", list)103 }104 // Clicking a suggestion inserts it.105 b, _ := m.entry.assist.Box(m.host())106 send(m, tea.MouseClickMsg{X: b.X + 3, Y: b.Y + 1, Button: tea.MouseLeft})107 if m.line.Text() != "=SUM(Sales" || m.line.Pos != start+5 {108 t.Fatalf("click: %q", m.line.Text())109 }110 // Editing inside existing parentheses doesn't double them.111 m = newModel()112 press(t, m, "=AB(1)", "<f2>", "<left>", "<left>", "<left>", "<backspace>", "B")113 press(t, m, "<tab>")114 if m.line.Text() != "=ABS(1)" || m.line.Pos != 5 {115 t.Errorf("into parens: %q at %d", m.line.Text(), m.line.Pos)116 }117}118119func TestSignatureWhilePointing(t *testing.T) {120 m := newModel()121 press(t, m, "=JEV.TEST(", "<down>")122 if m.mode != modePoint {123 t.Fatalf("mode %v", m.mode)124 }125 if ctx := line(m, contextLine); !strings.HasPrefix(ctx, "JEV.TEST(value, question") {126 t.Errorf("context %q", ctx)127 }128}