1package cli
2
3import (
4 "bytes"
5 "context"
6 "testing"
7
8 "github.com/stretchr/testify/assert"
9 "github.com/stretchr/testify/require"
10
11 "github.com/bnema/gordon/internal/adapters/dto"
12)
13
14type fakeVolumesClient struct {
15 listResp []dto.Volume
16 pruneResp *dto.VolumePruneResponse
17 listErr error
18 pruneErr error
19
20 pruneCalls []dto.VolumePruneRequest
21}
22
23func (f *fakeVolumesClient) ListVolumes(_ context.Context) ([]dto.Volume, error) {
24 return f.listResp, f.listErr
25}
26
27func (f *fakeVolumesClient) PruneVolumes(_ context.Context, req dto.VolumePruneRequest) (*dto.VolumePruneResponse, error) {
28 f.pruneCalls = append(f.pruneCalls, req)
29 return f.pruneResp, f.pruneErr
30}
31
32func TestRunVolumesList_ShowsVolumes(t *testing.T) {
33 client := &fakeVolumesClient{
34 listResp: []dto.Volume{
35 {Name: "db-data", InUse: true, Containers: []string{"postgres"}, Size: 1024 * 1024},
36 {Name: "orphaned-vol", InUse: false, Size: 512},
37 },
38 }
39
40 var out bytes.Buffer
41 err := runVolumesList(context.Background(), client, &out, false)
42 require.NoError(t, err)
43 assert.Contains(t, out.String(), "db-data")
44 assert.Contains(t, out.String(), "orphaned-vol")
45}
46
47func TestRunVolumesList_JSON(t *testing.T) {
48 client := &fakeVolumesClient{
49 listResp: []dto.Volume{
50 {Name: "vol1", InUse: true},
51 },
52 }
53
54 var out bytes.Buffer
55 err := runVolumesList(context.Background(), client, &out, true)
56 require.NoError(t, err)
57 assert.Contains(t, out.String(), `"name"`)
58}
59
60func TestRunVolumesPrune_JSONExecutesActualPrune(t *testing.T) {
61 client := &fakeVolumesClient{
62 pruneResp: &dto.VolumePruneResponse{
63 VolumesRemoved: 1,
64 SpaceReclaimed: 1024,
65 Volumes: []dto.Volume{{Name: "orphan1", Size: 1024}},
66 },
67 }
68
69 var out bytes.Buffer
70 err := runVolumesPrune(context.Background(), client, volumesPruneOptions{Json: true}, &out)
71 require.NoError(t, err)
72
73 // Should have called PruneVolumes twice: once dry-run (preview), once actual
74 require.Len(t, client.pruneCalls, 2)
75 assert.True(t, client.pruneCalls[0].DryRun, "first call should be dry-run preview")
76 assert.False(t, client.pruneCalls[1].DryRun, "second call should be actual prune")
77 assert.Contains(t, out.String(), `"volumes_removed"`)
78}
79
80func TestRunVolumesPrune_DryRun(t *testing.T) {
81 client := &fakeVolumesClient{
82 pruneResp: &dto.VolumePruneResponse{
83 VolumesRemoved: 2,
84 SpaceReclaimed: 4096,
85 Volumes: []dto.Volume{
86 {Name: "orphan1", Size: 2048},
87 {Name: "orphan2", Size: 2048},
88 },
89 },
90 }
91
92 var out bytes.Buffer
93 err := runVolumesPrune(context.Background(), client, volumesPruneOptions{DryRun: true}, &out)
94 require.NoError(t, err)
95 assert.Contains(t, out.String(), "orphan1")
96}