1package tfe
2
3import (
4	"context"
5	"testing"
6
7	"github.com/stretchr/testify/assert"
8	"github.com/stretchr/testify/require"
9)
10
11func TestTeamAccessesList(t *testing.T) {
12	client := testClient(t)
13	ctx := context.Background()
14
15	orgTest, orgTestCleanup := createOrganization(t, client)
16	defer orgTestCleanup()
17
18	wTest, _ := createWorkspace(t, client, orgTest)
19
20	tmTest1, tmTest1Cleanup := createTeam(t, client, orgTest)
21	defer tmTest1Cleanup()
22	tmTest2, tmTest2Cleanup := createTeam(t, client, orgTest)
23	defer tmTest2Cleanup()
24
25	taTest1, taTest1Cleanup := createTeamAccess(t, client, tmTest1, wTest, orgTest)
26	defer taTest1Cleanup()
27	taTest2, taTest2Cleanup := createTeamAccess(t, client, tmTest2, wTest, orgTest)
28	defer taTest2Cleanup()
29
30	t.Run("with valid options", func(t *testing.T) {
31		tal, err := client.TeamAccess.List(ctx, TeamAccessListOptions{
32			WorkspaceID: String(wTest.ID),
33		})
34		require.NoError(t, err)
35		assert.Contains(t, tal.Items, taTest1)
36		assert.Contains(t, tal.Items, taTest2)
37
38		t.Skip("paging not supported yet in API")
39		assert.Equal(t, 1, tal.CurrentPage)
40		assert.Equal(t, 2, tal.TotalCount)
41	})
42
43	t.Run("with list options", func(t *testing.T) {
44		t.Skip("paging not supported yet in API")
45		// Request a page number which is out of range. The result should
46		// be successful, but return no results if the paging options are
47		// properly passed along.
48		tal, err := client.TeamAccess.List(ctx, TeamAccessListOptions{
49			ListOptions: ListOptions{
50				PageNumber: 999,
51				PageSize:   100,
52			},
53		})
54		require.NoError(t, err)
55		assert.Empty(t, tal.Items)
56		assert.Equal(t, 999, tal.CurrentPage)
57		assert.Equal(t, 2, tal.TotalCount)
58	})
59
60	t.Run("without list options", func(t *testing.T) {
61		tal, err := client.TeamAccess.List(ctx, TeamAccessListOptions{})
62		assert.Nil(t, tal)
63		assert.EqualError(t, err, "workspace ID is required")
64	})
65
66	t.Run("without a valid workspace ID", func(t *testing.T) {
67		tal, err := client.TeamAccess.List(ctx, TeamAccessListOptions{
68			WorkspaceID: String(badIdentifier),
69		})
70		assert.Nil(t, tal)
71		assert.EqualError(t, err, "invalid value for workspace ID")
72	})
73}
74
75func TestTeamAccessesAdd(t *testing.T) {
76	client := testClient(t)
77	ctx := context.Background()
78
79	orgTest, orgTestCleanup := createOrganization(t, client)
80	defer orgTestCleanup()
81
82	wTest, _ := createWorkspace(t, client, orgTest)
83
84	tmTest, tmTestCleanup := createTeam(t, client, orgTest)
85	defer tmTestCleanup()
86
87	t.Run("with valid options", func(t *testing.T) {
88		options := TeamAccessAddOptions{
89			Access:    Access(AccessAdmin),
90			Team:      tmTest,
91			Workspace: wTest,
92		}
93
94		ta, err := client.TeamAccess.Add(ctx, options)
95		defer client.TeamAccess.Remove(ctx, ta.ID)
96
97		require.NoError(t, err)
98
99		// Get a refreshed view from the API.
100		refreshed, err := client.TeamAccess.Read(ctx, ta.ID)
101		require.NoError(t, err)
102
103		for _, item := range []*TeamAccess{
104			ta,
105			refreshed,
106		} {
107			assert.NotEmpty(t, item.ID)
108			assert.Equal(t, *options.Access, item.Access)
109		}
110	})
111
112	t.Run("with valid custom options", func(t *testing.T) {
113		options := TeamAccessAddOptions{
114			Access:        Access(AccessCustom),
115			Runs:          RunsPermission(RunsPermissionRead),
116			StateVersions: StateVersionsPermission(StateVersionsPermissionNone),
117			Team:          tmTest,
118			Workspace:     wTest,
119		}
120
121		ta, err := client.TeamAccess.Add(ctx, options)
122		defer client.TeamAccess.Remove(ctx, ta.ID)
123
124		require.NoError(t, err)
125
126		// Get a refreshed view from the API.
127		refreshed, err := client.TeamAccess.Read(ctx, ta.ID)
128		require.NoError(t, err)
129
130		for _, item := range []*TeamAccess{
131			ta,
132			refreshed,
133		} {
134			assert.NotEmpty(t, item.ID)
135			assert.Equal(t, *options.Access, item.Access)
136		}
137	})
138
139	t.Run("with invalid custom options", func(t *testing.T) {
140		options := TeamAccessAddOptions{
141			Access:    Access(AccessRead),
142			Runs:      RunsPermission(RunsPermissionApply),
143			Team:      tmTest,
144			Workspace: wTest,
145		}
146
147		_, err := client.TeamAccess.Add(ctx, options)
148
149		assert.EqualError(t, err, "invalid attribute\n\nRuns is read-only when access level is 'read'; use the 'custom' access level to set this attribute.")
150	})
151
152	t.Run("when the team already has access", func(t *testing.T) {
153		_, taTestCleanup := createTeamAccess(t, client, tmTest, wTest, nil)
154		defer taTestCleanup()
155
156		options := TeamAccessAddOptions{
157			Access:    Access(AccessAdmin),
158			Team:      tmTest,
159			Workspace: wTest,
160		}
161
162		_, err := client.TeamAccess.Add(ctx, options)
163		assert.Error(t, err)
164	})
165
166	t.Run("when options is missing access", func(t *testing.T) {
167		ta, err := client.TeamAccess.Add(ctx, TeamAccessAddOptions{
168			Team:      tmTest,
169			Workspace: wTest,
170		})
171		assert.Nil(t, ta)
172		assert.EqualError(t, err, "access is required")
173	})
174
175	t.Run("when options is missing team", func(t *testing.T) {
176		ta, err := client.TeamAccess.Add(ctx, TeamAccessAddOptions{
177			Access:    Access(AccessAdmin),
178			Workspace: wTest,
179		})
180		assert.Nil(t, ta)
181		assert.EqualError(t, err, "team is required")
182	})
183
184	t.Run("when options is missing workspace", func(t *testing.T) {
185		ta, err := client.TeamAccess.Add(ctx, TeamAccessAddOptions{
186			Access: Access(AccessAdmin),
187			Team:   tmTest,
188		})
189		assert.Nil(t, ta)
190		assert.EqualError(t, err, "workspace is required")
191	})
192}
193
194func TestTeamAccessesRead(t *testing.T) {
195	client := testClient(t)
196	ctx := context.Background()
197
198	taTest, taTestCleanup := createTeamAccess(t, client, nil, nil, nil)
199	defer taTestCleanup()
200
201	t.Run("when the team access exists", func(t *testing.T) {
202		ta, err := client.TeamAccess.Read(ctx, taTest.ID)
203		require.NoError(t, err)
204
205		assert.Equal(t, AccessAdmin, ta.Access)
206
207		t.Run("permission attributes are decoded", func(t *testing.T) {
208			assert.Equal(t, RunsPermissionApply, ta.Runs)
209			assert.Equal(t, VariablesPermissionWrite, ta.Variables)
210			assert.Equal(t, StateVersionsPermissionWrite, ta.StateVersions)
211			assert.Equal(t, SentinelMocksPermissionRead, ta.SentinelMocks)
212			assert.Equal(t, true, ta.WorkspaceLocking)
213		})
214
215		t.Run("team relationship is decoded", func(t *testing.T) {
216			assert.NotEmpty(t, ta.Team)
217		})
218
219		t.Run("workspace relationship is decoded", func(t *testing.T) {
220			assert.NotEmpty(t, ta.Workspace)
221		})
222	})
223
224	t.Run("when the team access does not exist", func(t *testing.T) {
225		ta, err := client.TeamAccess.Read(ctx, "nonexisting")
226		assert.Nil(t, ta)
227		assert.Equal(t, err, ErrResourceNotFound)
228	})
229
230	t.Run("without a valid team access ID", func(t *testing.T) {
231		ta, err := client.TeamAccess.Read(ctx, badIdentifier)
232		assert.Nil(t, ta)
233		assert.EqualError(t, err, "invalid value for team access ID")
234	})
235}
236
237func TestTeamAccessesUpdate(t *testing.T) {
238	client := testClient(t)
239	ctx := context.Background()
240
241	orgTest, orgTestCleanup := createOrganization(t, client)
242	defer orgTestCleanup()
243
244	wTest, wTestCleanup := createWorkspace(t, client, orgTest)
245	defer wTestCleanup()
246
247	tmTest, tmTestCleanup := createTeam(t, client, orgTest)
248	defer tmTestCleanup()
249
250	taTest, taTestCleanup := createTeamAccess(t, client, tmTest, wTest, nil)
251	defer taTestCleanup()
252
253	t.Run("with valid attributes", func(t *testing.T) {
254		options := TeamAccessUpdateOptions{
255			Access: Access(AccessCustom),
256			Runs:   RunsPermission(RunsPermissionPlan),
257		}
258
259		ta, err := client.TeamAccess.Update(ctx, taTest.ID, options)
260		require.NoError(t, err)
261
262		assert.Equal(t, ta.Access, AccessCustom)
263		assert.Equal(t, ta.Runs, RunsPermissionPlan)
264	})
265}
266
267func TestTeamAccessesRemove(t *testing.T) {
268	client := testClient(t)
269	ctx := context.Background()
270
271	orgTest, orgTestCleanup := createOrganization(t, client)
272	defer orgTestCleanup()
273
274	tmTest, tmTestCleanup := createTeam(t, client, orgTest)
275	defer tmTestCleanup()
276
277	taTest, _ := createTeamAccess(t, client, tmTest, nil, orgTest)
278
279	t.Run("with valid options", func(t *testing.T) {
280		err := client.TeamAccess.Remove(ctx, taTest.ID)
281		require.NoError(t, err)
282
283		// Try loading the workspace - it should fail.
284		_, err = client.TeamAccess.Read(ctx, taTest.ID)
285		assert.Equal(t, err, ErrResourceNotFound)
286	})
287
288	t.Run("when the team access does not exist", func(t *testing.T) {
289		err := client.TeamAccess.Remove(ctx, taTest.ID)
290		assert.Equal(t, err, ErrResourceNotFound)
291	})
292
293	t.Run("when the team access ID is invalid", func(t *testing.T) {
294		err := client.TeamAccess.Remove(ctx, badIdentifier)
295		assert.EqualError(t, err, "invalid value for team access ID")
296	})
297}
298