From bfa10edda8cf143ce65924c4bdb2e3d73e323014 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 22 Dec 2022 09:38:54 +0100 Subject: [PATCH 01/10] Remove duplication when creating WireMock requests/responses --- .../Extensions/WireMockExtensions.cs | 50 ++++++++++++++++--- .../ChangeStreamLayoutTest.cs | 18 ++----- .../CreateSession/CreateSessionTest.cs | 33 ++++-------- .../Video/Sessions/GetStream/GetStreamTest.cs | 28 +++-------- .../Sessions/GetStreams/GetStreamsTest.cs | 28 +++-------- .../Signaling/SendSignal/SendSignalTest.cs | 16 ++---- .../Signaling/SendSignals/SendSignalsTest.cs | 16 ++---- .../Signaling/SendSignals/UseCaseHelper.cs | 6 +++ 8 files changed, 87 insertions(+), 108 deletions(-) create mode 100644 Vonage.Video.Beta.Test/Video/Signaling/SendSignals/UseCaseHelper.cs diff --git a/Vonage.Video.Beta.Test/Extensions/WireMockExtensions.cs b/Vonage.Video.Beta.Test/Extensions/WireMockExtensions.cs index d8494400b..b55d33fb2 100644 --- a/Vonage.Video.Beta.Test/Extensions/WireMockExtensions.cs +++ b/Vonage.Video.Beta.Test/Extensions/WireMockExtensions.cs @@ -1,15 +1,53 @@ -using WireMock.RequestBuilders; +using System.Net; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; namespace Vonage.Video.Beta.Test.Extensions { + /// + /// Extensions for WireMock.Net + /// public static class WireMockExtensions { - public static IRequestBuilder BuildRequestWithAuthenticationHeader(string token) => + /// + /// Creates a response. + /// + /// The http status code + /// The response body. + /// The response. + public static IResponseBuilder CreateResponse(HttpStatusCode code, string body) => + body is null ? CreateResponse(code) : CreateResponse(code).WithBody(body); + + /// + /// Creates a response without a body. + /// + /// The http status code + /// The response. + public static IResponseBuilder CreateResponse(HttpStatusCode code) => + Response.Create().WithStatusCode(code); + + /// + /// Creates a request. + /// + /// The authentication token. + /// The endpoint path. + /// The body. + /// The request. + public static IRequestBuilder CreateRequest(string token, string path, string body) => + body is null ? CreateRequest(token, path) : CreateRequest(token, path).WithBody(body); + + /// + /// Creates a request without a body. + /// + /// The authentication token. + /// The endpoint path. + /// The request. + public static IRequestBuilder CreateRequest(string token, string path) => + BuildRequestWithAuthenticationHeader(token).WithPath(path); + + private static IRequestBuilder BuildRequestWithAuthenticationHeader(string token) => WireMock.RequestBuilders.Request .Create() - .WithAuthenticationHeader(token); - - public static IRequestBuilder WithAuthenticationHeader(this IRequestBuilder builder, string token) => - builder.WithHeader("Authorization", $"Bearer {token}"); + .WithHeader("Authorization", $"Bearer {token}"); } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs index 2e53edb0e..b6dff4b81 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs @@ -9,7 +9,6 @@ using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.ChangeStreamLayout; using WireMock.RequestBuilders; -using WireMock.ResponseBuilders; using WireMock.Server; using Xunit; @@ -56,7 +55,7 @@ public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() { this.server .Given(this.CreateChangeStreamLayoutRequest()) - .RespondWith(CreateChangeStreamLayoutResponse(HttpStatusCode.OK)); + .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK)); var result = await this.request.BindAsync(requestValue => this.client.ChangeStreamLayoutAsync(requestValue)); result.Should().BeSuccess(Unit.Default); @@ -72,7 +71,7 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); this.server .Given(this.CreateChangeStreamLayoutRequest()) - .RespondWith(CreateChangeStreamLayoutResponse(code, expectedBody)); + .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.ChangeStreamLayoutAsync(requestValue)); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); @@ -83,7 +82,7 @@ private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode c var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; this.server .Given(this.CreateChangeStreamLayoutRequest()) - .RespondWith(CreateChangeStreamLayoutResponse(code, + .RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); var result = await this.request.BindAsync(requestValue => this.client.ChangeStreamLayoutAsync(requestValue)); @@ -96,16 +95,7 @@ private IRequestBuilder CreateChangeStreamLayoutRequest() this.request .Map(value => this.jsonSerializer.SerializeObject(new {value.Items})) .Match(_ => _, _ => string.Empty); - return WireMockExtensions.BuildRequestWithAuthenticationHeader(this.token).WithPath(this.path) - .WithBody(serializedItems).UsingPut(); + return WireMockExtensions.CreateRequest(this.token, this.path, serializedItems).UsingPut(); } - - private static IResponseBuilder CreateChangeStreamLayoutResponse(HttpStatusCode code, string body) => - body is null - ? CreateChangeStreamLayoutResponse(code) - : CreateChangeStreamLayoutResponse(code).WithBody(body); - - private static IResponseBuilder CreateChangeStreamLayoutResponse(HttpStatusCode code) => - Response.Create().WithStatusCode(code); } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs index f6ac51195..ce562930f 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs @@ -9,8 +9,6 @@ using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.CreateSession; -using WireMock.RequestBuilders; -using WireMock.ResponseBuilders; using WireMock.Server; using Xunit; @@ -25,6 +23,7 @@ public class CreateSessionTest : IDisposable private readonly WireMockServer server; private readonly CreateSessionResponse session; private readonly string token; + private readonly string path; public CreateSessionTest() { @@ -48,8 +47,8 @@ public async Task ShouldReturnSuccess_GivenSessionIsCreated() { var expectedResponse = this.jsonSerializer.SerializeObject(new[] {this.session}); this.server - .Given(this.CreateChangeStreamLayoutRequest()) - .RespondWith(CreateChangeStreamLayoutResponse(HttpStatusCode.OK, expectedResponse)); + .Given(WireMockExtensions.CreateRequest(this.token, this.request.GetEndpointPath())) + .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, expectedResponse)); var result = await this.client.CreateSessionAsync(this.request); result.Should().BeSuccess(this.session); } @@ -63,8 +62,8 @@ public async Task ShouldReturnSuccess_GivenMultipleSessionsAreCreated() this.fixture.Create(), }); this.server - .Given(this.CreateChangeStreamLayoutRequest()) - .RespondWith(CreateChangeStreamLayoutResponse(HttpStatusCode.OK, expectedResponse)); + .Given(WireMockExtensions.CreateRequest(this.token, this.request.GetEndpointPath())) + .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, expectedResponse)); var result = await this.client.CreateSessionAsync(this.request); result.Should().BeSuccess(this.session); } @@ -74,8 +73,8 @@ public async Task ShouldReturnFailure_GivenResponseContainsNoSession() { var expectedResponse = this.jsonSerializer.SerializeObject(Array.Empty()); this.server - .Given(this.CreateChangeStreamLayoutRequest()) - .RespondWith(CreateChangeStreamLayoutResponse(HttpStatusCode.OK, expectedResponse)); + .Given(WireMockExtensions.CreateRequest(this.token, this.request.GetEndpointPath())) + .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, expectedResponse)); var result = await this.client.CreateSessionAsync(this.request); result.Should().BeFailure(ResultFailure.FromErrorMessage(CreateSessionResponse.NoSessionCreated)); } @@ -93,24 +92,10 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c ? null : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); this.server - .Given(this.CreateChangeStreamLayoutRequest()) - .RespondWith(CreateChangeStreamLayoutResponse(code, expectedBody)); + .Given(WireMockExtensions.CreateRequest(this.token, this.request.GetEndpointPath())) + .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.client.CreateSessionAsync(this.request); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); } - - private IRequestBuilder CreateChangeStreamLayoutRequest() => - WireMockExtensions.BuildRequestWithAuthenticationHeader(this.token) - .WithPath(CreateSessionRequest.CreateSessionEndpoint) - .WithBody(this.request.GetUrlEncoded()) - .UsingPost(); - - private static IResponseBuilder CreateChangeStreamLayoutResponse(HttpStatusCode code, string body) => - body is null - ? CreateChangeStreamLayoutResponse(code) - : CreateChangeStreamLayoutResponse(code).WithBody(body); - - private static IResponseBuilder CreateChangeStreamLayoutResponse(HttpStatusCode code) => - Response.Create().WithStatusCode(code); } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs index 5c1ae60a1..d7bad3f32 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs @@ -10,8 +10,6 @@ using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.GetStream; -using WireMock.RequestBuilders; -using WireMock.ResponseBuilders; using WireMock.Server; using Xunit; @@ -67,8 +65,8 @@ public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() { var expectedResponse = this.fixture.Create(); this.server - .Given(this.CreateGetStreamRequest()) - .RespondWith(CreateGetStreamResponse(HttpStatusCode.OK, + .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, this.jsonSerializer.SerializeObject(expectedResponse))); var result = await this.request.BindAsync(requestValue => this.client.GetStreamAsync(requestValue)); result.Should().BeSuccess(response => @@ -86,8 +84,8 @@ public async Task ShouldReturnFailure_GivenApiResponseCannotBeParsed() var body = this.fixture.Create(); var expectedFailureMessage = $"Unable to deserialize '{body}' into '{nameof(GetStreamResponse)}'."; this.server - .Given(this.CreateGetStreamRequest()) - .RespondWith(CreateGetStreamResponse(HttpStatusCode.OK, body)); + .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, body)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); } @@ -98,8 +96,8 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c ? null : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); this.server - .Given(this.CreateGetStreamRequest()) - .RespondWith(CreateGetStreamResponse(code, expectedBody)); + .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamAsync(requestValue)); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); } @@ -111,20 +109,10 @@ private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode c { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; this.server - .Given(this.CreateGetStreamRequest()) - .RespondWith(CreateGetStreamResponse(code, - jsonError)); + .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + .RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); } - - private IRequestBuilder CreateGetStreamRequest() => - WireMockExtensions.BuildRequestWithAuthenticationHeader(this.token).WithPath(this.path).UsingGet(); - - private static IResponseBuilder CreateGetStreamResponse(HttpStatusCode code, string body) => - body is null ? CreateGetStreamResponse(code) : CreateGetStreamResponse(code).WithBody(body); - - private static IResponseBuilder CreateGetStreamResponse(HttpStatusCode code) => - Response.Create().WithStatusCode(code); } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs index a06c9aeb1..fb2bf0e83 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs @@ -10,8 +10,6 @@ using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.GetStreams; -using WireMock.RequestBuilders; -using WireMock.ResponseBuilders; using WireMock.Server; using Xunit; @@ -66,8 +64,8 @@ public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() { var expectedResponse = this.fixture.Create(); this.server - .Given(this.CreateGetStreamsRequest()) - .RespondWith(CreateGetStreamsResponse(HttpStatusCode.OK, + .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, this.jsonSerializer.SerializeObject(expectedResponse))); var result = await this.request.BindAsync(requestValue => this.client.GetStreamsAsync(requestValue)); result.Should().BeSuccess(response => @@ -83,8 +81,8 @@ public async Task ShouldReturnFailure_GivenApiResponseCannotBeParsed() var body = this.fixture.Create(); var expectedFailureMessage = $"Unable to deserialize '{body}' into '{nameof(GetStreamsResponse)}'."; this.server - .Given(this.CreateGetStreamsRequest()) - .RespondWith(CreateGetStreamsResponse(HttpStatusCode.OK, body)); + .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, body)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamsAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); } @@ -95,8 +93,8 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c ? null : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); this.server - .Given(this.CreateGetStreamsRequest()) - .RespondWith(CreateGetStreamsResponse(code, expectedBody)); + .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamsAsync(requestValue)); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); } @@ -108,20 +106,10 @@ private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode c { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; this.server - .Given(this.CreateGetStreamsRequest()) - .RespondWith(CreateGetStreamsResponse(code, - jsonError)); + .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + .RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamsAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); } - - private IRequestBuilder CreateGetStreamsRequest() => - WireMockExtensions.BuildRequestWithAuthenticationHeader(this.token).WithPath(this.path).UsingGet(); - - private static IResponseBuilder CreateGetStreamsResponse(HttpStatusCode code, string body) => - body is null ? CreateGetStreamsResponse(code) : CreateGetStreamsResponse(code).WithBody(body); - - private static IResponseBuilder CreateGetStreamsResponse(HttpStatusCode code) => - Response.Create().WithStatusCode(code); } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs index 9128f6a5c..5a0d44115 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs @@ -10,7 +10,6 @@ using Vonage.Video.Beta.Video.Signaling; using Vonage.Video.Beta.Video.Signaling.SendSignal; using WireMock.RequestBuilders; -using WireMock.ResponseBuilders; using WireMock.Server; using Xunit; @@ -58,7 +57,7 @@ public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() { this.server .Given(this.CreateRequest()) - .RespondWith(CreateResponse(HttpStatusCode.OK)); + .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalAsync(requestValue)); result.Should().BeSuccess(Unit.Default); @@ -69,7 +68,7 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c var expectedBody = message is null ? null : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); - this.server.Given(this.CreateRequest()).RespondWith(CreateResponse(code, expectedBody)); + this.server.Given(this.CreateRequest()).RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalAsync(requestValue)); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); } @@ -80,23 +79,16 @@ private IRequestBuilder CreateRequest() this.request .Map(value => this.jsonSerializer.SerializeObject(value.Content)) .Match(_ => _, _ => string.Empty); - return WireMockExtensions.BuildRequestWithAuthenticationHeader(this.token).WithPath(this.path) - .WithBody(serializedItems).UsingPost(); + return WireMockExtensions.CreateRequest(this.token, this.path, serializedItems).UsingPost(); } private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; - this.server.Given(this.CreateRequest()).RespondWith(CreateResponse(code, jsonError)); + this.server.Given(this.CreateRequest()).RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); } - - private static IResponseBuilder CreateResponse(HttpStatusCode code, string body) => - body is null ? CreateResponse(code) : CreateResponse(code).WithBody(body); - - private static IResponseBuilder CreateResponse(HttpStatusCode code) => - Response.Create().WithStatusCode(code); } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs index c66687d74..548f7b420 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs @@ -10,7 +10,6 @@ using Vonage.Video.Beta.Video.Signaling; using Vonage.Video.Beta.Video.Signaling.SendSignals; using WireMock.RequestBuilders; -using WireMock.ResponseBuilders; using WireMock.Server; using Xunit; @@ -58,7 +57,7 @@ public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() { this.server .Given(this.CreateRequest()) - .RespondWith(CreateResponse(HttpStatusCode.OK)); + .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalsAsync(requestValue)); result.Should().BeSuccess(Unit.Default); @@ -69,7 +68,7 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c var expectedBody = message is null ? null : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); - this.server.Given(this.CreateRequest()).RespondWith(CreateResponse(code, expectedBody)); + this.server.Given(this.CreateRequest()).RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalsAsync(requestValue)); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); } @@ -80,23 +79,16 @@ private IRequestBuilder CreateRequest() this.request .Map(value => this.jsonSerializer.SerializeObject(value.Content)) .Match(_ => _, _ => string.Empty); - return WireMockExtensions.BuildRequestWithAuthenticationHeader(this.token).WithPath(this.path) - .WithBody(serializedItems).UsingPost(); + return WireMockExtensions.CreateRequest(this.token, this.path, serializedItems).UsingPost(); } private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; - this.server.Given(this.CreateRequest()).RespondWith(CreateResponse(code, jsonError)); + this.server.Given(this.CreateRequest()).RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalsAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); } - - private static IResponseBuilder CreateResponse(HttpStatusCode code, string body) => - body is null ? CreateResponse(code) : CreateResponse(code).WithBody(body); - - private static IResponseBuilder CreateResponse(HttpStatusCode code) => - Response.Create().WithStatusCode(code); } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/UseCaseHelper.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/UseCaseHelper.cs new file mode 100644 index 000000000..177c89534 --- /dev/null +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/UseCaseHelper.cs @@ -0,0 +1,6 @@ +namespace Vonage.Video.Beta.Test.Video.Signaling.SendSignals +{ + public class UseCaseHelper + { + } +} \ No newline at end of file From 9c67ddaf0faa4cfce659ee7ba52bca56168d4fa6 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 22 Dec 2022 10:43:34 +0100 Subject: [PATCH 02/10] Implement UseCaseHelper to reduce duplication --- .../ChangeStreamLayoutTest.cs | 33 +++++----- .../CreateSession/CreateSessionTest.cs | 54 ++++++---------- .../Video/Sessions/GetStream/GetStreamTest.cs | 61 +++++++----------- .../Sessions/GetStreams/GetStreamsTest.cs | 63 ++++++++----------- .../Signaling/SendSignal/SendSignalTest.cs | 37 +++++------ .../Signaling/SendSignals/SendSignalsTest.cs | 35 +++++------ .../Signaling/SendSignals/UseCaseHelper.cs | 6 -- Vonage.Video.Beta.Test/Video/UseCaseHelper.cs | 51 +++++++++++++++ 8 files changed, 166 insertions(+), 174 deletions(-) delete mode 100644 Vonage.Video.Beta.Test/Video/Signaling/SendSignals/UseCaseHelper.cs create mode 100644 Vonage.Video.Beta.Test/Video/UseCaseHelper.cs diff --git a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs index b6dff4b81..8f6371227 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs @@ -9,7 +9,6 @@ using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.ChangeStreamLayout; using WireMock.RequestBuilders; -using WireMock.Server; using Xunit; namespace Vonage.Video.Beta.Test.Video.Sessions.ChangeStreamLayout @@ -17,22 +16,16 @@ namespace Vonage.Video.Beta.Test.Video.Sessions.ChangeStreamLayout public class ChangeStreamLayoutTest { private readonly SessionClient client; - private readonly JsonSerializer jsonSerializer; - private readonly string path; private readonly Result request; - private readonly WireMockServer server; - private readonly string token; + private readonly UseCaseHelper helper; public ChangeStreamLayoutTest() { - this.server = WireMockServer.Start(); - this.jsonSerializer = new JsonSerializer(); - var fixture = new Fixture(); - this.token = fixture.Create(); - this.request = ChangeStreamLayoutRequest.Parse(fixture.Create(), fixture.Create(), - fixture.CreateMany()); - this.path = this.GetPathFromRequest(); - this.client = new SessionClient(this.server.CreateClient(), () => this.token); + this.helper = new UseCaseHelper(); + this.request = ChangeStreamLayoutRequest.Parse(this.helper.Fixture.Create(), + this.helper.Fixture.Create(), + this.helper.Fixture.CreateMany()); + this.client = new SessionClient(this.helper.Server.CreateClient(), () => this.helper.Token); } [Property] @@ -53,7 +46,7 @@ public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => [Fact] public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() { - this.server + this.helper.Server .Given(this.CreateChangeStreamLayoutRequest()) .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK)); var result = @@ -68,8 +61,8 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c { var expectedBody = message is null ? null - : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); - this.server + : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + this.helper.Server .Given(this.CreateChangeStreamLayoutRequest()) .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = @@ -80,7 +73,7 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; - this.server + this.helper.Server .Given(this.CreateChangeStreamLayoutRequest()) .RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); @@ -93,9 +86,11 @@ private IRequestBuilder CreateChangeStreamLayoutRequest() { var serializedItems = this.request - .Map(value => this.jsonSerializer.SerializeObject(new {value.Items})) + .Map(value => this.helper.Serializer.SerializeObject(new {value.Items})) .Match(_ => _, _ => string.Empty); - return WireMockExtensions.CreateRequest(this.token, this.path, serializedItems).UsingPut(); + return WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request), serializedItems) + .UsingPut(); } } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs index ce562930f..0a1f11463 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs @@ -4,50 +4,34 @@ using AutoFixture; using FsCheck; using FsCheck.Xunit; -using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.CreateSession; -using WireMock.Server; using Xunit; namespace Vonage.Video.Beta.Test.Video.Sessions.CreateSession { - public class CreateSessionTest : IDisposable + public class CreateSessionTest { private readonly SessionClient client; - private readonly Fixture fixture; - private readonly JsonSerializer jsonSerializer; private readonly CreateSessionRequest request = CreateSessionRequest.Default; - private readonly WireMockServer server; private readonly CreateSessionResponse session; - private readonly string token; - private readonly string path; + private readonly UseCaseHelper helper; public CreateSessionTest() { - this.server = WireMockServer.Start(); - this.jsonSerializer = new JsonSerializer(); - this.fixture = new Fixture(); - this.token = this.fixture.Create(); - this.session = this.fixture.Create(); - this.client = new SessionClient(this.server.CreateClient(), () => this.token); - } - - public void Dispose() - { - this.server.Stop(); - this.server.Reset(); - GC.SuppressFinalize(this); + this.helper = new UseCaseHelper(); + this.session = this.helper.Fixture.Create(); + this.client = new SessionClient(this.helper.Server.CreateClient(), () => this.helper.Token); } [Fact] public async Task ShouldReturnSuccess_GivenSessionIsCreated() { - var expectedResponse = this.jsonSerializer.SerializeObject(new[] {this.session}); - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.request.GetEndpointPath())) + var expectedResponse = this.helper.Serializer.SerializeObject(new[] {this.session}); + this.helper.Server + .Given(WireMockExtensions.CreateRequest(this.helper.Token, this.request.GetEndpointPath())) .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, expectedResponse)); var result = await this.client.CreateSessionAsync(this.request); result.Should().BeSuccess(this.session); @@ -56,13 +40,13 @@ public async Task ShouldReturnSuccess_GivenSessionIsCreated() [Fact] public async Task ShouldReturnSuccess_GivenMultipleSessionsAreCreated() { - var expectedResponse = this.jsonSerializer.SerializeObject(new[] + var expectedResponse = this.helper.Serializer.SerializeObject(new[] { - this.session, this.fixture.Create(), - this.fixture.Create(), + this.session, this.helper.Fixture.Create(), + this.helper.Fixture.Create(), }); - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.request.GetEndpointPath())) + this.helper.Server + .Given(WireMockExtensions.CreateRequest(this.helper.Token, this.request.GetEndpointPath())) .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, expectedResponse)); var result = await this.client.CreateSessionAsync(this.request); result.Should().BeSuccess(this.session); @@ -71,9 +55,9 @@ public async Task ShouldReturnSuccess_GivenMultipleSessionsAreCreated() [Fact] public async Task ShouldReturnFailure_GivenResponseContainsNoSession() { - var expectedResponse = this.jsonSerializer.SerializeObject(Array.Empty()); - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.request.GetEndpointPath())) + var expectedResponse = this.helper.Serializer.SerializeObject(Array.Empty()); + this.helper.Server + .Given(WireMockExtensions.CreateRequest(this.helper.Token, this.request.GetEndpointPath())) .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, expectedResponse)); var result = await this.client.CreateSessionAsync(this.request); result.Should().BeFailure(ResultFailure.FromErrorMessage(CreateSessionResponse.NoSessionCreated)); @@ -90,9 +74,9 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c { var expectedBody = message is null ? null - : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.request.GetEndpointPath())) + : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + this.helper.Server + .Given(WireMockExtensions.CreateRequest(this.helper.Token, this.request.GetEndpointPath())) .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.client.CreateSessionAsync(this.request); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs index d7bad3f32..df18ec683 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs @@ -1,5 +1,4 @@ -using System; -using System.Net; +using System.Net; using System.Threading.Tasks; using AutoFixture; using FluentAssertions; @@ -10,39 +9,23 @@ using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.GetStream; -using WireMock.Server; using Xunit; namespace Vonage.Video.Beta.Test.Video.Sessions.GetStream { - public class GetStreamTest : IDisposable + public class GetStreamTest { private readonly SessionClient client; - private readonly Fixture fixture; - private readonly JsonSerializer jsonSerializer; - private readonly string path; private readonly Result request; - private readonly WireMockServer server; - private readonly string token; + private readonly UseCaseHelper helper; public GetStreamTest() { - this.server = WireMockServer.Start(); - this.jsonSerializer = new JsonSerializer(); - this.fixture = new Fixture(); - this.fixture.Create(); - this.token = this.fixture.Create(); - this.request = GetStreamRequest.Parse(this.fixture.Create(), this.fixture.Create(), - this.fixture.Create()); - this.path = this.GetPathFromRequest(); - this.client = new SessionClient(this.server.CreateClient(), () => this.token); - } - - public void Dispose() - { - this.server.Stop(); - this.server.Reset(); - GC.SuppressFinalize(this); + this.helper = new UseCaseHelper(); + this.request = GetStreamRequest.Parse(this.helper.Fixture.Create(), + this.helper.Fixture.Create(), + this.helper.Fixture.Create()); + this.client = new SessionClient(this.helper.Server.CreateClient(), () => this.helper.Token); } [Property] @@ -63,11 +46,12 @@ public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => [Fact] public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() { - var expectedResponse = this.fixture.Create(); - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + var expectedResponse = this.helper.Fixture.Create(); + this.helper.Server + .Given(WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, - this.jsonSerializer.SerializeObject(expectedResponse))); + this.helper.Serializer.SerializeObject(expectedResponse))); var result = await this.request.BindAsync(requestValue => this.client.GetStreamAsync(requestValue)); result.Should().BeSuccess(response => { @@ -81,10 +65,11 @@ public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() [Fact] public async Task ShouldReturnFailure_GivenApiResponseCannotBeParsed() { - var body = this.fixture.Create(); + var body = this.helper.Fixture.Create(); var expectedFailureMessage = $"Unable to deserialize '{body}' into '{nameof(GetStreamResponse)}'."; - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + this.helper.Server + .Given(WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, body)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); @@ -94,9 +79,10 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c { var expectedBody = message is null ? null - : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + this.helper.Server + .Given(WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamAsync(requestValue)); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); @@ -108,8 +94,9 @@ private string GetPathFromRequest() => private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + this.helper.Server + .Given(WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) .RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs index fb2bf0e83..346d80850 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs @@ -1,5 +1,4 @@ -using System; -using System.Net; +using System.Net; using System.Threading.Tasks; using AutoFixture; using FluentAssertions; @@ -10,38 +9,22 @@ using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.GetStreams; -using WireMock.Server; using Xunit; namespace Vonage.Video.Beta.Test.Video.Sessions.GetStreams { - public class GetStreamsTest : IDisposable + public class GetStreamsTest { private readonly SessionClient client; - private readonly Fixture fixture; - private readonly JsonSerializer jsonSerializer; - private readonly string path; private readonly Result request; - private readonly WireMockServer server; - private readonly string token; + private readonly UseCaseHelper helper; public GetStreamsTest() { - this.server = WireMockServer.Start(); - this.jsonSerializer = new JsonSerializer(); - this.fixture = new Fixture(); - this.fixture.Create(); - this.token = this.fixture.Create(); - this.request = GetStreamsRequest.Parse(this.fixture.Create(), this.fixture.Create()); - this.path = this.GetPathFromRequest(); - this.client = new SessionClient(this.server.CreateClient(), () => this.token); - } - - public void Dispose() - { - this.server.Stop(); - this.server.Reset(); - GC.SuppressFinalize(this); + this.helper = new UseCaseHelper(); + this.request = GetStreamsRequest.Parse(this.helper.Fixture.Create(), + this.helper.Fixture.Create()); + this.client = new SessionClient(this.helper.Server.CreateClient(), () => this.helper.Token); } [Property] @@ -62,26 +45,28 @@ public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => [Fact] public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() { - var expectedResponse = this.fixture.Create(); - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + var expectedResponse = this.helper.Fixture.Create(); + this.helper.Server + .Given(WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, - this.jsonSerializer.SerializeObject(expectedResponse))); + this.helper.Serializer.SerializeObject(expectedResponse))); var result = await this.request.BindAsync(requestValue => this.client.GetStreamsAsync(requestValue)); result.Should().BeSuccess(response => { - this.jsonSerializer.SerializeObject(response).Should() - .Be(this.jsonSerializer.SerializeObject(expectedResponse)); + this.helper.Serializer.SerializeObject(response).Should() + .Be(this.helper.Serializer.SerializeObject(expectedResponse)); }); } [Fact] public async Task ShouldReturnFailure_GivenApiResponseCannotBeParsed() { - var body = this.fixture.Create(); + var body = this.helper.Fixture.Create(); var expectedFailureMessage = $"Unable to deserialize '{body}' into '{nameof(GetStreamsResponse)}'."; - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + this.helper.Server + .Given(WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK, body)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamsAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); @@ -91,9 +76,10 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c { var expectedBody = message is null ? null - : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + this.helper.Server + .Given(WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamsAsync(requestValue)); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); @@ -105,8 +91,9 @@ private string GetPathFromRequest() => private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; - this.server - .Given(WireMockExtensions.CreateRequest(this.token, this.path).UsingGet()) + this.helper.Server + .Given(WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) .RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamsAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs index 5a0d44115..1bcd3659d 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs @@ -10,7 +10,6 @@ using Vonage.Video.Beta.Video.Signaling; using Vonage.Video.Beta.Video.Signaling.SendSignal; using WireMock.RequestBuilders; -using WireMock.Server; using Xunit; namespace Vonage.Video.Beta.Test.Video.Signaling.SendSignal @@ -18,23 +17,17 @@ namespace Vonage.Video.Beta.Test.Video.Signaling.SendSignal public class SendSignalTest { private readonly SignalingClient client; - private readonly JsonSerializer jsonSerializer; - private readonly string path; private readonly Result request; - private readonly WireMockServer server; - private readonly string token; + private readonly UseCaseHelper helper; public SendSignalTest() { - this.server = WireMockServer.Start(); - this.jsonSerializer = new JsonSerializer(); - var fixture = new Fixture(); - this.token = fixture.Create(); - this.request = SendSignalRequest.Parse(fixture.Create(), fixture.Create(), - fixture.Create(), - fixture.Create()); - this.path = this.request.Match(value => value.GetEndpointPath(), _ => string.Empty); - this.client = new SignalingClient(this.server.CreateClient(), () => this.token); + this.helper = new UseCaseHelper(); + this.request = SendSignalRequest.Parse(this.helper.Fixture.Create(), + this.helper.Fixture.Create(), + this.helper.Fixture.Create(), + this.helper.Fixture.Create()); + this.client = new SignalingClient(this.helper.Server.CreateClient(), () => this.helper.Token); } [Property] @@ -55,7 +48,7 @@ public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => [Fact] public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() { - this.server + this.helper.Server .Given(this.CreateRequest()) .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK)); var result = @@ -67,8 +60,9 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c { var expectedBody = message is null ? null - : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); - this.server.Given(this.CreateRequest()).RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); + : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + this.helper.Server.Given(this.CreateRequest()) + .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalAsync(requestValue)); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); } @@ -77,15 +71,18 @@ private IRequestBuilder CreateRequest() { var serializedItems = this.request - .Map(value => this.jsonSerializer.SerializeObject(value.Content)) + .Map(value => this.helper.Serializer.SerializeObject(value.Content)) .Match(_ => _, _ => string.Empty); - return WireMockExtensions.CreateRequest(this.token, this.path, serializedItems).UsingPost(); + return WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request), serializedItems) + .UsingPost(); } private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; - this.server.Given(this.CreateRequest()).RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); + this.helper.Server.Given(this.CreateRequest()) + .RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs index 548f7b420..965157205 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs @@ -10,7 +10,6 @@ using Vonage.Video.Beta.Video.Signaling; using Vonage.Video.Beta.Video.Signaling.SendSignals; using WireMock.RequestBuilders; -using WireMock.Server; using Xunit; namespace Vonage.Video.Beta.Test.Video.Signaling.SendSignals @@ -19,22 +18,16 @@ namespace Vonage.Video.Beta.Test.Video.Signaling.SendSignals public class SendSignalsTest { private readonly SignalingClient client; - private readonly JsonSerializer jsonSerializer; - private readonly string path; private readonly Result request; - private readonly WireMockServer server; - private readonly string token; + private readonly UseCaseHelper helper; public SendSignalsTest() { - this.server = WireMockServer.Start(); - this.jsonSerializer = new JsonSerializer(); - var fixture = new Fixture(); - this.token = fixture.Create(); - this.request = SendSignalsRequest.Parse(fixture.Create(), fixture.Create(), - fixture.Create()); - this.path = this.request.Match(value => value.GetEndpointPath(), _ => string.Empty); - this.client = new SignalingClient(this.server.CreateClient(), () => this.token); + this.helper = new UseCaseHelper(); + this.request = SendSignalsRequest.Parse(this.helper.Fixture.Create(), + this.helper.Fixture.Create(), + this.helper.Fixture.Create()); + this.client = new SignalingClient(this.helper.Server.CreateClient(), () => this.helper.Token); } [Property] @@ -55,7 +48,7 @@ public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => [Fact] public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() { - this.server + this.helper.Server .Given(this.CreateRequest()) .RespondWith(WireMockExtensions.CreateResponse(HttpStatusCode.OK)); var result = @@ -67,8 +60,9 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c { var expectedBody = message is null ? null - : this.jsonSerializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); - this.server.Given(this.CreateRequest()).RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); + : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + this.helper.Server.Given(this.CreateRequest()) + .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalsAsync(requestValue)); result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); } @@ -77,15 +71,18 @@ private IRequestBuilder CreateRequest() { var serializedItems = this.request - .Map(value => this.jsonSerializer.SerializeObject(value.Content)) + .Map(value => this.helper.Serializer.SerializeObject(value.Content)) .Match(_ => _, _ => string.Empty); - return WireMockExtensions.CreateRequest(this.token, this.path, serializedItems).UsingPost(); + return WireMockExtensions + .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request), serializedItems) + .UsingPost(); } private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; - this.server.Given(this.CreateRequest()).RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); + this.helper.Server.Given(this.CreateRequest()) + .RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalsAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/UseCaseHelper.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/UseCaseHelper.cs deleted file mode 100644 index 177c89534..000000000 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/UseCaseHelper.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Vonage.Video.Beta.Test.Video.Signaling.SendSignals -{ - public class UseCaseHelper - { - } -} \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/UseCaseHelper.cs b/Vonage.Video.Beta.Test/Video/UseCaseHelper.cs new file mode 100644 index 000000000..7261021ee --- /dev/null +++ b/Vonage.Video.Beta.Test/Video/UseCaseHelper.cs @@ -0,0 +1,51 @@ +using System; +using AutoFixture; +using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Video; +using WireMock.Server; + +namespace Vonage.Video.Beta.Test.Video +{ + /// + /// Helper for use cases. + /// + public class UseCaseHelper : IDisposable + { + public JsonSerializer Serializer { get; } + + public WireMockServer Server { get; } + + public string Token { get; } + + public Fixture Fixture { get; } + + /// + /// Creates the helper and initialize dependencies. + /// + public UseCaseHelper() + { + this.Server = WireMockServer.Start(); + this.Serializer = new JsonSerializer(); + this.Fixture = new Fixture(); + this.Token = this.Fixture.Create(); + } + + /// + public void Dispose() + { + this.Server.Stop(); + this.Server.Reset(); + this.Server.Dispose(); + GC.SuppressFinalize(this); + } + + /// + /// Retrieves the path from a request. + /// + /// The request. + /// The type of the request. + /// The path. + public static string GetPathFromRequest(Result request) where T : IVideoRequest => + request.Match(value => value.GetEndpointPath(), failure => string.Empty); + } +} \ No newline at end of file From 46e8f4ca5cab8eb58de00d9a2031d30f815ebd7e Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 22 Dec 2022 10:52:36 +0100 Subject: [PATCH 03/10] Code cleanup --- .../Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs | 3 --- .../Video/Sessions/GetStream/GetStreamTest.cs | 3 --- .../Video/Sessions/GetStreams/GetStreamsTest.cs | 3 --- 3 files changed, 9 deletions(-) diff --git a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs index 8f6371227..d887d84d8 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs @@ -54,9 +54,6 @@ public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() result.Should().BeSuccess(Unit.Default); } - private string GetPathFromRequest() => - this.request.Match(value => value.GetEndpointPath(), failure => string.Empty); - private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) { var expectedBody = message is null diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs index df18ec683..debdf523d 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs @@ -88,9 +88,6 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); } - private string GetPathFromRequest() => - this.request.Match(value => value.GetEndpointPath(), failure => string.Empty); - private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs index 346d80850..e14292cbf 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs @@ -85,9 +85,6 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode c result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); } - private string GetPathFromRequest() => - this.request.Match(value => value.GetEndpointPath(), failure => string.Empty); - private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) { var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; From c60a2f9068a8f89abfd8340fe2a31941814a19b4 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 22 Dec 2022 11:05:21 +0100 Subject: [PATCH 04/10] Reduce duplication on property-based tests --- .../Extensions/FsCheckExtensions.cs | 23 ++++++++++++++++++- .../ChangeStreamLayoutTest.cs | 15 ++++++++---- .../CreateSession/CreateSessionTest.cs | 4 ++-- .../Video/Sessions/GetStream/GetStreamTest.cs | 14 +++++++---- .../Sessions/GetStreams/GetStreamsTest.cs | 12 ++++++---- .../Signaling/SendSignal/SendSignalTest.cs | 17 +++++++++----- .../Signaling/SendSignals/SendSignalsTest.cs | 14 +++++++---- 7 files changed, 71 insertions(+), 28 deletions(-) diff --git a/Vonage.Video.Beta.Test/Extensions/FsCheckExtensions.cs b/Vonage.Video.Beta.Test/Extensions/FsCheckExtensions.cs index 1d930190d..1b7a86bdf 100644 --- a/Vonage.Video.Beta.Test/Extensions/FsCheckExtensions.cs +++ b/Vonage.Video.Beta.Test/Extensions/FsCheckExtensions.cs @@ -3,9 +3,30 @@ namespace Vonage.Video.Beta.Test.Extensions { + /// + /// Extensions for FsCheck. + /// public static class FsCheckExtensions { - public static Arbitrary GetInvalidStatusCodes() => Arb.From() + /// + /// Retrieves a HttpStatusCode generator that produces only invalid codes. + /// + /// An Arbitrary of status codes. + public static Arbitrary GetInvalidStatusCodes() => GetAny() .MapFilter(_ => _, code => (int) code >= 400 && (int) code < 600); + + /// + /// Retrieves a string generator that produces only non-null/non-empty string. + /// + /// An Arbitrary of strings. + public static Arbitrary GetNonEmptyStrings() => + GetAny().MapFilter(_ => _, value => !string.IsNullOrWhiteSpace(value)); + + /// + /// Retrieves a generator that produces any value. + /// + /// Type of the value. + /// An Arbitrary. + public static Arbitrary GetAny() => Arb.From(); } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs index d887d84d8..4228a038a 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs @@ -1,6 +1,7 @@ using System.Net; using System.Threading.Tasks; using AutoFixture; +using AutoFixture.Kernel; using FsCheck; using FsCheck.Xunit; using Vonage.Video.Beta.Common; @@ -22,24 +23,22 @@ public class ChangeStreamLayoutTest public ChangeStreamLayoutTest() { this.helper = new UseCaseHelper(); - this.request = ChangeStreamLayoutRequest.Parse(this.helper.Fixture.Create(), - this.helper.Fixture.Create(), - this.helper.Fixture.CreateMany()); this.client = new SessionClient(this.helper.Server.CreateClient(), () => this.helper.Token); + this.request = BuildRequest(this.helper.Fixture); } [Property] public Property ShouldReturnFailure_GivenApiResponseIsError() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From(), + FsCheckExtensions.GetAny(), (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); [Property] public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From().MapFilter(_ => _, value => !string.IsNullOrWhiteSpace(value)), + FsCheckExtensions.GetNonEmptyStrings(), (statusCode, jsonError) => this.VerifyReturnsFailureGivenErrorCannotBeParsed(statusCode, jsonError).Wait()); @@ -54,6 +53,12 @@ public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() result.Should().BeSuccess(Unit.Default); } + private static Result BuildRequest(ISpecimenBuilder fixture) => + ChangeStreamLayoutRequest.Parse( + fixture.Create(), + fixture.Create(), + fixture.CreateMany()); + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) { var expectedBody = message is null diff --git a/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs index 0a1f11463..dd74f622f 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs @@ -22,8 +22,8 @@ public class CreateSessionTest public CreateSessionTest() { this.helper = new UseCaseHelper(); - this.session = this.helper.Fixture.Create(); this.client = new SessionClient(this.helper.Server.CreateClient(), () => this.helper.Token); + this.session = this.helper.Fixture.Create(); } [Fact] @@ -67,7 +67,7 @@ public async Task ShouldReturnFailure_GivenResponseContainsNoSession() public Property ShouldReturnFailure_GivenStatusCodeIsFailure() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From(), + FsCheckExtensions.GetAny(), (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs index debdf523d..0c354671f 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs @@ -1,6 +1,7 @@ using System.Net; using System.Threading.Tasks; using AutoFixture; +using AutoFixture.Kernel; using FluentAssertions; using FsCheck; using FsCheck.Xunit; @@ -22,24 +23,22 @@ public class GetStreamTest public GetStreamTest() { this.helper = new UseCaseHelper(); - this.request = GetStreamRequest.Parse(this.helper.Fixture.Create(), - this.helper.Fixture.Create(), - this.helper.Fixture.Create()); this.client = new SessionClient(this.helper.Server.CreateClient(), () => this.helper.Token); + this.request = BuildRequest(this.helper.Fixture); } [Property] public Property ShouldReturnFailure_GivenApiResponseIsError() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From(), + FsCheckExtensions.GetAny(), (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); [Property] public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From().MapFilter(_ => _, value => !string.IsNullOrWhiteSpace(value)), + FsCheckExtensions.GetNonEmptyStrings(), (statusCode, jsonError) => this.VerifyReturnsFailureGivenErrorCannotBeParsed(statusCode, jsonError).Wait()); @@ -75,6 +74,11 @@ public async Task ShouldReturnFailure_GivenApiResponseCannotBeParsed() result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); } + private static Result BuildRequest(ISpecimenBuilder fixture) => + GetStreamRequest.Parse(fixture.Create(), + fixture.Create(), + fixture.Create()); + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) { var expectedBody = message is null diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs index e14292cbf..6dbabdc24 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs @@ -1,6 +1,7 @@ using System.Net; using System.Threading.Tasks; using AutoFixture; +using AutoFixture.Kernel; using FluentAssertions; using FsCheck; using FsCheck.Xunit; @@ -22,23 +23,22 @@ public class GetStreamsTest public GetStreamsTest() { this.helper = new UseCaseHelper(); - this.request = GetStreamsRequest.Parse(this.helper.Fixture.Create(), - this.helper.Fixture.Create()); this.client = new SessionClient(this.helper.Server.CreateClient(), () => this.helper.Token); + this.request = BuildRequest(this.helper.Fixture); } [Property] public Property ShouldReturnFailure_GivenApiResponseIsError() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From(), + FsCheckExtensions.GetAny(), (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); [Property] public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From().MapFilter(_ => _, value => !string.IsNullOrWhiteSpace(value)), + FsCheckExtensions.GetNonEmptyStrings(), (statusCode, jsonError) => this.VerifyReturnsFailureGivenErrorCannotBeParsed(statusCode, jsonError).Wait()); @@ -72,6 +72,10 @@ public async Task ShouldReturnFailure_GivenApiResponseCannotBeParsed() result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); } + private static Result BuildRequest(ISpecimenBuilder fixture) => + GetStreamsRequest.Parse(fixture.Create(), + fixture.Create()); + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) { var expectedBody = message is null diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs index 1bcd3659d..7f2183c51 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs @@ -1,6 +1,7 @@ using System.Net; using System.Threading.Tasks; using AutoFixture; +using AutoFixture.Kernel; using FsCheck; using FsCheck.Xunit; using Vonage.Video.Beta.Common; @@ -23,25 +24,22 @@ public class SendSignalTest public SendSignalTest() { this.helper = new UseCaseHelper(); - this.request = SendSignalRequest.Parse(this.helper.Fixture.Create(), - this.helper.Fixture.Create(), - this.helper.Fixture.Create(), - this.helper.Fixture.Create()); this.client = new SignalingClient(this.helper.Server.CreateClient(), () => this.helper.Token); + this.request = BuildRequest(this.helper.Fixture); } [Property] public Property ShouldReturnFailure_GivenApiResponseIsError() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From(), + FsCheckExtensions.GetAny(), (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); [Property] public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From().MapFilter(_ => _, value => !string.IsNullOrWhiteSpace(value)), + FsCheckExtensions.GetNonEmptyStrings(), (statusCode, jsonError) => this.VerifyReturnsFailureGivenErrorCannotBeParsed(statusCode, jsonError).Wait()); @@ -56,6 +54,13 @@ public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() result.Should().BeSuccess(Unit.Default); } + private static Result BuildRequest(ISpecimenBuilder fixture) => + SendSignalRequest.Parse( + fixture.Create(), + fixture.Create(), + fixture.Create(), + fixture.Create()); + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) { var expectedBody = message is null diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs index 965157205..c1ca81693 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs @@ -1,6 +1,7 @@ using System.Net; using System.Threading.Tasks; using AutoFixture; +using AutoFixture.Kernel; using FsCheck; using FsCheck.Xunit; using Vonage.Video.Beta.Common; @@ -24,24 +25,22 @@ public class SendSignalsTest public SendSignalsTest() { this.helper = new UseCaseHelper(); - this.request = SendSignalsRequest.Parse(this.helper.Fixture.Create(), - this.helper.Fixture.Create(), - this.helper.Fixture.Create()); this.client = new SignalingClient(this.helper.Server.CreateClient(), () => this.helper.Token); + this.request = BuildRequest(this.helper.Fixture); } [Property] public Property ShouldReturnFailure_GivenApiResponseIsError() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From(), + FsCheckExtensions.GetAny(), (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); [Property] public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), - Arb.From().MapFilter(_ => _, value => !string.IsNullOrWhiteSpace(value)), + FsCheckExtensions.GetNonEmptyStrings(), (statusCode, jsonError) => this.VerifyReturnsFailureGivenErrorCannotBeParsed(statusCode, jsonError).Wait()); @@ -56,6 +55,11 @@ public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() result.Should().BeSuccess(Unit.Default); } + private static Result BuildRequest(ISpecimenBuilder fixture) => + SendSignalsRequest.Parse(fixture.Create(), + fixture.Create(), + fixture.Create()); + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) { var expectedBody = message is null From fdd61b7c30282b3c65c7e403794a02c3b38c226a Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 22 Dec 2022 11:59:34 +0100 Subject: [PATCH 05/10] Use generator for FsCheck, use HttpStatusCode instead of string for ErrorResponse --- .../Common/JsonSerializerTest.cs | 16 +++++++----- .../Extensions/FsCheckExtensions.cs | 10 +++++++ .../ChangeStreamLayoutTest.cs | 15 +++++------ .../CreateSession/CreateSessionTest.cs | 15 +++++------ .../Video/Sessions/GetStream/GetStreamTest.cs | 15 +++++------ .../Sessions/GetStreams/GetStreamsTest.cs | 15 +++++------ .../Signaling/SendSignal/SendSignalTest.cs | 15 +++++------ .../Signaling/SendSignals/SendSignalsTest.cs | 25 +++++++++--------- .../Video/Sessions/ErrorResponse.cs | 26 ++++++++++--------- 9 files changed, 80 insertions(+), 72 deletions(-) diff --git a/Vonage.Video.Beta.Test/Common/JsonSerializerTest.cs b/Vonage.Video.Beta.Test/Common/JsonSerializerTest.cs index fa597f8e8..ff710850f 100644 --- a/Vonage.Video.Beta.Test/Common/JsonSerializerTest.cs +++ b/Vonage.Video.Beta.Test/Common/JsonSerializerTest.cs @@ -1,4 +1,5 @@ -using FluentAssertions; +using System.Net; +using FluentAssertions; using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Test.Extensions; using Xunit; @@ -7,14 +8,14 @@ namespace Vonage.Video.Beta.Test.Common { public class JsonSerializerTest { - private const string DummyString = @"{""id"":10,""name"":""Hello World""}"; + private const string DummyString = @"{""id"":10,""name"":""Hello World"",""code"":200}"; private readonly JsonSerializer serializer; public JsonSerializerTest() => this.serializer = new JsonSerializer(); [Fact] public void SerializeObject_ShouldReturnSerializedString() => this.serializer - .SerializeObject(new DummyObject {Id = 10, Name = "Hello World"}).Should() + .SerializeObject(new DummyObject {Id = 10, Name = "Hello World", Code = HttpStatusCode.OK}).Should() .Be(DummyString); [Theory] @@ -28,19 +29,20 @@ public void DeserializeObject_ShouldReturnFailure_GivenDeserializationFailed(str failure.GetFailureMessage().Should().Be($"Unable to deserialize '{value}' into 'DummyObject'.")); [Theory] - [InlineData("{}", 0, null)] - [InlineData(DummyString, 10, "Hello World")] + [InlineData("{}", 0, null, new HttpStatusCode())] + [InlineData(DummyString, 10, "Hello World", HttpStatusCode.OK)] public void DeserializeObject_ShouldReturnSuccess_GivenDeserializationSucceeded(string value, int expectedId, - string expectedName) => + string expectedName, HttpStatusCode expectedCode) => this.serializer .DeserializeObject(value) .Should() - .BeSuccess(new DummyObject {Id = expectedId, Name = expectedName}); + .BeSuccess(new DummyObject {Id = expectedId, Name = expectedName, Code = expectedCode}); private struct DummyObject { public int Id { get; set; } public string Name { get; set; } + public HttpStatusCode Code { get; set; } } } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Extensions/FsCheckExtensions.cs b/Vonage.Video.Beta.Test/Extensions/FsCheckExtensions.cs index 1b7a86bdf..ad0282e04 100644 --- a/Vonage.Video.Beta.Test/Extensions/FsCheckExtensions.cs +++ b/Vonage.Video.Beta.Test/Extensions/FsCheckExtensions.cs @@ -1,5 +1,6 @@ using System.Net; using FsCheck; +using Vonage.Video.Beta.Video.Sessions; namespace Vonage.Video.Beta.Test.Extensions { @@ -28,5 +29,14 @@ public static Arbitrary GetNonEmptyStrings() => /// Type of the value. /// An Arbitrary. public static Arbitrary GetAny() => Arb.From(); + + /// + /// Retrieves a generator that produces error responses with invalid status codes. + /// + /// An Arbitrary of ErrorResponse. + public static Arbitrary GetErrorResponses() => + Arb.From(from message in GetAny().Generator + from code in GetInvalidStatusCodes().Generator + select new ErrorResponse(code, message)); } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs index 4228a038a..1bc99bda1 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs @@ -30,9 +30,8 @@ public ChangeStreamLayoutTest() [Property] public Property ShouldReturnFailure_GivenApiResponseIsError() => Prop.ForAll( - FsCheckExtensions.GetInvalidStatusCodes(), - FsCheckExtensions.GetAny(), - (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); + FsCheckExtensions.GetErrorResponses(), + error => this.VerifyReturnsFailureGivenStatusCodeIsFailure(error).Wait()); [Property] public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => @@ -59,17 +58,17 @@ private static Result BuildRequest(ISpecimenBuilder f fixture.Create(), fixture.CreateMany()); - private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse error) { - var expectedBody = message is null + var expectedBody = error.Message is null ? null - : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + : this.helper.Serializer.SerializeObject(error); this.helper.Server .Given(this.CreateChangeStreamLayoutRequest()) - .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); + .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.ChangeStreamLayoutAsync(requestValue)); - result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); + result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); } private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) diff --git a/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs index dd74f622f..3ae990e9d 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs @@ -66,20 +66,19 @@ public async Task ShouldReturnFailure_GivenResponseContainsNoSession() [Property] public Property ShouldReturnFailure_GivenStatusCodeIsFailure() => Prop.ForAll( - FsCheckExtensions.GetInvalidStatusCodes(), - FsCheckExtensions.GetAny(), - (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); + FsCheckExtensions.GetErrorResponses(), + error => this.VerifyReturnsFailureGivenStatusCodeIsFailure(error).Wait()); - private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse error) { - var expectedBody = message is null + var expectedBody = error.Message is null ? null - : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + : this.helper.Serializer.SerializeObject(error); this.helper.Server .Given(WireMockExtensions.CreateRequest(this.helper.Token, this.request.GetEndpointPath())) - .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); + .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.client.CreateSessionAsync(this.request); - result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); + result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); } } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs index 0c354671f..313cab078 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs @@ -30,9 +30,8 @@ public GetStreamTest() [Property] public Property ShouldReturnFailure_GivenApiResponseIsError() => Prop.ForAll( - FsCheckExtensions.GetInvalidStatusCodes(), - FsCheckExtensions.GetAny(), - (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); + FsCheckExtensions.GetErrorResponses(), + error => this.VerifyReturnsFailureGivenStatusCodeIsFailure(error).Wait()); [Property] public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => @@ -79,17 +78,17 @@ private static Result BuildRequest(ISpecimenBuilder fixture) = fixture.Create(), fixture.Create()); - private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse error) { - var expectedBody = message is null + var expectedBody = error.Message is null ? null - : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + : this.helper.Serializer.SerializeObject(error); this.helper.Server .Given(WireMockExtensions .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) - .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); + .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamAsync(requestValue)); - result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); + result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); } private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs index 6dbabdc24..900974a2d 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs @@ -30,9 +30,8 @@ public GetStreamsTest() [Property] public Property ShouldReturnFailure_GivenApiResponseIsError() => Prop.ForAll( - FsCheckExtensions.GetInvalidStatusCodes(), - FsCheckExtensions.GetAny(), - (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); + FsCheckExtensions.GetErrorResponses(), + error => this.VerifyReturnsFailureGivenStatusCodeIsFailure(error).Wait()); [Property] public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => @@ -76,17 +75,17 @@ private static Result BuildRequest(ISpecimenBuilder fixture) GetStreamsRequest.Parse(fixture.Create(), fixture.Create()); - private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse error) { - var expectedBody = message is null + var expectedBody = error.Message is null ? null - : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + : this.helper.Serializer.SerializeObject(error); this.helper.Server .Given(WireMockExtensions .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) - .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); + .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamsAsync(requestValue)); - result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); + result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); } private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs index 7f2183c51..9a4262ee8 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs @@ -31,9 +31,8 @@ public SendSignalTest() [Property] public Property ShouldReturnFailure_GivenApiResponseIsError() => Prop.ForAll( - FsCheckExtensions.GetInvalidStatusCodes(), - FsCheckExtensions.GetAny(), - (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); + FsCheckExtensions.GetErrorResponses(), + error => this.VerifyReturnsFailureGivenStatusCodeIsFailure(error).Wait()); [Property] public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => @@ -61,15 +60,15 @@ private static Result BuildRequest(ISpecimenBuilder fixture) fixture.Create(), fixture.Create()); - private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse error) { - var expectedBody = message is null + var expectedBody = error.Message is null ? null - : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + : this.helper.Serializer.SerializeObject(error); this.helper.Server.Given(this.CreateRequest()) - .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); + .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalAsync(requestValue)); - result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); + result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); } private IRequestBuilder CreateRequest() diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs index c1ca81693..934c4d1d7 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs @@ -32,17 +32,16 @@ public SendSignalsTest() [Property] public Property ShouldReturnFailure_GivenApiResponseIsError() => Prop.ForAll( - FsCheckExtensions.GetInvalidStatusCodes(), - FsCheckExtensions.GetAny(), - (statusCode, message) => this.VerifyReturnsFailureGivenStatusCodeIsFailure(statusCode, message).Wait()); + FsCheckExtensions.GetErrorResponses(), + error => this.VerifyReturnsFailureGivenStatusCodeIsFailure(error).Wait()); [Property] public Property ShouldReturnFailure_GivenApiErrorCannotBeParsed() => Prop.ForAll( FsCheckExtensions.GetInvalidStatusCodes(), FsCheckExtensions.GetNonEmptyStrings(), - (statusCode, jsonError) => - this.VerifyReturnsFailureGivenErrorCannotBeParsed(statusCode, jsonError).Wait()); + (statusCode, invalidJson) => + this.VerifyReturnsFailureGivenErrorCannotBeParsed(statusCode, invalidJson).Wait()); [Fact] public async Task ShouldReturnSuccess_GivenApiResponseIsSuccess() @@ -60,15 +59,15 @@ private static Result BuildRequest(ISpecimenBuilder fixture) fixture.Create(), fixture.Create()); - private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(HttpStatusCode code, string message) + private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse error) { - var expectedBody = message is null + var expectedBody = error.Message is null ? null - : this.helper.Serializer.SerializeObject(new ErrorResponse(((int) code).ToString(), message)); + : this.helper.Serializer.SerializeObject(error); this.helper.Server.Given(this.CreateRequest()) - .RespondWith(WireMockExtensions.CreateResponse(code, expectedBody)); + .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalsAsync(requestValue)); - result.Should().BeFailure(HttpFailure.From(code, message ?? string.Empty)); + result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); } private IRequestBuilder CreateRequest() @@ -82,11 +81,11 @@ private IRequestBuilder CreateRequest() .UsingPost(); } - private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) + private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string invalidJson) { - var expectedFailureMessage = $"Unable to deserialize '{jsonError}' into '{nameof(ErrorResponse)}'."; + var expectedFailureMessage = $"Unable to deserialize '{invalidJson}' into '{nameof(ErrorResponse)}'."; this.helper.Server.Given(this.CreateRequest()) - .RespondWith(WireMockExtensions.CreateResponse(code, jsonError)); + .RespondWith(WireMockExtensions.CreateResponse(code, invalidJson)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalsAsync(requestValue)); result.Should().BeFailure(ResultFailure.FromErrorMessage(expectedFailureMessage)); diff --git a/Vonage.Video.Beta/Video/Sessions/ErrorResponse.cs b/Vonage.Video.Beta/Video/Sessions/ErrorResponse.cs index b7530c4ac..61e19370c 100644 --- a/Vonage.Video.Beta/Video/Sessions/ErrorResponse.cs +++ b/Vonage.Video.Beta/Video/Sessions/ErrorResponse.cs @@ -1,28 +1,30 @@ -namespace Vonage.Video.Beta.Video.Sessions; +using System.Net; + +namespace Vonage.Video.Beta.Video.Sessions; /// /// Represents an error api response. /// public struct ErrorResponse { + /// + /// The response code. + /// + public HttpStatusCode Code { get; } + + /// + /// The response message. + /// + public string Message { get; } + /// /// Creates a response. /// /// The response code. /// The response message. - public ErrorResponse(string code, string message) + public ErrorResponse(HttpStatusCode code, string message) { this.Code = code; this.Message = message; } - - /// - /// The response code. - /// - public string Code { get; } - - /// - /// The response message. - /// - public string Message { get; } } \ No newline at end of file From d3a03305acce915169920a6429538333fc2da721 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 22 Dec 2022 14:13:14 +0100 Subject: [PATCH 06/10] Create method for converting an ErrorReponse to HttpFailure --- .../Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs | 2 +- .../Video/Sessions/CreateSession/CreateSessionTest.cs | 2 +- .../Video/Sessions/GetStream/GetStreamTest.cs | 2 +- .../Video/Sessions/GetStreams/GetStreamsTest.cs | 2 +- .../Video/Signaling/SendSignal/SendSignalTest.cs | 2 +- .../Video/Signaling/SendSignals/SendSignalsTest.cs | 2 +- Vonage.Video.Beta/Video/Sessions/ErrorResponse.cs | 7 +++++++ 7 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs index 1bc99bda1..3607586e5 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs @@ -68,7 +68,7 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse er .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.ChangeStreamLayoutAsync(requestValue)); - result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); + result.Should().BeFailure(error.ToHttpFailure()); } private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) diff --git a/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs index 3ae990e9d..b02685b6d 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/CreateSession/CreateSessionTest.cs @@ -78,7 +78,7 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse er .Given(WireMockExtensions.CreateRequest(this.helper.Token, this.request.GetEndpointPath())) .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.client.CreateSessionAsync(this.request); - result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); + result.Should().BeFailure(error.ToHttpFailure()); } } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs index 313cab078..1fbc55124 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs @@ -88,7 +88,7 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse er .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamAsync(requestValue)); - result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); + result.Should().BeFailure(error.ToHttpFailure()); } private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs index 900974a2d..dc1a9530a 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs @@ -85,7 +85,7 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse er .CreateRequest(this.helper.Token, UseCaseHelper.GetPathFromRequest(this.request)).UsingGet()) .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.GetStreamsAsync(requestValue)); - result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); + result.Should().BeFailure(error.ToHttpFailure()); } private async Task VerifyReturnsFailureGivenErrorCannotBeParsed(HttpStatusCode code, string jsonError) diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs index 9a4262ee8..5033423f4 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs @@ -68,7 +68,7 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse er this.helper.Server.Given(this.CreateRequest()) .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalAsync(requestValue)); - result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); + result.Should().BeFailure(error.ToHttpFailure()); } private IRequestBuilder CreateRequest() diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs index 934c4d1d7..111a889f7 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs @@ -67,7 +67,7 @@ private async Task VerifyReturnsFailureGivenStatusCodeIsFailure(ErrorResponse er this.helper.Server.Given(this.CreateRequest()) .RespondWith(WireMockExtensions.CreateResponse(error.Code, expectedBody)); var result = await this.request.BindAsync(requestValue => this.client.SendSignalsAsync(requestValue)); - result.Should().BeFailure(HttpFailure.From(error.Code, error.Message ?? string.Empty)); + result.Should().BeFailure(error.ToHttpFailure()); } private IRequestBuilder CreateRequest() diff --git a/Vonage.Video.Beta/Video/Sessions/ErrorResponse.cs b/Vonage.Video.Beta/Video/Sessions/ErrorResponse.cs index 61e19370c..7426f6ec5 100644 --- a/Vonage.Video.Beta/Video/Sessions/ErrorResponse.cs +++ b/Vonage.Video.Beta/Video/Sessions/ErrorResponse.cs @@ -1,4 +1,5 @@ using System.Net; +using Vonage.Video.Beta.Common.Failures; namespace Vonage.Video.Beta.Video.Sessions; @@ -27,4 +28,10 @@ public ErrorResponse(HttpStatusCode code, string message) this.Code = code; this.Message = message; } + + /// + /// Converts to HttpFailure. + /// + /// The failure. + public HttpFailure ToHttpFailure() => HttpFailure.From(this.Code, this.Message ?? string.Empty); } \ No newline at end of file From c5af8c845e109ddc8fdafc6ef4d4a9cdaf1ba53b Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 22 Dec 2022 15:35:43 +0100 Subject: [PATCH 07/10] Implement ValueObject and StringIdentifier --- .../Identifiers/StringIdentifierTest.cs | 31 ++++++++ .../Common/{ => Monads}/MaybeTest.cs | 4 +- .../Common/{ => Monads}/ResultTest.cs | 4 +- .../Common/ValueObjectTest.cs | 59 +++++++++++++++ .../Extensions/FluentAssertionExtensions.cs | 2 +- .../Extensions/MaybeAssertionExtensions.cs | 6 +- .../Extensions/ResultAssertionExtension.cs | 7 +- .../ChangeStreamLayoutTest.cs | 2 +- .../Video/Sessions/GetStream/GetStreamTest.cs | 2 +- .../Sessions/GetStreams/GetStreamsTest.cs | 2 +- .../Signaling/SendSignal/SendSignalTest.cs | 2 +- .../Signaling/SendSignals/SendSignalsTest.cs | 2 +- Vonage.Video.Beta.Test/Video/UseCaseHelper.cs | 1 + .../Common/{ => Failures}/IResultFailure.cs | 2 +- Vonage.Video.Beta/Common/IJsonSerializer.cs | 4 +- .../Common/Identifiers/StringIdentifier.cs | 39 ++++++++++ Vonage.Video.Beta/Common/IpAddress.cs | 21 +++--- Vonage.Video.Beta/Common/JsonSerializer.cs | 1 + .../Common/{ => Monads}/Maybe.cs | 72 +++++++++---------- .../Common/{ => Monads}/Result.cs | 67 +++++++++-------- Vonage.Video.Beta/Common/{ => Monads}/Unit.cs | 2 +- .../{ => Monads}/UnsafeValueException.cs | 2 +- Vonage.Video.Beta/Common/ValueObject.cs | 45 ++++++++++++ .../ChangeStreamLayoutRequest.cs | 1 + .../ChangeStreamLayoutUseCase.cs | 2 +- .../IChangeStreamLayoutUseCase.cs | 2 +- .../CreateSession/CreateSessionRequest.cs | 1 + .../CreateSession/CreateSessionUseCase.cs | 2 +- .../CreateSession/ICreateSessionUseCase.cs | 2 +- .../Sessions/GetStream/GetStreamRequest.cs | 2 +- .../Sessions/GetStream/GetStreamUseCase.cs | 2 +- .../Sessions/GetStream/IGetStreamUseCase.cs | 2 +- .../Sessions/GetStreams/GetStreamsRequest.cs | 2 +- .../Sessions/GetStreams/GetStreamsUseCase.cs | 2 +- .../Sessions/GetStreams/IGetStreamsUseCase.cs | 2 +- .../Video/Sessions/SessionClient.cs | 2 +- .../SendSignal/ISendSignalUseCase.cs | 2 +- .../Signaling/SendSignal/SendSignalRequest.cs | 1 + .../Signaling/SendSignal/SendSignalUseCase.cs | 2 +- .../SendSignals/ISendSignalsUseCase.cs | 2 +- .../SendSignals/SendSignalsRequest.cs | 1 + .../SendSignals/SendSignalsUseCase.cs | 2 +- .../Video/Signaling/SignalingClient.cs | 2 +- Vonage.Video.Beta/Video/VideoHttpClient.cs | 1 + 44 files changed, 306 insertions(+), 110 deletions(-) create mode 100644 Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs rename Vonage.Video.Beta.Test/Common/{ => Monads}/MaybeTest.cs (98%) rename Vonage.Video.Beta.Test/Common/{ => Monads}/ResultTest.cs (98%) create mode 100644 Vonage.Video.Beta.Test/Common/ValueObjectTest.cs rename Vonage.Video.Beta/Common/{ => Failures}/IResultFailure.cs (85%) create mode 100644 Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs rename Vonage.Video.Beta/Common/{ => Monads}/Maybe.cs (99%) rename Vonage.Video.Beta/Common/{ => Monads}/Result.cs (92%) rename Vonage.Video.Beta/Common/{ => Monads}/Unit.cs (85%) rename Vonage.Video.Beta/Common/{ => Monads}/UnsafeValueException.cs (91%) create mode 100644 Vonage.Video.Beta/Common/ValueObject.cs diff --git a/Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs b/Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs new file mode 100644 index 000000000..9158e1fed --- /dev/null +++ b/Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs @@ -0,0 +1,31 @@ +using AutoFixture; +using FluentAssertions; +using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Identifiers; +using Vonage.Video.Beta.Test.Extensions; +using Xunit; + +namespace Vonage.Video.Beta.Test.Common.Identifiers +{ + public class StringIdentifierTest + { + private readonly string value; + + public StringIdentifierTest() => this.value = new Fixture().Create(); + + [Theory] + [InlineData("")] + [InlineData(" ")] + [InlineData(null)] + public void Parse_ShouldReturnFailure_GivenValueIsEmpty(string emptyValue) => + StringIdentifier.Parse(emptyValue) + .Should() + .BeFailure(ResultFailure.FromErrorMessage("Value cannot be null or whitespace.")); + + [Fact] + public void Parse_ShouldReturnSuccess_GivenValuesAreProvided() => + StringIdentifier.Parse(this.value) + .Should() + .BeSuccess(request => request.Value.Should().Be(this.value)); + } +} \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Common/MaybeTest.cs b/Vonage.Video.Beta.Test/Common/Monads/MaybeTest.cs similarity index 98% rename from Vonage.Video.Beta.Test/Common/MaybeTest.cs rename to Vonage.Video.Beta.Test/Common/Monads/MaybeTest.cs index d30b0161e..3eb5c3277 100644 --- a/Vonage.Video.Beta.Test/Common/MaybeTest.cs +++ b/Vonage.Video.Beta.Test/Common/Monads/MaybeTest.cs @@ -1,10 +1,10 @@ using System; using FluentAssertions; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Test.Extensions; using Xunit; -namespace Vonage.Video.Beta.Test.Common +namespace Vonage.Video.Beta.Test.Common.Monads { public class MaybeTest { diff --git a/Vonage.Video.Beta.Test/Common/ResultTest.cs b/Vonage.Video.Beta.Test/Common/Monads/ResultTest.cs similarity index 98% rename from Vonage.Video.Beta.Test/Common/ResultTest.cs rename to Vonage.Video.Beta.Test/Common/Monads/ResultTest.cs index c6153e35a..a0bd0f4d6 100644 --- a/Vonage.Video.Beta.Test/Common/ResultTest.cs +++ b/Vonage.Video.Beta.Test/Common/Monads/ResultTest.cs @@ -1,12 +1,12 @@ using System; using System.Threading.Tasks; using FluentAssertions; -using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Test.Extensions; using Xunit; -namespace Vonage.Video.Beta.Test.Common +namespace Vonage.Video.Beta.Test.Common.Monads { public class ResultTest { diff --git a/Vonage.Video.Beta.Test/Common/ValueObjectTest.cs b/Vonage.Video.Beta.Test/Common/ValueObjectTest.cs new file mode 100644 index 000000000..a93104b15 --- /dev/null +++ b/Vonage.Video.Beta.Test/Common/ValueObjectTest.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using FluentAssertions; +using Vonage.Video.Beta.Common; +using Xunit; + +namespace Vonage.Video.Beta.Test.Common +{ + public class ValueObjectTest + { + [Fact] + public void Equals_ShouldReturnFalse_GivenValueAreDifferent() => + FakeValueObject.Hello.Equals(FakeValueObject.World).Should().BeFalse(); + + [Fact] + public void Equals_ShouldReturnTrue_GivenValueAreSame() => + FakeValueObject.Hello.Equals(FakeValueObject.Hello).Should().BeTrue(); + + [Fact] + public void EqualsOperator_ShouldReturnFalse_GivenValueAreDifferent() => + (FakeValueObject.Hello == FakeValueObject.World).Should().BeFalse(); + + [Fact] + public void EqualsOperator_ShouldReturnTrue_GivenValueAreSame() => + (FakeValueObject.Hello == FakeValueObject.Hello).Should().BeTrue(); + + [Fact] + public void DifferentOperator_ShouldReturnFalse_GivenValueAreSame() => + (FakeValueObject.Hello != FakeValueObject.Hello).Should().BeFalse(); + + [Fact] + public void DifferentOperator_ShouldReturnTrue_GivenValueAreDifferent() => + (FakeValueObject.Hello != FakeValueObject.World).Should().BeTrue(); + + [Fact] + public void GetHashCode_ShouldReturnSameValue_GivenValueAreSame() => + FakeValueObject.Hello.GetHashCode().Should() + .Be(FakeValueObject.Hello.GetHashCode()); + + [Fact] + public void GetHashCode_ShouldReturnDifferent_GivenValueAreDifferent() => + FakeValueObject.Hello.GetHashCode().Should() + .NotBe(FakeValueObject.World.GetHashCode()); + + private class FakeValueObject : ValueObject + { + private readonly string value; + + private FakeValueObject(string value) + { + this.value = value; + } + + public static FakeValueObject Hello => new FakeValueObject("Hello"); + public static FakeValueObject World => new FakeValueObject("World"); + + protected override IEnumerable GetEqualityComponents() => new[] {this.value}; + } + } +} \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Extensions/FluentAssertionExtensions.cs b/Vonage.Video.Beta.Test/Extensions/FluentAssertionExtensions.cs index 6db1b0da0..40d6463f3 100644 --- a/Vonage.Video.Beta.Test/Extensions/FluentAssertionExtensions.cs +++ b/Vonage.Video.Beta.Test/Extensions/FluentAssertionExtensions.cs @@ -1,4 +1,4 @@ -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Test.Extensions { diff --git a/Vonage.Video.Beta.Test/Extensions/MaybeAssertionExtensions.cs b/Vonage.Video.Beta.Test/Extensions/MaybeAssertionExtensions.cs index d42d5d686..c94c329c2 100644 --- a/Vonage.Video.Beta.Test/Extensions/MaybeAssertionExtensions.cs +++ b/Vonage.Video.Beta.Test/Extensions/MaybeAssertionExtensions.cs @@ -2,7 +2,7 @@ using FluentAssertions; using FluentAssertions.Execution; using FluentAssertions.Primitives; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Test.Extensions { @@ -12,8 +12,6 @@ public MaybeAssertionExtensions(Maybe subject) : base(subject) { } - protected override string Identifier => "maybe"; - public AndConstraint> BeNone(string because = "", params object[] becauseArgs) { Execute.Assertion @@ -52,5 +50,7 @@ public AndConstraint> BeSome(T expected, string beca .FailWith("but found Some {0}.", this.Subject); return new AndConstraint>(this); } + + protected override string Identifier => "maybe"; } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Extensions/ResultAssertionExtension.cs b/Vonage.Video.Beta.Test/Extensions/ResultAssertionExtension.cs index b5ec50a44..bf5dbef15 100644 --- a/Vonage.Video.Beta.Test/Extensions/ResultAssertionExtension.cs +++ b/Vonage.Video.Beta.Test/Extensions/ResultAssertionExtension.cs @@ -2,7 +2,8 @@ using FluentAssertions; using FluentAssertions.Execution; using FluentAssertions.Primitives; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Test.Extensions { @@ -12,8 +13,6 @@ public ResultAssertionExtension(Result subject) : base(subject) { } - protected override string Identifier => "result"; - public AndConstraint> BeFailure(Action action, string because = "", params object[] becauseArgs) { @@ -69,5 +68,7 @@ public AndConstraint> BeFailure(IResultFailure expec .FailWith("but found Success {0}.", this.Subject); return new AndConstraint>(this); } + + protected override string Identifier => "result"; } } \ No newline at end of file diff --git a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs index 3607586e5..2dbca8c5a 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutTest.cs @@ -4,8 +4,8 @@ using AutoFixture.Kernel; using FsCheck; using FsCheck.Xunit; -using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.ChangeStreamLayout; diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs index 1fbc55124..a36ac87dc 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStream/GetStreamTest.cs @@ -5,8 +5,8 @@ using FluentAssertions; using FsCheck; using FsCheck.Xunit; -using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.GetStream; diff --git a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs index dc1a9530a..63c93bd41 100644 --- a/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Sessions/GetStreams/GetStreamsTest.cs @@ -5,8 +5,8 @@ using FluentAssertions; using FsCheck; using FsCheck.Xunit; -using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Sessions.GetStreams; diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs index 5033423f4..d240f3464 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignal/SendSignalTest.cs @@ -4,8 +4,8 @@ using AutoFixture.Kernel; using FsCheck; using FsCheck.Xunit; -using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Signaling; diff --git a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs index 111a889f7..5dab8c5ad 100644 --- a/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs +++ b/Vonage.Video.Beta.Test/Video/Signaling/SendSignals/SendSignalsTest.cs @@ -4,8 +4,8 @@ using AutoFixture.Kernel; using FsCheck; using FsCheck.Xunit; -using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Test.Extensions; using Vonage.Video.Beta.Video.Sessions; using Vonage.Video.Beta.Video.Signaling; diff --git a/Vonage.Video.Beta.Test/Video/UseCaseHelper.cs b/Vonage.Video.Beta.Test/Video/UseCaseHelper.cs index 7261021ee..57b14eca6 100644 --- a/Vonage.Video.Beta.Test/Video/UseCaseHelper.cs +++ b/Vonage.Video.Beta.Test/Video/UseCaseHelper.cs @@ -1,6 +1,7 @@ using System; using AutoFixture; using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Video; using WireMock.Server; diff --git a/Vonage.Video.Beta/Common/IResultFailure.cs b/Vonage.Video.Beta/Common/Failures/IResultFailure.cs similarity index 85% rename from Vonage.Video.Beta/Common/IResultFailure.cs rename to Vonage.Video.Beta/Common/Failures/IResultFailure.cs index b7c3117c1..313e0d9ad 100644 --- a/Vonage.Video.Beta/Common/IResultFailure.cs +++ b/Vonage.Video.Beta/Common/Failures/IResultFailure.cs @@ -1,4 +1,4 @@ -namespace Vonage.Video.Beta.Common; +namespace Vonage.Video.Beta.Common.Failures; /// /// Represents a Failure with an error message. diff --git a/Vonage.Video.Beta/Common/IJsonSerializer.cs b/Vonage.Video.Beta/Common/IJsonSerializer.cs index 349a4e0dd..3e680703d 100644 --- a/Vonage.Video.Beta/Common/IJsonSerializer.cs +++ b/Vonage.Video.Beta/Common/IJsonSerializer.cs @@ -1,4 +1,6 @@ -namespace Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; + +namespace Vonage.Video.Beta.Common; /// /// Provides serialization features to/from JSON. diff --git a/Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs b/Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs new file mode 100644 index 000000000..667c3cd43 --- /dev/null +++ b/Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; + +namespace Vonage.Video.Beta.Common.Identifiers; + +/// +/// Represents a string identifier. +/// +public class StringIdentifier : ValueObject +{ + private const string CannotBeNullOrWhitespace = "Value cannot be null or whitespace."; + + private StringIdentifier(string value) + { + this.Value = value; + } + + /// + /// Retrieves the identifier value. + /// + public string Value { get; } + + /// + /// Parses the value into an Identifier. + /// + /// The value. + /// A success state with the value if the parsing succeeded. A failure state with an error if it failed. + public static Result Parse(string value) => + string.IsNullOrWhiteSpace(value) + ? Result.FromFailure(CreateFailure()) + : new StringIdentifier(value); + + private static IResultFailure CreateFailure() => + ResultFailure.FromErrorMessage("Value cannot be null or whitespace."); + + /// + protected override IEnumerable GetEqualityComponents() => new[] {this.Value}; +} \ No newline at end of file diff --git a/Vonage.Video.Beta/Common/IpAddress.cs b/Vonage.Video.Beta/Common/IpAddress.cs index 18ea0dc8d..5a12c0f28 100644 --- a/Vonage.Video.Beta/Common/IpAddress.cs +++ b/Vonage.Video.Beta/Common/IpAddress.cs @@ -1,5 +1,6 @@ using System.Net; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Common; @@ -20,6 +21,16 @@ private IpAddress(string address) /// public string Address { get; } + /// + /// Returns the Localhost address. + /// + public static IpAddress Localhost => new("localhost"); + + /// + /// Returns an empty address. + /// + public static IpAddress Empty => new(string.Empty); + /// /// Parses the provided ip address. /// @@ -38,14 +49,4 @@ public static Result Parse(string location) => private static bool IsEmpty(string location) => location == Empty.Address; private static bool CanBeParsed(string location) => IPAddress.TryParse(location, out _); - - /// - /// Returns the Localhost address. - /// - public static IpAddress Localhost => new("localhost"); - - /// - /// Returns an empty address. - /// - public static IpAddress Empty => new(string.Empty); } \ No newline at end of file diff --git a/Vonage.Video.Beta/Common/JsonSerializer.cs b/Vonage.Video.Beta/Common/JsonSerializer.cs index ee268ab70..d721bbc01 100644 --- a/Vonage.Video.Beta/Common/JsonSerializer.cs +++ b/Vonage.Video.Beta/Common/JsonSerializer.cs @@ -2,6 +2,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Common; diff --git a/Vonage.Video.Beta/Common/Maybe.cs b/Vonage.Video.Beta/Common/Monads/Maybe.cs similarity index 99% rename from Vonage.Video.Beta/Common/Maybe.cs rename to Vonage.Video.Beta/Common/Monads/Maybe.cs index 30578b73d..98382aaac 100644 --- a/Vonage.Video.Beta/Common/Maybe.cs +++ b/Vonage.Video.Beta/Common/Monads/Maybe.cs @@ -1,6 +1,6 @@ using System; -namespace Vonage.Video.Beta.Common; +namespace Vonage.Video.Beta.Common.Monads; /// /// Discriminated union type. Can be in one of two states: Some, or None. @@ -11,30 +11,6 @@ public readonly struct Maybe public const string NullValueMessage = "Value cannot be null."; private readonly TA value = default; - /// - /// Construct a Maybe in a None state. - /// - public static readonly Maybe None = new(); - - /// - /// Construct a Maybe in a Some state. - /// - /// Value to bind, must be non-null. - /// Bound value type. - /// Maybe containing Some value. - /// Given value is null. - public static Maybe Some(TB value) => value is null - ? throw new InvalidOperationException(NullValueMessage) - : new Maybe(value); - - /// - /// Constructor for a None. - /// - public Maybe() - { - this.IsSome = false; - } - /// /// Constructor for a Some. /// @@ -55,6 +31,25 @@ private Maybe(TA value) /// public bool IsSome { get; } + /// + /// Constructor for a None. + /// + public Maybe() + { + this.IsSome = false; + } + + /// + /// Construct a Maybe in a Some state. + /// + /// Value to bind, must be non-null. + /// Bound value type. + /// Maybe containing Some value. + /// Given value is null. + public static Maybe Some(TB value) => value is null + ? throw new InvalidOperationException(NullValueMessage) + : new Maybe(value); + /// /// Projects from one value to another. /// @@ -101,17 +96,6 @@ public Unit IfSome(Action some) /// public override int GetHashCode() => this.IsSome ? this.value.GetHashCode() : 0; - /// - /// Verifies of both Maybes are either None or Some with the same values. - /// - /// Other maybe to be compared with. - /// Whether both Maybes are equal. - private bool Equals(Maybe other) - { - var bothAreNone = this.IsNone && other.IsNone; - return bothAreNone || this.value.Equals(other.value); - } - /// /// Implicit operator from TA to Maybe of TA. /// @@ -125,4 +109,20 @@ private bool Equals(Maybe other) /// The value if in Some state. /// When in None state. public TA GetUnsafe() => this.Match(_ => _, () => throw new UnsafeValueException("State is none.")); + + /// + /// Verifies of both Maybes are either None or Some with the same values. + /// + /// Other maybe to be compared with. + /// Whether both Maybes are equal. + private bool Equals(Maybe other) + { + var bothAreNone = this.IsNone && other.IsNone; + return bothAreNone || this.value.Equals(other.value); + } + + /// + /// Construct a Maybe in a None state. + /// + public static readonly Maybe None = new(); } \ No newline at end of file diff --git a/Vonage.Video.Beta/Common/Result.cs b/Vonage.Video.Beta/Common/Monads/Result.cs similarity index 92% rename from Vonage.Video.Beta/Common/Result.cs rename to Vonage.Video.Beta/Common/Monads/Result.cs index 1a33b1893..95e5c7011 100644 --- a/Vonage.Video.Beta/Common/Result.cs +++ b/Vonage.Video.Beta/Common/Monads/Result.cs @@ -1,7 +1,8 @@ using System; using System.Threading.Tasks; +using Vonage.Video.Beta.Common.Failures; -namespace Vonage.Video.Beta.Common; +namespace Vonage.Video.Beta.Common.Monads; /// /// Represents the result of an operation. Can be in one of two states: Success, or Failure. @@ -59,15 +60,6 @@ private Result(IResultFailure failure) /// Success Result. public static Result FromSuccess(T value) => new(value); - /// - /// Enum representing the state of Result. - /// - private enum ResultState - { - Success, - Failure, - } - /// /// Projects from one value to another. /// @@ -103,24 +95,6 @@ public Result Bind(Func> bind) => /// public override int GetHashCode() => this.IsSuccess ? this.success.GetHashCode() : this.failure.GetHashCode(); - /// - /// Verifies if both Results are either Failure or Success with the same values. - /// - /// Other Result to be compared with. - /// Whether both Results are equal. - private bool Equals(Result other) => this.EqualsFailure(other) && this.success.Equals(other.success); - - /// - /// Verifies if both failures are equal. - /// - /// Other Result to be compared with. - /// Whether both failures are equal. - /// Using IResultFailure for the Failure value makes it nullable. Comparing both cases is now mandatory. - private bool EqualsFailure(Result other) => - this.IsFailure && other.IsFailure - ? this.failure.Equals(other.failure) - : this.failure == other.failure; - /// /// Implicit operator from TA to Result of TA. /// @@ -186,4 +160,41 @@ public IResultFailure GetFailureUnsafe() => /// The Success value if in Success state. /// When in Failure state. public T GetSuccessUnsafe() => this.Match(_ => _, _ => throw new UnsafeValueException("State is Failure.")); + + /// + /// Verifies if both Results are either Failure or Success with the same values. + /// + /// Other Result to be compared with. + /// Whether both Results are equal. + private bool Equals(Result other) => this.EqualsFailure(other) && this.EqualsSuccess(other); + + /// + /// Verifies if both failures are equal. + /// + /// Other Result to be compared with. + /// Whether both failures are equal. + /// Using IResultFailure for the Failure value makes it nullable. Comparing both cases is now mandatory. + private bool EqualsFailure(Result other) => + this.IsFailure + ? this.failure.Equals(other.failure) + : other.IsSuccess; + + /// + /// Verifies if both successes are equal. + /// + /// Other Result to be compared with. + /// Whether both successes are equal. + private bool EqualsSuccess(Result other) => + this.IsSuccess + ? this.success.Equals(other.success) + : other.IsFailure; + + /// + /// Enum representing the state of Result. + /// + private enum ResultState + { + Success, + Failure, + } } \ No newline at end of file diff --git a/Vonage.Video.Beta/Common/Unit.cs b/Vonage.Video.Beta/Common/Monads/Unit.cs similarity index 85% rename from Vonage.Video.Beta/Common/Unit.cs rename to Vonage.Video.Beta/Common/Monads/Unit.cs index c4a548f07..01afea0ef 100644 --- a/Vonage.Video.Beta/Common/Unit.cs +++ b/Vonage.Video.Beta/Common/Monads/Unit.cs @@ -1,4 +1,4 @@ -namespace Vonage.Video.Beta.Common; +namespace Vonage.Video.Beta.Common.Monads; /// /// A unit type is a type that allows only one value (and thus can hold no information) diff --git a/Vonage.Video.Beta/Common/UnsafeValueException.cs b/Vonage.Video.Beta/Common/Monads/UnsafeValueException.cs similarity index 91% rename from Vonage.Video.Beta/Common/UnsafeValueException.cs rename to Vonage.Video.Beta/Common/Monads/UnsafeValueException.cs index dff5c2f54..55de7df44 100644 --- a/Vonage.Video.Beta/Common/UnsafeValueException.cs +++ b/Vonage.Video.Beta/Common/Monads/UnsafeValueException.cs @@ -1,6 +1,6 @@ using System; -namespace Vonage.Video.Beta.Common +namespace Vonage.Video.Beta.Common.Monads { /// /// Represents errors that occur during unsafe value retrieval. diff --git a/Vonage.Video.Beta/Common/ValueObject.cs b/Vonage.Video.Beta/Common/ValueObject.cs new file mode 100644 index 000000000..82db635a0 --- /dev/null +++ b/Vonage.Video.Beta/Common/ValueObject.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Vonage.Video.Beta.Common; + +/// +/// Represents a ValueObject with value equality comparison. +/// +/// Type of the value. +public abstract class ValueObject +{ + /// + public override bool Equals(object obj) => obj is ValueObject other && this.EqualsValueObject(other); + + /// + public override int GetHashCode() => + this.GetEqualityComponents() + .Select(item => item?.GetHashCode() ?? 0) + .Aggregate(1, (hash, element) => hash * 23 + element); + + /// + /// Override for equality operator. + /// + /// A ValueObject. + /// A ValueObject. + /// If both ValueObjects are equal. + public static bool operator ==(ValueObject first, ValueObject second) => + first?.EqualsValueObject(second) ?? second is null; + + /// + /// Override for difference operator. + /// + /// A ValueObject. + /// A ValueObject. + /// If both ValueObjects are different. + public static bool operator !=(ValueObject first, ValueObject second) => !(first == second); + + private bool EqualsValueObject(ValueObject other) => + this.GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); + + /// + /// + /// + protected abstract IEnumerable GetEqualityComponents(); +} \ No newline at end of file diff --git a/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutRequest.cs b/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutRequest.cs index 5ea79578b..eee878f93 100644 --- a/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutRequest.cs +++ b/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutRequest.cs @@ -4,6 +4,7 @@ using System.Text; using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.ChangeStreamLayout; diff --git a/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutUseCase.cs b/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutUseCase.cs index 9490523ae..a83e95d6b 100644 --- a/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutUseCase.cs +++ b/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutUseCase.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.ChangeStreamLayout; diff --git a/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/IChangeStreamLayoutUseCase.cs b/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/IChangeStreamLayoutUseCase.cs index 9f6dc52a1..281fab0e0 100644 --- a/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/IChangeStreamLayoutUseCase.cs +++ b/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/IChangeStreamLayoutUseCase.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.ChangeStreamLayout; diff --git a/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionRequest.cs b/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionRequest.cs index 247c263b7..e369744b7 100644 --- a/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionRequest.cs +++ b/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionRequest.cs @@ -4,6 +4,7 @@ using System.Web; using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.CreateSession; diff --git a/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionUseCase.cs b/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionUseCase.cs index 318b2eae9..64bc3b1be 100644 --- a/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionUseCase.cs +++ b/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionUseCase.cs @@ -1,8 +1,8 @@ using System; using System.Linq; using System.Threading.Tasks; -using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.CreateSession; diff --git a/Vonage.Video.Beta/Video/Sessions/CreateSession/ICreateSessionUseCase.cs b/Vonage.Video.Beta/Video/Sessions/CreateSession/ICreateSessionUseCase.cs index 91937f459..64442d7ac 100644 --- a/Vonage.Video.Beta/Video/Sessions/CreateSession/ICreateSessionUseCase.cs +++ b/Vonage.Video.Beta/Video/Sessions/CreateSession/ICreateSessionUseCase.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.CreateSession; diff --git a/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamRequest.cs b/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamRequest.cs index 6f7484d86..70843adb6 100644 --- a/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamRequest.cs +++ b/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamRequest.cs @@ -1,7 +1,7 @@ using System.Net.Http; using System.Net.Http.Headers; -using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.GetStream; diff --git a/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamUseCase.cs b/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamUseCase.cs index a16c7ba97..111a74d35 100644 --- a/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamUseCase.cs +++ b/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamUseCase.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.GetStream; diff --git a/Vonage.Video.Beta/Video/Sessions/GetStream/IGetStreamUseCase.cs b/Vonage.Video.Beta/Video/Sessions/GetStream/IGetStreamUseCase.cs index 5d83065e6..6e3374f8f 100644 --- a/Vonage.Video.Beta/Video/Sessions/GetStream/IGetStreamUseCase.cs +++ b/Vonage.Video.Beta/Video/Sessions/GetStream/IGetStreamUseCase.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.GetStream; diff --git a/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsRequest.cs b/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsRequest.cs index 0a4c57219..9c91dff89 100644 --- a/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsRequest.cs +++ b/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsRequest.cs @@ -1,7 +1,7 @@ using System.Net.Http; using System.Net.Http.Headers; -using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.GetStreams; diff --git a/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsUseCase.cs b/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsUseCase.cs index 7ac926da5..bcebcc53d 100644 --- a/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsUseCase.cs +++ b/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsUseCase.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.GetStreams; diff --git a/Vonage.Video.Beta/Video/Sessions/GetStreams/IGetStreamsUseCase.cs b/Vonage.Video.Beta/Video/Sessions/GetStreams/IGetStreamsUseCase.cs index 9e92033e2..fc9eb6982 100644 --- a/Vonage.Video.Beta/Video/Sessions/GetStreams/IGetStreamsUseCase.cs +++ b/Vonage.Video.Beta/Video/Sessions/GetStreams/IGetStreamsUseCase.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Sessions.GetStreams; diff --git a/Vonage.Video.Beta/Video/Sessions/SessionClient.cs b/Vonage.Video.Beta/Video/Sessions/SessionClient.cs index 1d8e7cfee..34a9c1c2c 100644 --- a/Vonage.Video.Beta/Video/Sessions/SessionClient.cs +++ b/Vonage.Video.Beta/Video/Sessions/SessionClient.cs @@ -1,7 +1,7 @@ using System; using System.Net.Http; using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Video.Sessions.ChangeStreamLayout; using Vonage.Video.Beta.Video.Sessions.CreateSession; using Vonage.Video.Beta.Video.Sessions.GetStream; diff --git a/Vonage.Video.Beta/Video/Signaling/SendSignal/ISendSignalUseCase.cs b/Vonage.Video.Beta/Video/Signaling/SendSignal/ISendSignalUseCase.cs index 17ec7d1cf..de9dc983c 100644 --- a/Vonage.Video.Beta/Video/Signaling/SendSignal/ISendSignalUseCase.cs +++ b/Vonage.Video.Beta/Video/Signaling/SendSignal/ISendSignalUseCase.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Signaling.SendSignal; diff --git a/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalRequest.cs b/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalRequest.cs index 57f5232bb..a9bf62d2c 100644 --- a/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalRequest.cs +++ b/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalRequest.cs @@ -3,6 +3,7 @@ using System.Text; using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Signaling.SendSignal; diff --git a/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalUseCase.cs b/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalUseCase.cs index 3e5d327ee..6bc3feadf 100644 --- a/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalUseCase.cs +++ b/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalUseCase.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Signaling.SendSignal; diff --git a/Vonage.Video.Beta/Video/Signaling/SendSignals/ISendSignalsUseCase.cs b/Vonage.Video.Beta/Video/Signaling/SendSignals/ISendSignalsUseCase.cs index 88b1ba2bf..25b07e52e 100644 --- a/Vonage.Video.Beta/Video/Signaling/SendSignals/ISendSignalsUseCase.cs +++ b/Vonage.Video.Beta/Video/Signaling/SendSignals/ISendSignalsUseCase.cs @@ -1,5 +1,5 @@ using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Signaling.SendSignals; diff --git a/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsRequest.cs b/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsRequest.cs index 9c3ff8670..1e61d324e 100644 --- a/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsRequest.cs +++ b/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsRequest.cs @@ -3,6 +3,7 @@ using System.Text; using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Signaling.SendSignals; diff --git a/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsUseCase.cs b/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsUseCase.cs index 8a107d53b..6163af7ae 100644 --- a/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsUseCase.cs +++ b/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsUseCase.cs @@ -1,6 +1,6 @@ using System; using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; namespace Vonage.Video.Beta.Video.Signaling.SendSignals; diff --git a/Vonage.Video.Beta/Video/Signaling/SignalingClient.cs b/Vonage.Video.Beta/Video/Signaling/SignalingClient.cs index 39c04e334..eb8d15320 100644 --- a/Vonage.Video.Beta/Video/Signaling/SignalingClient.cs +++ b/Vonage.Video.Beta/Video/Signaling/SignalingClient.cs @@ -1,7 +1,7 @@ using System; using System.Net.Http; using System.Threading.Tasks; -using Vonage.Video.Beta.Common; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Video.Signaling.SendSignal; using Vonage.Video.Beta.Video.Signaling.SendSignals; diff --git a/Vonage.Video.Beta/Video/VideoHttpClient.cs b/Vonage.Video.Beta/Video/VideoHttpClient.cs index 6694cd848..70efbb5f7 100644 --- a/Vonage.Video.Beta/Video/VideoHttpClient.cs +++ b/Vonage.Video.Beta/Video/VideoHttpClient.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; using Vonage.Video.Beta.Video.Sessions; namespace Vonage.Video.Beta.Video; From e4d7f4f7f5174d955807e3fb16a1d74a010ed7b9 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 22 Dec 2022 15:48:04 +0100 Subject: [PATCH 08/10] Implement implicit operator for Identifier --- .../Common/Identifiers/StringIdentifierTest.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs b/Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs index 9158e1fed..bb2d56e5b 100644 --- a/Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs +++ b/Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs @@ -27,5 +27,13 @@ public void Parse_ShouldReturnSuccess_GivenValuesAreProvided() => StringIdentifier.Parse(this.value) .Should() .BeSuccess(request => request.Value.Should().Be(this.value)); + + [Fact] + public void ImplicitOperator_ShouldExtractValueFromIdentifier() + { + var identifier = StringIdentifier.Parse(this.value).GetSuccessUnsafe(); + string implicitValue = identifier; + implicitValue.Should().Be(this.value); + } } } \ No newline at end of file From 8b0e65c160de543425a23463b9129263214b6626 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 22 Dec 2022 15:49:37 +0100 Subject: [PATCH 09/10] Missing constant on Identifier --- Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs b/Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs index 667c3cd43..112c2c3cd 100644 --- a/Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs +++ b/Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs @@ -31,8 +31,15 @@ public static Result Parse(string value) => ? Result.FromFailure(CreateFailure()) : new StringIdentifier(value); + /// + /// Extracts the value from the identifier. + /// + /// The identifier. + /// The value. + public static implicit operator string(StringIdentifier identifier) => identifier.Value; + private static IResultFailure CreateFailure() => - ResultFailure.FromErrorMessage("Value cannot be null or whitespace."); + ResultFailure.FromErrorMessage(CannotBeNullOrWhitespace); /// protected override IEnumerable GetEqualityComponents() => new[] {this.Value}; From 0fae8055b2f4869d5ddebfc88caaf806c0f410d5 Mon Sep 17 00:00:00 2001 From: Tr00d Date: Thu, 22 Dec 2022 17:20:33 +0100 Subject: [PATCH 10/10] Address duplication in InputValidation --- .../Identifiers/StringIdentifierTest.cs | 39 ---------------- .../Common/Identifiers/StringIdentifier.cs | 46 ------------------- .../Common/Validation/InputValidation.cs | 41 +++++++++++++++++ .../ChangeStreamLayoutRequest.cs | 18 ++------ .../CreateSession/CreateSessionRequest.cs | 2 +- .../Sessions/GetStream/GetStreamRequest.cs | 14 ++---- .../Sessions/GetStreams/GetStreamsRequest.cs | 13 ++---- .../Signaling/SendSignal/SendSignalRequest.cs | 13 +++--- .../SendSignals/SendSignalsRequest.cs | 7 +-- 9 files changed, 64 insertions(+), 129 deletions(-) delete mode 100644 Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs delete mode 100644 Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs create mode 100644 Vonage.Video.Beta/Common/Validation/InputValidation.cs diff --git a/Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs b/Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs deleted file mode 100644 index bb2d56e5b..000000000 --- a/Vonage.Video.Beta.Test/Common/Identifiers/StringIdentifierTest.cs +++ /dev/null @@ -1,39 +0,0 @@ -using AutoFixture; -using FluentAssertions; -using Vonage.Video.Beta.Common.Failures; -using Vonage.Video.Beta.Common.Identifiers; -using Vonage.Video.Beta.Test.Extensions; -using Xunit; - -namespace Vonage.Video.Beta.Test.Common.Identifiers -{ - public class StringIdentifierTest - { - private readonly string value; - - public StringIdentifierTest() => this.value = new Fixture().Create(); - - [Theory] - [InlineData("")] - [InlineData(" ")] - [InlineData(null)] - public void Parse_ShouldReturnFailure_GivenValueIsEmpty(string emptyValue) => - StringIdentifier.Parse(emptyValue) - .Should() - .BeFailure(ResultFailure.FromErrorMessage("Value cannot be null or whitespace.")); - - [Fact] - public void Parse_ShouldReturnSuccess_GivenValuesAreProvided() => - StringIdentifier.Parse(this.value) - .Should() - .BeSuccess(request => request.Value.Should().Be(this.value)); - - [Fact] - public void ImplicitOperator_ShouldExtractValueFromIdentifier() - { - var identifier = StringIdentifier.Parse(this.value).GetSuccessUnsafe(); - string implicitValue = identifier; - implicitValue.Should().Be(this.value); - } - } -} \ No newline at end of file diff --git a/Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs b/Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs deleted file mode 100644 index 112c2c3cd..000000000 --- a/Vonage.Video.Beta/Common/Identifiers/StringIdentifier.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using Vonage.Video.Beta.Common.Failures; -using Vonage.Video.Beta.Common.Monads; - -namespace Vonage.Video.Beta.Common.Identifiers; - -/// -/// Represents a string identifier. -/// -public class StringIdentifier : ValueObject -{ - private const string CannotBeNullOrWhitespace = "Value cannot be null or whitespace."; - - private StringIdentifier(string value) - { - this.Value = value; - } - - /// - /// Retrieves the identifier value. - /// - public string Value { get; } - - /// - /// Parses the value into an Identifier. - /// - /// The value. - /// A success state with the value if the parsing succeeded. A failure state with an error if it failed. - public static Result Parse(string value) => - string.IsNullOrWhiteSpace(value) - ? Result.FromFailure(CreateFailure()) - : new StringIdentifier(value); - - /// - /// Extracts the value from the identifier. - /// - /// The identifier. - /// The value. - public static implicit operator string(StringIdentifier identifier) => identifier.Value; - - private static IResultFailure CreateFailure() => - ResultFailure.FromErrorMessage(CannotBeNullOrWhitespace); - - /// - protected override IEnumerable GetEqualityComponents() => new[] {this.Value}; -} \ No newline at end of file diff --git a/Vonage.Video.Beta/Common/Validation/InputValidation.cs b/Vonage.Video.Beta/Common/Validation/InputValidation.cs new file mode 100644 index 000000000..ce2d9e5b6 --- /dev/null +++ b/Vonage.Video.Beta/Common/Validation/InputValidation.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using Vonage.Video.Beta.Common.Failures; +using Vonage.Video.Beta.Common.Monads; +using Vonage.Video.Beta.Video; + +namespace Vonage.Video.Beta.Common.Validation; + +/// +/// +public static class InputValidation +{ + private const string CollectionCannotBeNull = "cannot be null."; + private const string StringCannotBeNullOrWhitespace = "cannot be null or whitespace."; + + /// + /// + /// + /// + /// + /// + /// + public static Result VerifyNotEmpty(T request, string value, string name) where T : IVideoRequest => + string.IsNullOrWhiteSpace(value) + ? Result.FromFailure( + ResultFailure.FromErrorMessage($"{name} {StringCannotBeNullOrWhitespace}")) + : request; + + /// + /// + /// + /// + /// + /// + /// + /// + public static Result VerifyItems(TA request, IEnumerable value, string name) => + value is null + ? Result.FromFailure( + ResultFailure.FromErrorMessage($"{name} {CollectionCannotBeNull}")) + : request; +} \ No newline at end of file diff --git a/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutRequest.cs b/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutRequest.cs index eee878f93..91494f319 100644 --- a/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutRequest.cs +++ b/Vonage.Video.Beta/Video/Sessions/ChangeStreamLayout/ChangeStreamLayoutRequest.cs @@ -3,8 +3,8 @@ using System.Net.Http.Headers; using System.Text; using Vonage.Video.Beta.Common; -using Vonage.Video.Beta.Common.Failures; using Vonage.Video.Beta.Common.Monads; +using Vonage.Video.Beta.Common.Validation; namespace Vonage.Video.Beta.Video.Sessions.ChangeStreamLayout; @@ -68,23 +68,13 @@ public HttpRequestMessage BuildRequestMessage(string token) } private static Result VerifyApplicationId(ChangeStreamLayoutRequest request) => - VerifyNotEmptyValue(request, request.ApplicationId, nameof(ApplicationId)); - - private static Result - VerifyNotEmptyValue(ChangeStreamLayoutRequest request, string value, string name) => - string.IsNullOrWhiteSpace(value) - ? Result.FromFailure( - ResultFailure.FromErrorMessage($"{name} {CannotBeNullOrWhitespace}")) - : request; + InputValidation.VerifyNotEmpty(request, request.ApplicationId, nameof(ApplicationId)); private static Result VerifySessionId(ChangeStreamLayoutRequest request) => - VerifyNotEmptyValue(request, request.SessionId, nameof(SessionId)); + InputValidation.VerifyNotEmpty(request, request.SessionId, nameof(SessionId)); private static Result VerifyItems(ChangeStreamLayoutRequest request) => - request.Items is null - ? Result.FromFailure( - ResultFailure.FromErrorMessage($"{nameof(Items)} {CannotBeNull}")) - : request; + InputValidation.VerifyItems(request, request.Items, nameof(Items)); /// /// Represents a request to change a stream with layout classes. diff --git a/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionRequest.cs b/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionRequest.cs index e369744b7..dff8ff4a3 100644 --- a/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionRequest.cs +++ b/Vonage.Video.Beta/Video/Sessions/CreateSession/CreateSessionRequest.cs @@ -16,7 +16,7 @@ namespace Vonage.Video.Beta.Video.Sessions.CreateSession; /// /// The endpoint for creating a session. /// - public const string CreateSessionEndpoint = "/session/create"; + private const string CreateSessionEndpoint = "/session/create"; /// /// Indicates media mode and archive mode are incompatible. diff --git a/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamRequest.cs b/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamRequest.cs index 70843adb6..a780f4007 100644 --- a/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamRequest.cs +++ b/Vonage.Video.Beta/Video/Sessions/GetStream/GetStreamRequest.cs @@ -1,7 +1,7 @@ using System.Net.Http; using System.Net.Http.Headers; -using Vonage.Video.Beta.Common.Failures; using Vonage.Video.Beta.Common.Monads; +using Vonage.Video.Beta.Common.Validation; namespace Vonage.Video.Beta.Video.Sessions.GetStream; @@ -61,17 +61,11 @@ public HttpRequestMessage BuildRequestMessage(string token) } private static Result VerifyApplicationId(GetStreamRequest request) => - VerifyNotEmptyValue(request, request.ApplicationId, nameof(ApplicationId)); - - private static Result VerifyNotEmptyValue(GetStreamRequest request, string value, string name) => - string.IsNullOrWhiteSpace(value) - ? Result.FromFailure( - ResultFailure.FromErrorMessage($"{name} {CannotBeNullOrWhitespace}")) - : request; + InputValidation.VerifyNotEmpty(request, request.ApplicationId, nameof(ApplicationId)); private static Result VerifySessionId(GetStreamRequest request) => - VerifyNotEmptyValue(request, request.SessionId, nameof(SessionId)); + InputValidation.VerifyNotEmpty(request, request.SessionId, nameof(SessionId)); private static Result VerifyStreamId(GetStreamRequest request) => - VerifyNotEmptyValue(request, request.StreamId, nameof(StreamId)); + InputValidation.VerifyNotEmpty(request, request.StreamId, nameof(StreamId)); } \ No newline at end of file diff --git a/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsRequest.cs b/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsRequest.cs index 9c91dff89..3b4a242aa 100644 --- a/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsRequest.cs +++ b/Vonage.Video.Beta/Video/Sessions/GetStreams/GetStreamsRequest.cs @@ -1,7 +1,7 @@ using System.Net.Http; using System.Net.Http.Headers; -using Vonage.Video.Beta.Common.Failures; using Vonage.Video.Beta.Common.Monads; +using Vonage.Video.Beta.Common.Validation; namespace Vonage.Video.Beta.Video.Sessions.GetStreams; @@ -53,15 +53,8 @@ public HttpRequestMessage BuildRequestMessage(string token) } private static Result VerifyApplicationId(GetStreamsRequest request) => - VerifyNotEmptyValue(request, request.ApplicationId, nameof(ApplicationId)); - - private static Result - VerifyNotEmptyValue(GetStreamsRequest request, string value, string name) => - string.IsNullOrWhiteSpace(value) - ? Result.FromFailure( - ResultFailure.FromErrorMessage($"{name} {CannotBeNullOrWhitespace}")) - : request; + InputValidation.VerifyNotEmpty(request, request.ApplicationId, nameof(ApplicationId)); private static Result VerifySessionId(GetStreamsRequest request) => - VerifyNotEmptyValue(request, request.SessionId, nameof(SessionId)); + InputValidation.VerifyNotEmpty(request, request.SessionId, nameof(SessionId)); } \ No newline at end of file diff --git a/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalRequest.cs b/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalRequest.cs index a9bf62d2c..6c2508024 100644 --- a/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalRequest.cs +++ b/Vonage.Video.Beta/Video/Signaling/SendSignal/SendSignalRequest.cs @@ -4,6 +4,7 @@ using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; using Vonage.Video.Beta.Common.Monads; +using Vonage.Video.Beta.Common.Validation; namespace Vonage.Video.Beta.Video.Signaling.SendSignal; @@ -93,14 +94,14 @@ private static Result : request; private static Result VerifySessionId(SendSignalRequest request) => - VerifyNotEmptyValue(request, request.SessionId, nameof(SessionId)); - - private static Result VerifyConnectionId(SendSignalRequest request) => - VerifyNotEmptyValue(request, request.ConnectionId, nameof(ConnectionId)); + InputValidation.VerifyNotEmpty(request, request.SessionId, nameof(SessionId)); private static Result VerifyContentType(SendSignalRequest request) => - VerifyNotEmptyValue(request, request.Content.Type, nameof(SignalContent.Type)); + InputValidation.VerifyNotEmpty(request, request.Content.Type, nameof(SignalContent.Type)); private static Result VerifyContentData(SendSignalRequest request) => - VerifyNotEmptyValue(request, request.Content.Data, nameof(SignalContent.Data)); + InputValidation.VerifyNotEmpty(request, request.Content.Data, nameof(SignalContent.Data)); + + private static Result VerifyConnectionId(SendSignalRequest request) => + InputValidation.VerifyNotEmpty(request, request.ConnectionId, nameof(ConnectionId)); } \ No newline at end of file diff --git a/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsRequest.cs b/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsRequest.cs index 1e61d324e..b0f7f94af 100644 --- a/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsRequest.cs +++ b/Vonage.Video.Beta/Video/Signaling/SendSignals/SendSignalsRequest.cs @@ -4,6 +4,7 @@ using Vonage.Video.Beta.Common; using Vonage.Video.Beta.Common.Failures; using Vonage.Video.Beta.Common.Monads; +using Vonage.Video.Beta.Common.Validation; namespace Vonage.Video.Beta.Video.Signaling.SendSignals; @@ -83,11 +84,11 @@ private static Result : request; private static Result VerifySessionId(SendSignalsRequest request) => - VerifyNotEmptyValue(request, request.SessionId, nameof(SessionId)); + InputValidation.VerifyNotEmpty(request, request.SessionId, nameof(SessionId)); private static Result VerifyContentType(SendSignalsRequest request) => - VerifyNotEmptyValue(request, request.Content.Type, nameof(SignalContent.Type)); + InputValidation.VerifyNotEmpty(request, request.Content.Type, nameof(SignalContent.Type)); private static Result VerifyContentData(SendSignalsRequest request) => - VerifyNotEmptyValue(request, request.Content.Data, nameof(SignalContent.Data)); + InputValidation.VerifyNotEmpty(request, request.Content.Data, nameof(SignalContent.Data)); } \ No newline at end of file