diff --git a/Iggy_SDK/Contracts/Http/Auth/AuthResponse.cs b/Iggy_SDK/Contracts/Http/Auth/AuthResponse.cs index 241d228..86d737e 100644 --- a/Iggy_SDK/Contracts/Http/Auth/AuthResponse.cs +++ b/Iggy_SDK/Contracts/Http/Auth/AuthResponse.cs @@ -1,7 +1,3 @@ namespace Iggy_SDK.Contracts.Http; -public record AuthResponse(int UserId, TokenInfo AccessToken) -{ - // public required int UserId { get; init; } - // public TokenInfo AccessToken { get; init; } -} +public record AuthResponse(int UserId, TokenInfo AccessToken); diff --git a/Iggy_SDK/Contracts/Http/Auth/PersonalAccessTokenResponse.cs b/Iggy_SDK/Contracts/Http/Auth/PersonalAccessTokenResponse.cs index 7c14082..7e9e2ee 100644 --- a/Iggy_SDK/Contracts/Http/Auth/PersonalAccessTokenResponse.cs +++ b/Iggy_SDK/Contracts/Http/Auth/PersonalAccessTokenResponse.cs @@ -3,5 +3,5 @@ namespace Iggy_SDK.Contracts.Http; public sealed class PersonalAccessTokenResponse { public required string Name { get; init; } - public DateTimeOffset? Expiry { get; init; } + public DateTimeOffset? ExpiryAt { get; init; } } \ No newline at end of file diff --git a/Iggy_SDK/IggyClient/Implementations/HttpMessageStream.cs b/Iggy_SDK/IggyClient/Implementations/HttpMessageStream.cs index 886e306..68451db 100644 --- a/Iggy_SDK/IggyClient/Implementations/HttpMessageStream.cs +++ b/Iggy_SDK/IggyClient/Implementations/HttpMessageStream.cs @@ -622,27 +622,26 @@ public async Task DeletePersonalAccessTokenAsync(DeletePersonalAccessTokenReques } public async Task LoginWithPersonalAccessToken(LoginWithPersonalAccessToken request, CancellationToken token = default) { - // var json = JsonSerializer.Serialize(request, JsonConverterFactory.SnakeCaseOptions); - // var content = new StringContent(json, Encoding.UTF8, "application/json"); - // var response = await _httpClient.PostAsync("/personal-access-tokens/login", content, token); - // if (response.IsSuccessStatusCode) - // { - // var authResponse = await response.Content.ReadFromJsonAsync(JsonConverterFactory.AuthResponseOptions, cancellationToken: token); - // var jwtToken = authResponse!.Tokens?.AccessToken?.Token; - // if (!string.IsNullOrEmpty(authResponse!.Tokens!.AccessToken!.Token)) - // { - // _httpClient.DefaultRequestHeaders.Authorization = - // new AuthenticationHeaderValue("Bearer", jwtToken); - // } - // else - // { - // throw new Exception("The JWT token is missing."); - // } - // return authResponse; - // } - // await HandleResponseAsync(response); - // return null; - - throw new NotImplementedException(); + var json = JsonSerializer.Serialize(request, JsonConverterFactory.SnakeCaseOptions); + var content = new StringContent(json, Encoding.UTF8, "application/json"); + var response = await _httpClient.PostAsync("/personal-access-tokens/login", content, token); + if (response.IsSuccessStatusCode) + { + var authResponse = await response.Content.ReadFromJsonAsync(JsonConverterFactory.AuthResponseOptions, cancellationToken: token); + var jwtToken = authResponse!.AccessToken?.Token; + if (!string.IsNullOrEmpty(authResponse!.AccessToken!.Token)) + { + _httpClient.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", jwtToken); + } + else + { + throw new Exception("The JWT token is missing."); + } + return authResponse; + } + await HandleResponseAsync(response); + + return null; } } \ No newline at end of file diff --git a/Iggy_SDK/JsonConfiguration/PersonAccessTokenResponseConverter.cs b/Iggy_SDK/JsonConfiguration/PersonAccessTokenResponseConverter.cs index bba82b3..6a801e2 100644 --- a/Iggy_SDK/JsonConfiguration/PersonAccessTokenResponseConverter.cs +++ b/Iggy_SDK/JsonConfiguration/PersonAccessTokenResponseConverter.cs @@ -12,7 +12,7 @@ public sealed class PersonalAccessTokenResponseConverter : JsonConverter null, @@ -23,7 +23,7 @@ public sealed class PersonalAccessTokenResponseConverter : JsonConverter MapUsers(ReadOnlySpan payload) diff --git a/Iggy_SDK_Tests/E2ETests/Fixtures/IggyBaseFixture.cs b/Iggy_SDK_Tests/E2ETests/Fixtures/IggyBaseFixture.cs index 71ccb3c..ef88208 100644 --- a/Iggy_SDK_Tests/E2ETests/Fixtures/IggyBaseFixture.cs +++ b/Iggy_SDK_Tests/E2ETests/Fixtures/IggyBaseFixture.cs @@ -28,6 +28,7 @@ public abstract class IggyBaseFixture : IAsyncLifetime .WithPortBinding(3000, true) .WithOutputConsumer(Consume.RedirectStdoutAndStderrToConsole()) .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(3000)) + .WithCleanUp(true) .Build(); public IIggyClient[] SubjectsUnderTest { get; } = new IIggyClient[2]; diff --git a/Iggy_SDK_Tests/E2ETests/PATE2E.cs b/Iggy_SDK_Tests/E2ETests/PATE2E.cs index 14e783e..4bc9be2 100644 --- a/Iggy_SDK_Tests/E2ETests/PATE2E.cs +++ b/Iggy_SDK_Tests/E2ETests/PATE2E.cs @@ -20,76 +20,140 @@ public PATE2E(IggyPATFixture fixture) _fixture = fixture; } - [Fact(Skip = SkipMessage), TestPriority(1)] + [Fact, TestPriority(1)] public async Task CreatePersonalAccessToken_HappyPath_Should_CreatePersonalAccessToken_Successfully() { - var tasks = _fixture.SubjectsUnderTest.Select(sut => Task.Run(async () => - { - await sut.Invoking(x => x.CreatePersonalAccessTokenAsync(PATFixtureBootstrap.CreatePersonalAccessTokenRequest)) - .Should() - .NotThrowAsync(); - })).ToArray(); - await Task.WhenAll(tasks); + // act & assert + await _fixture.HttpSut.Invoking(y => + y.CreatePersonalAccessTokenAsync(PATFixtureBootstrap.CreatePersonalAccessTokenRequest) + ).Should() + .NotThrowAsync(); + + // TODO: This code block is commmented bacause TCP implementation is not working properly. + // var tasks = _fixture.SubjectsUnderTest.Select(sut => Task.Run(async () => + // { + // await sut.Invoking(x => x.CreatePersonalAccessTokenAsync(PATFixtureBootstrap.CreatePersonalAccessTokenRequest)) + // .Should() + // .NotThrowAsync(); + // })).ToArray(); + // + // await Task.WhenAll(tasks); } - [Fact(Skip = SkipMessage), TestPriority(2)] + [Fact, TestPriority(2)] public async Task CreatePersonalAccessToken_Duplicate_Should_Throw_InvalidResponse() { - var tasks = _fixture.SubjectsUnderTest.Select(sut => Task.Run(async () => - { - await sut.Invoking(x => x.CreatePersonalAccessTokenAsync(PATFixtureBootstrap.CreatePersonalAccessTokenRequest)) - .Should() - .ThrowExactlyAsync(); - })).ToArray(); - await Task.WhenAll(tasks); + // act & assert + await _fixture.HttpSut.Invoking(y => + y.CreatePersonalAccessTokenAsync(PATFixtureBootstrap.CreatePersonalAccessTokenRequest) + ).Should() + .ThrowExactlyAsync(); + + // TODO: This code block is commmented bacause TCP implementation is not working properly. + // var tasks = _fixture.SubjectsUnderTest.Select(sut => Task.Run(async () => + // { + // await sut.Invoking(x => x.CreatePersonalAccessTokenAsync(PATFixtureBootstrap.CreatePersonalAccessTokenRequest)) + // .Should() + // .ThrowExactlyAsync(); + // })).ToArray(); + // + // await Task.WhenAll(tasks); } - [Fact(Skip = SkipMessage), TestPriority(3)] + [Fact, TestPriority(3)] public async Task GetPersonalAccessTokens_Should_ReturnValidResponse() { - var tasks = _fixture.SubjectsUnderTest.Select( sut => Task.Run(async () => - { - var response = await sut.GetPersonalAccessTokensAsync(); - response.Should().NotBeNull(); - response.Count.Should().Be(1); - response[0].Name.Should().Be(PATFixtureBootstrap.CreatePersonalAccessTokenRequest.Name); - var tokenExpiryDateTimeOffset = DateTime.UtcNow.AddSeconds((double)PATFixtureBootstrap.CreatePersonalAccessTokenRequest.Expiry!).ToDateTimeOffset(); - response[0].Expiry!.Value.Date.Should().Be(tokenExpiryDateTimeOffset.Date); - })).ToArray(); - await Task.WhenAll(tasks); + // arrange + var expectedTokenExpiryLocaltime = DateTime.UtcNow.AddMicroseconds((double)PATFixtureBootstrap.CreatePersonalAccessTokenRequest.Expiry!).ToLocalTime(); + var expectedPersonalTokenName = PATFixtureBootstrap.CreatePersonalAccessTokenRequest.Name; + + // act + var response = await _fixture.HttpSut.GetPersonalAccessTokensAsync(); + + // assert + response.Should() + .NotBeNull() + .And + .NotBeEmpty() + .And + .ContainSingle(x => + x.Name.Equals(expectedPersonalTokenName) && + x.ExpiryAt!.Value.Date == expectedTokenExpiryLocaltime.Date); + + // TODO: This code block is commmented bacause TCP implementation is not working properly. + // var tasks = _fixture.SubjectsUnderTest.Select( sut => Task.Run(async () => + // { + // var response = await sut.GetPersonalAccessTokensAsync(); + // response.Should().NotBeNull(); + // response.Count.Should().Be(1); + // response[0].Name.Should().Be(PATFixtureBootstrap.CreatePersonalAccessTokenRequest.Name); + // var tokenExpiryDateTimeOffset = DateTime.UtcNow.AddSeconds((double)PATFixtureBootstrap.CreatePersonalAccessTokenRequest.Expiry!).ToDateTimeOffset(); + // response[0].Expiry!.Value.Date.Should().Be(tokenExpiryDateTimeOffset.Date); + // })).ToArray(); + // + // await Task.WhenAll(tasks); } - [Fact(Skip = SkipMessage), TestPriority(4)] + [Fact, TestPriority(4)] public async Task LoginWithPersonalAccessToken_Should_Be_Successfull() { - var tasks = _fixture.SubjectsUnderTest.Select(sut => Task.Run(async () => + // act + var response = await _fixture.HttpSut.CreatePersonalAccessTokenAsync(new CreatePersonalAccessTokenRequest { - var response = await sut.CreatePersonalAccessTokenAsync(new CreatePersonalAccessTokenRequest - { - Name = "test-login", - Expiry = 69420 - }); - await sut.LogoutUser(); - await sut.Invoking(x => x.LoginWithPersonalAccessToken(new LoginWithPersonalAccessToken - { - Token = response!.Token - })).Should().NotThrowAsync(); - })).ToArray(); - await Task.WhenAll(tasks); + Name = "test-login", + Expiry = 1726574121 + }); + + await _fixture.HttpSut.LogoutUser(); + + // assert + await _fixture.HttpSut.Invoking(x => x.LoginWithPersonalAccessToken(new LoginWithPersonalAccessToken + { + Token = response!.Token + })) + .Should() + .NotThrowAsync(); + + // TODO: This code block is commmented bacause TCP implementation is not working properly. + // var tasks = _fixture.SubjectsUnderTest.Select(sut => Task.Run(async () => + // { + // var response = await sut.CreatePersonalAccessTokenAsync(new CreatePersonalAccessTokenRequest + // { + // Name = "test-login", + // Expiry = 69420 + // }); + // await sut.LogoutUser(); + // await sut.Invoking(x => x.LoginWithPersonalAccessToken(new LoginWithPersonalAccessToken + // { + // Token = response!.Token + // })).Should().NotThrowAsync(); + // })).ToArray(); + // + // await Task.WhenAll(tasks); } - [Fact(Skip = SkipMessage), TestPriority(5)] + [Fact, TestPriority(5)] public async Task DeletePersonalAccessToken_Should_DeletePersonalAccessToken_Successfully() { - var tasks = _fixture.SubjectsUnderTest.Select(sut => Task.Run(async () => - { - await sut.Invoking(x => x.DeletePersonalAccessTokenAsync(new DeletePersonalAccessTokenRequest + // act & assert + await _fixture.HttpSut.Invoking(x => x.DeletePersonalAccessTokenAsync(new DeletePersonalAccessTokenRequest { Name = PATFixtureBootstrap.CreatePersonalAccessTokenRequest.Name })) .Should() .NotThrowAsync(); - })).ToArray(); - await Task.WhenAll(tasks); + + // TODO: This code block is commmented bacause TCP implementation is not working properly. + // var tasks = _fixture.SubjectsUnderTest.Select(sut => Task.Run(async () => + // { + // await sut.Invoking(x => x.DeletePersonalAccessTokenAsync(new DeletePersonalAccessTokenRequest + // { + // Name = PATFixtureBootstrap.CreatePersonalAccessTokenRequest.Name + // })) + // .Should() + // .NotThrowAsync(); + // })).ToArray(); + // + // await Task.WhenAll(tasks); } } \ No newline at end of file diff --git a/Iggy_SDK_Tests/MapperTests/BinaryMapper.cs b/Iggy_SDK_Tests/MapperTests/BinaryMapper.cs index 446a654..f43fec0 100644 --- a/Iggy_SDK_Tests/MapperTests/BinaryMapper.cs +++ b/Iggy_SDK_Tests/MapperTests/BinaryMapper.cs @@ -29,7 +29,7 @@ public void MapPersonalAccessTokens_ReturnsValidPersonalAccessTokenResponse() // Assert Assert.NotNull(response); Assert.Equal(name, response[0].Name); - Assert.Equal(assertExpiry, response[0].Expiry); + Assert.Equal(assertExpiry, response[0].ExpiryAt); } [Fact] public void MapOffsets_ReturnsValidOffsetResponse()