github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/cmd/syft/cli/ui/handle_cataloger_task_test.go (about)

     1  package ui
     2  
     3  import (
     4  	"testing"
     5  
     6  	tea "github.com/charmbracelet/bubbletea"
     7  	"github.com/gkampitakis/go-snaps/snaps"
     8  	"github.com/stretchr/testify/require"
     9  	"github.com/wagoodman/go-partybus"
    10  	"github.com/wagoodman/go-progress"
    11  
    12  	syftEvent "github.com/anchore/syft/syft/event"
    13  	"github.com/anchore/syft/syft/event/monitor"
    14  )
    15  
    16  func TestHandler_handleCatalogerTaskStarted(t *testing.T) {
    17  	title := monitor.Title{
    18  		Default:   "some task title",
    19  		OnSuccess: "some task done",
    20  	}
    21  	tests := []struct {
    22  		name       string
    23  		eventFn    func(*testing.T) partybus.Event
    24  		iterations int
    25  	}{
    26  		{
    27  			name: "cataloging task in progress",
    28  			eventFn: func(t *testing.T) partybus.Event {
    29  				value := &monitor.CatalogerTaskProgress{
    30  					AtomicStage: progress.NewAtomicStage("some stage"),
    31  					Manual:      progress.NewManual(100),
    32  				}
    33  
    34  				value.Manual.Add(50)
    35  
    36  				return partybus.Event{
    37  					Type: syftEvent.CatalogerTaskStarted,
    38  					Source: monitor.GenericTask{
    39  						Title:              title,
    40  						HideOnSuccess:      false,
    41  						HideStageOnSuccess: false,
    42  						ID:                 "my-id",
    43  					},
    44  					Value: value,
    45  				}
    46  			},
    47  		},
    48  		{
    49  			name: "cataloging sub task in progress",
    50  			eventFn: func(t *testing.T) partybus.Event {
    51  				value := &monitor.CatalogerTaskProgress{
    52  					AtomicStage: progress.NewAtomicStage("some stage"),
    53  					Manual:      progress.NewManual(100),
    54  				}
    55  
    56  				value.Manual.Add(50)
    57  
    58  				return partybus.Event{
    59  					Type: syftEvent.CatalogerTaskStarted,
    60  					Source: monitor.GenericTask{
    61  						Title:              title,
    62  						HideOnSuccess:      false,
    63  						HideStageOnSuccess: false,
    64  						ID:                 "my-id",
    65  						ParentID:           "top-level-task",
    66  					},
    67  					Value: value,
    68  				}
    69  			},
    70  		},
    71  		{
    72  			name: "cataloging sub task complete",
    73  			eventFn: func(t *testing.T) partybus.Event {
    74  				value := &monitor.CatalogerTaskProgress{
    75  					AtomicStage: progress.NewAtomicStage("some stage"),
    76  					Manual:      progress.NewManual(100),
    77  				}
    78  
    79  				value.SetCompleted()
    80  
    81  				return partybus.Event{
    82  					Type: syftEvent.CatalogerTaskStarted,
    83  					Source: monitor.GenericTask{
    84  						Title:              title,
    85  						HideOnSuccess:      false,
    86  						HideStageOnSuccess: false,
    87  						ID:                 "my-id",
    88  						ParentID:           "top-level-task",
    89  					},
    90  					Value: value,
    91  				}
    92  			},
    93  		},
    94  		{
    95  			name: "cataloging sub task complete -- hide stage",
    96  			eventFn: func(t *testing.T) partybus.Event {
    97  				value := &monitor.CatalogerTaskProgress{
    98  					AtomicStage: progress.NewAtomicStage("some stage"),
    99  					Manual:      progress.NewManual(100),
   100  				}
   101  
   102  				value.SetCompleted()
   103  
   104  				return partybus.Event{
   105  					Type: syftEvent.CatalogerTaskStarted,
   106  					Source: monitor.GenericTask{
   107  						Title:              title,
   108  						HideOnSuccess:      false,
   109  						HideStageOnSuccess: true,
   110  						ID:                 "my-id",
   111  						ParentID:           "top-level-task",
   112  					},
   113  					Value: value,
   114  				}
   115  			},
   116  		},
   117  		{
   118  			name: "cataloging sub task complete with removal",
   119  			eventFn: func(t *testing.T) partybus.Event {
   120  				value := &monitor.CatalogerTaskProgress{
   121  					AtomicStage: progress.NewAtomicStage("some stage"),
   122  					Manual:      progress.NewManual(100),
   123  				}
   124  
   125  				value.SetCompleted()
   126  
   127  				return partybus.Event{
   128  					Type: syftEvent.CatalogerTaskStarted,
   129  					Source: monitor.GenericTask{
   130  						Title:              title,
   131  						HideOnSuccess:      true,
   132  						HideStageOnSuccess: false,
   133  						ID:                 "my-id",
   134  						ParentID:           "top-level-task",
   135  					},
   136  					Value: value,
   137  				}
   138  			},
   139  		},
   140  	}
   141  	for _, tt := range tests {
   142  		t.Run(tt.name, func(t *testing.T) {
   143  			// need to be able to get the initial newCatalogerTaskRowEvent + initialize the nested taskprogress model
   144  			if tt.iterations == 0 {
   145  				tt.iterations = 2
   146  			}
   147  
   148  			e := tt.eventFn(t)
   149  			handler := New(DefaultHandlerConfig())
   150  			handler.WindowSize = tea.WindowSizeMsg{
   151  				Width:  100,
   152  				Height: 80,
   153  			}
   154  
   155  			info := monitor.GenericTask{
   156  				Title: monitor.Title{
   157  					Default:      "Catalog contents",
   158  					WhileRunning: "Cataloging contents",
   159  					OnSuccess:    "Cataloged contents",
   160  				},
   161  				ID: "top-level-task",
   162  			}
   163  
   164  			// note: this line / event is not under test, only needed to show a sub status
   165  			kickoffEvent := &monitor.CatalogerTaskProgress{
   166  				AtomicStage: progress.NewAtomicStage(""),
   167  				Manual:      progress.NewManual(-1),
   168  			}
   169  
   170  			models, cmd := handler.Handle(
   171  				partybus.Event{
   172  					Type:   syftEvent.CatalogerTaskStarted,
   173  					Source: info,
   174  					Value:  progress.StagedProgressable(kickoffEvent),
   175  				},
   176  			)
   177  			require.Len(t, models, 1)
   178  			require.NotNil(t, cmd)
   179  			model := models[0]
   180  
   181  			tr, ok := model.(*catalogerTaskModel)
   182  			require.True(t, ok)
   183  
   184  			gotModel := runModel(t, tr, tt.iterations, cmd())
   185  
   186  			models, cmd = handler.Handle(e)
   187  			require.Len(t, models, 0)
   188  			require.NotNil(t, cmd)
   189  
   190  			gotModel = runModel(t, gotModel, tt.iterations, cmd())
   191  
   192  			got := gotModel.View()
   193  
   194  			t.Log(got)
   195  			snaps.MatchSnapshot(t, got)
   196  		})
   197  	}
   198  }