Skip to content

Commit 0ab01f5

Browse files
refactor: Implement manual linking for connected players with enhanced UI and search functionality
1 parent 237aeb9 commit 0ab01f5

6 files changed

Lines changed: 965 additions & 15 deletions

File tree

src/XtremeIdiots.Portal.Web.Tests/ApiControllers/ConnectedPlayersControllerTests.cs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
using System.Net;
1414
using System.Security.Claims;
1515
using System.Text;
16+
using XtremeIdiots.Portal.Repository.Abstractions.Constants.V1;
1617
using XtremeIdiots.Portal.Repository.Abstractions.Models.V1.ConnectedPlayers;
18+
using XtremeIdiots.Portal.Repository.Abstractions.Models.V1.UserProfiles;
1719
using XtremeIdiots.Portal.Repository.Api.Client.V1;
1820
using ConnectedPlayersApiController = XtremeIdiots.Portal.Web.ApiControllers.ConnectedPlayersController;
1921

@@ -48,6 +50,21 @@ private ConnectedPlayersApiController CreateSut(ClaimsPrincipal? user = null)
4850
return controller;
4951
}
5052

53+
private static ClaimsPrincipal CreateSeniorAdminUser(Guid? userProfileId = null)
54+
{
55+
var claims = new List<Claim>
56+
{
57+
new(UserProfileClaimType.SeniorAdmin, "true")
58+
};
59+
60+
if (userProfileId.HasValue)
61+
{
62+
claims.Add(new Claim(UserProfileClaimType.UserProfileId, userProfileId.Value.ToString()));
63+
}
64+
65+
return new ClaimsPrincipal(new ClaimsIdentity(claims, "TestAuth"));
66+
}
67+
5168
[Fact]
5269
public async Task GetConnectedPlayersAjax_WithEmptyBody_ReturnsBadRequest()
5370
{
@@ -144,6 +161,120 @@ public async Task GetConnectedPlayersAjax_WithInvalidOrderColumnIndex_ReturnsBad
144161
It.IsAny<CancellationToken>()), Times.Never);
145162
}
146163

164+
[Fact]
165+
public async Task SearchPlayers_WithoutGameType_ReturnsEmptyArray()
166+
{
167+
// Arrange
168+
var sut = CreateSut(CreateSeniorAdminUser());
169+
170+
// Act
171+
var result = await sut.SearchPlayers("Player", null);
172+
173+
// Assert
174+
var okResult = Assert.IsType<OkObjectResult>(result);
175+
var payload = Assert.IsAssignableFrom<Array>(okResult.Value);
176+
Assert.Empty(payload);
177+
178+
mockRepositoryApiClient.Verify(x => x.Players.V1.GetPlayers(
179+
It.IsAny<GameType?>(),
180+
It.IsAny<PlayersFilter?>(),
181+
It.IsAny<string>(),
182+
It.IsAny<int>(),
183+
It.IsAny<int>(),
184+
It.IsAny<PlayersOrder?>(),
185+
It.IsAny<PlayerEntityOptions>()), Times.Never);
186+
}
187+
188+
[Fact]
189+
public async Task SearchUserProfiles_ReturnsOnlyProfilesWithForumId()
190+
{
191+
// Arrange
192+
var withForumId = CreateUserProfileDto("AdminOne", "12345", "admin1@example.com");
193+
var withoutForumId = CreateUserProfileDto("AdminTwo", null, "admin2@example.com");
194+
195+
var response = new ApiResponse<CollectionModel<UserProfileDto>>(new CollectionModel<UserProfileDto>([withForumId, withoutForumId]))
196+
{
197+
Pagination = new ApiPagination(totalCount: 2, filteredCount: 2, skip: 0, top: 20)
198+
};
199+
200+
mockRepositoryApiClient
201+
.Setup(x => x.UserProfiles.V1.GetUserProfiles("Admin", null, 0, 20, UserProfilesOrder.DisplayNameAsc, It.IsAny<CancellationToken>()))
202+
.ReturnsAsync(new ApiResult<CollectionModel<UserProfileDto>>(HttpStatusCode.OK, response));
203+
204+
var sut = CreateSut(CreateSeniorAdminUser());
205+
206+
// Act
207+
var result = await sut.SearchUserProfiles("Admin");
208+
209+
// Assert
210+
var okResult = Assert.IsType<OkObjectResult>(result);
211+
var payload = JArray.Parse(JsonConvert.SerializeObject(okResult.Value));
212+
213+
Assert.Single(payload);
214+
Assert.Equal(withForumId.UserProfileId.ToString(), payload[0]?["id"]?.ToString());
215+
}
216+
217+
[Fact]
218+
public async Task CreateManualLinkAjax_WhenPlayerHasDifferentActiveLink_ReturnsConflict()
219+
{
220+
// Arrange
221+
var actorProfileId = Guid.NewGuid();
222+
var selectedUserProfileId = Guid.NewGuid();
223+
var differentLinkedUserProfileId = Guid.NewGuid();
224+
var playerId = Guid.NewGuid();
225+
226+
var selectedUserProfile = CreateUserProfileDto("Admin", "778899", "admin@example.com", selectedUserProfileId);
227+
228+
var existingLink = CreateConnectedPlayerDto();
229+
var existingLinkJson = JObject.FromObject(existingLink);
230+
existingLinkJson["PlayerId"] = playerId;
231+
existingLinkJson["UserProfileId"] = differentLinkedUserProfileId;
232+
existingLinkJson["IsActive"] = true;
233+
var activeLink = existingLinkJson.ToObject<ConnectedPlayerDto>()!;
234+
235+
var activeLinksResponse = new ApiResponse<CollectionModel<ConnectedPlayerDto>>(new CollectionModel<ConnectedPlayerDto>([activeLink]))
236+
{
237+
Pagination = new ApiPagination(totalCount: 1, filteredCount: 1, skip: 0, top: 5)
238+
};
239+
240+
mockRepositoryApiClient
241+
.Setup(x => x.UserProfiles.V1.GetUserProfile(selectedUserProfileId, It.IsAny<CancellationToken>()))
242+
.ReturnsAsync(new ApiResult<UserProfileDto>(HttpStatusCode.OK, new ApiResponse<UserProfileDto>(selectedUserProfile)));
243+
244+
mockRepositoryApiClient
245+
.Setup(x => x.ConnectedPlayers.V1.GetConnectedPlayers(playerId, null, null, true, 0, 5, It.IsAny<CancellationToken>()))
246+
.ReturnsAsync(new ApiResult<CollectionModel<ConnectedPlayerDto>>(HttpStatusCode.OK, activeLinksResponse));
247+
248+
var sut = CreateSut(CreateSeniorAdminUser(actorProfileId));
249+
250+
// Act
251+
var result = await sut.CreateManualLinkAjax(new ConnectedPlayersApiController.CreateManualLinkAjaxRequest
252+
{
253+
PlayerId = playerId,
254+
UserProfileId = selectedUserProfileId
255+
});
256+
257+
// Assert
258+
Assert.IsType<ConflictObjectResult>(result);
259+
260+
mockRepositoryApiClient.Verify(x => x.ConnectedPlayers.V1.CreateConnectedPlayerLink(
261+
It.IsAny<CreateConnectedPlayerLinkDto>(),
262+
It.IsAny<CancellationToken>()), Times.Never);
263+
}
264+
265+
private static UserProfileDto CreateUserProfileDto(string? displayName, string? forumId, string? email, Guid? userProfileId = null)
266+
{
267+
var json = JsonConvert.SerializeObject(new
268+
{
269+
UserProfileId = userProfileId ?? Guid.NewGuid(),
270+
DisplayName = displayName,
271+
XtremeIdiotsForumId = forumId,
272+
Email = email
273+
});
274+
275+
return JsonConvert.DeserializeObject<UserProfileDto>(json)!;
276+
}
277+
147278
private static ConnectedPlayerDto CreateConnectedPlayerDto()
148279
{
149280
var now = DateTime.UtcNow;

0 commit comments

Comments
 (0)