Skip to content

Commit 375a205

Browse files
chore: add acceptance tests to user data source (#23)
1 parent ee5c4e5 commit 375a205

File tree

5 files changed

+115
-52
lines changed

5 files changed

+115
-52
lines changed

docs/data-sources/user.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@ An existing user on the coder deployment
2222

2323
### Read-Only
2424

25+
- `avatar_url` (String) URL of the user's avatar.
2526
- `created_at` (Number) Unix timestamp of when the user was created.
2627
- `email` (String) Email of the user.
2728
- `last_seen_at` (Number) Unix timestamp of when the user was last seen.
2829
- `login_type` (String) Type of login for the user. Valid types are 'none', 'password', 'github', and 'oidc'.
29-
- `name` (String) Display name of the user. Defaults to username.
30+
- `name` (String) Display name of the user.
3031
- `organization_ids` (Set of String) IDs of organizations the user is associated with.
3132
- `roles` (Set of String) Roles assigned to the user. Valid roles are 'owner', 'template-admin', 'user-admin', and 'auditor'.
3233
- `suspended` (Boolean) Whether the user is suspended.

integration/user-test/main.tf

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@ data "coderd_user" "ethan" {
2222
}
2323

2424
resource "coderd_user" "ethan2" {
25-
username = "${data.coderd_user.ethan.username}2"
26-
name = "${data.coderd_user.ethan.name}2"
27-
email = "${data.coderd_user.ethan.email}.au"
28-
roles = data.coderd_user.ethan.roles
25+
username = "${data.coderd_user.ethan.username}2"
26+
name = "${data.coderd_user.ethan.name}2"
27+
email = "${data.coderd_user.ethan.email}.au"
28+
roles = data.coderd_user.ethan.roles
2929
suspended = data.coderd_user.ethan.suspended
3030
}
31-

internal/provider/user_data_source.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@ func (d *UserDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
155155
resp.Diagnostics.AddError("Client Error", "User is not associated with any organizations")
156156
return
157157
}
158+
if !data.ID.IsNull() && user.ID.String() != data.ID.ValueString() {
159+
resp.Diagnostics.AddError("Client Error", "Retrieved User's ID does not match the provided ID")
160+
return
161+
} else if !data.Username.IsNull() && user.Username != data.Username.ValueString() {
162+
resp.Diagnostics.AddError("Client Error", "Retrieved User's username does not match the provided username")
163+
return
164+
}
158165

159166
data.ID = types.StringValue(user.ID.String())
160167
data.Username = types.StringValue(user.Username)

internal/provider/user_data_source_test.go

Lines changed: 98 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,119 @@
11
package provider
22

3-
/*
43
import (
4+
"context"
55
"html/template"
6+
"os"
7+
"regexp"
68
"strings"
79
"testing"
810

11+
"github.com/coder/coder/v2/codersdk"
12+
"github.com/coder/terraform-provider-coderd/integration"
913
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
14+
"github.com/stretchr/testify/require"
1015
)
1116

1217
func TestAccUserDataSource(t *testing.T) {
13-
// User by Username
14-
resource.Test(t, resource.TestCase{
15-
PreCheck: func() { testAccPreCheck(t) },
16-
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
17-
Steps: []resource.TestStep{
18-
{
19-
Config: testAccUserDataSourceConfig{
20-
Username: "example",
21-
}.String(t),
22-
Check: resource.ComposeAggregateTestCheckFunc(
23-
resource.TestCheckResourceAttr("coderd_user.test", "username", "example"),
24-
resource.TestCheckResourceAttr("coderd_user.test", "name", "Example User"),
25-
resource.TestCheckResourceAttr("coderd_user.test", "email", "[email protected]"),
26-
resource.TestCheckResourceAttr("coderd_user.test", "roles.#", "2"),
27-
resource.TestCheckResourceAttr("coderd_user.test", "roles.0", "auditor"),
28-
resource.TestCheckResourceAttr("coderd_user.test", "roles.1", "owner"),
29-
resource.TestCheckResourceAttr("coderd_user.test", "login_type", "password"),
30-
resource.TestCheckResourceAttr("coderd_user.test", "password", "SomeSecurePassword!"),
31-
resource.TestCheckResourceAttr("coderd_user.test", "suspended", "false"),
32-
),
18+
if os.Getenv("TF_ACC") == "" {
19+
t.Skip("Acceptance tests are disabled.")
20+
}
21+
ctx := context.Background()
22+
client := integration.StartCoder(ctx, t, "user_data_acc")
23+
firstUser, err := client.User(ctx, codersdk.Me)
24+
require.NoError(t, err)
25+
user, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
26+
27+
Username: "example",
28+
Password: "SomeSecurePassword!",
29+
UserLoginType: "password",
30+
OrganizationID: firstUser.OrganizationIDs[0],
31+
})
32+
require.NoError(t, err)
33+
_, err = client.UpdateUserRoles(ctx, user.Username, codersdk.UpdateRoles{
34+
Roles: []string{"auditor"},
35+
})
36+
require.NoError(t, err)
37+
_, err = client.UpdateUserProfile(ctx, user.Username, codersdk.UpdateUserProfileRequest{
38+
Username: user.Username,
39+
Name: "Example User",
40+
})
41+
require.NoError(t, err)
42+
t.Run("UserByUsername", func(t *testing.T) {
43+
cfg := testAccUserDataSourceConfig{
44+
URL: client.URL.String(),
45+
Token: client.SessionToken(),
46+
Username: user.Username,
47+
}
48+
resource.Test(t, resource.TestCase{
49+
PreCheck: func() { testAccPreCheck(t) },
50+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
51+
Steps: []resource.TestStep{
52+
{
53+
Config: cfg.String(t),
54+
Check: resource.ComposeAggregateTestCheckFunc(
55+
resource.TestCheckResourceAttr("data.coderd_user.test", "username", "example"),
56+
resource.TestCheckResourceAttr("data.coderd_user.test", "name", "Example User"),
57+
resource.TestCheckResourceAttr("data.coderd_user.test", "email", "[email protected]"),
58+
resource.TestCheckResourceAttr("data.coderd_user.test", "roles.#", "1"),
59+
resource.TestCheckResourceAttr("data.coderd_user.test", "roles.0", "auditor"),
60+
resource.TestCheckResourceAttr("data.coderd_user.test", "login_type", "password"),
61+
resource.TestCheckResourceAttr("data.coderd_user.test", "suspended", "false"),
62+
),
63+
},
3364
},
34-
},
65+
})
3566
})
36-
resource.Test(t, resource.TestCase{
37-
PreCheck: func() { testAccPreCheck(t) },
38-
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
39-
// User by ID
40-
Steps: []resource.TestStep{
41-
{
42-
Config: testAccUserDataSourceConfig{
43-
ID: "example",
44-
}.String(t),
45-
Check: resource.ComposeAggregateTestCheckFunc(
46-
resource.TestCheckResourceAttr("coderd_user.test", "username", "example"),
47-
resource.TestCheckResourceAttr("coderd_user.test", "name", "Example User"),
48-
resource.TestCheckResourceAttr("coderd_user.test", "email", "[email protected]"),
49-
resource.TestCheckResourceAttr("coderd_user.test", "roles.#", "2"),
50-
resource.TestCheckResourceAttr("coderd_user.test", "roles.0", "auditor"),
51-
resource.TestCheckResourceAttr("coderd_user.test", "roles.1", "owner"),
52-
resource.TestCheckResourceAttr("coderd_user.test", "login_type", "password"),
53-
resource.TestCheckResourceAttr("coderd_user.test", "password", "SomeSecurePassword!"),
54-
resource.TestCheckResourceAttr("coderd_user.test", "suspended", "false"),
55-
),
67+
68+
t.Run("UserByID", func(t *testing.T) {
69+
cfg := testAccUserDataSourceConfig{
70+
URL: client.URL.String(),
71+
Token: client.SessionToken(),
72+
ID: user.ID.String(),
73+
}
74+
resource.Test(t, resource.TestCase{
75+
PreCheck: func() { testAccPreCheck(t) },
76+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
77+
// User by ID
78+
Steps: []resource.TestStep{
79+
{
80+
Config: cfg.String(t),
81+
Check: resource.ComposeAggregateTestCheckFunc(
82+
resource.TestCheckResourceAttr("data.coderd_user.test", "username", "example"),
83+
resource.TestCheckResourceAttr("data.coderd_user.test", "name", "Example User"),
84+
resource.TestCheckResourceAttr("data.coderd_user.test", "email", "[email protected]"),
85+
resource.TestCheckResourceAttr("data.coderd_user.test", "roles.#", "1"),
86+
resource.TestCheckResourceAttr("data.coderd_user.test", "roles.0", "auditor"),
87+
resource.TestCheckResourceAttr("data.coderd_user.test", "login_type", "password"),
88+
resource.TestCheckResourceAttr("data.coderd_user.test", "suspended", "false"),
89+
),
90+
},
91+
},
92+
})
93+
})
94+
t.Run("NeitherIDNorUsername", func(t *testing.T) {
95+
cfg := testAccUserDataSourceConfig{
96+
URL: client.URL.String(),
97+
Token: client.SessionToken(),
98+
}
99+
resource.Test(t, resource.TestCase{
100+
PreCheck: func() { testAccPreCheck(t) },
101+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
102+
// Neither ID nor Username
103+
Steps: []resource.TestStep{
104+
{
105+
Config: cfg.String(t),
106+
ExpectError: regexp.MustCompile(`At least one of these attributes must be configured: \[id,username\]`),
107+
},
56108
},
57-
},
109+
})
58110
})
111+
59112
}
60113

61114
type testAccUserDataSourceConfig struct {
62-
URL string
63-
Token string
115+
URL string
116+
Token string
64117

65118
ID string
66119
Username string
@@ -92,4 +145,3 @@ data "coderd_user" "test" {
92145

93146
return buf.String()
94147
}
95-
*/

internal/provider/user_resource_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package provider
33
import (
44
"context"
55
"fmt"
6+
"os"
67
"strings"
78
"testing"
89
"text/template"
@@ -13,6 +14,9 @@ import (
1314
)
1415

1516
func TestAccUserResource(t *testing.T) {
17+
if os.Getenv("TF_ACC") == "" {
18+
t.Skip("Acceptance tests are disabled.")
19+
}
1620
ctx := context.Background()
1721
client := integration.StartCoder(ctx, t, "user_acc")
1822

0 commit comments

Comments
 (0)