Skip to content

Commit 3eb6813

Browse files
committed
chore: add golden files for json commands
1 parent 54b0a94 commit 3eb6813

File tree

3 files changed

+170
-8
lines changed

3 files changed

+170
-8
lines changed

cli/root_test.go

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package cli_test
22

33
import (
44
"bytes"
5+
"context"
56
"flag"
67
"fmt"
78
"net/http"
89
"net/http/httptest"
910
"os"
1011
"path/filepath"
12+
"regexp"
1113
"runtime"
1214
"strings"
1315
"testing"
@@ -20,6 +22,8 @@ import (
2022
"github.com/coder/coder/buildinfo"
2123
"github.com/coder/coder/cli"
2224
"github.com/coder/coder/cli/clitest"
25+
"github.com/coder/coder/coderd/coderdtest"
26+
"github.com/coder/coder/coderd/database/dbtestutil"
2327
"github.com/coder/coder/codersdk"
2428
"github.com/coder/coder/testutil"
2529
)
@@ -28,13 +32,17 @@ import (
2832
// make update-golden-files
2933
var updateGoldenFiles = flag.Bool("update", false, "update .golden files")
3034

35+
var timestampRegex = regexp.MustCompile(`(?i)\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d+)?Z`)
36+
3137
//nolint:tparallel,paralleltest // These test sets env vars.
3238
func TestCommandHelp(t *testing.T) {
3339
commonEnv := map[string]string{
3440
"HOME": "~",
3541
"CODER_CONFIG_DIR": "~/.config/coderv2",
3642
}
3743

44+
rootClient, replacements := prepareTestData(t)
45+
3846
type testCase struct {
3947
name string
4048
cmd []string
@@ -59,6 +67,14 @@ func TestCommandHelp(t *testing.T) {
5967
"CODER_AGENT_LOG_DIR": "/tmp",
6068
},
6169
},
70+
{
71+
name: "coder list --output json",
72+
cmd: []string{"list", "--output", "json"},
73+
},
74+
{
75+
name: "coder users list --output json",
76+
cmd: []string{"users", "list", "--output", "json"},
77+
},
6278
}
6379

6480
root := cli.Root(cli.AGPL())
@@ -111,21 +127,33 @@ ExtractCommandPathsLoop:
111127
}
112128
err := os.Chdir(tmpwd)
113129
var buf bytes.Buffer
114-
root, _ := clitest.New(t, tt.cmd...)
115-
root.SetOut(&buf)
130+
cmd, cfg := clitest.New(t, tt.cmd...)
131+
clitest.SetupConfig(t, rootClient, cfg)
132+
cmd.SetOut(&buf)
116133
assert.NoError(t, err)
117-
err = root.ExecuteContext(ctx)
134+
err = cmd.ExecuteContext(ctx)
118135
err2 := os.Chdir(wd)
119136
require.NoError(t, err)
120137
require.NoError(t, err2)
121138

122139
got := buf.Bytes()
123-
// Remove CRLF newlines (Windows).
124-
got = bytes.ReplaceAll(got, []byte{'\r', '\n'}, []byte{'\n'})
125140

126-
// The `coder templates create --help` command prints the path
127-
// to the working directory (--directory flag default value).
128-
got = bytes.ReplaceAll(got, []byte(fmt.Sprintf("%q", tmpwd)), []byte("\"[current directory]\""))
141+
replace := map[string][]byte{
142+
// Remove CRLF newlines (Windows).
143+
string([]byte{'\r', '\n'}): []byte("\n"),
144+
// The `coder templates create --help` command prints the path
145+
// to the working directory (--directory flag default value).
146+
fmt.Sprintf("%q", tmpwd): []byte("\"[current directory]\""),
147+
}
148+
for k, v := range replacements {
149+
replace[k] = []byte(v)
150+
}
151+
for k, v := range replace {
152+
got = bytes.ReplaceAll(got, []byte(k), v)
153+
}
154+
155+
// Replace any timestamps with a placeholder.
156+
got = timestampRegex.ReplaceAll(got, []byte("[timestamp]"))
129157

130158
gf := filepath.Join("testdata", strings.Replace(tt.name, " ", "_", -1)+".golden")
131159
if *updateGoldenFiles {
@@ -156,6 +184,56 @@ func extractVisibleCommandPaths(cmdPath []string, cmds []*cobra.Command) [][]str
156184
return cmdPaths
157185
}
158186

187+
func prepareTestData(t *testing.T) (*codersdk.Client, map[string]string) {
188+
t.Helper()
189+
190+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
191+
defer cancel()
192+
193+
db, pubsub := dbtestutil.NewDB(t)
194+
rootClient := coderdtest.New(t, &coderdtest.Options{
195+
Database: db,
196+
Pubsub: pubsub,
197+
IncludeProvisionerDaemon: true,
198+
})
199+
firstUser := coderdtest.CreateFirstUser(t, rootClient)
200+
secondUser, err := rootClient.CreateUser(ctx, codersdk.CreateUserRequest{
201+
Email: "testuser2@coder.com",
202+
Username: "testuser2",
203+
Password: coderdtest.FirstUserParams.Password,
204+
OrganizationID: firstUser.OrganizationID,
205+
})
206+
require.NoError(t, err)
207+
version := coderdtest.CreateTemplateVersion(t, rootClient, firstUser.OrganizationID, nil)
208+
version = coderdtest.AwaitTemplateVersionJob(t, rootClient, version.ID)
209+
template := coderdtest.CreateTemplate(t, rootClient, firstUser.OrganizationID, version.ID, func(req *codersdk.CreateTemplateRequest) {
210+
req.Name = "test-template"
211+
})
212+
workspace := coderdtest.CreateWorkspace(t, rootClient, firstUser.OrganizationID, template.ID, func(req *codersdk.CreateWorkspaceRequest) {
213+
req.Name = "test-workspace"
214+
})
215+
workspaceBuild := coderdtest.AwaitWorkspaceBuildJob(t, rootClient, workspace.LatestBuild.ID)
216+
217+
replacements := map[string]string{
218+
firstUser.UserID.String(): "[first user ID]",
219+
secondUser.ID.String(): "[second user ID]",
220+
firstUser.OrganizationID.String(): "[first org ID]",
221+
version.ID.String(): "[version ID]",
222+
version.Name: "[version name]",
223+
version.Job.ID.String(): "[version job ID]",
224+
version.Job.FileID.String(): "[version file ID]",
225+
version.Job.WorkerID.String(): "[version worker ID]",
226+
template.ID.String(): "[template ID]",
227+
workspace.ID.String(): "[workspace ID]",
228+
workspaceBuild.ID.String(): "[workspace build ID]",
229+
workspaceBuild.Job.ID.String(): "[workspace build job ID]",
230+
workspaceBuild.Job.FileID.String(): "[workspace build file ID]",
231+
workspaceBuild.Job.WorkerID.String(): "[workspace build worker ID]",
232+
}
233+
234+
return rootClient, replacements
235+
}
236+
159237
func TestRoot(t *testing.T) {
160238
t.Parallel()
161239
t.Run("FormatCobraError", func(t *testing.T) {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
[
2+
{
3+
"id": "[workspace ID]",
4+
"created_at": "[timestamp]",
5+
"updated_at": "[timestamp]",
6+
"owner_id": "[first user ID]",
7+
"owner_name": "testuser",
8+
"template_id": "[template ID]",
9+
"template_name": "test-template",
10+
"template_display_name": "",
11+
"template_icon": "",
12+
"template_allow_user_cancel_workspace_jobs": false,
13+
"latest_build": {
14+
"id": "[workspace build ID]",
15+
"created_at": "[timestamp]",
16+
"updated_at": "[timestamp]",
17+
"workspace_id": "[workspace ID]",
18+
"workspace_name": "test-workspace",
19+
"workspace_owner_id": "[first user ID]",
20+
"workspace_owner_name": "testuser",
21+
"template_version_id": "[version ID]",
22+
"template_version_name": "[version name]",
23+
"build_number": 1,
24+
"transition": "start",
25+
"initiator_id": "[first user ID]",
26+
"initiator_name": "testuser",
27+
"job": {
28+
"id": "[workspace build job ID]",
29+
"created_at": "[timestamp]",
30+
"started_at": "[timestamp]",
31+
"completed_at": "[timestamp]",
32+
"status": "succeeded",
33+
"worker_id": "[workspace build worker ID]",
34+
"file_id": "[workspace build file ID]",
35+
"tags": {
36+
"scope": "organization"
37+
}
38+
},
39+
"reason": "initiator",
40+
"resources": [],
41+
"deadline": "[timestamp]",
42+
"status": "running",
43+
"daily_cost": 0
44+
},
45+
"outdated": false,
46+
"name": "test-workspace",
47+
"autostart_schedule": "CRON_TZ=US/Central 30 9 * * 1-5",
48+
"ttl_ms": 28800000,
49+
"last_used_at": "[timestamp]"
50+
}
51+
]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[
2+
{
3+
"id": "[first user ID]",
4+
"username": "testuser",
5+
"email": "testuser@coder.com",
6+
"created_at": "[timestamp]",
7+
"last_seen_at": "[timestamp]",
8+
"status": "active",
9+
"organization_ids": [
10+
"[first org ID]"
11+
],
12+
"roles": [
13+
{
14+
"name": "owner",
15+
"display_name": "Owner"
16+
}
17+
],
18+
"avatar_url": ""
19+
},
20+
{
21+
"id": "[second user ID]",
22+
"username": "testuser2",
23+
"email": "testuser2@coder.com",
24+
"created_at": "[timestamp]",
25+
"last_seen_at": "[timestamp]",
26+
"status": "active",
27+
"organization_ids": [
28+
"[first org ID]"
29+
],
30+
"roles": [],
31+
"avatar_url": ""
32+
}
33+
]

0 commit comments

Comments
 (0)