Skip to content

Commit

Permalink
feat: implement SimSwap Check
Browse files Browse the repository at this point in the history
  • Loading branch information
Tr00d committed May 22, 2024
1 parent 5c7f4c1 commit db8c97d
Show file tree
Hide file tree
Showing 19 changed files with 472 additions and 24 deletions.
20 changes: 1 addition & 19 deletions Vonage.Test/SimSwap/Authenticate/AuthenticateRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@ public void Parse_ShouldReturnFailure_GivenNumberIsNullOrWhitespace(string value
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse(value).Should()
.BeFailure(ResultFailure.FromErrorMessage("Number cannot be null or whitespace."));

[Fact]
public void Parse_ShouldReturnNumberWithPlusIndicator() =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse("123456789")
.Map(number => number.PhoneNumber.NumberWithInternationalIndicator)
.Should()
.BeSuccess("+123456789");

[Fact]
public void Parse_ShouldReturnFailure_GivenNumberContainsNonDigits() =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse("1234567abc123").Should()
Expand All @@ -41,24 +34,13 @@ public void Parse_ShouldReturnFailure_GivenNumberLengthIsLowerThan15() =>
[Theory]
[InlineData("1234567", "1234567")]
[InlineData("123456789012345", "123456789012345")]
public void Parse_ShouldReturnSuccess_GivenNumberIsValid(string value, string expected) =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse(value).Map(number => number.PhoneNumber.Number).Should()
.BeSuccess(expected);

[Theory]
[InlineData("+1234567890", "1234567890")]
[InlineData("+123456789012345", "123456789012345")]
[InlineData("+++1234567890", "1234567890")]
public void Parse_ShouldReturnSuccess_GivenNumberStartWithPlus(string value, string expected) =>
public void Parse_ShouldReturnSuccess_GivenNumberIsValid(string value, string expected) =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse(value).Map(number => number.PhoneNumber.Number).Should()
.BeSuccess(expected);

[Fact]
public void ToString_ShouldReturnNumber() =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse("123456789").Map(number => number.PhoneNumber.ToString())
.Should()
.BeSuccess("123456789");

[Fact]
public void BuildAuthorizeRequest()
{
Expand Down
17 changes: 17 additions & 0 deletions Vonage.Test/SimSwap/Authenticate/AuthenticateResponseTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Net.Http.Headers;
using FluentAssertions;
using Vonage.SimSwap.Authenticate;
using Xunit;

namespace Vonage.Test.SimSwap.Authenticate;

[Trait("Category", "Request")]
public class AuthenticateResponseTest
{
[Fact]
public void BuildAuthenticationHeader_ShouldReturnBearerAuth() =>
new AuthenticateResponse("123456789")
.BuildAuthenticationHeader()
.Should()
.Be(new AuthenticationHeaderValue("Bearer", "123456789"));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"access_token": "ABCDEFG",
"token_type": "Bearer",
"expires_in": 3600
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"auth_req_id": "123456789",
"expires_in": "120",
"interval": "2"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"swapped": true
}
4 changes: 4 additions & 0 deletions Vonage.Test/SimSwap/Check/Data/ShouldSerialize-request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"phoneNumber": "346661113334",
"maxAge": 240
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"phoneNumber": "346661113334",
"maxAge": 15
}
68 changes: 68 additions & 0 deletions Vonage.Test/SimSwap/Check/E2ETest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System.Net;
using System.Threading.Tasks;
using Vonage.SimSwap.Check;
using Vonage.Test.Common.Extensions;
using WireMock.ResponseBuilders;
using Xunit;

namespace Vonage.Test.SimSwap.Check;

[Trait("Category", "E2E")]
public class E2ETest : E2EBase
{
public E2ETest() : base(typeof(E2ETest).Namespace)
{
}

[Fact]
public async Task CheckAsync()
{
this.SetupAuthorization();
this.SetupToken();
this.SetupSimSwap(nameof(SerializationTest.ShouldSerialize));
await this.Helper.VonageClient.SimSwapClient
.CheckAsync(CheckRequest.Build().WithPhoneNumber("346661113334").Create())
.Should()
.BeSuccessAsync(true);
}

[Fact]
public async Task CheckAsyncWithPeriod()
{
this.SetupAuthorization();
this.SetupToken();
this.SetupSimSwap(nameof(SerializationTest.ShouldSerializeWithPeriod));
await this.Helper.VonageClient.SimSwapClient
.CheckAsync(CheckRequest.Build().WithPhoneNumber("346661113334").WithPeriod(15).Create())
.Should()
.BeSuccessAsync(true);
}

private void SetupSimSwap(string expectedOutput) =>
this.Helper.Server.Given(WireMock.RequestBuilders.Request.Create()
.WithPath("/camara/sim-swap/v040/check")
.WithHeader("Authorization", "Bearer ABCDEFG")
.WithBody(this.Serialization.GetRequestJson(expectedOutput))
.UsingPost())
.RespondWith(Response.Create().WithStatusCode(HttpStatusCode.OK)
.WithBody(this.Serialization.GetResponseJson(nameof(SerializationTest.ShouldDeserializeCheck))));

private void SetupToken() =>
this.Helper.Server.Given(WireMock.RequestBuilders.Request.Create()
.WithPath("/oauth2/token")
.WithHeader("Authorization", this.Helper.ExpectedAuthorizationHeaderValue)
.WithBody("auth_req_id=123456789&grant_type=urn:openid:params:grant-type:ciba")
.UsingPost())
.RespondWith(Response.Create().WithStatusCode(HttpStatusCode.OK)
.WithBody(this.Serialization.GetResponseJson(nameof(SerializationTest.ShouldDeserializeAccessToken))));

private void SetupAuthorization() =>
this.Helper.Server.Given(WireMock.RequestBuilders.Request.Create()
.WithPath("/oauth2/bc-authorize")
.WithHeader("Authorization", this.Helper.ExpectedAuthorizationHeaderValue)
.WithBody(
"login_hint=tel:%2B346661113334&scope=openid+dpv%3AFraudPreventionAndDetection%23check-sim-swap")
.UsingPost())
.RespondWith(Response.Create().WithStatusCode(HttpStatusCode.OK)
.WithBody(this.Serialization.GetResponseJson(nameof(SerializationTest.ShouldDeserializeAuthorize))));
}
102 changes: 102 additions & 0 deletions Vonage.Test/SimSwap/Check/RequestBuilderTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using Vonage.Common.Failures;
using Vonage.SimSwap.Check;
using Vonage.Test.Common.Extensions;
using Xunit;

namespace Vonage.Test.SimSwap.Check;

[Trait("Category", "Request")]
public class RequestBuilderTest
{
[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData(null)]
public void Build_ShouldReturnFailure_GivenNumberIsNullOrWhitespace(string value) =>
CheckRequest.Build()
.WithPhoneNumber(value)
.Create()
.Should()
.BeFailure(ResultFailure.FromErrorMessage("Number cannot be null or whitespace."));

[Fact]
public void Build_ShouldReturnFailure_GivenNumberContainsNonDigits() =>
CheckRequest.Build()
.WithPhoneNumber("1234567abc123")
.Create()
.Should()
.BeFailure(ResultFailure.FromErrorMessage("Number can only contain digits."));

[Fact]
public void Build_ShouldReturnFailure_GivenNumberLengthIsHigherThan7() =>
CheckRequest.Build()
.WithPhoneNumber("123456")
.Create()
.Should()
.BeFailure(ResultFailure.FromErrorMessage("Number length cannot be lower than 7."));

[Fact]
public void Build_ShouldReturnFailure_GivenNumberLengthIsLowerThan15() =>
CheckRequest.Build()
.WithPhoneNumber("1234567890123456")
.Create()
.Should()
.BeFailure(ResultFailure.FromErrorMessage("Number length cannot be higher than 15."));

[Theory]
[InlineData("1234567", "1234567")]
[InlineData("123456789012345", "123456789012345")]
[InlineData("+1234567890", "1234567890")]
[InlineData("+123456789012345", "123456789012345")]
[InlineData("+++1234567890", "1234567890")]
public void Build_ShouldSetPhoneNumber_GivenNumberIsValid(string value, string expected) =>
CheckRequest.Build()
.WithPhoneNumber(value)
.Create()
.Map(number => number.PhoneNumber.Number)
.Should()
.BeSuccess(expected);

[Theory]
[InlineData(1)]
[InlineData(2400)]
public void Build_ShouldSetPeriod(int value) =>
CheckRequest.Build()
.WithPhoneNumber("1234567")
.WithPeriod(value)
.Create()
.Map(number => number.Period)
.Should()
.BeSuccess(value);

[Fact]
public void Build_ShouldSetPeriodToDefault_GivenPeriodIsNotSet() =>
CheckRequest.Build()
.WithPhoneNumber("1234567")
.Create()
.Map(number => number.Period)
.Should()
.BeSuccess(240);

[Theory]
[InlineData(0)]
[InlineData(-1)]
public void Build_ShouldReturnFailure_GivenPeriodIsLowerThan15(int incorrectValue) =>
CheckRequest.Build()
.WithPhoneNumber("1234567")
.WithPeriod(incorrectValue)
.Create()
.Should()
.BeParsingFailure("Period cannot be lower than 1.");

[Theory]
[InlineData(2401)]
[InlineData(2402)]
public void Build_ShouldReturnFailure_GivenPeriodIsHigherThan2400(int incorrectValue) =>
CheckRequest.Build()
.WithPhoneNumber("1234567")
.WithPeriod(incorrectValue)
.Create()
.Should()
.BeParsingFailure("Period cannot be higher than 2400.");
}
18 changes: 18 additions & 0 deletions Vonage.Test/SimSwap/Check/RequestTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Vonage.SimSwap.Check;
using Vonage.Test.Common.Extensions;
using Xunit;

namespace Vonage.Test.SimSwap.Check;

[Trait("Category", "Request")]
public class RequestTest
{
[Fact]
public void GetEndpointPath_ShouldReturnApiEndpoint() =>
CheckRequest.Build()
.WithPhoneNumber("123456789")
.Create()
.Map(request => request.GetEndpointPath())
.Should()
.BeSuccess("camara/sim-swap/v040/check");
}
59 changes: 59 additions & 0 deletions Vonage.Test/SimSwap/Check/SerializationTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using Vonage.Serialization;
using Vonage.SimSwap.Authenticate;
using Vonage.SimSwap.Check;
using Vonage.Test.Common;
using Vonage.Test.Common.Extensions;
using Xunit;

namespace Vonage.Test.SimSwap.Check;

[Trait("Category", "Serialization")]
public class SerializationTest
{
private readonly SerializationTestHelper helper = new SerializationTestHelper(
typeof(SerializationTest).Namespace,
JsonSerializerBuilder.BuildWithSnakeCase());

[Fact]
public void ShouldDeserializeAuthorize() => this.helper.Serializer
.DeserializeObject<AuthorizeResponse>(this.helper.GetResponseJson())
.Should()
.BeSuccess(GetExpectedAuthorizeResponse());

[Fact]
public void ShouldDeserializeAccessToken() => this.helper.Serializer
.DeserializeObject<GetTokenResponse>(this.helper.GetResponseJson())
.Should()
.BeSuccess(GetExpectedTokenResponse());

[Fact]
public void ShouldDeserializeCheck() => this.helper.Serializer
.DeserializeObject<CheckResponse>(this.helper.GetResponseJson())
.Should()
.BeSuccess(GetExpectedResponse());

[Fact]
public void ShouldSerialize() =>
CheckRequest.Build()
.WithPhoneNumber("346661113334")
.Create()
.GetStringContent()
.Should()
.BeSuccess(this.helper.GetRequestJson());

[Fact]
public void ShouldSerializeWithPeriod() =>
CheckRequest.Build()
.WithPhoneNumber("346661113334")
.WithPeriod(15)
.Create()
.GetStringContent()
.Should()
.BeSuccess(this.helper.GetRequestJson());

private static AuthorizeResponse GetExpectedAuthorizeResponse() => new AuthorizeResponse("123456789", "120", "2");

private static GetTokenResponse GetExpectedTokenResponse() => new GetTokenResponse("ABCDEFG", "Bearer", 3600);

private static CheckResponse GetExpectedResponse() => new CheckResponse(true);
}
16 changes: 15 additions & 1 deletion Vonage.Test/Vonage.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
</ItemGroup>

<ItemGroup>
<Folder Include="SimSwap\Check\"/>
<None Update="Data\NccoTests\TestRecord-request.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down Expand Up @@ -1108,6 +1107,21 @@
<None Update="SimSwap\Authenticate\Data\ShouldDeserializeAccessToken-response.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SimSwap\Check\Data\ShouldDeserializeAuthorize-response.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SimSwap\Check\Data\ShouldDeserializeAccessToken-response.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SimSwap\Check\Data\ShouldDeserializeCheck-response.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SimSwap\Check\Data\ShouldSerialize-request.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="SimSwap\Check\Data\ShouldSerializeWithPeriod-request.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="node ../.scripts/init.js"/>
Expand Down
Loading

0 comments on commit db8c97d

Please sign in to comment.