github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/cmd/syft/cli/ui/util_test.go (about) 1 package ui 2 3 import ( 4 "reflect" 5 "sync" 6 "testing" 7 "unsafe" 8 9 tea "github.com/charmbracelet/bubbletea" 10 ) 11 12 func runModel(t testing.TB, m tea.Model, iterations int, message tea.Msg, h ...*sync.WaitGroup) string { 13 t.Helper() 14 if iterations == 0 { 15 iterations = 1 16 } 17 m.Init() 18 var cmd tea.Cmd = func() tea.Msg { 19 return message 20 } 21 22 for _, each := range h { 23 if each != nil { 24 each.Wait() 25 } 26 } 27 28 for i := 0; cmd != nil && i < iterations; i++ { 29 msgs := flatten(cmd()) 30 var nextCmds []tea.Cmd 31 var next tea.Cmd 32 for _, msg := range msgs { 33 t.Logf("Message: %+v %+v\n", reflect.TypeOf(msg), msg) 34 m, next = m.Update(msg) 35 nextCmds = append(nextCmds, next) 36 } 37 cmd = tea.Batch(nextCmds...) 38 } 39 40 return m.View() 41 } 42 43 func flatten(p tea.Msg) (msgs []tea.Msg) { 44 if reflect.TypeOf(p).Name() == "batchMsg" { 45 partials := extractBatchMessages(p) 46 for _, m := range partials { 47 msgs = append(msgs, flatten(m)...) 48 } 49 } else { 50 msgs = []tea.Msg{p} 51 } 52 return msgs 53 } 54 55 func extractBatchMessages(m tea.Msg) (ret []tea.Msg) { 56 sliceMsgType := reflect.SliceOf(reflect.TypeOf(tea.Cmd(nil))) 57 value := reflect.ValueOf(m) // note: this is technically unaddressable 58 59 // make our own instance that is addressable 60 valueCopy := reflect.New(value.Type()).Elem() 61 valueCopy.Set(value) 62 63 cmds := reflect.NewAt(sliceMsgType, unsafe.Pointer(valueCopy.UnsafeAddr())).Elem() 64 for i := 0; i < cmds.Len(); i++ { 65 item := cmds.Index(i) 66 r := item.Call(nil) 67 ret = append(ret, r[0].Interface().(tea.Msg)) 68 } 69 return ret 70 }