Skip to content

Commit 492b521

Browse files
authored
feat(cli): show message when no components or stacks found in list command (#1754)
* feat(cli): show message when no stacks found Display a user-friendly message in color when the list stacks command returns no results, improving user feedback and clarity. * feat(cli): show message when no components found Display a user-friendly message when the list components command returns no results. This improves UX by providing clear feedback instead of showing an empty output. * fix: consistent formatting * refactor(ui): use ui.Error for empty list messages Replaced usage of u.PrintMessageInColor for empty component and stack lists with the new ui.Error function. This improves consistency in error messaging and centralizes UI logic. Imports were updated accordingly. * test: add tests for empty and missing components/stacks Add tests to cover scenarios where no components are found in stacks and where no stacks match a given component. This improves coverage for edge cases in FilterAndListComponents and FilterAndListStacks. * test(list): add tests for empty list results Add tests to verify that the list commands handle empty results correctly. These tests ensure that the "No components found" and "No stacks found" messages are triggered when the filter functions return empty slices. * fix(ui): use Info instead of Error for empty list messages Changed the message level from Error to Info when no components or stacks are found in the list commands. This avoids treating empty results as errors and provides a clearer user experience.
1 parent cb4e876 commit 492b521

File tree

5 files changed

+85
-0
lines changed

5 files changed

+85
-0
lines changed

cmd/list_components.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/cloudposse/atmos/pkg/config"
1111
l "github.com/cloudposse/atmos/pkg/list"
1212
"github.com/cloudposse/atmos/pkg/schema"
13+
"github.com/cloudposse/atmos/pkg/ui"
1314
"github.com/cloudposse/atmos/pkg/ui/theme"
1415
u "github.com/cloudposse/atmos/pkg/utils"
1516
)
@@ -29,6 +30,11 @@ var listComponentsCmd = &cobra.Command{
2930
return err
3031
}
3132

33+
if len(output) == 0 {
34+
ui.Info("No components found")
35+
return nil
36+
}
37+
3238
u.PrintMessageInColor(strings.Join(output, "\n")+"\n", theme.Colors.Success)
3339
return nil
3440
},

cmd/list_stacks.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/cloudposse/atmos/pkg/config"
1111
l "github.com/cloudposse/atmos/pkg/list"
1212
"github.com/cloudposse/atmos/pkg/schema"
13+
"github.com/cloudposse/atmos/pkg/ui"
1314
"github.com/cloudposse/atmos/pkg/ui/theme"
1415
u "github.com/cloudposse/atmos/pkg/utils"
1516
)
@@ -30,6 +31,11 @@ var listStacksCmd = &cobra.Command{
3031
return err
3132
}
3233

34+
if len(output) == 0 {
35+
ui.Info("No stacks found")
36+
return nil
37+
}
38+
3339
u.PrintMessageInColor(strings.Join(output, "\n")+"\n", theme.Colors.Success)
3440
return nil
3541
},

cmd/list_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/spf13/cobra"
77
"github.com/stretchr/testify/assert"
88

9+
l "github.com/cloudposse/atmos/pkg/list"
910
"github.com/cloudposse/atmos/pkg/list/errors"
1011
)
1112

@@ -202,3 +203,42 @@ func TestListCmds_Error(t *testing.T) {
202203
err = listWorkflowsCmd.RunE(listWorkflowsCmd, []string{"--invalid-flag"})
203204
assert.Error(t, err, "list workflows command should return an error when called with invalid flags")
204205
}
206+
207+
// TestListCmds_NoResults verifies that the list commands can handle empty results.
208+
// This tests the condition that triggers "No components found" and "No stacks found" messages.
209+
// Note: This test verifies the underlying filter functions return empty slices, which is the
210+
// condition that causes the RunE functions to display the "No X found" UI error messages.
211+
func TestListCmds_NoResults(t *testing.T) {
212+
// Test that FilterAndListComponents can return empty results
213+
t.Run("list components returns empty when no components exist", func(t *testing.T) {
214+
emptyStacksMap := map[string]any{
215+
"test-stack": map[string]any{
216+
"components": map[string]any{
217+
"terraform": map[string]any{},
218+
"helmfile": map[string]any{},
219+
},
220+
},
221+
}
222+
223+
output, err := l.FilterAndListComponents("", emptyStacksMap)
224+
assert.NoError(t, err)
225+
assert.Empty(t, output, "Expected empty output when no components exist")
226+
})
227+
228+
// Test that FilterAndListStacks can return empty results
229+
t.Run("list stacks returns empty when no matching stacks exist", func(t *testing.T) {
230+
stacksMap := map[string]any{
231+
"test-stack": map[string]any{
232+
"components": map[string]any{
233+
"terraform": map[string]any{
234+
"existing-component": map[string]any{},
235+
},
236+
},
237+
},
238+
}
239+
240+
output, err := l.FilterAndListStacks(stacksMap, "nonexistent-component")
241+
assert.NoError(t, err)
242+
assert.Nil(t, output, "Expected nil output when no matching stacks exist")
243+
})
244+
}

pkg/list/list_components_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,23 @@ func TestFilterAndListComponents(t *testing.T) {
259259
assert.ElementsMatch(t, []string{"vpc", "eks", "rds", "s3", "test", "elasticache"}, components)
260260
})
261261

262+
// Test no components found
263+
t.Run("no components", func(t *testing.T) {
264+
emptyStacks := map[string]any{
265+
"stack1": map[string]any{
266+
"components": map[string]any{
267+
"terraform": map[string]any{},
268+
"helmfile": map[string]any{},
269+
"packer": map[string]any{},
270+
},
271+
},
272+
}
273+
274+
components, err := FilterAndListComponents("", emptyStacks)
275+
require.NoError(t, err)
276+
assert.Empty(t, components)
277+
})
278+
262279
// Test error cases
263280
t.Run("non-existent stack", func(t *testing.T) {
264281
_, err := FilterAndListComponents("non-existent-stack", stacksMap)

pkg/list/list_stacks_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,19 @@ func TestListStacksWithComponent(t *testing.T) {
4848
assert.Contains(t, dependentsYaml, "tenant1-uw1-test-1")
4949
assert.Contains(t, dependentsYaml, "tenant1-uw2-test-1")
5050
}
51+
52+
func TestFilterAndListStacks_NoMatchingComponent(t *testing.T) {
53+
stacksMap := map[string]any{
54+
"stack1": map[string]any{
55+
"components": map[string]any{
56+
"terraform": map[string]any{
57+
"existing": map[string]any{},
58+
},
59+
},
60+
},
61+
}
62+
63+
output, err := FilterAndListStacks(stacksMap, "missing")
64+
assert.NoError(t, err)
65+
assert.Nil(t, output)
66+
}

0 commit comments

Comments
 (0)