src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/cli/tk/utils_test.go (about) 1 package tk 2 3 import ( 4 "reflect" 5 "testing" 6 7 "src.elv.sh/pkg/cli/term" 8 "src.elv.sh/pkg/ui" 9 ) 10 11 // renderTest is a test case to be used in TestRenderer. 12 type renderTest struct { 13 Name string 14 Given Renderer 15 Width int 16 Height int 17 Want interface{ Buffer() *term.Buffer } 18 } 19 20 // testRender runs the given Renderer tests. 21 func testRender(t *testing.T, tests []renderTest) { 22 t.Helper() 23 for _, test := range tests { 24 t.Run(test.Name, func(t *testing.T) { 25 t.Helper() 26 buf := test.Given.Render(test.Width, test.Height) 27 wantBuf := test.Want.Buffer() 28 if !reflect.DeepEqual(buf, wantBuf) { 29 t.Errorf("Buffer mismatch") 30 t.Logf("Got: %s", buf.TTYString()) 31 t.Logf("Want: %s", wantBuf.TTYString()) 32 } 33 }) 34 } 35 } 36 37 // handleTest is a test case to be used in testHandle. 38 type handleTest struct { 39 Name string 40 Given Handler 41 Event term.Event 42 Events []term.Event 43 44 WantNewState any 45 WantUnhandled bool 46 } 47 48 // testHandle runs the given Handler tests. 49 func testHandle(t *testing.T, tests []handleTest) { 50 t.Helper() 51 52 for _, test := range tests { 53 t.Run(test.Name, func(t *testing.T) { 54 t.Helper() 55 56 handler := test.Given 57 oldState := getState(handler) 58 defer setState(handler, oldState) 59 60 var handled bool 61 switch { 62 case test.Event != nil && test.Events != nil: 63 t.Fatal("Malformed test case: both Event and Events non-nil:", 64 test.Event, test.Events) 65 case test.Event == nil && test.Events == nil: 66 t.Fatal("Malformed test case: both Event and Events nil") 67 case test.Event != nil: 68 handled = handler.Handle(test.Event) 69 default: // test.Events != nil 70 for _, event := range test.Events { 71 handled = handler.Handle(event) 72 } 73 } 74 if handled != !test.WantUnhandled { 75 t.Errorf("Got handled %v, want %v", handled, !test.WantUnhandled) 76 } 77 if test.WantNewState != nil { 78 state := getState(test.Given) 79 if !reflect.DeepEqual(state, test.WantNewState) { 80 t.Errorf("Got state %v, want %v", state, test.WantNewState) 81 } 82 } 83 }) 84 } 85 } 86 87 func getState(v any) any { 88 return reflectState(v).Interface() 89 } 90 91 func setState(v, state any) { 92 reflectState(v).Set(reflect.ValueOf(state)) 93 } 94 95 func reflectState(v any) reflect.Value { 96 rv := reflect.ValueOf(v) 97 if rv.Kind() == reflect.Ptr { 98 rv = reflect.Indirect(rv) 99 } 100 return rv.FieldByName("State") 101 } 102 103 // Test for the test utilities. 104 105 func TestTestRender(t *testing.T) { 106 testRender(t, []renderTest{ 107 { 108 Name: "test", 109 Given: &testWidget{text: ui.T("test")}, 110 Width: 10, Height: 10, 111 112 Want: term.NewBufferBuilder(10).Write("test"), 113 }, 114 }) 115 } 116 117 type testHandlerWithState struct { 118 State testHandlerState 119 } 120 121 type testHandlerState struct { 122 last term.Event 123 total int 124 } 125 126 func (h *testHandlerWithState) Handle(e term.Event) bool { 127 if e == term.K('x') { 128 return false 129 } 130 h.State.last = e 131 h.State.total++ 132 return true 133 } 134 135 func TestTestHandle(t *testing.T) { 136 testHandle(t, []handleTest{ 137 { 138 Name: "WantNewState", 139 Given: &testHandlerWithState{}, 140 Event: term.K('a'), 141 142 WantNewState: testHandlerState{last: term.K('a'), total: 1}, 143 }, 144 { 145 Name: "Multiple events", 146 Given: &testHandlerWithState{}, 147 Events: []term.Event{term.K('a'), term.K('b')}, 148 149 WantNewState: testHandlerState{last: term.K('b'), total: 2}, 150 }, 151 { 152 Name: "WantUnhaneld", 153 Given: &testHandlerWithState{}, 154 Event: term.K('x'), 155 156 WantUnhandled: true, 157 }, 158 }) 159 }