Keeps screenlist_test.go under 500 lines and each test under the cognitive complexity limit.
- commit
- 75ec2bbb85d2f6988d476b4800bbb1705dc0ead2
- parent
- bd785aa20552c7f6e61d101b4ed703f123dc6fd2
- author
- Dami <dami.etoile@gmail.com>
| M | e2e/ | 9 | - |
| M | e2e/ | 8 | - |
| A | e2e/ | 25 | +++ |
| M | internal/ | 224 | +++++++++++++++--------------- |
@@ -263,15 +263,6 @@ var screens = []screen{
263263 s.keys("<alt+f>", "<down>", "<down>", "<down>")264264 s.waitFor("Save the sheet")265265 }},266- // High contrast: WCAG AAA text, dark and light, with a selection and267- // an open menu.268- {name: "theme-high-contrast", opts: options{config: "theme = high-contrast\n"}, setup: highContrast},269- {name: "theme-high-contrast-light", opts: options{light: true, config: "theme = high-contrast\n"}, setup: highContrast},270- {name: "theme-high-contrast-menu", opts: options{config: "theme = high-contrast\n"}, setup: func(s *session) {271- budget(s)272- s.keys("<alt+f>", "<down>", "<down>", "<down>")273- s.waitFor("Save the sheet")274- }},275266 {name: "theme-picker", setup: func(s *session) {276267 budget(s)277268 openTheme(s)@@ -21,14 +21,6 @@ func budget(s *session) {
2121 s.waitForBar("B7", "=SUM(B3:B5)")2222 }2323 24-// highContrast is the budget with an error and a selection, for the25-// high-contrast theme.26-func highContrast(s *session) {27- budget(s)28- s.keys("<up>", "<up>", "<up>", "<up>", "<shift+down>", "<shift+down>")29- s.waitFor("Sum 2158.4")30-}31-3224 // formatted types a bill schedule with dates, currency and percentages,3325 // then styles it with Sheets' shortcuts: bold title and totals, headers3426 // aligned over their numbers, a struck-out cancelled bill and an italic@@ -0,0 +1,25 @@
1+package e2e2+3+// Golden screens for the high-contrast theme (WCAG AAA text), on a dark4+// and a light terminal, with a selection and an error, and an open menu.5+6+// highContrast is the budget with an error and a selection.7+func highContrast(s *session) {8+ budget(s)9+ s.keys("<up>", "<up>", "<up>", "<up>", "<shift+down>", "<shift+down>")10+ s.waitFor("Sum 2158.4")11+}12+13+const highContrastConfig = "theme = high-contrast\n"14+15+func init() {16+ screens = append(screens,17+ screen{name: "theme-high-contrast", opts: options{config: highContrastConfig}, setup: highContrast},18+ screen{name: "theme-high-contrast-light", opts: options{light: true, config: highContrastConfig}, setup: highContrast},19+ screen{name: "theme-high-contrast-menu", opts: options{config: highContrastConfig}, setup: func(s *session) {20+ budget(s)21+ s.keys("<alt+f>", "<down>", "<down>", "<down>")22+ s.waitFor("Save the sheet")23+ }},24+ )25+}@@ -144,129 +144,127 @@ func every(cs []monoCell, text bool, f func(monoCell) bool) bool {
144144 return true145145 }146146 147-func TestMonochromeSheetStates(t *testing.T) {148- isReverse := func(c monoCell) bool { return c.reverse }149- plain := func(c monoCell) bool { return c.attrs == attrs{} }147+func isReverse(c monoCell) bool { return c.reverse }148+func plain(c monoCell) bool { return c.attrs == attrs{} }150149 151- t.Run("pointer and plain cell", func(t *testing.T) {152- m := newModel()153- m.sheet.Set(addr("B1"), "text")154- if p := cellAt(m, addr("A1")); !every(p, false, isReverse) {155- t.Errorf("the pointer isn't in reverse video: %+v", p)156- }157- if c := cellAt(m, addr("B1")); !every(c, false, plain) {158- t.Errorf("a plain cell has attributes: %+v", c)159- }160- })150+func TestMonochromePointer(t *testing.T) {151+ m := newModel()152+ m.sheet.Set(addr("B1"), "text")153+ if p := cellAt(m, addr("A1")); !every(p, false, isReverse) {154+ t.Errorf("the pointer isn't in reverse video: %+v", p)155+ }156+ if c := cellAt(m, addr("B1")); !every(c, false, plain) {157+ t.Errorf("a plain cell has attributes: %+v", c)158+ }159+}161160 162- t.Run("selection and headers", func(t *testing.T) {163- m := newModel()164- press(t, m, "<shift+right>", "<shift+down>")165- for _, a := range []string{"A1", "B1", "A2", "B2"} {166- if c := cellAt(m, addr(a)); !every(c, false, isReverse) {167- t.Errorf("%s in the selection isn't in reverse video", a)168- }169- }170- if c := cellAt(m, addr("C3")); !every(c, false, plain) {171- t.Error("a cell outside the selection has attributes")172- }173- // Column headers: the active cell's (the selection's anchor, A1)174- // bold and reversed, another selected one reversed, the rest plain.175- hdr := monoLine(m, headerLine)176- x := m.hdrW()177- col := func(c int) []monoCell { return hdr[x+c*sheet.DefaultWidth : x+(c+1)*sheet.DefaultWidth] }178- if !every(col(0), true, func(c monoCell) bool { return c.reverse && c.bold }) {179- t.Errorf("the active column's header: %+v", col(0))180- }181- if !every(col(1), true, func(c monoCell) bool { return c.reverse && !c.bold }) {182- t.Errorf("a selected column's header: %+v", col(1))183- }184- if every(col(2), true, isReverse) {185- t.Error("an unselected column's header is reversed")186- }187- if !strings.Contains(cellText(monoLine(m, formulaLine)), "A1:B2") {188- t.Error("the name box doesn't name the selection")161+func TestMonochromeSelection(t *testing.T) {162+ m := newModel()163+ press(t, m, "<shift+right>", "<shift+down>")164+ for _, a := range []string{"A1", "B1", "A2", "B2"} {165+ if c := cellAt(m, addr(a)); !every(c, false, isReverse) {166+ t.Errorf("%s in the selection isn't in reverse video", a)189167 }190- })168+ }169+ if c := cellAt(m, addr("C3")); !every(c, false, plain) {170+ t.Error("a cell outside the selection has attributes")171+ }172+ // Column headers: the active cell's (the selection's anchor, A1)173+ // bold and reversed, another selected one reversed, the rest plain.174+ hdr := monoLine(m, headerLine)175+ x := m.hdrW()176+ col := func(c int) []monoCell { return hdr[x+c*sheet.DefaultWidth : x+(c+1)*sheet.DefaultWidth] }177+ if !every(col(0), true, func(c monoCell) bool { return c.reverse && c.bold }) {178+ t.Errorf("the active column's header: %+v", col(0))179+ }180+ if !every(col(1), true, func(c monoCell) bool { return c.reverse && !c.bold }) {181+ t.Errorf("a selected column's header: %+v", col(1))182+ }183+ if every(col(2), true, isReverse) {184+ t.Error("an unselected column's header is reversed")185+ }186+ if !strings.Contains(cellText(monoLine(m, formulaLine)), "A1:B2") {187+ t.Error("the name box doesn't name the selection")188+ }189+}191190 192- t.Run("error", func(t *testing.T) {193- m := newModel()194- m.sheet.Set(addr("B1"), "=1/0")195- c := cellAt(m, addr("B1"))196- if !strings.Contains(cellText(c), "#DIV/0!") || !every(c, true, func(c monoCell) bool { return c.underline == "3" }) {197- t.Errorf("an error cell: %q %+v", cellText(c), c)198- }199- })191+func TestMonochromeError(t *testing.T) {192+ m := newModel()193+ m.sheet.Set(addr("B1"), "=1/0")194+ c := cellAt(m, addr("B1"))195+ if !strings.Contains(cellText(c), "#DIV/0!") || !every(c, true, func(c monoCell) bool { return c.underline == "3" }) {196+ t.Errorf("an error cell: %q %+v", cellText(c), c)197+ }198+}200199 201- t.Run("invalid entry and its warning", func(t *testing.T) {202- m := newModel()203- mustValidate(t, m, `{"ranges":"B1:B9","criteria":"number","condition":"between","values":["1","10"]}`)204- m.sheet.Set(addr("B1"), "42")205- c := cellAt(m, addr("B1"))206- if !every(c, true, func(c monoCell) bool { return c.underline == "4" }) {207- t.Errorf("an invalid cell isn't dotted: %+v", c)208- }209- m.cur = addr("B1")210- if l := cellText(monoLine(m, contextLine)); !strings.Contains(l, "Invalid:") {211- t.Errorf("no warning in words: %q", l)212- }213- })200+func TestMonochromeInvalid(t *testing.T) {201+ m := newModel()202+ mustValidate(t, m, `{"ranges":"B1:B9","criteria":"number","condition":"between","values":["1","10"]}`)203+ m.sheet.Set(addr("B1"), "42")204+ c := cellAt(m, addr("B1"))205+ if !every(c, true, func(c monoCell) bool { return c.underline == "4" }) {206+ t.Errorf("an invalid cell isn't dotted: %+v", c)207+ }208+ m.cur = addr("B1")209+ if l := cellText(monoLine(m, contextLine)); !strings.Contains(l, "Invalid:") {210+ t.Errorf("no warning in words: %q", l)211+ }212+}214213 215- t.Run("circular reference", func(t *testing.T) {216- m := newModel()217- m.sheet.Set(addr("A1"), "=A1+1")218- if l := cellText(monoLine(m, m.height-1)); !strings.Contains(l, "Circular reference") {219- t.Errorf("status line: %q", l)220- }221- })214+func TestMonochromeCircular(t *testing.T) {215+ m := newModel()216+ m.sheet.Set(addr("A1"), "=A1+1")217+ if l := cellText(monoLine(m, m.height-1)); !strings.Contains(l, "Circular reference") {218+ t.Errorf("status line: %q", l)219+ }220+}222221 223- t.Run("spill", func(t *testing.T) {224- m := newModel()225- m.sheet.Set(addr("B1"), "=SEQUENCE(3)")226- m.cur = addr("D1")227- c := cellAt(m, addr("B2"))228- if strings.TrimSpace(cellText(c)) != "2" || !every(c, true, func(c monoCell) bool { return c.italic }) {229- t.Errorf("a spilled value isn't italic: %+v", c)230- }231- m.cur = addr("B2")232- if l := cellText(monoLine(m, contextLine)); !strings.Contains(l, "Spilled from B1") {233- t.Errorf("context line: %q", l)234- }235- })222+func TestMonochromeSpill(t *testing.T) {223+ m := newModel()224+ m.sheet.Set(addr("B1"), "=SEQUENCE(3)")225+ m.cur = addr("D1")226+ c := cellAt(m, addr("B2"))227+ if strings.TrimSpace(cellText(c)) != "2" || !every(c, true, func(c monoCell) bool { return c.italic }) {228+ t.Errorf("a spilled value isn't italic: %+v", c)229+ }230+ m.cur = addr("B2")231+ if l := cellText(monoLine(m, contextLine)); !strings.Contains(l, "Spilled from B1") {232+ t.Errorf("context line: %q", l)233+ }234+}236235 237- t.Run("note", func(t *testing.T) {238- m := newModel()239- m.sheet.Set(addr("B1"), "x")240- m.sheet.SetNote(addr("B1"), "Checked")241- if c := cellAt(m, addr("B1")); c[len(c)-1].text != "▝" {242- t.Errorf("no note mark: %q", cellText(c))243- }244- })236+func TestMonochromeNote(t *testing.T) {237+ m := newModel()238+ m.sheet.Set(addr("B1"), "x")239+ m.sheet.SetNote(addr("B1"), "Checked")240+ if c := cellAt(m, addr("B1")); c[len(c)-1].text != "▝" {241+ t.Errorf("no note mark: %q", cellText(c))242+ }243+}245244 246- t.Run("found and traced", func(t *testing.T) {247- m := traceModel(t)248- m.cur = addr("B1")249- press(t, m, "<alt+,>")250- if c := cellAt(m, addr("A2")); !every(c, false, isReverse) {251- t.Errorf("a traced cell isn't reversed: %+v", c)252- }253- m = newModel()254- m.sheet.Set(addr("B2"), "Rent")255- press(t, m, "<ctrl+f>", "Rent")256- if c := cellAt(m, addr("B2")); !every(c, false, isReverse) {257- t.Errorf("a match isn't reversed: %+v", c)258- }259- })245+func TestMonochromeFoundTraced(t *testing.T) {246+ m := traceModel(t)247+ m.cur = addr("B1")248+ press(t, m, "<alt+,>")249+ if c := cellAt(m, addr("A2")); !every(c, false, isReverse) {250+ t.Errorf("a traced cell isn't reversed: %+v", c)251+ }252+ m = newModel()253+ m.sheet.Set(addr("B2"), "Rent")254+ press(t, m, "<ctrl+f>", "Rent")255+ if c := cellAt(m, addr("B2")); !every(c, false, isReverse) {256+ t.Errorf("a match isn't reversed: %+v", c)257+ }258+}260259 261- t.Run("copied", func(t *testing.T) {262- m := newModel()263- m.sheet.Set(addr("A1"), "1")264- press(t, m, "<ctrl+c>", "<right>")265- c := cellAt(m, addr("A1"))266- if !every(c, false, func(c monoCell) bool { return c.underline != "" }) || !every(c, true, func(c monoCell) bool { return c.underline == "5" }) {267- t.Errorf("the copied range isn't underlined, dashed under its text: %+v", c)268- }269- })260+func TestMonochromeCopied(t *testing.T) {261+ m := newModel()262+ m.sheet.Set(addr("A1"), "1")263+ press(t, m, "<ctrl+c>", "<right>")264+ c := cellAt(m, addr("A1"))265+ if !every(c, false, func(c monoCell) bool { return c.underline != "" }) || !every(c, true, func(c monoCell) bool { return c.underline == "5" }) {266+ t.Errorf("the copied range isn't underlined, dashed under its text: %+v", c)267+ }270268 }271269 272270 // States told in words: the mode indicator, recording, protected ranges