1package tfe
2
3import (
4	"context"
5	"fmt"
6	"testing"
7
8	"github.com/stretchr/testify/assert"
9	"github.com/stretchr/testify/require"
10)
11
12func TestOrganizationMembershipsList(t *testing.T) {
13	client := testClient(t)
14	ctx := context.Background()
15
16	orgTest, orgTestCleanup := createOrganization(t, client)
17	defer orgTestCleanup()
18
19	t.Run("without list options", func(t *testing.T) {
20		memTest1, memTest1Cleanup := createOrganizationMembership(t, client, orgTest)
21		defer memTest1Cleanup()
22		memTest2, memTest2Cleanup := createOrganizationMembership(t, client, orgTest)
23		defer memTest2Cleanup()
24
25		// The create helper includes the related user, so we should remove it for our equality test
26		memTest1.User = &User{ID: memTest1.User.ID}
27		memTest2.User = &User{ID: memTest2.User.ID}
28
29		ml, err := client.OrganizationMemberships.List(ctx, orgTest.Name, OrganizationMembershipListOptions{})
30		require.NoError(t, err)
31
32		assert.Contains(t, ml.Items, memTest1)
33		assert.Contains(t, ml.Items, memTest2)
34	})
35
36	t.Run("with pagination options", func(t *testing.T) {
37		_, memTest1Cleanup := createOrganizationMembership(t, client, orgTest)
38		defer memTest1Cleanup()
39		_, memTest2Cleanup := createOrganizationMembership(t, client, orgTest)
40		defer memTest2Cleanup()
41
42		ml, err := client.OrganizationMemberships.List(ctx, orgTest.Name, OrganizationMembershipListOptions{
43			ListOptions: ListOptions{
44				PageNumber: 999,
45				PageSize:   100,
46			},
47		})
48
49		require.NoError(t, err)
50		assert.Empty(t, ml.Items)
51		assert.Equal(t, 999, ml.CurrentPage)
52
53		// Three because the creator of the organizaiton is a member, in addition to the two we added to setup the test.
54		assert.Equal(t, 3, ml.TotalCount)
55	})
56
57	t.Run("with include options", func(t *testing.T) {
58		memTest1, memTest1Cleanup := createOrganizationMembership(t, client, orgTest)
59		defer memTest1Cleanup()
60		memTest2, memTest2Cleanup := createOrganizationMembership(t, client, orgTest)
61		defer memTest2Cleanup()
62
63		ml, err := client.OrganizationMemberships.List(ctx, orgTest.Name, OrganizationMembershipListOptions{
64			Include: "user",
65		})
66		require.NoError(t, err)
67
68		assert.Contains(t, ml.Items, memTest1)
69		assert.Contains(t, ml.Items, memTest2)
70	})
71
72	t.Run("without a valid organization", func(t *testing.T) {
73		ml, err := client.OrganizationMemberships.List(ctx, badIdentifier, OrganizationMembershipListOptions{})
74		assert.Nil(t, ml)
75		assert.EqualError(t, err, "invalid value for organization")
76	})
77}
78
79func TestOrganizationMembershipsCreate(t *testing.T) {
80	client := testClient(t)
81	ctx := context.Background()
82
83	orgTest, orgTestCleanup := createOrganization(t, client)
84	defer orgTestCleanup()
85
86	t.Run("with valid options", func(t *testing.T) {
87		options := OrganizationMembershipCreateOptions{
88			Email: String(fmt.Sprintf("%s@tfe.local", randomString(t))),
89		}
90
91		mem, err := client.OrganizationMemberships.Create(ctx, orgTest.Name, options)
92		require.NoError(t, err)
93
94		// Get a refreshed view from the API.
95		refreshed, err := client.OrganizationMemberships.ReadWithOptions(ctx, mem.ID, OrganizationMembershipReadOptions{
96			Include: "user",
97		})
98		require.NoError(t, err)
99		assert.Equal(t, refreshed, mem)
100	})
101
102	t.Run("when options is missing email", func(t *testing.T) {
103		mem, err := client.OrganizationMemberships.Create(ctx, orgTest.Name, OrganizationMembershipCreateOptions{})
104
105		assert.Nil(t, mem)
106		assert.EqualError(t, err, "email is required")
107	})
108
109	t.Run("with an invalid organization", func(t *testing.T) {
110		mem, err := client.OrganizationMemberships.Create(ctx, badIdentifier, OrganizationMembershipCreateOptions{
111			Email: String(fmt.Sprintf("%s@tfe.local", randomString(t))),
112		})
113
114		assert.Nil(t, mem)
115		assert.EqualError(t, err, "invalid value for organization")
116	})
117
118	t.Run("when an error is returned from the api", func(t *testing.T) {
119		mem, err := client.OrganizationMemberships.Create(ctx, orgTest.Name, OrganizationMembershipCreateOptions{
120			Email: String("not-an-email-address"),
121		})
122
123		assert.Nil(t, mem)
124		assert.Error(t, err)
125	})
126}
127
128func TestOrganizationMembershipsRead(t *testing.T) {
129	client := testClient(t)
130	ctx := context.Background()
131
132	memTest, memTestCleanup := createOrganizationMembership(t, client, nil)
133	defer memTestCleanup()
134
135	// The create API endpoint automatically includes the related user, so we should drop
136	// the additional parts of the user which get deserialized.
137	memTest.User = &User{
138		ID: memTest.User.ID,
139	}
140
141	t.Run("when the membership exists", func(t *testing.T) {
142		mem, err := client.OrganizationMemberships.Read(ctx, memTest.ID)
143		require.NoError(t, err)
144
145		assert.Equal(t, memTest, mem)
146	})
147
148	t.Run("when the membership does not exist", func(t *testing.T) {
149		mem, err := client.OrganizationMemberships.Read(ctx, "nonexisting")
150		assert.Nil(t, mem)
151		assert.Equal(t, err, ErrResourceNotFound)
152	})
153
154	t.Run("with invalid membership id", func(t *testing.T) {
155		mem, err := client.OrganizationMemberships.Read(ctx, badIdentifier)
156		assert.Nil(t, mem)
157		assert.EqualError(t, err, "invalid value for membership")
158	})
159}
160
161func TestOrganizationMembershipsReadWithOptions(t *testing.T) {
162	client := testClient(t)
163	ctx := context.Background()
164
165	memTest, memTestCleanup := createOrganizationMembership(t, client, nil)
166	defer memTestCleanup()
167
168	options := OrganizationMembershipReadOptions{
169		Include: "user",
170	}
171
172	t.Run("when the membership exists", func(t *testing.T) {
173		mem, err := client.OrganizationMemberships.ReadWithOptions(ctx, memTest.ID, options)
174		require.NoError(t, err)
175
176		assert.Equal(t, memTest, mem)
177	})
178
179	t.Run("when the membership does not exist", func(t *testing.T) {
180		mem, err := client.OrganizationMemberships.ReadWithOptions(ctx, "nonexisting", options)
181		assert.Nil(t, mem)
182		assert.Equal(t, err, ErrResourceNotFound)
183	})
184
185	t.Run("with invalid membership id", func(t *testing.T) {
186		mem, err := client.OrganizationMemberships.ReadWithOptions(ctx, badIdentifier, options)
187		assert.Nil(t, mem)
188		assert.EqualError(t, err, "invalid value for membership")
189	})
190}
191
192func TestOrganizationMembershipsDelete(t *testing.T) {
193	client := testClient(t)
194	ctx := context.Background()
195
196	orgTest, orgTestCleanup := createOrganization(t, client)
197	defer orgTestCleanup()
198
199	mem, _ := createOrganizationMembership(t, client, orgTest)
200
201	t.Run("with valid options", func(t *testing.T) {
202		err := client.OrganizationMemberships.Delete(ctx, mem.ID)
203		require.NoError(t, err)
204
205		// Get a refreshed view from the API.
206		refreshed, err := client.OrganizationMemberships.List(ctx, orgTest.Name, OrganizationMembershipListOptions{})
207		require.NoError(t, err)
208		assert.NotContains(t, refreshed.Items, mem)
209	})
210
211	t.Run("when membership is invalid", func(t *testing.T) {
212		err := client.OrganizationMemberships.Delete(ctx, badIdentifier)
213
214		assert.EqualError(t, err, "invalid value for membership")
215	})
216
217	t.Run("when an error is returned from the api", func(t *testing.T) {
218		err := client.OrganizationMemberships.Delete(ctx, "not-an-identifier")
219
220		assert.Error(t, err)
221	})
222}
223