1package e2e23import (4 "os"5 "path/filepath"6 "strings"7 "testing"89 ghostty "go.mitchellh.com/libghostty"10)1112// Rules as a user meets them: a dropdown picked from with Alt+Down and13// the mouse, a checkbox toggled with Space and a click, an entry a rule14// rejects, a conditional format added from the panel, and all of it15// saved and opened again.16func TestRules(t *testing.T) {17 t.Parallel()18 dir := t.TempDir()19 tasksFile(t, dir)20 s := start(t, dir, "tasks.012")21 s.waitFor("Write spec")2223 // B3's dropdown, from the keyboard.24 s.keys("<down>", "<down>", "<right>", "<alt+down>")25 s.waitFor("Search the items")26 s.keys("cy", "<enter>")27 s.waitForBar("B3", "Cy")2829 // D3's checkbox, with Space, then B5's dropdown and D5's checkbox30 // with the mouse (row 5 is screen line gridRow1+4).31 s.keys("<right>", "<right>", "<space>")32 s.waitForBar("D3", "TRUE")33 s.waitForLine(gridRow1+2, " 3 Build UI Cy ▾ 40 [✓]")34 s.click(ghostty.MouseButtonLeft, 6+14+10-1, gridRow1+4) // B's last column35 s.waitFor("Search the items")36 s.keys("ann", "<enter>")37 s.waitForBar("B5", "Ann")38 s.click(ghostty.MouseButtonLeft, 6+14+10+8+3, gridRow1+4) // D's glyph39 s.waitForBar("D5", "TRUE")4041 // Hours reject anything over 80, with Sheets' words.42 s.keys("<left>", "120", "<enter>")43 s.waitFor("Invalid entry in C5: Input must be a number between 0 and 80")44 s.keys("<esc>")45 s.waitForBar("C5", "6")4647 // Format > Conditional formatting: a new rule over the selection.48 s.keys("<ctrl+k>", "conditional formatting", "<enter>")49 s.waitFor("3 rules")50 s.keys("<enter>")51 s.waitFor("Add conditional format")52 s.keys("<enter>")53 s.waitFor("4 rules")54 s.keys("<esc>", "<ctrl+s>")55 s.eventually("saved", func() bool { return !strings.Contains(s.line(29), "modified") })56 body, err := os.ReadFile(filepath.Join(dir, "tasks.012"))57 if err != nil {58 t.Fatal(err)59 }60 for _, want := range []string{`{"ranges":"C5","condition":"not_empty","fill":"green"}`, `"B3": "Cy"`, `"D5": "TRUE"`, `"validations": [`} {61 if !strings.Contains(string(body), want) {62 t.Errorf("file lacks %s:\n%s", want, body)63 }64 }6566 // Opened again, the rules are there.67 s2 := start(t, dir, "tasks.012")68 s2.waitForLine(gridRow1+2, " 3 Build UI Cy ▾ 40 [✓]")69 s2.keys("<ctrl+k>", "conditional formatting", "<enter>")70 s2.waitFor("4 rules")71}7273// Rules that draw their own, as a user meets them: bars, icons and74// chips on opening, a checkbox of its own values toggled with Space, a75// data bar added from the panel, and cells cut to another sheet taking76// their rules along.77func TestBarsIconsAndChips(t *testing.T) {78 t.Parallel()79 dir := t.TempDir()80 scoresFile(t, dir)81 s := start(t, dir, "scores.012")82 s.waitFor("Dee")83 for _, want := range []string{"▐Math ▾▌", "██████92", "↑ 12", "●"} {84 s.waitFor(want)85 }86 // F3's checkbox holds No; Space checks it, entering Yes.87 s.keys("<ctrl+g>", "F3", "<enter>", "<space>")88 s.waitForBar("F3", "Yes")8990 // A data bar from the panel, over C2:C6.91 s.keys("<ctrl+g>", "C2:C6", "<enter>")92 s.keys("<ctrl+k>", "conditional formatting", "<enter>")93 s.waitFor("4 rules")94 s.keys("<enter>")95 s.waitFor("Add conditional format")96 s.keys("<down>", "<right>", "<right>")97 s.waitFor("Show bar only")98 s.keys("<enter>")99 s.waitFor("5 rules")100 s.keys("<esc>")101102 // Cut to another sheet, the points take their bars along.103 s.keys("<shift+f11>")104 s.waitFor("Sheet2")105 s.keys("<alt+left>")106 s.waitFor("Dee")107 s.keys("<ctrl+g>", "B2:B6", "<enter>")108 s.waitForName("B2:B6")109 s.keys("<ctrl+x>")110 s.waitFor("Ctrl+V move here")111 s.keys("<alt+right>", "<ctrl+v>")112 s.waitFor("██████92")113 s.keys("<ctrl+s>")114 s.eventually("saved", func() bool { return !strings.Contains(s.line(29), "modified") })115 body, err := os.ReadFile(filepath.Join(dir, "scores.012"))116 if err != nil {117 t.Fatal(err)118 }119 for _, want := range []string{`"F3": "Yes"`, `{"ranges":"C2:C6","dataBar":{"color":"blue"`, `{"ranges":"A1:A5","dataBar":`} {120 if !strings.Contains(string(body), want) {121 t.Errorf("file lacks %s:\n%s", want, body)122 }123 }124}