-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathKcTestingModule.cs
More file actions
583 lines (471 loc) · 25.3 KB
/
KcTestingModule.cs
File metadata and controls
583 lines (471 loc) · 25.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
using System.Net;
using Bogus;
using Microsoft.Extensions.Logging;
using Moq;
using NETCore.Keycloak.Client.HttpClients.Abstraction;
using NETCore.Keycloak.Client.HttpClients.Implementation;
using NETCore.Keycloak.Client.Models.Auth;
using NETCore.Keycloak.Client.Models.Clients;
using NETCore.Keycloak.Client.Models.ClientScope;
using NETCore.Keycloak.Client.Models.Common;
using NETCore.Keycloak.Client.Models.Groups;
using NETCore.Keycloak.Client.Models.KcEnum;
using NETCore.Keycloak.Client.Models.Organizations;
using NETCore.Keycloak.Client.Models.Roles;
using NETCore.Keycloak.Client.Models.Tokens;
using NETCore.Keycloak.Client.Models.Users;
using NETCore.Keycloak.Client.Tests.MockData;
using NETCore.Keycloak.Client.Tests.Models;
using NETCore.Keycloak.Client.Tests.Modules;
using Newtonsoft.Json;
namespace NETCore.Keycloak.Client.Tests.Abstraction;
/// <summary>
/// Base class for Keycloak testing modules, providing a shared testing environment configuration
/// and utility methods for Keycloak integration tests.
/// This class is intended to be inherited by specific Keycloak test modules to standardize setup and test execution.
/// </summary>
public abstract class KcTestingModule
{
/// <summary>
/// Indicates whether the admin token has been initialized.
/// This ensures that the token is only fetched once during the test lifecycle.---
/// </summary>
private bool _isAdminTokenInitialized;
/// <summary>
/// Instance of the <see cref="IKeycloakClient"/> used to perform Keycloak authentication operations.
/// </summary>
protected IKeycloakClient KeycloakRestClient;
/// <summary>
/// Represents the testing environment configuration for Keycloak integration tests.
/// Loaded from the `Assets/testing_environment.json` file.
/// </summary>
protected KcTestEnvironment TestEnvironment = new();
/// <summary>
/// Initializes a new instance of the <see cref="KcTestingModule"/> class.
/// Performs setup operations, including loading configuration, initializing a mock logger,
/// and setting up the Keycloak client.
/// </summary>
protected KcTestingModule()
{
// Load the test environment configuration from the base module.
LoadConfiguration();
// Initialize the mock logger.
var mockLogger = new Mock<ILogger>();
_ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
// Initialize the Keycloak client using the configured base URL and mock logger.
KeycloakRestClient = new KeycloakClient(TestEnvironment.BaseUrl, mockLogger.Object);
}
/// <summary>
/// Retrieves the realm admin token for a specific context.
/// If the token is already initialized, it retrieves the token from the environment variable.
/// Otherwise, it fetches the token using the resource owner password credentials flow.
/// </summary>
/// <param name="context">The context name used for managing environment variables.</param>
/// <returns>A task representing the asynchronous operation, with a result of <see cref="KcIdentityProviderToken"/>.</returns>
protected async Task<KcIdentityProviderToken> GetRealmAdminTokenAsync(string context)
{
Assert.IsFalse(string.IsNullOrWhiteSpace(context), "The context must not be null or empty.");
if ( !_isAdminTokenInitialized )
{
// Act
var tokenResponse = await KeycloakRestClient.Auth.GetResourceOwnerPasswordTokenAsync(
TestEnvironment.TestingRealm.Name,
new KcClientCredentials
{
ClientId = TestEnvironment.TestingRealm.PublicClient.ClientId
}, new KcUserLogin
{
Username = TestEnvironment.TestingRealm.User.Username,
Password = TestEnvironment.TestingRealm.User.Password
}).ConfigureAwait(false);
// Assert
KcCommonAssertion.AssertIdentityProviderTokenResponse(tokenResponse);
// Validate monitoring metrics for the successful request.
KcCommonAssertion.AssertResponseMonitoringMetrics(tokenResponse.MonitoringMetrics, HttpStatusCode.OK,
HttpMethod.Post);
// Store the token in the environment variable for reuse.
Environment.SetEnvironmentVariable($"{context.ToUpperInvariant()}_KC_ADMIN_TOKEN",
JsonConvert.SerializeObject(tokenResponse.Response));
_isAdminTokenInitialized = true;
return tokenResponse.Response;
}
try
{
// Retrieve the token from the environment variable.
return JsonConvert.DeserializeObject<KcIdentityProviderToken>(
Environment.GetEnvironmentVariable($"{context.ToUpperInvariant()}_KC_ADMIN_TOKEN") ??
string.Empty);
}
catch ( Exception e )
{
Assert.Fail($"Failed to deserialize admin token: {e.Message}");
return null;
}
}
/// <summary>
/// Creates a new realm role in the Keycloak system asynchronously, using the specified context.
/// </summary>
protected async Task CreateRealmRoleAsync(string context, KcRole role)
{
// Retrieve the realm administrator token
var accessToken = await GetRealmAdminTokenAsync(context).ConfigureAwait(false);
Assert.IsNotNull(accessToken);
// Ensure that the realm role object is not null
Assert.IsNotNull(role);
// Send the request to create the realm role
var createRoleResponse = await KeycloakRestClient.Roles
.CreateAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, role).ConfigureAwait(false);
// Assert that the response from the operation is not null
Assert.IsNotNull(createRoleResponse);
// Assert that the response does not indicate an error
Assert.IsFalse(createRoleResponse.IsError);
// Validate the response monitoring metrics
KcCommonAssertion.AssertResponseMonitoringMetrics(createRoleResponse.MonitoringMetrics, HttpStatusCode.Created,
HttpMethod.Post);
}
/// <summary>
/// Asynchronously creates a Keycloak realm role and retrieves its details.
/// </summary>
protected async Task<KcRole> CreateAndGetRealmRoleAsync(string context)
{
// Retrieve the realm administrator token
var accessToken = await GetRealmAdminTokenAsync(context).ConfigureAwait(false);
Assert.IsNotNull(accessToken);
// Generate a new realm role with a random name and predefined attributes
var kcRole = KcRoleMocks.Generate();
// Send the request to create the realm role
var createRoleResponse = await KeycloakRestClient.Roles
.CreateAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, kcRole).ConfigureAwait(false);
// Assert that the response from the operation is not null
Assert.IsNotNull(createRoleResponse);
// Assert that the response does not indicate an error
Assert.IsFalse(createRoleResponse.IsError);
// Validate the response monitoring metrics
KcCommonAssertion.AssertResponseMonitoringMetrics(createRoleResponse.MonitoringMetrics, HttpStatusCode.Created,
HttpMethod.Post);
// Send the request to list realm roles, filtering by the test role's name
var listRolesResponse = await KeycloakRestClient.Roles
.ListAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, new KcFilter
{
Search = kcRole.Name
}).ConfigureAwait(false);
// Assert that the response from the operation is not null
Assert.IsNotNull(listRolesResponse);
// Assert that the response does not indicate an error
Assert.IsFalse(listRolesResponse.IsError);
// Assert that the response contains valid data
Assert.IsNotNull(listRolesResponse.Response);
// Assert that the test role is present in the response
Assert.IsTrue(listRolesResponse.Response.Any(role => role.Name == kcRole.Name));
// Validate the response monitoring metrics
KcCommonAssertion.AssertResponseMonitoringMetrics(listRolesResponse.MonitoringMetrics, HttpStatusCode.OK,
HttpMethod.Get);
return listRolesResponse.Response.First(role => role.Name == kcRole.Name);
}
/// <summary>
/// Retrieves a list of all realm roles in the Keycloak system asynchronously, using the specified context.
/// </summary>
protected async Task<IEnumerable<KcRole>> ListRealmRolesAsync(string context)
{
// Retrieve the realm administrator token
var accessToken = await GetRealmAdminTokenAsync(context).ConfigureAwait(false);
// Ensure that the access token is not null
Assert.IsNotNull(accessToken);
// Send the request to list realm roles
var listRolesResponse = await KeycloakRestClient.Roles
.ListAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken).ConfigureAwait(false);
// Assert that the response from the operation is not null
Assert.IsNotNull(listRolesResponse);
// Assert that the response does not indicate an error
Assert.IsFalse(listRolesResponse.IsError);
// Assert that the response contains valid data
Assert.IsNotNull(listRolesResponse.Response);
return listRolesResponse.Response;
}
/// <summary>
/// Asynchronously creates a client role in the Keycloak realm and retrieves its details.
/// </summary>
protected async Task<KcRole> CreateAndGetClientRoleAsync(string context, KcClient client)
{
// Ensure that the test client exists
Assert.IsNotNull(client);
// Retrieve the realm administrator token
var accessToken = await GetRealmAdminTokenAsync(context).ConfigureAwait(false);
// Ensure that the access token is not null
Assert.IsNotNull(accessToken);
// Generate a new client role for testing
var kcRole = KcRoleMocks.Generate();
// Ensure that the generated role is not null
Assert.IsNotNull(kcRole);
// Send the request to create the client role
var clientRoleResponse = await KeycloakRestClient.Roles
.CreateClientRoleAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, client.Id, kcRole)
.ConfigureAwait(false);
// Ensure that the response is not null
Assert.IsNotNull(clientRoleResponse);
// Ensure the response does not indicate an error
Assert.IsFalse(clientRoleResponse.IsError);
// Ensure that the response content is null as expected for this type of request
Assert.IsNull(clientRoleResponse.Response);
// Validate monitoring metrics for the request
KcCommonAssertion.AssertResponseMonitoringMetrics(clientRoleResponse.MonitoringMetrics, HttpStatusCode.Created,
HttpMethod.Post);
// Send the request to list client roles filtered by the role's name
var listClientRolesResponse = await KeycloakRestClient.Roles
.ListClientRoleAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, client.Id, new KcFilter
{
Search = kcRole.Name
}).ConfigureAwait(false);
// Ensure that the response is not null
Assert.IsNotNull(listClientRolesResponse);
// Ensure the response does not indicate an error
Assert.IsFalse(listClientRolesResponse.IsError);
// Ensure that the response contains a list of client roles
Assert.IsNotNull(listClientRolesResponse.Response);
// Ensure that the test role is present in the response
Assert.IsTrue(listClientRolesResponse.Response.Any(role => role.Name == kcRole.Name));
// Validate monitoring metrics for the request
KcCommonAssertion.AssertResponseMonitoringMetrics(listClientRolesResponse.MonitoringMetrics, HttpStatusCode.OK,
HttpMethod.Get);
return listClientRolesResponse.Response.First(role => role.Name == kcRole.Name);
}
/// <summary>
/// Creates a new user in the specified Keycloak realm and retrieves the created user based on the provided context.
/// </summary>
protected async Task<KcUser> CreateAndGetRealmUserAsync(string context, string password = null,
IDictionary<string, object> attributes = null)
{
// Create a faker instance for generating random data
var faker = new Faker();
// Generate a new user using mock data
var user = KcUserMocks.GenerateUser(faker, password, attributes);
// Ensure the generated user is not null
Assert.IsNotNull(user);
// Retrieve an access token for the realm admin to perform the user creation
var accessToken = await GetRealmAdminTokenAsync(context).ConfigureAwait(false);
Assert.IsNotNull(accessToken);
// Execute the operation to create the user in the specified realm
var createUserResponse = await KeycloakRestClient.Users
.CreateAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, user)
.ConfigureAwait(false);
// Validate the response from the user creation operation
Assert.IsNotNull(createUserResponse);
Assert.IsFalse(createUserResponse.IsError);
// Validate the monitoring metrics for the successful user creation request
KcCommonAssertion.AssertResponseMonitoringMetrics(createUserResponse.MonitoringMetrics, HttpStatusCode.Created,
HttpMethod.Post);
// Execute the operation to list users matching the specified filter criteria
var listUsersResponse = await KeycloakRestClient.Users.ListUserAsync(
TestEnvironment.TestingRealm.Name,
accessToken.AccessToken,
new KcUserFilter
{
Email = user.Email,
Exact = true
}).ConfigureAwait(false);
// Validate the response from the user listing operation
Assert.IsNotNull(listUsersResponse);
Assert.IsFalse(listUsersResponse.IsError);
Assert.IsNotNull(listUsersResponse.Response);
// Ensure that the response contains exactly one user matching the filter criteria
Assert.IsTrue(listUsersResponse.Response.Count() == 1);
// Validate the monitoring metrics for the successful user listing request
KcCommonAssertion.AssertResponseMonitoringMetrics(listUsersResponse.MonitoringMetrics, HttpStatusCode.OK,
HttpMethod.Get);
return listUsersResponse.Response.First();
}
/// <summary>
/// Asynchronously creates a Keycloak client with generated data and retrieves the created client details.
/// </summary>
protected async Task<KcClient> CreateAndGetClientAsync(string context)
{
// Retrieve the realm admin token for authentication.
var accessToken = await GetRealmAdminTokenAsync(context).ConfigureAwait(false);
Assert.IsNotNull(accessToken);
// Use Faker to generate realistic test data for the Keycloak client.
var faker = new Faker();
// Define the Keycloak client object with properties and attributes.
var kClient = KcClientMocks.GeneratePublicClient(faker);
Assert.IsNotNull(kClient);
// Create the Keycloak client via the REST API.
var clientResponse = await KeycloakRestClient.Clients
.CreateAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, kClient).ConfigureAwait(false);
Assert.IsNotNull(clientResponse);
Assert.IsFalse(clientResponse.IsError);
// Validate monitoring metrics for the successful request.
KcCommonAssertion.AssertResponseMonitoringMetrics(clientResponse.MonitoringMetrics, HttpStatusCode.Created,
HttpMethod.Post);
// List clients matching the created client's name.
var clientsResponse = await KeycloakRestClient.Clients
.ListAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, new KcClientFilter
{
Search = kClient.Name
}).ConfigureAwait(false);
Assert.IsNotNull(clientsResponse);
Assert.IsFalse(clientsResponse.IsError);
Assert.IsNotNull(clientsResponse.Response);
Assert.IsTrue(clientsResponse.Response.Any(client => client.ClientId == kClient.ClientId));
// Validate monitoring metrics for the successful request.
KcCommonAssertion.AssertResponseMonitoringMetrics(clientsResponse.MonitoringMetrics, HttpStatusCode.OK,
HttpMethod.Get);
return clientsResponse.Response.FirstOrDefault(client => client.ClientId == kClient.ClientId);
}
/// <summary>
/// Asynchronously creates a Keycloak client scope with generated data and retrieves the created client scope details.
/// </summary>
protected async Task<KcClientScope> CreateAndGetClientScopeAsync(string context)
{
// Retrieve the realm administrator token
var accessToken = await GetRealmAdminTokenAsync(context).ConfigureAwait(false);
Assert.IsNotNull(accessToken);
// Create a faker instance to generate random data
var faker = new Faker();
// Define the client scope to be created
var clientScope = new KcClientScope
{
Description = faker.Random.Words(3),
Name = Guid.NewGuid().ToString().Replace("-", string.Empty, StringComparison.Ordinal),
Protocol = KcProtocol.OpenidConnect
};
// Send the request to create the client scope
var createClientScopeResponse = await KeycloakRestClient.ClientScopes
.CreateAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, clientScope).ConfigureAwait(false);
Assert.IsNotNull(createClientScopeResponse);
Assert.IsFalse(createClientScopeResponse.IsError);
// Validate the response monitoring metrics
KcCommonAssertion.AssertResponseMonitoringMetrics(createClientScopeResponse.MonitoringMetrics,
HttpStatusCode.Created, HttpMethod.Post);
// Send the request to list client scopes
var listClientScopesResponse = await KeycloakRestClient.ClientScopes
.ListAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken).ConfigureAwait(false);
Assert.IsNotNull(listClientScopesResponse);
Assert.IsFalse(listClientScopesResponse.IsError);
Assert.IsNotNull(listClientScopesResponse.Response);
// Assert that the test client scope is present in the list
Assert.IsTrue(listClientScopesResponse.Response.Any(scope => scope.Name == clientScope.Name));
// Validate the response monitoring metrics
KcCommonAssertion.AssertResponseMonitoringMetrics(listClientScopesResponse.MonitoringMetrics,
HttpStatusCode.OK, HttpMethod.Get);
return listClientScopesResponse.Response.First(scope => scope.Name == clientScope.Name);
}
/// <summary>
/// Asynchronously creates a group in the Keycloak realm and retrieves its details.
/// </summary>
protected async Task<KcGroup> CreateAndGetGroupAsync(string context)
{
// Retrieve an access token for the realm admin to perform the group creation.
var accessToken = await GetRealmAdminTokenAsync(context).ConfigureAwait(false);
Assert.IsNotNull(accessToken);
// Generate a mock group.
var kcGroup = new KcGroup
{
Name = Guid.NewGuid().ToString().Replace("-", string.Empty, StringComparison.Ordinal),
Attributes = new Dictionary<string, IEnumerable<string>>
{
{
"test", [
"0"
]
}
}
};
// Execute the operation to create the group.
var createGroupResponse = await KeycloakRestClient.Groups.CreateAsync(
TestEnvironment.TestingRealm.Name,
accessToken.AccessToken,
kcGroup).ConfigureAwait(false);
// Validate the response from the group creation operation.
Assert.IsNotNull(createGroupResponse);
Assert.IsFalse(createGroupResponse.IsError);
// Validate the monitoring metrics for the successful group creation request.
KcCommonAssertion.AssertResponseMonitoringMetrics(createGroupResponse.MonitoringMetrics,
HttpStatusCode.Created, HttpMethod.Post);
// Execute the operation to list groups matching the specified filter criteria.
var listGroupsResponse = await KeycloakRestClient.Groups
.ListAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, new KcGroupFilter
{
Exact = true,
Search = kcGroup.Name
}).ConfigureAwait(false);
// Validate the response from the group listing operation.
Assert.IsNotNull(listGroupsResponse);
Assert.IsFalse(listGroupsResponse.IsError);
Assert.IsNotNull(listGroupsResponse.Response);
// Ensure that the test group is included in the results.
Assert.IsTrue(listGroupsResponse.Response.Any(group => group.Name == kcGroup.Name));
// Validate the monitoring metrics for the successful group listing request.
KcCommonAssertion.AssertResponseMonitoringMetrics(listGroupsResponse.MonitoringMetrics,
HttpStatusCode.OK, HttpMethod.Get);
return listGroupsResponse.Response.First();
}
/// <summary>
/// Creates a new organization in the Keycloak realm and retrieves its details.
/// This method generates a mock organization, creates it via the Keycloak Admin API,
/// then retrieves the created organization by listing organizations with a matching name filter.
/// </summary>
/// <param name="context">The context name used for managing environment variables.</param>
/// <returns>A task representing the asynchronous operation, with a result of <see cref="KcOrganization"/>.</returns>
protected async Task<KcOrganization> CreateAndGetOrganizationAsync(string context)
{
// Retrieve an access token for the realm admin to perform the organization creation.
var accessToken = await GetRealmAdminTokenAsync(context).ConfigureAwait(false);
Assert.IsNotNull(accessToken);
// Create a faker instance for generating random data.
var faker = new Faker();
// Generate a mock organization.
var kcOrganization = KcOrganizationMocks.Generate(faker);
// Execute the operation to create the organization.
var createOrganizationResponse = await KeycloakRestClient.Organizations.CreateAsync(
TestEnvironment.TestingRealm.Name,
accessToken.AccessToken,
kcOrganization).ConfigureAwait(false);
// Validate the response from the organization creation operation.
Assert.IsNotNull(createOrganizationResponse);
Assert.IsFalse(createOrganizationResponse.IsError);
// Validate the monitoring metrics for the successful organization creation request.
KcCommonAssertion.AssertResponseMonitoringMetrics(createOrganizationResponse.MonitoringMetrics,
HttpStatusCode.Created, HttpMethod.Post);
// Execute the operation to list organizations matching the specified filter criteria.
var listOrganizationsResponse = await KeycloakRestClient.Organizations
.ListAsync(TestEnvironment.TestingRealm.Name, accessToken.AccessToken, new KcOrganizationFilter
{
Exact = true,
Search = kcOrganization.Name
}).ConfigureAwait(false);
// Validate the response from the organization listing operation.
Assert.IsNotNull(listOrganizationsResponse);
Assert.IsFalse(listOrganizationsResponse.IsError);
Assert.IsNotNull(listOrganizationsResponse.Response);
// Ensure that the test organization is included in the results.
Assert.IsTrue(listOrganizationsResponse.Response.Any(org => org.Name == kcOrganization.Name));
// Validate the monitoring metrics for the successful organization listing request.
KcCommonAssertion.AssertResponseMonitoringMetrics(listOrganizationsResponse.MonitoringMetrics,
HttpStatusCode.OK, HttpMethod.Get);
return listOrganizationsResponse.Response.First();
}
/// <summary>
/// Loads the test environment configuration from the `Assets/testing_environment.json` file.
/// The loaded configuration is deserialized into the <see cref="KcTestEnvironment"/> object.
/// Ensures that the configuration is not null after loading.
/// </summary>
protected void LoadConfiguration()
{
using var sr =
new StreamReader(Path.Combine(Directory.GetCurrentDirectory(), "Assets/testing_environment.json"));
TestEnvironment = JsonConvert.DeserializeObject<KcTestEnvironment>(sr.ReadToEnd());
Assert.IsNotNull(TestEnvironment, "The test environment configuration must not be null.");
}
/// <summary>
/// Gets the major version of the Keycloak server from the test environment configuration.
/// </summary>
/// <returns>The major version number, or 0 if the version is not set.</returns>
protected int GetKcMajorVersion()
{
if ( string.IsNullOrWhiteSpace(TestEnvironment?.KcVersion) )
{
return 0;
}
var parts = TestEnvironment.KcVersion.Split('.');
return int.TryParse(parts[0], out var major) ? major : 0;
}
}