workos 2.16.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/Gemfile.lock +5 -14
  4. data/lib/workos/authentication_factor_and_challenge.rb +31 -0
  5. data/lib/workos/authentication_response.rb +27 -0
  6. data/lib/workos/client.rb +1 -1
  7. data/lib/workos/configuration.rb +1 -1
  8. data/lib/workos/invitation.rb +68 -0
  9. data/lib/workos/organization_membership.rb +50 -0
  10. data/lib/workos/sso.rb +1 -1
  11. data/lib/workos/types/invitation_struct.rb +20 -0
  12. data/lib/workos/types/magic_auth_challenge_struct.rb +12 -0
  13. data/lib/workos/types/organization_membership_struct.rb +15 -0
  14. data/lib/workos/types/provider_enum.rb +1 -0
  15. data/lib/workos/types/user_struct.rb +17 -0
  16. data/lib/workos/types.rb +9 -5
  17. data/lib/workos/user.rb +57 -0
  18. data/lib/workos/user_and_token.rb +29 -0
  19. data/lib/workos/user_management.rb +1008 -0
  20. data/lib/workos/user_response.rb +25 -0
  21. data/lib/workos/version.rb +1 -1
  22. data/lib/workos.rb +35 -28
  23. data/spec/lib/workos/sso_spec.rb +8 -8
  24. data/spec/lib/workos/user_management_spec.rb +1092 -0
  25. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/invalid.yml +84 -0
  26. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_code/valid.yml +82 -0
  27. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_email_verification/invalid.yml +83 -0
  28. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_email_verification/valid.yml +81 -0
  29. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_magic_auth/invalid.yml +82 -0
  30. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_magic_auth/valid.yml +82 -0
  31. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_organization_selection/invalid.yml +81 -0
  32. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_organization_selection/valid.yml +82 -0
  33. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_password/invalid.yml +82 -0
  34. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_password/valid.yml +82 -0
  35. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_totp/invalid.yml +83 -0
  36. data/spec/support/fixtures/vcr_cassettes/user_management/authenticate_with_totp/valid.yml +81 -0
  37. data/spec/support/fixtures/vcr_cassettes/user_management/confirm_password_reset/invalid.yml +82 -0
  38. data/spec/support/fixtures/vcr_cassettes/user_management/confirm_password_reset/valid.yml +82 -0
  39. data/spec/support/fixtures/vcr_cassettes/user_management/create_organization_membership/invalid.yml +83 -0
  40. data/spec/support/fixtures/vcr_cassettes/user_management/create_organization_membership/valid.yml +82 -0
  41. data/spec/support/fixtures/vcr_cassettes/user_management/create_user_invalid.yml +83 -0
  42. data/spec/support/fixtures/vcr_cassettes/user_management/create_user_valid.yml +82 -0
  43. data/spec/support/fixtures/vcr_cassettes/user_management/delete_organization_membership/invalid.yml +82 -0
  44. data/spec/support/fixtures/vcr_cassettes/user_management/delete_organization_membership/valid.yml +78 -0
  45. data/spec/support/fixtures/vcr_cassettes/user_management/delete_user/invalid.yml +82 -0
  46. data/spec/support/fixtures/vcr_cassettes/user_management/delete_user/valid.yml +78 -0
  47. data/spec/support/fixtures/vcr_cassettes/user_management/enroll_auth_factor/invalid.yml +82 -0
  48. data/spec/support/fixtures/vcr_cassettes/user_management/enroll_auth_factor/valid.yml +82 -0
  49. data/spec/support/fixtures/vcr_cassettes/user_management/get_invitation/invalid.yml +82 -0
  50. data/spec/support/fixtures/vcr_cassettes/user_management/get_invitation/valid.yml +82 -0
  51. data/spec/support/fixtures/vcr_cassettes/user_management/get_organization_membership.yml +82 -0
  52. data/spec/support/fixtures/vcr_cassettes/user_management/get_user.yml +82 -0
  53. data/spec/support/fixtures/vcr_cassettes/user_management/list_auth_factors/invalid.yml +82 -0
  54. data/spec/support/fixtures/vcr_cassettes/user_management/list_auth_factors/valid.yml +82 -0
  55. data/spec/support/fixtures/vcr_cassettes/user_management/list_invitations/with_after.yml +83 -0
  56. data/spec/support/fixtures/vcr_cassettes/user_management/list_invitations/with_before.yml +83 -0
  57. data/spec/support/fixtures/vcr_cassettes/user_management/list_invitations/with_limit.yml +83 -0
  58. data/spec/support/fixtures/vcr_cassettes/user_management/list_invitations/with_no_options.yml +83 -0
  59. data/spec/support/fixtures/vcr_cassettes/user_management/list_invitations/with_organization_id.yml +83 -0
  60. data/spec/support/fixtures/vcr_cassettes/user_management/list_organization_memberships/no_options.yml +82 -0
  61. data/spec/support/fixtures/vcr_cassettes/user_management/list_organization_memberships/with_options.yml +82 -0
  62. data/spec/support/fixtures/vcr_cassettes/user_management/list_users/no_options.yml +82 -0
  63. data/spec/support/fixtures/vcr_cassettes/user_management/list_users/with_options.yml +82 -0
  64. data/spec/support/fixtures/vcr_cassettes/user_management/reset_password/invalid.yml +82 -0
  65. data/spec/support/fixtures/vcr_cassettes/user_management/reset_password/valid.yml +82 -0
  66. data/spec/support/fixtures/vcr_cassettes/user_management/revoke_invitation/invalid.yml +82 -0
  67. data/spec/support/fixtures/vcr_cassettes/user_management/revoke_invitation/valid.yml +82 -0
  68. data/spec/support/fixtures/vcr_cassettes/user_management/send_invitation/invalid.yml +82 -0
  69. data/spec/support/fixtures/vcr_cassettes/user_management/send_invitation/valid.yml +82 -0
  70. data/spec/support/fixtures/vcr_cassettes/user_management/send_magic_auth_code/valid.yml +82 -0
  71. data/spec/support/fixtures/vcr_cassettes/user_management/send_password_reset_email/invalid.yml +83 -0
  72. data/spec/support/fixtures/vcr_cassettes/user_management/send_password_reset_email/valid.yml +82 -0
  73. data/spec/support/fixtures/vcr_cassettes/user_management/send_verification_email/invalid.yml +82 -0
  74. data/spec/support/fixtures/vcr_cassettes/user_management/send_verification_email/valid.yml +82 -0
  75. data/spec/support/fixtures/vcr_cassettes/user_management/update_user/invalid.yml +82 -0
  76. data/spec/support/fixtures/vcr_cassettes/user_management/update_user/valid.yml +82 -0
  77. data/spec/support/fixtures/vcr_cassettes/user_management/update_user_password/invalid.yml +82 -0
  78. data/spec/support/fixtures/vcr_cassettes/user_management/update_user_password/valid.yml +82 -0
  79. data/spec/support/fixtures/vcr_cassettes/user_management/verify_email/invalid_code.yml +83 -0
  80. data/spec/support/fixtures/vcr_cassettes/user_management/verify_email/invalid_magic_auth_challenge.yml +82 -0
  81. data/spec/support/fixtures/vcr_cassettes/user_management/verify_email/valid.yml +82 -0
  82. data/workos.gemspec +0 -2
  83. metadata +132 -55
  84. data/bin/docs +0 -5
  85. data/docs/WorkOS/APIError.html +0 -160
  86. data/docs/WorkOS/AuditLog.html +0 -235
  87. data/docs/WorkOS/AuditTrail.html +0 -235
  88. data/docs/WorkOS/AuthenticationError.html +0 -160
  89. data/docs/WorkOS/Base.html +0 -287
  90. data/docs/WorkOS/Client.html +0 -504
  91. data/docs/WorkOS/InvalidRequestError.html +0 -160
  92. data/docs/WorkOS/Profile.html +0 -788
  93. data/docs/WorkOS/RequestError.html +0 -135
  94. data/docs/WorkOS/SSO.html +0 -691
  95. data/docs/WorkOS/Types/ProfileStruct.html +0 -135
  96. data/docs/WorkOS/Types/Provider.html +0 -135
  97. data/docs/WorkOS/Types.html +0 -128
  98. data/docs/WorkOS/WorkOSError.html +0 -447
  99. data/docs/WorkOS.html +0 -324
  100. data/docs/class_list.html +0 -51
  101. data/docs/css/common.css +0 -1
  102. data/docs/css/full_list.css +0 -58
  103. data/docs/css/style.css +0 -496
  104. data/docs/file.README.html +0 -252
  105. data/docs/file_list.html +0 -56
  106. data/docs/frames.html +0 -17
  107. data/docs/index.html +0 -250
  108. data/docs/js/app.js +0 -314
  109. data/docs/js/full_list.js +0 -216
  110. data/docs/js/jquery.js +0 -4
  111. data/docs/method_list.html +0 -267
  112. data/docs/top-level-namespace.html +0 -110
  113. data/lib/workos/audit_trail.rb +0 -111
  114. data/spec/lib/workos/audit_trail_spec.rb +0 -146
@@ -0,0 +1,1092 @@
1
+ # frozen_string_literal: true
2
+ # typed: false
3
+
4
+ describe WorkOS::UserManagement do
5
+ it_behaves_like 'client'
6
+
7
+ describe '.authorization_url' do
8
+ context 'with a provider' do
9
+ let(:args) do
10
+ {
11
+ provider: 'authkit',
12
+ client_id: 'workos-proj-123',
13
+ redirect_uri: 'foo.com/auth/callback',
14
+ state: {
15
+ next_page: '/dashboard/edit',
16
+ }.to_s,
17
+ }
18
+ end
19
+ it 'returns a valid URL' do
20
+ authorization_url = described_class.authorization_url(**args)
21
+
22
+ expect(URI.parse(authorization_url)).to be_a URI
23
+ end
24
+
25
+ it 'returns the expected hostname' do
26
+ authorization_url = described_class.authorization_url(**args)
27
+
28
+ expect(URI.parse(authorization_url).host).to eq(WorkOS.config.api_hostname)
29
+ end
30
+
31
+ it 'returns the expected query string' do
32
+ authorization_url = described_class.authorization_url(**args)
33
+
34
+ expect(URI.parse(authorization_url).query).to eq(
35
+ 'client_id=workos-proj-123&redirect_uri=foo.com%2Fauth%2Fcallback' \
36
+ '&response_type=code&state=%7B%3Anext_page%3D%3E%22%2Fdashboard%2F' \
37
+ 'edit%22%7D&provider=authkit',
38
+ )
39
+ end
40
+ end
41
+
42
+ context 'with a connection selector' do
43
+ let(:args) do
44
+ {
45
+ connection_id: 'connection_123',
46
+ client_id: 'workos-proj-123',
47
+ redirect_uri: 'foo.com/auth/callback',
48
+ state: {
49
+ next_page: '/dashboard/edit',
50
+ }.to_s,
51
+ }
52
+ end
53
+ it 'returns a valid URL' do
54
+ authorization_url = described_class.authorization_url(**args)
55
+
56
+ expect(URI.parse(authorization_url)).to be_a URI
57
+ end
58
+
59
+ it 'returns the expected hostname' do
60
+ authorization_url = described_class.authorization_url(**args)
61
+
62
+ expect(URI.parse(authorization_url).host).to eq(WorkOS.config.api_hostname)
63
+ end
64
+
65
+ it 'returns the expected query string' do
66
+ authorization_url = described_class.authorization_url(**args)
67
+
68
+ expect(URI.parse(authorization_url).query).to eq(
69
+ 'client_id=workos-proj-123&redirect_uri=foo.com%2Fauth%2Fcallback' \
70
+ '&response_type=code&state=%7B%3Anext_page%3D%3E%22%2Fdashboard%2F' \
71
+ 'edit%22%7D&connection_id=connection_123',
72
+ )
73
+ end
74
+ end
75
+
76
+ context 'with an organization selector' do
77
+ let(:args) do
78
+ {
79
+ organization_id: 'org_123',
80
+ client_id: 'workos-proj-123',
81
+ redirect_uri: 'foo.com/auth/callback',
82
+ state: {
83
+ next_page: '/dashboard/edit',
84
+ }.to_s,
85
+ }
86
+ end
87
+ it 'returns a valid URL' do
88
+ authorization_url = described_class.authorization_url(**args)
89
+
90
+ expect(URI.parse(authorization_url)).to be_a URI
91
+ end
92
+
93
+ it 'returns the expected hostname' do
94
+ authorization_url = described_class.authorization_url(**args)
95
+
96
+ expect(URI.parse(authorization_url).host).to eq(WorkOS.config.api_hostname)
97
+ end
98
+
99
+ it 'returns the expected query string' do
100
+ authorization_url = described_class.authorization_url(**args)
101
+
102
+ expect(URI.parse(authorization_url).query).to eq(
103
+ 'client_id=workos-proj-123&redirect_uri=foo.com%2Fauth%2Fcallback' \
104
+ '&response_type=code&state=%7B%3Anext_page%3D%3E%22%2Fdashboard%2F' \
105
+ 'edit%22%7D&organization_id=org_123',
106
+ )
107
+ end
108
+ end
109
+
110
+ context 'with a domain hint' do
111
+ let(:args) do
112
+ {
113
+ connection_id: 'connection_123',
114
+ domain_hint: 'foo.com',
115
+ client_id: 'workos-proj-123',
116
+ redirect_uri: 'foo.com/auth/callback',
117
+ state: {
118
+ next_page: '/dashboard/edit',
119
+ }.to_s,
120
+ }
121
+ end
122
+ it 'returns a valid URL' do
123
+ authorization_url = described_class.authorization_url(**args)
124
+
125
+ expect(URI.parse(authorization_url)).to be_a URI
126
+ end
127
+
128
+ it 'returns the expected hostname' do
129
+ authorization_url = described_class.authorization_url(**args)
130
+
131
+ expect(URI.parse(authorization_url).host).to eq(WorkOS.config.api_hostname)
132
+ end
133
+
134
+ it 'returns the expected query string' do
135
+ authorization_url = described_class.authorization_url(**args)
136
+
137
+ expect(URI.parse(authorization_url).query).to eq(
138
+ 'client_id=workos-proj-123&redirect_uri=foo.com%2Fauth%2Fcallback' \
139
+ '&response_type=code&state=%7B%3Anext_page%3D%3E%22%2Fdashboard%2' \
140
+ 'Fedit%22%7D&domain_hint=foo.com&connection_id=connection_123',
141
+ )
142
+ end
143
+ end
144
+
145
+ context 'with a login hint' do
146
+ let(:args) do
147
+ {
148
+ connection_id: 'connection_123',
149
+ login_hint: 'foo@workos.com',
150
+ client_id: 'workos-proj-123',
151
+ redirect_uri: 'foo.com/auth/callback',
152
+ state: {
153
+ next_page: '/dashboard/edit',
154
+ }.to_s,
155
+ }
156
+ end
157
+ it 'returns a valid URL' do
158
+ authorization_url = described_class.authorization_url(**args)
159
+
160
+ expect(URI.parse(authorization_url)).to be_a URI
161
+ end
162
+
163
+ it 'returns the expected hostname' do
164
+ authorization_url = described_class.authorization_url(**args)
165
+
166
+ expect(URI.parse(authorization_url).host).to eq(WorkOS.config.api_hostname)
167
+ end
168
+
169
+ it 'returns the expected query string' do
170
+ authorization_url = described_class.authorization_url(**args)
171
+
172
+ expect(URI.parse(authorization_url).query).to eq(
173
+ 'client_id=workos-proj-123&redirect_uri=foo.com%2Fauth%2Fcallback' \
174
+ '&response_type=code&state=%7B%3Anext_page%3D%3E%22%2Fdashboard%2' \
175
+ 'Fedit%22%7D&login_hint=foo%40workos.com&connection_id=connection_123',
176
+ )
177
+ end
178
+ end
179
+
180
+ context 'with neither connection_id, organization_id or provider' do
181
+ let(:args) do
182
+ {
183
+ client_id: 'workos-proj-123',
184
+ redirect_uri: 'foo.com/auth/callback',
185
+ state: {
186
+ next_page: '/dashboard/edit',
187
+ }.to_s,
188
+ }
189
+ end
190
+ it 'raises an error' do
191
+ expect do
192
+ described_class.authorization_url(**args)
193
+ end.to raise_error(
194
+ ArgumentError,
195
+ 'Either connection ID, organization ID, or provider is required.',
196
+ )
197
+ end
198
+ end
199
+
200
+ context 'with an invalid provider' do
201
+ let(:args) do
202
+ {
203
+ provider: 'Okta',
204
+ client_id: 'workos-proj-123',
205
+ redirect_uri: 'foo.com/auth/callback',
206
+ state: {
207
+ next_page: '/dashboard/edit',
208
+ }.to_s,
209
+ }
210
+ end
211
+ it 'raises an error' do
212
+ expect do
213
+ described_class.authorization_url(**args)
214
+ end.to raise_error(
215
+ ArgumentError,
216
+ 'Okta is not a valid value. `provider` must be in ' \
217
+ '["GitHubOAuth", "GoogleOAuth", "MicrosoftOAuth", "authkit"]',
218
+ )
219
+ end
220
+ end
221
+ end
222
+
223
+ describe '.get_user' do
224
+ context 'with a valid id' do
225
+ it 'returns a user' do
226
+ VCR.use_cassette 'user_management/get_user' do
227
+ user = described_class.get_user(
228
+ id: 'user_01H7TVSKS45SDHN5V9XPSM6H44',
229
+ )
230
+
231
+ expect(user.id.instance_of?(String))
232
+ expect(user.instance_of?(WorkOS::User))
233
+ end
234
+ end
235
+ end
236
+
237
+ context 'with an invalid id' do
238
+ it 'returns an error' do
239
+ expect do
240
+ described_class.get_user(
241
+ id: 'invalid_user_id',
242
+ ).to raise_error(WorkOS::APIError)
243
+ end
244
+ end
245
+ end
246
+ end
247
+
248
+ describe '.list_users' do
249
+ context 'with no options' do
250
+ it 'returns a list of users' do
251
+ expected_metadata = {
252
+ 'after' => nil,
253
+ 'before' => 'before-id',
254
+ }
255
+
256
+ VCR.use_cassette 'user_management/list_users/no_options' do
257
+ users = described_class.list_users
258
+
259
+ expect(users.data.size).to eq(2)
260
+ expect(users.list_metadata).to eq(expected_metadata)
261
+ end
262
+ end
263
+ end
264
+
265
+ context 'with options' do
266
+ it 'returns a list of matching users' do
267
+ request_args = [
268
+ '/user_management/users?email=lucy.lawless%40example.com&order=desc&limit=5',
269
+ 'Content-Type' => 'application/json'
270
+ ]
271
+
272
+ expected_request = Net::HTTP::Get.new(*request_args)
273
+
274
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
275
+ and_return(expected_request)
276
+
277
+ VCR.use_cassette 'user_management/list_users/with_options' do
278
+ users = described_class.list_users(
279
+ email: 'lucy.lawless@example.com',
280
+ order: 'desc',
281
+ limit: '5',
282
+ )
283
+
284
+ expect(users.data.size).to eq(1)
285
+ expect(users.data[0].email).to eq('lucy.lawless@example.com')
286
+ end
287
+ end
288
+ end
289
+ end
290
+
291
+ describe '.create_user' do
292
+ context 'with a valid payload' do
293
+ it 'creates a user' do
294
+ VCR.use_cassette 'user_management/create_user_valid' do
295
+ user = described_class.create_user(
296
+ email: 'foo@example.com',
297
+ first_name: 'Foo',
298
+ last_name: 'Bar',
299
+ email_verified: true,
300
+ )
301
+
302
+ expect(user.first_name).to eq('Foo')
303
+ expect(user.last_name).to eq('Bar')
304
+ expect(user.email).to eq('foo@example.com')
305
+ end
306
+ end
307
+
308
+ context 'with an invalid payload' do
309
+ it 'returns an error' do
310
+ VCR.use_cassette 'user_management/create_user_invalid' do
311
+ expect do
312
+ described_class.create_user(email: '')
313
+ end.to raise_error(
314
+ WorkOS::InvalidRequestError,
315
+ /email_string_required/,
316
+ )
317
+ end
318
+ end
319
+ end
320
+ end
321
+ end
322
+
323
+ describe '.update_user' do
324
+ context 'with a valid payload' do
325
+ it 'update_user a user' do
326
+ VCR.use_cassette 'user_management/update_user/valid' do
327
+ user = described_class.update_user(
328
+ id: 'user_01H7TVSKS45SDHN5V9XPSM6H44',
329
+ first_name: 'Jane',
330
+ last_name: 'Doe',
331
+ email_verified: false,
332
+ )
333
+ expect(user.first_name).to eq('Jane')
334
+ expect(user.last_name).to eq('Doe')
335
+ expect(user.email_verified).to eq(false)
336
+ end
337
+ end
338
+
339
+ context 'with an invalid payload' do
340
+ it 'returns an error' do
341
+ VCR.use_cassette 'user_management/update_user/invalid' do
342
+ expect do
343
+ described_class.update_user(id: 'invalid')
344
+ end.to raise_error(WorkOS::APIError, /User not found/)
345
+ end
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+ describe '.delete_user' do
352
+ context 'with a valid id' do
353
+ it 'returns true' do
354
+ VCR.use_cassette('user_management/delete_user/valid') do
355
+ response = WorkOS::UserManagement.delete_user(
356
+ id: 'user_01H7WRJBPAAHX1BYRQHEK7QC4A',
357
+ )
358
+
359
+ expect(response).to be(true)
360
+ end
361
+ end
362
+ end
363
+
364
+ context 'with an invalid id' do
365
+ it 'raises an error' do
366
+ VCR.use_cassette('user_management/delete_user/invalid') do
367
+ expect do
368
+ WorkOS::UserManagement.delete_user(id: 'invalid')
369
+ end.to raise_error(WorkOS::APIError, /User not found/)
370
+ end
371
+ end
372
+ end
373
+ end
374
+
375
+ describe '.authenticate_with_password' do
376
+ context 'with a valid password' do
377
+ it 'returns user' do
378
+ VCR.use_cassette('user_management/authenticate_with_password/valid') do
379
+ authentication_response = WorkOS::UserManagement.authenticate_with_password(
380
+ email: 'test@workos.app',
381
+ password: '7YtYic00VWcXatPb',
382
+ client_id: 'client_123',
383
+ ip_address: '200.240.210.16',
384
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
385
+ )
386
+ expect(authentication_response.user.id).to eq('user_01H7TVSKS45SDHN5V9XPSM6H44')
387
+ end
388
+ end
389
+ end
390
+
391
+ context 'with an invalid user' do
392
+ it 'raises an error' do
393
+ VCR.use_cassette('user_management/authenticate_with_password/invalid') do
394
+ expect do
395
+ WorkOS::UserManagement.authenticate_with_password(
396
+ email: 'invalid@workos.app',
397
+ password: 'invalid',
398
+ client_id: 'client_123',
399
+ ip_address: '200.240.210.16',
400
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
401
+ )
402
+ end.to raise_error(WorkOS::APIError, /User not found/)
403
+ end
404
+ end
405
+ end
406
+ end
407
+
408
+ describe '.authenticate_with_code' do
409
+ context 'with a valid code' do
410
+ it 'returns user' do
411
+ VCR.use_cassette('user_management/authenticate_with_code/valid') do
412
+ authentication_response = WorkOS::UserManagement.authenticate_with_code(
413
+ code: '01H93ZZHA0JBHFJH9RR11S83YN',
414
+ client_id: 'client_123',
415
+ ip_address: '200.240.210.16',
416
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
417
+ )
418
+ expect(authentication_response.user.id).to eq('user_01H93ZY4F80YZRRS6N59Z2HFVS')
419
+ end
420
+ end
421
+ end
422
+
423
+ context 'with an invalid code' do
424
+ it 'raises an error' do
425
+ VCR.use_cassette('user_management/authenticate_with_code/invalid') do
426
+ expect do
427
+ WorkOS::UserManagement.authenticate_with_code(
428
+ code: 'invalid',
429
+ client_id: 'client_123',
430
+ ip_address: '200.240.210.16',
431
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
432
+ )
433
+ end.to raise_error(WorkOS::InvalidRequestError, /Status 400/)
434
+ end
435
+ end
436
+ end
437
+ end
438
+
439
+ describe '.authenticate_with_magic_auth' do
440
+ context 'with a valid code' do
441
+ it 'returns user' do
442
+ VCR.use_cassette('user_management/authenticate_with_magic_auth/valid') do
443
+ authentication_response = WorkOS::UserManagement.authenticate_with_magic_auth(
444
+ code: '452079',
445
+ client_id: 'project_01EGKAEB7G5N88E83MF99J785F',
446
+ email: 'test@workos.com',
447
+ ip_address: '200.240.210.16',
448
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
449
+ )
450
+ expect(authentication_response.user.id).to eq('user_01H93WD0R0KWF8Q7BK02C0RPYJ')
451
+ end
452
+ end
453
+ end
454
+
455
+ context 'with an invalid code' do
456
+ it 'returns an error' do
457
+ VCR.use_cassette('user_management/authenticate_with_magic_auth/invalid') do
458
+ expect do
459
+ WorkOS::UserManagement.authenticate_with_magic_auth(
460
+ code: 'invalid',
461
+ client_id: 'client_123',
462
+ email: 'test@workos.com',
463
+ )
464
+ end.to raise_error(WorkOS::APIError, /User not found/)
465
+ end
466
+ end
467
+ end
468
+ end
469
+
470
+ describe '.authenticate_with_organization_selection' do
471
+ context 'with a valid code' do
472
+ it 'returns user' do
473
+ VCR.use_cassette('user_management/authenticate_with_organization_selection/valid') do
474
+ authentication_response = WorkOS::UserManagement.authenticate_with_organization_selection(
475
+ client_id: 'project_01EGKAEB7G5N88E83MF99J785F',
476
+ organization_id: 'org_01H5JQDV7R7ATEYZDEG0W5PRYS',
477
+ pending_authentication_token: 'pending_authentication_token_1234',
478
+ ip_address: '200.240.210.16',
479
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
480
+ )
481
+ expect(authentication_response.user.id).to eq('user_01H93WD0R0KWF8Q7BK02C0RPYJ')
482
+ expect(authentication_response.organization_id).to eq('org_01H5JQDV7R7ATEYZDEG0W5PRYS')
483
+ end
484
+ end
485
+ end
486
+
487
+ context 'with an invalid token' do
488
+ it 'returns an error' do
489
+ VCR.use_cassette('user_management/authenticate_with_organization_selection/invalid') do
490
+ expect do
491
+ WorkOS::UserManagement.authenticate_with_organization_selection(
492
+ organization_id: 'invalid_org_id',
493
+ client_id: 'project_01EGKAEB7G5N88E83MF99J785F',
494
+ pending_authentication_token: 'pending_authentication_token_1234',
495
+ )
496
+ end.to raise_error(WorkOS::InvalidRequestError, /Status 400/)
497
+ end
498
+ end
499
+ end
500
+ end
501
+
502
+ describe '.authenticate_with_totp' do
503
+ context 'with a valid code' do
504
+ it 'returns user' do
505
+ VCR.use_cassette('user_management/authenticate_with_totp/valid') do
506
+ authentication_response = WorkOS::UserManagement.authenticate_with_totp(
507
+ code: '01H93ZZHA0JBHFJH9RR11S83YN',
508
+ client_id: 'client_123',
509
+ pending_authentication_token: 'pending_authentication_token_1234',
510
+ authentication_challenge_id: 'authentication_challenge_id',
511
+ ip_address: '200.240.210.16',
512
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
513
+ )
514
+ expect(authentication_response.user.id).to eq('user_01H93ZY4F80YZRRS6N59Z2HFVS')
515
+ end
516
+ end
517
+ end
518
+
519
+ context 'with an invalid code' do
520
+ it 'raises an error' do
521
+ VCR.use_cassette('user_management/authenticate_with_totp/invalid') do
522
+ expect do
523
+ WorkOS::UserManagement.authenticate_with_totp(
524
+ code: 'invalid',
525
+ client_id: 'client_123',
526
+ pending_authentication_token: 'pending_authentication_token_1234',
527
+ authentication_challenge_id: 'authentication_challenge_id',
528
+ ip_address: '200.240.210.16',
529
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
530
+ )
531
+ end.to raise_error(WorkOS::InvalidRequestError, /Status 400/)
532
+ end
533
+ end
534
+ end
535
+ end
536
+
537
+ describe '.authenticate_with_email_verification' do
538
+ context 'with a valid code' do
539
+ it 'returns user' do
540
+ VCR.use_cassette('user_management/authenticate_with_email_verification/valid') do
541
+ authentication_response = WorkOS::UserManagement.authenticate_with_email_verification(
542
+ code: '01H93ZZHA0JBHFJH9RR11S83YN',
543
+ client_id: 'client_123',
544
+ pending_authentication_token: 'pending_authentication_token_1234',
545
+ ip_address: '200.240.210.16',
546
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
547
+ )
548
+ expect(authentication_response.user.id).to eq('user_01H93ZY4F80YZRRS6N59Z2HFVS')
549
+ end
550
+ end
551
+ end
552
+
553
+ context 'with an invalid code' do
554
+ it 'raises an error' do
555
+ VCR.use_cassette('user_management/authenticate_with_email_verification/invalid') do
556
+ expect do
557
+ WorkOS::UserManagement.authenticate_with_email_verification(
558
+ code: 'invalid',
559
+ client_id: 'client_123',
560
+ pending_authentication_token: 'pending_authentication_token_1234',
561
+ ip_address: '200.240.210.16',
562
+ user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/108.0.0.0 Safari/537.36',
563
+ )
564
+ end.to raise_error(WorkOS::InvalidRequestError, /Status 400/)
565
+ end
566
+ end
567
+ end
568
+ end
569
+
570
+ describe '.send_magic_auth_code' do
571
+ context 'with valid parameters' do
572
+ it 'sends a magic link to the email address' do
573
+ VCR.use_cassette 'user_management/send_magic_auth_code/valid' do
574
+ described_class.send_magic_auth_code(
575
+ email: 'test@gmail.com',
576
+ )
577
+ end
578
+ end
579
+ end
580
+ end
581
+
582
+ describe '.enroll_auth_factor' do
583
+ context 'with a valid user_id and auth factor type' do
584
+ it 'returns an auth factor and challenge' do
585
+ VCR.use_cassette('user_management/enroll_auth_factor/valid') do
586
+ authentication_response = WorkOS::UserManagement.enroll_auth_factor(
587
+ user_id: 'user_01H7TVSKS45SDHN5V9XPSM6H44',
588
+ type: 'totp',
589
+ )
590
+
591
+ expect(authentication_response.authentication_factor.id).to eq('auth_factor_01H96FETXENNY99ARX0GRC804C')
592
+ expect(authentication_response.authentication_challenge.id).to eq('auth_challenge_01H96FETXGTW1QMBSBT2T36PW0')
593
+ end
594
+ end
595
+ end
596
+
597
+ context 'with an incorrect user id' do
598
+ it 'raises an error' do
599
+ VCR.use_cassette('user_management/enroll_auth_factor/invalid') do
600
+ expect do
601
+ WorkOS::UserManagement.enroll_auth_factor(
602
+ user_id: 'user_01H7TVSKS45SDHN5V9XPSM6H44',
603
+ type: 'totp',
604
+ )
605
+ end.to raise_error(WorkOS::InvalidRequestError, /Status 400/)
606
+ end
607
+ end
608
+ end
609
+
610
+ context 'with an invalid auth factor type' do
611
+ it 'raises an error' do
612
+ expect do
613
+ described_class.enroll_auth_factor(user_id: 'user_01H7TVSKS45SDHN5V9XPSM6H44',
614
+ type: 'invalid-factor',)
615
+ end.to raise_error(
616
+ ArgumentError,
617
+ 'invalid-factor is not a valid value. `type` must be in ["totp"]',
618
+ )
619
+ end
620
+ end
621
+ end
622
+
623
+ describe '.list_auth_factors' do
624
+ context 'with a valid user_id' do
625
+ it 'returns a list of auth factors' do
626
+ VCR.use_cassette('user_management/list_auth_factors/valid') do
627
+ authentication_response = WorkOS::UserManagement.list_auth_factors(
628
+ user_id: 'user_01H7TVSKS45SDHN5V9XPSM6H44',
629
+ )
630
+
631
+ expect(authentication_response.data.first.id).to eq('auth_factor_01H96FETXENNY99ARX0GRC804C')
632
+ end
633
+ end
634
+ end
635
+ context 'with an incorrect user id' do
636
+ it 'raises an error' do
637
+ VCR.use_cassette('user_management/list_auth_factors/invalid') do
638
+ expect do
639
+ WorkOS::UserManagement.list_auth_factors(
640
+ user_id: 'user_01H7TVSKS45SDHN5V9XPSM6H44',
641
+ )
642
+ end.to raise_error(WorkOS::InvalidRequestError, /Status 400/)
643
+ end
644
+ end
645
+ end
646
+ end
647
+
648
+ describe '.send_verification_email' do
649
+ context 'with valid parameters' do
650
+ it 'sends an email to that user and the magic auth challenge' do
651
+ VCR.use_cassette 'user_management/send_verification_email/valid' do
652
+ verification_response = described_class.send_verification_email(
653
+ user_id: 'user_01H93WD0R0KWF8Q7BK02C0RPYJ',
654
+ )
655
+ expect(verification_response.user.id).to eq('user_01H93WD0R0KWF8Q7BK02C0RPYJ')
656
+ end
657
+ end
658
+ end
659
+
660
+ context 'when the user does not exist' do
661
+ it 'returns an error' do
662
+ VCR.use_cassette 'user_management/send_verification_email/invalid' do
663
+ expect do
664
+ described_class.send_verification_email(
665
+ user_id: 'bad_id',
666
+ )
667
+ end.to raise_error(WorkOS::APIError, /User not found/)
668
+ end
669
+ end
670
+ end
671
+ end
672
+
673
+ describe '.verify_email' do
674
+ context 'with valid parameters' do
675
+ it 'verifies the email and returns the user' do
676
+ VCR.use_cassette 'user_management/verify_email/valid' do
677
+ verify_response = described_class.verify_email(
678
+ code: '333495',
679
+ user_id: 'user_01H968BR1R84DSPYS9QR5PM6RZ',
680
+ )
681
+
682
+ expect(verify_response.user.id).to eq('user_01H968BR1R84DSPYS9QR5PM6RZ')
683
+ end
684
+ end
685
+ end
686
+
687
+ context 'with invalid parameters' do
688
+ context 'when the id does not exist' do
689
+ it 'raises an error' do
690
+ VCR.use_cassette 'user_management/verify_email/invalid_magic_auth_challenge' do
691
+ expect do
692
+ described_class.verify_email(
693
+ code: '659770',
694
+ user_id: 'bad_id',
695
+ )
696
+ end.to raise_error(WorkOS::APIError, /User not found/)
697
+ end
698
+ end
699
+ end
700
+
701
+ context 'when the code is incorrect' do
702
+ it 'raises an error' do
703
+ VCR.use_cassette 'user_management/verify_email/invalid_code' do
704
+ expect do
705
+ described_class.verify_email(
706
+ code: '000000',
707
+ user_id: 'user_01H93WD0R0KWF8Q7BK02C0RPYJ',
708
+ )
709
+ end.to raise_error(WorkOS::InvalidRequestError, /Email verification code is incorrect/)
710
+ end
711
+ end
712
+ end
713
+ end
714
+ end
715
+
716
+ describe '.send_password_reset_email' do
717
+ context 'with a valid payload' do
718
+ it 'sends a password reset email' do
719
+ VCR.use_cassette 'user_management/send_password_reset_email/valid' do
720
+ response = described_class.send_password_reset_email(
721
+ email: 'lucy.lawless@example.com',
722
+ password_reset_url: 'https://example.com/reset',
723
+ )
724
+
725
+ expect(response).to be(true)
726
+ end
727
+ end
728
+ end
729
+
730
+ context 'with an invalid payload' do
731
+ it 'returns an error' do
732
+ VCR.use_cassette 'user_management/send_password_reset_email/invalid' do
733
+ expect do
734
+ described_class.send_password_reset_email(
735
+ email: 'foo@bar.com',
736
+ password_reset_url: '',
737
+ )
738
+ end.to raise_error(
739
+ WorkOS::InvalidRequestError,
740
+ /password_reset_url_string_required/,
741
+ )
742
+ end
743
+ end
744
+ end
745
+ end
746
+
747
+ describe '.reset_password' do
748
+ context 'with a valid payload' do
749
+ it 'resets the password and returns the user' do
750
+ VCR.use_cassette 'user_management/reset_password/valid' do
751
+ user = described_class.reset_password(
752
+ token: 'eEgAgvAE0blvU1zWV3yWVAD22',
753
+ new_password: 'very_cool_new_pa$$word',
754
+ )
755
+
756
+ expect(user.email).to eq('lucy.lawless@example.com')
757
+ end
758
+ end
759
+ end
760
+
761
+ context 'with an invalid payload' do
762
+ it 'returns an error' do
763
+ VCR.use_cassette 'user_management/reset_password/invalid' do
764
+ expect do
765
+ described_class.reset_password(
766
+ token: 'bogus_token',
767
+ new_password: 'new_password',
768
+ )
769
+ end.to raise_error(
770
+ WorkOS::APIError,
771
+ /Could not locate user with provided token/,
772
+ )
773
+ end
774
+ end
775
+ end
776
+ end
777
+
778
+ describe '.get_organization_membership' do
779
+ context 'with a valid id' do
780
+ it 'returns a organization membership' do
781
+ VCR.use_cassette 'user_management/get_organization_membership' do
782
+ organization_membership = described_class.get_organization_membership(
783
+ id: 'om_01H5JQDV7R7ATEYZDEG0W5PRYS',
784
+ )
785
+
786
+ expect(organization_membership.id.instance_of?(String))
787
+ expect(organization_membership.instance_of?(WorkOS::OrganizationMembership))
788
+ end
789
+ end
790
+ end
791
+
792
+ context 'with an invalid id' do
793
+ it 'returns an error' do
794
+ expect do
795
+ described_class.get_organization_membership(
796
+ id: 'invalid_organization_membership_id',
797
+ ).to raise_error(WorkOS::APIError)
798
+ end
799
+ end
800
+ end
801
+ end
802
+
803
+ describe '.list_organization_memberships' do
804
+ context 'with no options' do
805
+ it 'returns a list of users' do
806
+ expected_metadata = {
807
+ 'after' => nil,
808
+ 'before' => 'before-id',
809
+ }
810
+
811
+ VCR.use_cassette 'user_management/list_organization_memberships/no_options' do
812
+ organization_memberships = described_class.list_organization_memberships
813
+
814
+ expect(organization_memberships.data.size).to eq(2)
815
+ expect(organization_memberships.list_metadata).to eq(expected_metadata)
816
+ end
817
+ end
818
+ end
819
+
820
+ context 'with options' do
821
+ it 'returns a list of matching users' do
822
+ request_args = [
823
+ '/user_management/organization_memberships?user_id=user_01H5JQDV7R7ATEYZDEG0W5PRYS&order=desc&limit=5',
824
+ 'Content-Type' => 'application/json'
825
+ ]
826
+
827
+ expected_request = Net::HTTP::Get.new(*request_args)
828
+
829
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
830
+ and_return(expected_request)
831
+
832
+ VCR.use_cassette 'user_management/list_organization_memberships/with_options' do
833
+ organization_memberships = described_class.list_organization_memberships(
834
+ user_id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS',
835
+ order: 'desc',
836
+ limit: '5',
837
+ )
838
+
839
+ expect(organization_memberships.data.size).to eq(1)
840
+ expect(organization_memberships.data[0].user_id).to eq('user_01H5JQDV7R7ATEYZDEG0W5PRYS')
841
+ end
842
+ end
843
+ end
844
+ end
845
+
846
+ describe '.create_organization_membership' do
847
+ context 'with a valid payload' do
848
+ it 'creates an organization membership' do
849
+ VCR.use_cassette 'user_management/create_organization_membership/valid' do
850
+ organization_membership = described_class.create_organization_membership(
851
+ user_id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS',
852
+ organization_id: 'org_01H5JQDV7R7ATEYZDEG0W5PRYS',
853
+ )
854
+
855
+ expect(organization_membership.organization_id).to eq('organization_01H5JQDV7R7ATEYZDEG0W5PRYS')
856
+ expect(organization_membership.user_id).to eq('user_01H5JQDV7R7ATEYZDEG0W5PRYS')
857
+ end
858
+ end
859
+
860
+ context 'with an invalid payload' do
861
+ it 'returns an error' do
862
+ VCR.use_cassette 'user_management/create_organization_membership/invalid' do
863
+ expect do
864
+ described_class.create_organization_membership(user_id: '', organization_id: '')
865
+ end.to raise_error(
866
+ WorkOS::InvalidRequestError,
867
+ /user_id_string_required/,
868
+ )
869
+ end
870
+ end
871
+ end
872
+ end
873
+ end
874
+
875
+ describe '.delete_organization_membership' do
876
+ context 'with a valid id' do
877
+ it 'returns true' do
878
+ VCR.use_cassette('user_management/delete_organization_membership/valid') do
879
+ response = WorkOS::UserManagement.delete_organization_membership(
880
+ id: 'om_01H5JQDV7R7ATEYZDEG0W5PRYS',
881
+ )
882
+
883
+ expect(response).to be(true)
884
+ end
885
+ end
886
+ end
887
+
888
+ context 'with an invalid id' do
889
+ it 'raises an error' do
890
+ VCR.use_cassette('user_management/delete_organization_membership/invalid') do
891
+ expect do
892
+ WorkOS::UserManagement.delete_organization_membership(id: 'invalid')
893
+ end.to raise_error(WorkOS::APIError, /Organization Membership not found/)
894
+ end
895
+ end
896
+ end
897
+ end
898
+
899
+ describe '.get_invitation' do
900
+ context 'with a valid id' do
901
+ it 'returns an invitation' do
902
+ VCR.use_cassette 'user_management/get_invitation/valid' do
903
+ invitation = described_class.get_invitation(
904
+ id: 'invitation_01H5JQDV7R7ATEYZDEG0W5PRYS',
905
+ )
906
+
907
+ expect(invitation.id.instance_of?(String))
908
+ expect(invitation.instance_of?(WorkOS::Invitation))
909
+ end
910
+ end
911
+ end
912
+
913
+ context 'with an invalid id' do
914
+ it 'raises an error' do
915
+ VCR.use_cassette('user_management/get_invitation/invalid') do
916
+ expect do
917
+ WorkOS::UserManagement.get_invitation(id: 'invalid')
918
+ end.to raise_error(WorkOS::APIError, /Invitation not found/)
919
+ end
920
+ end
921
+ end
922
+ end
923
+
924
+ describe '.list_invitations' do
925
+ context 'with no options' do
926
+ it 'returns invitations and metadata' do
927
+ expected_metadata = {
928
+ 'after' => nil,
929
+ 'before' => 'before_id',
930
+ }
931
+
932
+ VCR.use_cassette 'user_management/list_invitations/with_no_options' do
933
+ invitations = described_class.list_invitations
934
+
935
+ expect(invitations.data.size).to eq(5)
936
+ expect(invitations.list_metadata).to eq(expected_metadata)
937
+ end
938
+ end
939
+ end
940
+
941
+ context 'with organization_id option' do
942
+ it 'forms the proper request to the API' do
943
+ request_args = [
944
+ '/user_management/invitations?organization_id=org_01H5JQDV7R7ATEYZDEG0W5PRYS',
945
+ 'Content-Type' => 'application/json'
946
+ ]
947
+
948
+ expected_request = Net::HTTP::Get.new(*request_args)
949
+
950
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
951
+ and_return(expected_request)
952
+
953
+ VCR.use_cassette 'user_management/list_invitations/with_organization_id' do
954
+ invitations = described_class.list_invitations(
955
+ organization_id: 'org_01H5JQDV7R7ATEYZDEG0W5PRYS',
956
+ )
957
+
958
+ expect(invitations.data.size).to eq(1)
959
+ expect(invitations.data.first.organization_id).to eq(
960
+ 'org_01H5JQDV7R7ATEYZDEG0W5PRYS',
961
+ )
962
+ end
963
+ end
964
+ end
965
+
966
+ context 'with limit option' do
967
+ it 'forms the proper request to the API' do
968
+ request_args = [
969
+ '/user_management/invitations?limit=2',
970
+ 'Content-Type' => 'application/json'
971
+ ]
972
+
973
+ expected_request = Net::HTTP::Get.new(*request_args)
974
+
975
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
976
+ and_return(expected_request)
977
+
978
+ VCR.use_cassette 'user_management/list_invitations/with_limit' do
979
+ invitations = described_class.list_invitations(
980
+ limit: 2,
981
+ )
982
+
983
+ expect(invitations.data.size).to eq(3)
984
+ end
985
+ end
986
+ end
987
+
988
+ context 'with before option' do
989
+ it 'forms the proper request to the API' do
990
+ request_args = [
991
+ '/user_management/invitations?before=invitation_01H5JQDV7R7ATEYZDEG0W5PRYS',
992
+ 'Content-Type' => 'application/json'
993
+ ]
994
+
995
+ expected_request = Net::HTTP::Get.new(*request_args)
996
+
997
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
998
+ and_return(expected_request)
999
+
1000
+ VCR.use_cassette 'user_management/list_invitations/with_before' do
1001
+ invitations = described_class.list_invitations(
1002
+ before: 'invitation_01H5JQDV7R7ATEYZDEG0W5PRYS',
1003
+ )
1004
+
1005
+ expect(invitations.data.size).to eq(2)
1006
+ end
1007
+ end
1008
+ end
1009
+
1010
+ context 'with after option' do
1011
+ it 'forms the proper request to the API' do
1012
+ request_args = [
1013
+ '/user_management/invitations?after=invitation_01H5JQDV7R7ATEYZDEG0W5PRYS',
1014
+ 'Content-Type' => 'application/json'
1015
+ ]
1016
+
1017
+ expected_request = Net::HTTP::Get.new(*request_args)
1018
+
1019
+ expect(Net::HTTP::Get).to receive(:new).with(*request_args).
1020
+ and_return(expected_request)
1021
+
1022
+ VCR.use_cassette 'user_management/list_invitations/with_after' do
1023
+ invitations = described_class.list_invitations(
1024
+ after: 'invitation_01H5JQDV7R7ATEYZDEG0W5PRYS',
1025
+ )
1026
+
1027
+ expect(invitations.data.size).to eq(2)
1028
+ end
1029
+ end
1030
+ end
1031
+ end
1032
+
1033
+ describe '.send_invitation' do
1034
+ context 'with valid payload' do
1035
+ it 'sends an invitation' do
1036
+ VCR.use_cassette 'user_management/send_invitation/valid' do
1037
+ invitation = described_class.send_invitation(
1038
+ email: 'test@workos.com',
1039
+ )
1040
+
1041
+ expect(invitation.id).to eq('invitation_01H5JQDV7R7ATEYZDEG0W5PRYS')
1042
+ expect(invitation.email).to eq('test@workos.com')
1043
+ end
1044
+ end
1045
+ end
1046
+
1047
+ context 'with an invalid payload' do
1048
+ it 'returns an error' do
1049
+ VCR.use_cassette 'user_management/send_invitation/invalid' do
1050
+ expect do
1051
+ described_class.send_invitation(
1052
+ email: 'invalid@workos.com',
1053
+ )
1054
+ end.to raise_error(
1055
+ WorkOS::APIError,
1056
+ /An Invitation with the email invalid@workos.com already exists/,
1057
+ )
1058
+ end
1059
+ end
1060
+ end
1061
+ end
1062
+
1063
+ describe '.revoke_invitation' do
1064
+ context 'with valid payload' do
1065
+ it 'revokes invitation' do
1066
+ VCR.use_cassette 'user_management/revoke_invitation/valid' do
1067
+ invitation = described_class.revoke_invitation(
1068
+ id: 'invitation_01H5JQDV7R7ATEYZDEG0W5PRYS',
1069
+ )
1070
+
1071
+ expect(invitation.id).to eq('invitation_01H5JQDV7R7ATEYZDEG0W5PRYS')
1072
+ expect(invitation.email).to eq('test@workos.com')
1073
+ end
1074
+ end
1075
+ end
1076
+
1077
+ context 'with an invalid payload' do
1078
+ it 'returns an error' do
1079
+ VCR.use_cassette 'user_management/revoke_invitation/invalid' do
1080
+ expect do
1081
+ described_class.revoke_invitation(
1082
+ id: 'invalid_id',
1083
+ )
1084
+ end.to raise_error(
1085
+ WorkOS::APIError,
1086
+ /Invitation not found/,
1087
+ )
1088
+ end
1089
+ end
1090
+ end
1091
+ end
1092
+ end