|
1 | 1 | package cli |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "context" |
| 5 | + "io" |
| 6 | + "os" |
| 7 | + "path/filepath" |
4 | 8 | "testing" |
5 | 9 |
|
6 | 10 | "github.com/spf13/cobra" |
| 11 | + |
| 12 | + "github.com/git-pkgs/forge" |
| 13 | + "github.com/git-pkgs/forge/internal/resolve" |
7 | 14 | ) |
8 | 15 |
|
9 | 16 | const flagTypeBool = "bool" |
@@ -69,45 +76,146 @@ func TestReleaseSubcommands(t *testing.T) { |
69 | 76 | } |
70 | 77 | } |
71 | 78 |
|
72 | | -func TestReleaseUploadTagFlag(t *testing.T) { |
73 | | - cmd := releaseUploadCmd() |
| 79 | +// mockReleaseService implements forges.ReleaseService, recording UploadAsset calls. |
| 80 | +type mockReleaseService struct { |
| 81 | + uploadCalls int |
| 82 | + uploadTag string |
| 83 | + uploadBody []byte |
| 84 | +} |
74 | 85 |
|
75 | | - f := cmd.Flags().Lookup("tag") |
76 | | - if f == nil { |
77 | | - t.Fatal("expected --tag flag to exist") |
| 86 | +func (m *mockReleaseService) List(_ context.Context, _, _ string, _ forges.ListReleaseOpts) ([]forges.Release, error) { |
| 87 | + return nil, nil |
| 88 | +} |
| 89 | + |
| 90 | +func (m *mockReleaseService) Get(_ context.Context, _, _, _ string) (*forges.Release, error) { |
| 91 | + return nil, nil |
| 92 | +} |
| 93 | + |
| 94 | +func (m *mockReleaseService) GetLatest(_ context.Context, _, _ string) (*forges.Release, error) { |
| 95 | + return nil, nil |
| 96 | +} |
| 97 | + |
| 98 | +func (m *mockReleaseService) Create(_ context.Context, _, _ string, _ forges.CreateReleaseOpts) (*forges.Release, error) { |
| 99 | + return nil, nil |
| 100 | +} |
| 101 | + |
| 102 | +func (m *mockReleaseService) Update(_ context.Context, _, _, _ string, _ forges.UpdateReleaseOpts) (*forges.Release, error) { |
| 103 | + return nil, nil |
| 104 | +} |
| 105 | + |
| 106 | +func (m *mockReleaseService) Delete(_ context.Context, _, _, _ string) error { |
| 107 | + return nil |
| 108 | +} |
| 109 | + |
| 110 | +func (m *mockReleaseService) UploadAsset(_ context.Context, _, _, tag string, file *os.File) (*forges.ReleaseAsset, error) { |
| 111 | + m.uploadCalls++ |
| 112 | + m.uploadTag = tag |
| 113 | + body, err := io.ReadAll(file) |
| 114 | + if err != nil { |
| 115 | + return nil, err |
78 | 116 | } |
79 | | - if f.Value.Type() != "string" { |
80 | | - t.Errorf("expected --tag to be string, got %s", f.Value.Type()) |
| 117 | + m.uploadBody = body |
| 118 | + return &forges.ReleaseAsset{Name: filepath.Base(file.Name()), Size: len(body)}, nil |
| 119 | +} |
| 120 | + |
| 121 | +func (m *mockReleaseService) DownloadAsset(_ context.Context, _, _ string, _ int64) (io.ReadCloser, error) { |
| 122 | + return nil, nil |
| 123 | +} |
| 124 | + |
| 125 | +func TestReleaseUploadCommand(t *testing.T) { |
| 126 | + const contents = "fake-zip-bytes" |
| 127 | + |
| 128 | + tests := []struct { |
| 129 | + name string |
| 130 | + args []string |
| 131 | + wantTag string |
| 132 | + wantErr bool |
| 133 | + }{ |
| 134 | + {name: "positional tag and file", args: []string{"v1.0.0", "{file}"}, wantTag: "v1.0.0"}, |
| 135 | + {name: "tag flag and file", args: []string{"--tag", "v1.0.0", "{file}"}, wantTag: "v1.0.0"}, |
| 136 | + {name: "tag flag with positional tag too", args: []string{"--tag", "v1.0.0", "v1.0.0", "{file}"}, wantErr: true}, |
| 137 | + {name: "empty tag flag with positional tag", args: []string{"--tag", "", "v1.0.0", "{file}"}, wantErr: true}, |
| 138 | + {name: "empty tag flag without positional tag", args: []string{"--tag", "", "{file}"}, wantErr: true}, |
| 139 | + {name: "no tag at all", args: []string{"{file}"}, wantErr: true}, |
| 140 | + {name: "tag flag without a file", args: []string{"--tag", "v1.0.0"}, wantErr: true}, |
| 141 | + } |
| 142 | + |
| 143 | + for _, tt := range tests { |
| 144 | + t.Run(tt.name, func(t *testing.T) { |
| 145 | + file := filepath.Join(t.TempDir(), "app.zip") |
| 146 | + if err := os.WriteFile(file, []byte(contents), 0644); err != nil { |
| 147 | + t.Fatalf("writing test file: %v", err) |
| 148 | + } |
| 149 | + args := make([]string, len(tt.args)) |
| 150 | + for i, a := range tt.args { |
| 151 | + if a == "{file}" { |
| 152 | + a = file |
| 153 | + } |
| 154 | + args[i] = a |
| 155 | + } |
| 156 | + |
| 157 | + releases := &mockReleaseService{} |
| 158 | + resolve.SetTestForge(&mockForge{releaseService: releases}, "owner", "repo", "example.com") |
| 159 | + t.Cleanup(resolve.ResetTestForge) |
| 160 | + |
| 161 | + cmd := releaseUploadCmd() |
| 162 | + cmd.SetArgs(args) |
| 163 | + err := cmd.Execute() |
| 164 | + if tt.wantErr { |
| 165 | + if err == nil { |
| 166 | + t.Fatalf("expected error, got success (tag %q uploaded)", releases.uploadTag) |
| 167 | + } |
| 168 | + if releases.uploadCalls != 0 { |
| 169 | + t.Errorf("UploadAsset calls = %d, want 0", releases.uploadCalls) |
| 170 | + } |
| 171 | + return |
| 172 | + } |
| 173 | + if err != nil { |
| 174 | + t.Fatalf("unexpected error: %v", err) |
| 175 | + } |
| 176 | + if releases.uploadCalls != 1 { |
| 177 | + t.Fatalf("UploadAsset calls = %d, want 1", releases.uploadCalls) |
| 178 | + } |
| 179 | + if releases.uploadTag != tt.wantTag { |
| 180 | + t.Errorf("uploaded tag = %q, want %q", releases.uploadTag, tt.wantTag) |
| 181 | + } |
| 182 | + if string(releases.uploadBody) != contents { |
| 183 | + t.Errorf("uploaded body = %q, want %q", releases.uploadBody, contents) |
| 184 | + } |
| 185 | + }) |
81 | 186 | } |
82 | 187 | } |
83 | 188 |
|
84 | 189 | func TestUploadTagAndFile(t *testing.T) { |
85 | 190 | tests := []struct { |
86 | | - name string |
87 | | - flagTag string |
88 | | - args []string |
89 | | - wantTag string |
90 | | - wantFile string |
91 | | - wantErr bool |
| 191 | + name string |
| 192 | + flagTag string |
| 193 | + tagChanged bool |
| 194 | + args []string |
| 195 | + wantTag string |
| 196 | + wantFile string |
| 197 | + wantErr bool |
92 | 198 | }{ |
93 | 199 | {name: "positional tag and file", args: []string{"v1.0.0", "app.zip"}, wantTag: "v1.0.0", wantFile: "app.zip"}, |
94 | | - {name: "tag flag and file", flagTag: "v1.0.0", args: []string{"app.zip"}, wantTag: "v1.0.0", wantFile: "app.zip"}, |
95 | | - {name: "tag flag with positional tag too", flagTag: "v1.0.0", args: []string{"v1.0.0", "app.zip"}, wantErr: true}, |
| 200 | + {name: "tag flag and file", flagTag: "v1.0.0", tagChanged: true, args: []string{"app.zip"}, wantTag: "v1.0.0", wantFile: "app.zip"}, |
| 201 | + {name: "tag flag with positional tag too", flagTag: "v1.0.0", tagChanged: true, args: []string{"v1.0.0", "app.zip"}, wantErr: true}, |
| 202 | + {name: "empty tag flag with positional tag", tagChanged: true, args: []string{"v1.0.0", "app.zip"}, wantErr: true}, |
| 203 | + {name: "empty tag flag without positional tag", tagChanged: true, args: []string{"app.zip"}, wantErr: true}, |
96 | 204 | {name: "no tag at all", args: []string{"app.zip"}, wantErr: true}, |
97 | 205 | {name: "no arguments", wantErr: true}, |
98 | | - {name: "tag flag without a file", flagTag: "v1.0.0", wantErr: true}, |
| 206 | + {name: "tag flag without a file", flagTag: "v1.0.0", tagChanged: true, wantErr: true}, |
99 | 207 | {name: "too many positional arguments", args: []string{"v1.0.0", "a.zip", "b.zip"}, wantErr: true}, |
100 | 208 | } |
101 | 209 |
|
102 | 210 | for _, tt := range tests { |
103 | 211 | t.Run(tt.name, func(t *testing.T) { |
104 | | - tag, file, err := uploadTagAndFile(tt.flagTag, tt.args) |
| 212 | + tag, file, err := uploadTagAndFile(tt.flagTag, tt.tagChanged, tt.args) |
105 | 213 | if (err != nil) != tt.wantErr { |
106 | | - t.Fatalf("uploadTagAndFile(%q, %v) error = %v, wantErr %v", tt.flagTag, tt.args, err, tt.wantErr) |
| 214 | + t.Fatalf("uploadTagAndFile(%q, %v, %v) error = %v, wantErr %v", tt.flagTag, tt.tagChanged, tt.args, err, tt.wantErr) |
107 | 215 | } |
108 | 216 | if tag != tt.wantTag || file != tt.wantFile { |
109 | | - t.Errorf("uploadTagAndFile(%q, %v) = (%q, %q), want (%q, %q)", |
110 | | - tt.flagTag, tt.args, tag, file, tt.wantTag, tt.wantFile) |
| 217 | + t.Errorf("uploadTagAndFile(%q, %v, %v) = (%q, %q), want (%q, %q)", |
| 218 | + tt.flagTag, tt.tagChanged, tt.args, tag, file, tt.wantTag, tt.wantFile) |
111 | 219 | } |
112 | 220 | }) |
113 | 221 | } |
|
0 commit comments