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  }