cat / 012
clone

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

main
012 / internal / sheet / macros_test.go
macros_test.go 4.2K
1package sheet23import (4 "bytes"5 "strings"6 "testing"7)89func TestSaveMacroIsUndoable(t *testing.T) {10 w := NewBook()11 if err := w.SaveMacro("", Macro{Name: "Totals", Key: "1", Source: "enter(\"x\")\n"}, "record macro Totals"); err != nil {12 t.Fatal(err)13 }14 if err := w.SaveMacro("totals", Macro{Name: "Sums", Key: "1", Source: "enter(\"y\")\n"}, "edit macro Sums"); err != nil {15 t.Fatal(err)16 }17 if ms := w.Macros(); len(ms) != 1 || ms[0].Name != "Sums" || ms[0].API != MacroAPI {18 t.Fatalf("macros %+v", ms)19 }20 c, ok := w.Undo()21 if !ok || c.Label != "edit macro Sums" || !c.Macros {22 t.Fatalf("undo %+v %v", c, ok)23 }24 if mc, ok := w.Macro("TOTALS"); !ok || mc.Source != "enter(\"x\")\n" {25 t.Fatalf("after undo %+v %v", mc, ok)26 }27 w.Undo()28 if len(w.Macros()) != 0 {29 t.Fatalf("macros after undoing the add: %+v", w.Macros())30 }31 w.Redo()32 if _, ok := w.MacroForKey("1"); !ok {33 t.Fatal("redo lost the shortcut")34 }35 if !w.DeleteMacro("Totals") || len(w.Macros()) != 0 {36 t.Fatal("delete")37 }38}3940func TestSaveMacroChecksNamesAndKeys(t *testing.T) {41 w := NewBook()42 w.SaveMacro("", Macro{Name: "A", Key: "1"}, "add")43 for _, tc := range []struct {44 old string45 mc Macro46 want string47 }{48 {"", Macro{Name: " "}, "needs a name"},49 {"", Macro{Name: "a"}, "already a macro named A"},50 {"", Macro{Name: "B", Key: "1"}, "Ctrl+Alt+Shift+1 already runs A"},51 {"", Macro{Name: "B", Key: "x"}, "is a digit"},52 {"C", Macro{Name: "C"}, "no macro named C"},53 } {54 if err := w.SaveMacro(tc.old, tc.mc, "x"); err == nil || !strings.Contains(err.Error(), tc.want) {55 t.Errorf("SaveMacro(%q, %+v) = %v, want %q", tc.old, tc.mc, err, tc.want)56 }57 }58}5960func TestMacrosRoundTrip(t *testing.T) {61 for _, sheets := range []int{1, 2} {62 w := NewBook()63 if sheets == 2 {64 w.AddSheet("Two", 1)65 }66 src := "# a <script> & more\nselect(\"B2\")\nenter(\"=SUM(A1:A3)\")\n"67 w.SaveMacro("", Macro{Name: "Totals", Key: "3", Source: src}, "add")68 w.SaveMacro("", Macro{Name: "Plain", Source: "move(0, 1)\n"}, "add")69 w.SetMacroOrigin("abc123")70 var b bytes.Buffer71 if err := w.Write(&b); err != nil {72 t.Fatal(err)73 }74 if !strings.Contains(b.String(), `{"name": "Totals", "key": "3", "api": 1, "source": "# a <script> & more\nselect(\"B2\")`) {75 t.Errorf("file:\n%s", b.String())76 }77 got, err := ReadBook(&b)78 if err != nil {79 t.Fatal(err)80 }81 ms := got.Macros()82 if len(ms) != 2 || ms[0] != (Macro{Name: "Totals", Key: "3", Source: src, API: 1}) || ms[1].Name != "Plain" || ms[1].Key != "" {83 t.Errorf("%d sheets: macros %+v", sheets, ms)84 }85 if got.MacroOrigin() != "abc123" {86 t.Errorf("origin %q", got.MacroOrigin())87 }88 if got.CanUndo() {89 t.Error("loading is undoable")90 }91 }92}9394func TestFileWithoutMacrosHasNoMacroFields(t *testing.T) {95 w := NewBook()96 w.SetMacroOrigin("abc")97 var b bytes.Buffer98 w.Write(&b)99 if strings.Contains(b.String(), "macro") {100 t.Errorf("file:\n%s", b.String())101 }102}103104func TestReadMacrosDropsClashingKeys(t *testing.T) {105 src := `{"version": 2, "macros": [{"name": "A", "key": "1", "api": 1, "source": ""}, {"name": "B", "key": "1", "api": 2, "source": ""}], "cells": {}}`106 w, err := ReadBook(strings.NewReader(src))107 if err != nil {108 t.Fatal(err)109 }110 if ms := w.Macros(); ms[1].Key != "" || ms[1].API != 2 {111 t.Errorf("macros %+v", ms)112 }113 dup := `{"version": 2, "macros": [{"name": "A", "api": 1, "source": ""}, {"name": "a", "api": 1, "source": ""}], "cells": {}}`114 if _, err := ReadBook(strings.NewReader(dup)); err == nil {115 t.Error("a name defined twice loads")116 }117}118119func TestBeginKeepsOneStepOpen(t *testing.T) {120 s := New()121 w := s.Book()122 end := w.Begin(Change{Label: "run macro M", Sheet: s})123 s.Set(Addr{}, "2")124 s.Set(Addr{Row: 1}, "=A1*10")125 w.Settle()126 if v := s.Value(Addr{Row: 1}); v.Num != 20 {127 t.Fatalf("A2 inside the step = %v", v)128 }129 s.Set(Addr{}, "3")130 if _, ok := w.Undo(); ok {131 t.Fatal("undo ran inside an open step")132 }133 end()134 end() // a second call does nothing135 if v := s.Value(Addr{Row: 1}); v.Num != 30 {136 t.Fatalf("A2 after the step = %v", v)137 }138 c, ok := w.Undo()139 if !ok || c.Label != "run macro M" || s.Cell(Addr{}) != nil || s.Cell(Addr{Row: 1}) != nil {140 t.Fatalf("undo %+v %v: A1 %v", c, ok, s.Cell(Addr{}))141 }142 if w.CanUndo() {143 t.Error("the step was split")144 }145}