From 32dba788b9e2a222b6a9dfcafee48183c942be5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luka=20Vukadinovi=C4=87?= <138505157+lvukadinovic-ib@users.noreply.github.com> Date: Wed, 13 Nov 2024 13:51:26 +0100 Subject: [PATCH] Build workflow with tests, sonar workflow, snyk workflow, added new CONTRIBUTING. (#40) * Added build, snyk & sonarcloud workflow. * Added tests. * Added new CONTRIBUTING.md. --- .github/workflows/build.yml | 22 + .github/workflows/snyk.yml | 28 + .github/workflows/sonarcloud.yml | 27 + ApiClient.Tests/Api/ApiTest.cs | 253 ++++ ApiClient.Tests/Api/EmailApiTest.cs | 1376 ++++++++++++++++++ ApiClient.Tests/Api/SmsApiTest.cs | 1325 +++++++++++++++++ ApiClient.Tests/Api/TfaApiTest.cs | 1278 ++++++++++++++++ ApiClient.Tests/ApiClient.Tests.csproj | 23 + ApiClient.Tests/ApiExceptionTest.cs | 110 ++ ApiClient.Tests/DateTimeSerializationTest.cs | 77 + ApiClient.Tests/GeneralSetupTest.cs | 70 + CONTRIBUTING.md | 195 ++- Infobip.Api.Client.sln | 21 +- 13 files changed, 4782 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/snyk.yml create mode 100644 .github/workflows/sonarcloud.yml create mode 100644 ApiClient.Tests/Api/ApiTest.cs create mode 100644 ApiClient.Tests/Api/EmailApiTest.cs create mode 100644 ApiClient.Tests/Api/SmsApiTest.cs create mode 100644 ApiClient.Tests/Api/TfaApiTest.cs create mode 100644 ApiClient.Tests/ApiClient.Tests.csproj create mode 100644 ApiClient.Tests/ApiExceptionTest.cs create mode 100644 ApiClient.Tests/DateTimeSerializationTest.cs create mode 100644 ApiClient.Tests/GeneralSetupTest.cs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..bfd6088 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,22 @@ +name: .NET build + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + dotnet-version: [6.x, 7.x, 8.x] + steps: + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ matrix.dotnet-version }} + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal diff --git a/.github/workflows/snyk.yml b/.github/workflows/snyk.yml new file mode 100644 index 0000000..b1deb4c --- /dev/null +++ b/.github/workflows/snyk.yml @@ -0,0 +1,28 @@ +name: Snyk vulenrability scan + +on: [push] +jobs: + security: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '6.x' + - name: Restore dependencies + run: dotnet restore + - name: Run Snyk to check for vulnerabilities + uses: snyk/actions/dotnet@master + continue-on-error: true # To make sure that SARIF upload gets called + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + args: + --all-projects + --sarif-file-output=snyk.sarif + --severity-threshold=high + - name: Upload result to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: snyk.sarif diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 0000000..e0c537e --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,27 @@ +name: SonarCloud analysis + +on: [push] + +jobs: + sonarcloud: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '6.x' + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Install SonarScanner for .NET + run: dotnet tool install --global dotnet-sonarscanner + - name: Run SonarCloud Scan + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + dotnet-sonarscanner begin /k:"infobip_infobip-api-csharp-client" /o:"infobip" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" + dotnet build + dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" diff --git a/ApiClient.Tests/Api/ApiTest.cs b/ApiClient.Tests/Api/ApiTest.cs new file mode 100644 index 0000000..8f42536 --- /dev/null +++ b/ApiClient.Tests/Api/ApiTest.cs @@ -0,0 +1,253 @@ +using System.Net; +using Infobip.Api.Client; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using WireMock.Matchers; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; +using WireMock.Types; + +namespace ApiClient.Tests.Api; + +public class ApiTest +{ + protected const string API_KEY_PREFIX = "App"; + protected const string API_KEY = "003026bbc133714df1834b8638bb496e-8f4b3d9a-e931-478d-a994-28a725159ab9"; + protected const string API_KEY_HEADER_VALUE = API_KEY_PREFIX + " " + API_KEY; + protected const string CONTENT_TYPE_HEADER_VALUE = "application/json; charset=utf-8"; + protected const string USER_AGENT_HEADER_VALUE = "infobip-api-client-csharp/" + Configuration.Version; + protected const string ACCEPT_HEADER_VALUE = "application/json"; + protected const string SERVER_HEADER_VALUE = "SMS API"; + protected const string SERVER_HEADER_VALUE_COMMA = "SMS,API"; + protected const string X_REQUEST_ID_HEADER_VALUE = "1608758729810312842"; + + protected Configuration? configuration; + + protected WireMockServer? wireMockServer; + + [TestInitialize] + public void StartMockServer() + { + wireMockServer = WireMockServer.Start(); + + configuration = new Configuration + { + ApiKey = API_KEY, + BasePath = "http://localhost:" + wireMockServer.Ports[0] + }; + } + + [TestCleanup] + public void TearDown() + { + wireMockServer!.Stop(); + } + + protected void SetUpGetRequest(string url, string expectedResponse, int statusCode) + { + SetUpGetRequest(url, new Dictionary(), expectedResponse, statusCode); + } + + protected void SetUpPostRequest(string url, string givenRequest, string expectedResponse, int statusCode) + { + SetUpPostRequest(url, new Dictionary(), givenRequest, expectedResponse, statusCode); + } + + protected void SetUpPutRequest(string url, string givenRequest, string expectedResponse, int statusCode) + { + SetUpPutRequest(url, new Dictionary(), givenRequest, expectedResponse, statusCode); + } + + protected void SetUpDeleteRequest(string url, int statusCode) + { + SetUpDeleteRequest(url, new Dictionary(), statusCode); + } + + protected void SetUpGetRequest(string url, Dictionary givenParameters, string expectedResponse, + int statusCode) + { + wireMockServer!.Given(Request.Create().UsingGet().WithPath(url) + .WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) + .WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) + .WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)) + .WithParam(EqualToParams(givenParameters)) + ) + .RespondWith(Response.Create() + .WithStatusCode(statusCode) + .WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) + .WithHeader("Server", SERVER_HEADER_VALUE) + .WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) + .WithBody(expectedResponse) + ); + } + + protected void SetUpPostRequest(string url, Dictionary givenParameters, string givenRequest, + string expectedResponse, int statusCode) + { + wireMockServer!.Given(Request.Create().UsingPost().WithPath(url) + .WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) + .WithHeader("Content-Type", new ExactMatcher(CONTENT_TYPE_HEADER_VALUE)) + .WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) + .WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)) + .WithParam(EqualToParams(givenParameters)) + .WithBody(new JsonMatcher(givenRequest, true)) + ) + .RespondWith(Response.Create() + .WithStatusCode(statusCode) + .WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) + .WithHeader("Server", SERVER_HEADER_VALUE) + .WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) + .WithBody(expectedResponse) + ); + } + + protected void SetUpPostRequestBinary(string url, Dictionary givenParameters, byte[] givenRequest, + string expectedResponse, int statusCode) + { + wireMockServer!.Given(Request.Create().UsingPost().WithPath(url) + .WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) + .WithHeader("Content-Type", new ExactMatcher("application/octet-stream")) + .WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) + .WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)) + .WithParam(EqualToParams(givenParameters)) + .WithBody(givenRequest) + ) + .RespondWith(Response.Create() + .WithStatusCode(statusCode) + .WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) + .WithHeader("Server", SERVER_HEADER_VALUE) + .WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) + .WithBody(expectedResponse) + ); + } + + protected void SetUpNoRequestBodyNoResponseBodyPostRequest(string url, int statusCode) + { + wireMockServer!.Given(Request.Create().UsingPost().WithPath(url) + .WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) + .WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) + .WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)) + ) + .RespondWith(Response.Create() + .WithStatusCode(statusCode) + .WithHeader("Server", SERVER_HEADER_VALUE) + .WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) + ); + } + + protected void SetUpPutRequest(string url, Dictionary givenParameters, string givenRequest, + string expectedResponse, int statusCode) + { + wireMockServer!.Given(Request.Create().UsingPut().WithPath(url) + .WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) + .WithHeader("Content-Type", new ExactMatcher(CONTENT_TYPE_HEADER_VALUE)) + .WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) + .WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)) + .WithParam(EqualToParams(givenParameters)) + .WithBody(new JsonMatcher(givenRequest, true)) + ) + .RespondWith(Response.Create() + .WithStatusCode(statusCode) + .WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) + .WithHeader("Server", SERVER_HEADER_VALUE) + .WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) + .WithBody(expectedResponse) + ); + } + + protected void SetUpDeleteRequest(string url, Dictionary givenParameters, int statusCode) + { + wireMockServer!.Given(Request.Create().UsingDelete().WithPath(url) + .WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) + .WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) + .WithParam(EqualToParams(givenParameters)) + ) + .RespondWith(Response.Create() + .WithStatusCode(statusCode) + .WithHeader("Server", SERVER_HEADER_VALUE) + .WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) + ); + } + + protected void SetUpDeleteRequestWithResponseBody(string url, Dictionary givenParameters, + string expectedResponse, int statusCode) + { + wireMockServer!.Given(Request.Create().UsingDelete().WithPath(url) + .WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) + .WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) + .WithParam(EqualToParams(givenParameters)) + ) + .RespondWith(Response.Create() + .WithStatusCode(statusCode) + .WithHeader("Server", SERVER_HEADER_VALUE) + .WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) + .WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) + .WithBody(expectedResponse) + ); + } + + protected void SetUpMultipartFormRequest(string url, Multimap givenParts, string expectedResponse, + int statusCode = 200) + { + var req = Request.Create().UsingPost().WithPath(url) + .WithHeader("Authorization", new ExactMatcher(API_KEY_HEADER_VALUE)) + .WithHeader("Content-Type", new WildcardMatcher("multipart/form-data; boundary=\"---------*", true)) + .WithHeader("Accept", new ExactMatcher(ACCEPT_HEADER_VALUE)) + .WithHeader("User-Agent", new ExactMatcher(USER_AGENT_HEADER_VALUE)); + + req.WithBody(body => + { + var allKeysFound = givenParts.All(kvp => + body.Contains($"name={kvp.Key}", StringComparison.InvariantCultureIgnoreCase)); + var allValuesFound = givenParts.All(kvp => + kvp.Value.All(value => body.Contains(value, StringComparison.InvariantCultureIgnoreCase))); + return allValuesFound && allKeysFound; + }); + + var resp = Response.Create() + .WithStatusCode(statusCode) + .WithHeader("Content-Type", CONTENT_TYPE_HEADER_VALUE) + .WithHeader("Server", SERVER_HEADER_VALUE) + .WithHeader("X-Request-Id", X_REQUEST_ID_HEADER_VALUE) + .WithBody(expectedResponse); + + wireMockServer!.Given(req).RespondWith(resp); + } + + private Func>, bool>[] EqualToParams(Dictionary parameters) + { + var funcs = new List>, bool>>(); + foreach (var param in parameters) + funcs.Add(delegate(IDictionary> inputParams) + { + return inputParams[param.Key][0] == param.Value; + }); + if (funcs.Count == 0) funcs.Add(x => true); + return funcs.ToArray(); + } + + public static void AssertResponse(T apiResponse, Action assertion) + { + assertion.Invoke(apiResponse); + } + + public static void AssertResponseWithHttpInfo(ApiResponse apiResponse, Action assertion) + { + Assert.AreEqual(HttpStatusCode.OK, apiResponse.StatusCode); + + Assert.AreEqual(SERVER_HEADER_VALUE_COMMA, apiResponse.Headers["Server"][0]); + Assert.AreEqual(X_REQUEST_ID_HEADER_VALUE, apiResponse.Headers["X-Request-ID"][0]); + Assert.AreEqual(CONTENT_TYPE_HEADER_VALUE, apiResponse.Headers["Content-Type"][0]); + + assertion.Invoke(apiResponse.Data); + } + + public static void AssertNoBodyResponseWithHttpInfo(ApiResponse apiResponse, + HttpStatusCode expectedHttpStatusCode) + { + Assert.AreEqual(expectedHttpStatusCode, apiResponse.StatusCode); + + Assert.AreEqual(SERVER_HEADER_VALUE_COMMA, apiResponse.Headers["Server"][0]); + Assert.AreEqual(X_REQUEST_ID_HEADER_VALUE, apiResponse.Headers["X-Request-ID"][0]); + } +} \ No newline at end of file diff --git a/ApiClient.Tests/Api/EmailApiTest.cs b/ApiClient.Tests/Api/EmailApiTest.cs new file mode 100644 index 0000000..8149546 --- /dev/null +++ b/ApiClient.Tests/Api/EmailApiTest.cs @@ -0,0 +1,1376 @@ +using System.Globalization; +using System.Net; +using System.Text; +using Infobip.Api.Client; +using Infobip.Api.Client.Api; +using Infobip.Api.Client.Client; +using Infobip.Api.Client.Model; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using static Infobip.Api.Client.Model.EmailAddDomainRequest; + +namespace ApiClient.Tests.Api; + +[TestClass] +public class EmailApiTest : ApiTest +{ + protected const string EMAIL_SEND_FULLY_FEATURED_ENDPOINT = "/email/3/send"; + protected const string EMAIL_VALIDATE_ADDRESSES_ENDPOINT = "/email/2/validation"; + protected const string EMAIL_LOGS_ENDPOINT = "/email/1/reports"; + protected const string EMAIL_REPORTS_ENDPOINT = "/email/1/logs"; + protected const string EMAIL_BULKS_ENDPOINT = "/email/1/bulks"; + protected const string EMAIL_BULKS_STATUS_ENDPOINT = "/email/1/bulks/status"; + + protected const string EMAIL_DOMAINS = "/email/1/domains"; + protected const string EMAIL_DOMAIN = "/email/1/domains/{domainName}"; + protected const string EMAIL_DOMAIN_TRACKING = "/email/1/domains/{domainName}/tracking"; + protected const string EMAIL_DOMAIN_RETURN_PATH = "/email/1/domains/{domainName}/return-path"; + protected const string EMAIL_DOMAIN_VERIFY = "/email/1/domains/{domainName}/verify"; + protected const string EMAIL_IPS = "/email/1/ips"; + protected const string EMAIL_DOMAIN_IPS = "/email/1/domain-ips"; + + protected const string DATE_FORMAT = "yyyy-MM-ddTHH:mm:ss.fffzzz"; + + internal static readonly Tuple[] ErrorResponses = + { + Tuple.Create(400, "BAD_REQUEST", "Bad Request", "[subject : may not be null]"), + Tuple.Create(500, "GENERAL_ERROR", "Internal Server Error", "Something went wrong. Please contact support.") + }; + + internal static readonly Tuple[] DeliveryReportErrorResponses = + { + Tuple.Create(400, "BAD_REQUEST", "Bad Request", "request.message.content.media.file.url: [is not a valid url]"), + Tuple.Create(500, "BAD_REQUEST", "Internal Server Error", + "request.message.content.media.file.url: [is not a valid url]") + }; + + [TestMethod] + public void ShouldSendEmailTest() + { + var expectedFrom = "Jane Doe + { + { "from", expectedFrom }, + { "to", expectedTo }, + { "to", expectedTo2 }, + { "cc", expectedCc }, + { "cc", expectedCc2 }, + { "bcc", expectedBcc }, + { "bcc", expectedBcc2 }, + { "text", expectedText }, + { "html", expectedHtml }, + { "replyTo", expectedReplyTo }, + { "subject", expectedSubject } + }; + + SetUpMultipartFormRequest(EMAIL_SEND_FULLY_FEATURED_ENDPOINT, parts, expectedResponse); + + var sendEmailApi = new EmailApi(configuration); + + var expectedToList = new List + { + expectedTo, + expectedTo2 + }; + + var expectedCcList = new List + { + expectedCc, + expectedCc2 + }; + + var expectedBccList = new List + { + expectedBcc, + expectedBcc2 + }; + + var response = sendEmailApi.SendEmail( + from: expectedFrom, + to: expectedToList, + subject: expectedSubject, + cc: expectedCcList, + bcc: expectedBccList, + text: expectedText, + bulkId: expectedBulkId, + messageId: expectedMessageId, + html: expectedHtml, + replyTo: expectedReplyTo + ); + + Assert.AreEqual(expectedMessageCount, response.Messages.Count); + Assert.AreEqual(expectedMessageId, response.Messages[0].MessageId); + Assert.AreEqual(expectedTo, response.Messages[0].To); + Assert.AreEqual(expectedStatusId, response.Messages[0].Status.Id); + Assert.AreEqual(expectedStatusName, response.Messages[0].Status.Name); + Assert.AreEqual(expectedStatusGroupId, response.Messages[0].Status.GroupId); + Assert.AreEqual(expectedStatusDescription, response.Messages[0].Status.Description); + Assert.AreEqual(expectedStatusGroupId, response.Messages[0].Status.GroupId); + Assert.AreEqual(expectedMessageId2, response.Messages[1].MessageId); + Assert.AreEqual(expectedTo2, response.Messages[1].To); + Assert.AreEqual(expectedStatusId, response.Messages[1].Status.Id); + Assert.AreEqual(expectedStatusName, response.Messages[1].Status.Name); + Assert.AreEqual(expectedStatusGroupId, response.Messages[1].Status.GroupId); + Assert.AreEqual(expectedStatusDescription, response.Messages[1].Status.Description); + Assert.AreEqual(expectedStatusGroupId, response.Messages[1].Status.GroupId); + } + + [TestMethod] + public void ShouldSendEmailWithAttachmentTest() + { + var expectedFrom = "Jane Doe + { + { "from", expectedFrom }, + { "to", expectedTo }, + { "text", expectedText }, + { "html", expectedHtml }, + { "replyTo", expectedReplyTo }, + { "subject", expectedSubject }, + { "attachment", expectedAttachmentText }, + { "attachment", expectedAttachmentText2 } + }; + + SetUpMultipartFormRequest(EMAIL_SEND_FULLY_FEATURED_ENDPOINT, parts, expectedResponse); + + var sendEmailApi = new EmailApi(configuration); + + var expectedToList = new List + { + expectedTo + }; + + var attachmentList = new List + { + attachmentStream, + attachmentStream2 + }; + + var response = sendEmailApi.SendEmail( + from: expectedFrom, + to: expectedToList, + subject: expectedSubject, + text: expectedText, + bulkId: expectedBulkId, + messageId: expectedMessageId, + attachment: attachmentList, + html: expectedHtml, + replyTo: expectedReplyTo + ); + + Assert.AreEqual(expectedMessageCount, response.Messages.Count); + Assert.AreEqual(expectedMessageId, response.Messages[0].MessageId); + Assert.AreEqual(expectedTo, response.Messages[0].To); + Assert.AreEqual(expectedStatusId, response.Messages[0].Status.Id); + Assert.AreEqual(expectedStatusName, response.Messages[0].Status.Name); + Assert.AreEqual(expectedStatusGroupId, response.Messages[0].Status.GroupId); + Assert.AreEqual(expectedStatusDescription, response.Messages[0].Status.Description); + Assert.AreEqual(expectedStatusGroupId, response.Messages[0].Status.GroupId); + } + + [TestMethod] + public void ShouldGetEmailDeliveryReportsTest() + { + var expectedTo = "john.smith@somedomain.com"; + var expectedMessageCount = 1; + var expectedMessageId = "MSG-1234"; + var expectedBulkId = "BULK-1234"; + var expectedSentAt = new DateTimeOffset(2021, 9, 2, 9, 57, 56, TimeSpan.FromHours(0)); + var expectedDoneAt = new DateTimeOffset(2021, 9, 2, 9, 58, 33, TimeSpan.FromHours(0)); + var expectedCurrency = "EUR"; + var expectedPricePerMessage = 0.0M; + var expectedStatusName = "DELIVERED_TO_HANDSET"; + var expectedStatusId = 5; + var expectedStatusDescription = "Message delivered to handset"; + var expectedStatusGroupId = 3; + var expectedStatusGroupName = "DELIVERED"; + var expectedErrorName = "NO_ERROR"; + var expectedErrorId = 5; + var expectedErrorDescription = "No Error"; + var expectedErrorGroupId = 0; + var expectedErrorGroupName = "OK"; + var expectedErrorPermanent = false; + var expectedChannel = "EMAIL"; + + var expectedResponse = $@" + {{ + ""results"": [ + {{ + ""bulkId"": ""{expectedBulkId}"", + ""messageId"": ""{expectedMessageId}"", + ""to"": ""{expectedTo}"", + ""sentAt"": ""{expectedSentAt.ToUniversalTime().ToString(DATE_FORMAT)}"", + ""doneAt"": ""{expectedDoneAt.ToUniversalTime().ToString(DATE_FORMAT)}"", + ""messageCount"": {expectedMessageCount}, + ""price"": {{ + ""pricePerMessage"": {expectedPricePerMessage.ToString("N", CultureInfo.InvariantCulture)}, + ""currency"": ""{expectedCurrency}"" + }}, + ""status"": {{ + ""groupId"": {expectedStatusGroupId}, + ""groupName"": ""{expectedStatusGroupName}"", + ""id"": {expectedStatusId}, + ""name"": ""{expectedStatusName}"", + ""description"": ""{expectedStatusDescription}"" + }}, + ""error"": {{ + ""groupId"": {expectedErrorGroupId}, + ""groupName"": ""{expectedErrorGroupName}"", + ""id"": {expectedErrorId}, + ""name"": ""{expectedErrorName}"", + ""description"": ""{expectedErrorDescription}"", + ""permanent"": {expectedErrorPermanent.ToString().ToLower()} + }}, + ""channel"": ""{expectedChannel}"" + }} + ] + }}"; + + SetUpGetRequest(EMAIL_LOGS_ENDPOINT, expectedResponse, 200); + + var sendEmailApi = new EmailApi(configuration); + + var response = sendEmailApi.GetEmailDeliveryReports(expectedBulkId, expectedMessageId, limit: 2); + + Assert.AreEqual(1, response.Results.Count); + Assert.AreEqual(expectedBulkId, response.Results[0].BulkId); + Assert.AreEqual(expectedMessageId, response.Results[0].MessageId); + + Assert.AreEqual(expectedSentAt, response.Results[0].SentAt); + Assert.AreEqual(expectedDoneAt, response.Results[0].DoneAt); + Assert.AreEqual(expectedMessageCount, response.Results[0].MessageCount); + + Assert.AreEqual(expectedStatusDescription, response.Results[0].Status.Description); + Assert.AreEqual(expectedStatusGroupId, response.Results[0].Status.GroupId); + Assert.AreEqual(expectedStatusGroupName, response.Results[0].Status.GroupName); + Assert.AreEqual(expectedStatusId, response.Results[0].Status.Id); + Assert.AreEqual(expectedStatusName, response.Results[0].Status.Name); + + Assert.AreEqual(expectedPricePerMessage, response.Results[0].Price.PricePerMessage); + + Assert.AreEqual(expectedErrorDescription, response.Results[0].Error.Description); + Assert.AreEqual(expectedErrorGroupId, response.Results[0].Error.GroupId); + Assert.AreEqual(expectedErrorGroupName, response.Results[0].Error.GroupName); + Assert.AreEqual(expectedErrorId, response.Results[0].Error.Id); + Assert.AreEqual(expectedErrorName, response.Results[0].Error.Name); + Assert.AreEqual(expectedErrorPermanent, response.Results[0].Error.Permanent); + } + + [TestMethod] + public void ShouldGetEmailLogsTest() + { + var expectedFrom = "Jane Doe + { + { "size", expectedSize.ToString() }, + { "page", expectedPage.ToString() } + }; + + SetUpGetRequest(EMAIL_DOMAINS, expectedQueryParameters, expectedResponse, 200); + + var emailApi = new EmailApi(configuration); + + void AssertEmailAllDomainsResponse(EmailAllDomainsResponse emailAllDomainsResponse) + { + Assert.IsNotNull(emailAllDomainsResponse.Paging); + Assert.AreEqual(expectedPage, emailAllDomainsResponse.Paging.Page); + Assert.AreEqual(expectedSize, emailAllDomainsResponse.Paging.Size); + Assert.AreEqual(expectedTotalPages, emailAllDomainsResponse.Paging.TotalPages); + Assert.AreEqual(expectedTotalResults, emailAllDomainsResponse.Paging.TotalResults); + + Assert.IsNotNull(emailAllDomainsResponse.Results); + Assert.AreEqual(expectedDomainId, emailAllDomainsResponse.Results[0].DomainId); + Assert.AreEqual(expectedDomainName, emailAllDomainsResponse.Results[0].DomainName); + Assert.AreEqual(expectedActive, emailAllDomainsResponse.Results[0].Active); + Assert.AreEqual(expectedClicks, emailAllDomainsResponse.Results[0].Tracking.Clicks); + Assert.AreEqual(expectedOpens, emailAllDomainsResponse.Results[0].Tracking.Opens); + Assert.AreEqual(expectedUnsubscribe, emailAllDomainsResponse.Results[0].Tracking.Unsubscribe); + Assert.AreEqual(expectedRecordType, emailAllDomainsResponse.Results[0].DnsRecords[0].RecordType); + Assert.AreEqual(expectedName, emailAllDomainsResponse.Results[0].DnsRecords[0].Name); + Assert.AreEqual(expectedExpectedValue, emailAllDomainsResponse.Results[0].DnsRecords[0].ExpectedValue); + Assert.AreEqual(expectedVerified, emailAllDomainsResponse.Results[0].DnsRecords[0].Verified); + Assert.AreEqual(expectedBlocked, emailAllDomainsResponse.Results[0].Blocked); + Assert.AreEqual(expectedCreatedAt, emailAllDomainsResponse.Results[0].CreatedAt); + Assert.AreEqual(expectedReturnPathAddress, emailAllDomainsResponse.Results[0].ReturnPathAddress); + } + + AssertResponse(emailApi.GetAllDomains(expectedSize, expectedPage), AssertEmailAllDomainsResponse); + AssertResponse(emailApi.GetAllDomainsAsync(expectedSize, expectedPage).Result, AssertEmailAllDomainsResponse); + + AssertResponseWithHttpInfo(emailApi.GetAllDomainsWithHttpInfo(expectedSize, expectedPage), + AssertEmailAllDomainsResponse); + AssertResponseWithHttpInfo(emailApi.GetAllDomainsWithHttpInfoAsync(expectedSize, expectedPage).Result, + AssertEmailAllDomainsResponse); + } + + [TestMethod] + public void ShouldAddNewDomain() + { + var givenDkimKeyLength = 1024; + long givenTargetedDailyTraffic = 1000; + var givenApplicationId = "string"; + var givenEntityId = "string"; + + var expectedDomainId = 1; + var expectedDomainName = "example.com"; + var expectedActive = false; + var expectedClicks = true; + var expectedOpens = true; + var expectedUnsubscribe = true; + var expectedRecordType = "string"; + var expectedName = "string"; + var expectedExpectedValue = "string"; + var expectedVerified = true; + var expectedBlocked = false; + var expectedCreatedAt = new DateTimeOffset(2021, 1, 2, 1, 0, 0, 123, TimeSpan.FromHours(0)); + var expectedReturnPathAddress = "returnpath@example.com"; + + var givenRequest = $@" + {{ + ""domainName"": ""{expectedDomainName}"", + ""dkimKeyLength"": {givenDkimKeyLength}, + ""targetedDailyTraffic"": {givenTargetedDailyTraffic}, + ""applicationId"": ""{givenApplicationId}"", + ""entityId"": ""{givenEntityId}"", + ""returnPathAddress"": ""{expectedReturnPathAddress}"" + }}"; + + var expectedResponse = $@" + {{ + ""domainId"": {expectedDomainId}, + ""domainName"": ""{expectedDomainName}"", + ""active"": {expectedActive.ToString().ToLower()}, + ""tracking"": {{ + ""clicks"": {expectedClicks.ToString().ToLower()}, + ""opens"": {expectedOpens.ToString().ToLower()}, + ""unsubscribe"": {expectedUnsubscribe.ToString().ToLower()} + }}, + ""dnsRecords"": [ + {{ + ""recordType"": ""{expectedRecordType}"", + ""name"": ""{expectedName}"", + ""expectedValue"": ""{expectedExpectedValue}"", + ""verified"": {expectedVerified.ToString().ToLower()} + }} + ], + ""blocked"": {expectedBlocked.ToString().ToLower()}, + ""createdAt"": ""{expectedCreatedAt.ToUniversalTime().ToString(DATE_FORMAT)}"", + ""returnPathAddress"": ""{expectedReturnPathAddress}"" + }}"; + + SetUpPostRequest(EMAIL_DOMAINS, givenRequest, expectedResponse, 200); + + var emailApi = new EmailApi(configuration); + + var emailAddDomainRequest = new EmailAddDomainRequest( + expectedDomainName, + DkimKeyLengthEnum.NUMBER1024, + givenTargetedDailyTraffic, + givenApplicationId, + givenEntityId, + expectedReturnPathAddress + ); + + void AssertEmailDomainResponse(EmailDomainResponse emailDomainResponse) + { + Assert.IsNotNull(emailDomainResponse); + Assert.AreEqual(expectedDomainId, emailDomainResponse.DomainId); + Assert.AreEqual(expectedDomainName, emailDomainResponse.DomainName); + Assert.AreEqual(expectedActive, emailDomainResponse.Active); + Assert.AreEqual(expectedClicks, emailDomainResponse.Tracking.Clicks); + Assert.AreEqual(expectedOpens, emailDomainResponse.Tracking.Opens); + Assert.AreEqual(expectedUnsubscribe, emailDomainResponse.Tracking.Unsubscribe); + Assert.AreEqual(expectedRecordType, emailDomainResponse.DnsRecords[0].RecordType); + Assert.AreEqual(expectedName, emailDomainResponse.DnsRecords[0].Name); + Assert.AreEqual(expectedExpectedValue, emailDomainResponse.DnsRecords[0].ExpectedValue); + Assert.AreEqual(expectedVerified, emailDomainResponse.DnsRecords[0].Verified); + Assert.AreEqual(expectedBlocked, emailDomainResponse.Blocked); + Assert.AreEqual(expectedCreatedAt, emailDomainResponse.CreatedAt); + Assert.AreEqual(expectedReturnPathAddress, emailDomainResponse.ReturnPathAddress); + } + + AssertResponse(emailApi.AddDomain(emailAddDomainRequest), AssertEmailDomainResponse); + AssertResponse(emailApi.AddDomainAsync(emailAddDomainRequest).Result, AssertEmailDomainResponse); + + AssertResponseWithHttpInfo(emailApi.AddDomainWithHttpInfo(emailAddDomainRequest), AssertEmailDomainResponse); + AssertResponseWithHttpInfo(emailApi.AddDomainWithHttpInfoAsync(emailAddDomainRequest).Result, + AssertEmailDomainResponse); + } + + [TestMethod] + public void ShouldGetDomainDetails() + { + var expectedDomainId = 1; + var expectedDomainName = "example.com"; + var expectedActive = false; + var expectedClicks = true; + var expectedOpens = true; + var expectedUnsubscribe = true; + var expectedRecordType = "string"; + var expectedName = "string"; + var expectedExpectedValue = "string"; + var expectedVerified = true; + var expectedBlocked = false; + var expectedCreatedAt = new DateTimeOffset(2021, 1, 2, 1, 0, 0, 123, TimeSpan.FromHours(0)); + var expectedReturnPathAddress = "returnpath@example.com"; + + var expectedResponse = $@" + {{ + ""domainId"": {expectedDomainId}, + ""domainName"": ""{expectedDomainName}"", + ""active"": {expectedActive.ToString().ToLower()}, + ""tracking"": {{ + ""clicks"": {expectedClicks.ToString().ToLower()}, + ""opens"": {expectedOpens.ToString().ToLower()}, + ""unsubscribe"": {expectedUnsubscribe.ToString().ToLower()} + }}, + ""dnsRecords"": [ + {{ + ""recordType"": ""{expectedRecordType}"", + ""name"": ""{expectedName}"", + ""expectedValue"": ""{expectedExpectedValue}"", + ""verified"": {expectedVerified.ToString().ToLower()} + }} + ], + ""blocked"": {expectedBlocked.ToString().ToLower()}, + ""createdAt"": ""{expectedCreatedAt.ToUniversalTime().ToString(DATE_FORMAT)}"", + ""returnPathAddress"": ""{expectedReturnPathAddress}"" + }}"; + + SetUpGetRequest(EMAIL_DOMAIN.Replace("{domainName}", expectedDomainName), expectedResponse, 200); + + var emailApi = new EmailApi(configuration); + + void AssertEmailDomainResponse(EmailDomainResponse emailDomainResponse) + { + Assert.IsNotNull(emailDomainResponse); + Assert.AreEqual(expectedDomainId, emailDomainResponse.DomainId); + Assert.AreEqual(expectedDomainName, emailDomainResponse.DomainName); + Assert.AreEqual(expectedActive, emailDomainResponse.Active); + Assert.AreEqual(expectedClicks, emailDomainResponse.Tracking.Clicks); + Assert.AreEqual(expectedOpens, emailDomainResponse.Tracking.Opens); + Assert.AreEqual(expectedUnsubscribe, emailDomainResponse.Tracking.Unsubscribe); + Assert.AreEqual(expectedRecordType, emailDomainResponse.DnsRecords[0].RecordType); + Assert.AreEqual(expectedName, emailDomainResponse.DnsRecords[0].Name); + Assert.AreEqual(expectedExpectedValue, emailDomainResponse.DnsRecords[0].ExpectedValue); + Assert.AreEqual(expectedVerified, emailDomainResponse.DnsRecords[0].Verified); + Assert.AreEqual(expectedBlocked, emailDomainResponse.Blocked); + Assert.AreEqual(expectedCreatedAt, emailDomainResponse.CreatedAt); + Assert.AreEqual(expectedReturnPathAddress, emailDomainResponse.ReturnPathAddress); + } + + AssertResponse(emailApi.GetDomainDetails(expectedDomainName), AssertEmailDomainResponse); + AssertResponse(emailApi.GetDomainDetailsAsync(expectedDomainName).Result, AssertEmailDomainResponse); + + AssertResponseWithHttpInfo(emailApi.GetDomainDetailsWithHttpInfo(expectedDomainName), + AssertEmailDomainResponse); + AssertResponseWithHttpInfo(emailApi.GetDomainDetailsWithHttpInfoAsync(expectedDomainName).Result, + AssertEmailDomainResponse); + } + + [TestMethod] + public void ShouldDeleteExistingDomain() + { + var givenDomainName = "domainName"; + + SetUpDeleteRequest(EMAIL_DOMAIN.Replace("{domainName}", givenDomainName), 204); + + var emailApi = new EmailApi(configuration); + + AssertNoBodyResponseWithHttpInfo(emailApi.DeleteDomainWithHttpInfo(givenDomainName), HttpStatusCode.NoContent); + AssertNoBodyResponseWithHttpInfo(emailApi.DeleteDomainWithHttpInfoAsync(givenDomainName).Result, + HttpStatusCode.NoContent); + } + + [TestMethod] + public void ShouldUpdateTrackingEvents() + { + var expectedDomainId = 1; + var expectedDomainName = "example.com"; + var expectedActive = false; + var expectedClicks = true; + var expectedOpens = true; + var expectedUnsubscribe = true; + var expectedRecordType = "string"; + var expectedName = "string"; + var expectedExpectedValue = "string"; + var expectedVerified = true; + var expectedBlocked = false; + var expectedCreatedAt = new DateTimeOffset(2021, 1, 2, 1, 0, 0, 123, TimeSpan.FromHours(0)); + var expectedReturnPathAddress = "returnpath@example.com"; + + var givenRequest = $@" + {{ + ""open"": {expectedOpens.ToString().ToLower()}, + ""clicks"": {expectedClicks.ToString().ToLower()}, + ""unsubscribe"": {expectedUnsubscribe.ToString().ToLower()} + }}"; + + var expectedResponse = $@" + {{ + ""domainId"": {expectedDomainId}, + ""domainName"": ""{expectedDomainName}"", + ""active"": {expectedActive.ToString().ToLower()}, + ""tracking"": {{ + ""clicks"": {expectedClicks.ToString().ToLower()}, + ""opens"": {expectedOpens.ToString().ToLower()}, + ""unsubscribe"": {expectedUnsubscribe.ToString().ToLower()} + }}, + ""dnsRecords"": [ + {{ + ""recordType"": ""{expectedRecordType}"", + ""name"": ""{expectedName}"", + ""expectedValue"": ""{expectedExpectedValue}"", + ""verified"": {expectedVerified.ToString().ToLower()} + }} + ], + ""blocked"": {expectedBlocked.ToString().ToLower()}, + ""createdAt"": ""{expectedCreatedAt.ToUniversalTime().ToString(DATE_FORMAT)}"", + ""returnPathAddress"": ""{expectedReturnPathAddress}"" + }}"; + + SetUpPutRequest(EMAIL_DOMAIN_TRACKING.Replace("{domainName}", expectedDomainName), givenRequest, + expectedResponse, 200); + + var emailApi = new EmailApi(configuration); + + var emailTrackingEventRequest = new EmailTrackingEventRequest( + expectedOpens, + expectedClicks, + expectedUnsubscribe + ); + + void AssertEmailDomainResponse(EmailDomainResponse emailDomainResponse) + { + Assert.IsNotNull(emailDomainResponse); + Assert.AreEqual(expectedDomainId, emailDomainResponse.DomainId); + Assert.AreEqual(expectedDomainName, emailDomainResponse.DomainName); + Assert.AreEqual(expectedActive, emailDomainResponse.Active); + Assert.AreEqual(expectedClicks, emailDomainResponse.Tracking.Clicks); + Assert.AreEqual(expectedOpens, emailDomainResponse.Tracking.Opens); + Assert.AreEqual(expectedUnsubscribe, emailDomainResponse.Tracking.Unsubscribe); + Assert.AreEqual(expectedRecordType, emailDomainResponse.DnsRecords[0].RecordType); + Assert.AreEqual(expectedName, emailDomainResponse.DnsRecords[0].Name); + Assert.AreEqual(expectedExpectedValue, emailDomainResponse.DnsRecords[0].ExpectedValue); + Assert.AreEqual(expectedVerified, emailDomainResponse.DnsRecords[0].Verified); + Assert.AreEqual(expectedBlocked, emailDomainResponse.Blocked); + Assert.AreEqual(expectedCreatedAt, emailDomainResponse.CreatedAt); + Assert.AreEqual(expectedReturnPathAddress, emailDomainResponse.ReturnPathAddress); + } + + AssertResponse(emailApi.UpdateTrackingEvents(expectedDomainName, emailTrackingEventRequest), + AssertEmailDomainResponse); + AssertResponse(emailApi.UpdateTrackingEventsAsync(expectedDomainName, emailTrackingEventRequest).Result, + AssertEmailDomainResponse); + + AssertResponseWithHttpInfo( + emailApi.UpdateTrackingEventsWithHttpInfo(expectedDomainName, emailTrackingEventRequest), + AssertEmailDomainResponse); + AssertResponseWithHttpInfo( + emailApi.UpdateTrackingEventsWithHttpInfoAsync(expectedDomainName, emailTrackingEventRequest).Result, + AssertEmailDomainResponse); + } + + [TestMethod] + public void ShouldUpdateReturnPath() + { + var expectedDomainId = 1; + var expectedDomainName = "example.com"; + var expectedActive = false; + var expectedClicks = true; + var expectedOpens = true; + var expectedUnsubscribe = true; + var expectedRecordType = "string"; + var expectedName = "string"; + var expectedExpectedValue = "string"; + var expectedVerified = true; + var expectedBlocked = false; + var expectedCreatedAt = new DateTimeOffset(2021, 1, 2, 1, 0, 0, 123, TimeSpan.FromHours(0)); + var expectedReturnPathAddress = "returnpath@example.com"; + + var givenRequest = $@" + {{ + ""returnPathAddress"": ""{expectedReturnPathAddress}"", + }}"; + + var expectedResponse = $@" + {{ + ""domainId"": {expectedDomainId}, + ""domainName"": ""{expectedDomainName}"", + ""active"": {expectedActive.ToString().ToLower()}, + ""tracking"": {{ + ""clicks"": {expectedClicks.ToString().ToLower()}, + ""opens"": {expectedOpens.ToString().ToLower()}, + ""unsubscribe"": {expectedUnsubscribe.ToString().ToLower()} + }}, + ""dnsRecords"": [ + {{ + ""recordType"": ""{expectedRecordType}"", + ""name"": ""{expectedName}"", + ""expectedValue"": ""{expectedExpectedValue}"", + ""verified"": {expectedVerified.ToString().ToLower()} + }} + ], + ""blocked"": {expectedBlocked.ToString().ToLower()}, + ""createdAt"": ""{expectedCreatedAt.ToUniversalTime().ToString(DATE_FORMAT)}"", + ""returnPathAddress"": ""{expectedReturnPathAddress}"" + }}"; + + SetUpPutRequest(EMAIL_DOMAIN_RETURN_PATH.Replace("{domainName}", expectedDomainName), givenRequest, + expectedResponse, 200); + + var emailApi = new EmailApi(configuration); + + var emailReturnPathAddressRequest = new EmailReturnPathAddressRequest( + expectedReturnPathAddress + ); + + void AssertEmailDomainResponse(EmailDomainResponse emailDomainResponse) + { + Assert.IsNotNull(emailDomainResponse); + Assert.AreEqual(expectedDomainId, emailDomainResponse.DomainId); + Assert.AreEqual(expectedDomainName, emailDomainResponse.DomainName); + Assert.AreEqual(expectedActive, emailDomainResponse.Active); + Assert.AreEqual(expectedClicks, emailDomainResponse.Tracking.Clicks); + Assert.AreEqual(expectedOpens, emailDomainResponse.Tracking.Opens); + Assert.AreEqual(expectedUnsubscribe, emailDomainResponse.Tracking.Unsubscribe); + Assert.AreEqual(expectedRecordType, emailDomainResponse.DnsRecords[0].RecordType); + Assert.AreEqual(expectedName, emailDomainResponse.DnsRecords[0].Name); + Assert.AreEqual(expectedExpectedValue, emailDomainResponse.DnsRecords[0].ExpectedValue); + Assert.AreEqual(expectedVerified, emailDomainResponse.DnsRecords[0].Verified); + Assert.AreEqual(expectedBlocked, emailDomainResponse.Blocked); + Assert.AreEqual(expectedCreatedAt, emailDomainResponse.CreatedAt); + Assert.AreEqual(expectedReturnPathAddress, emailDomainResponse.ReturnPathAddress); + } + + AssertResponse(emailApi.UpdateReturnPath(expectedDomainName, emailReturnPathAddressRequest), + AssertEmailDomainResponse); + AssertResponse(emailApi.UpdateReturnPathAsync(expectedDomainName, emailReturnPathAddressRequest).Result, + AssertEmailDomainResponse); + + AssertResponseWithHttpInfo( + emailApi.UpdateReturnPathWithHttpInfo(expectedDomainName, emailReturnPathAddressRequest), + AssertEmailDomainResponse); + AssertResponseWithHttpInfo( + emailApi.UpdateReturnPathWithHttpInfoAsync(expectedDomainName, emailReturnPathAddressRequest).Result, + AssertEmailDomainResponse); + } + + [TestMethod] + public void ShouldVerifyDomain() + { + var givenDomainName = "domainName"; + + SetUpNoRequestBodyNoResponseBodyPostRequest(EMAIL_DOMAIN_VERIFY.Replace("{domainName}", givenDomainName), 202); + + var emailApi = new EmailApi(configuration); + + AssertNoBodyResponseWithHttpInfo(emailApi.VerifyDomainWithHttpInfo(givenDomainName), HttpStatusCode.Accepted); + AssertNoBodyResponseWithHttpInfo(emailApi.VerifyDomainWithHttpInfoAsync(givenDomainName).Result, + HttpStatusCode.Accepted); + } + + [TestMethod] + public void ShouldListAllDedicatedIpsForProvidedAccountId() + { + var expectedIpAddress = "11.11.11.1"; + var expectedDedicated = true; + var expectedAssignedDomainCount = 1; + var expectedStatus = "ASSIGNABLE"; + + var expectedResponse = $@" + {{ + ""result"": [ + {{ + ""ipAddress"": ""{expectedIpAddress}"", + ""dedicated"": {expectedDedicated.ToString().ToLower()}, + ""assignedDomainCount"": {expectedAssignedDomainCount}, + ""status"": ""{expectedStatus}"" + }} + ] + }}"; + + SetUpGetRequest(EMAIL_IPS, expectedResponse, 200); + + var emailApi = new EmailApi(configuration); + + void AssertEmailDomainIpResponse(EmailDomainIpResponse emailDomainIpResponse) + { + Assert.IsNotNull(emailDomainIpResponse); + Assert.IsNotNull(emailDomainIpResponse.Result[0]); + Assert.AreEqual(expectedIpAddress, emailDomainIpResponse.Result[0].IpAddress); + Assert.AreEqual(expectedDedicated, emailDomainIpResponse.Result[0].Dedicated); + Assert.AreEqual(expectedAssignedDomainCount, emailDomainIpResponse.Result[0].AssignedDomainCount); + Assert.AreEqual(expectedStatus, emailDomainIpResponse.Result[0].Status); + } + + AssertResponse(emailApi.GetAllIps(), AssertEmailDomainIpResponse); + AssertResponse(emailApi.GetAllIpsAsync().Result, AssertEmailDomainIpResponse); + + AssertResponseWithHttpInfo(emailApi.GetAllIpsWithHttpInfo(), AssertEmailDomainIpResponse); + AssertResponseWithHttpInfo(emailApi.GetAllIpsWithHttpInfoAsync().Result, AssertEmailDomainIpResponse); + } + + [TestMethod] + public void ShouldListAllDedicatedIpsForDomainAndForProvidedAccountId() + { + var expectedIpAddress = "11.11.11.1"; + var expectedDedicated = true; + var expectedAssignedDomainCount = 1; + var expectedStatus = "ASSIGNABLE"; + + var expectedDomainName = "domainName"; + + var expectedResponse = $@" + {{ + ""result"": [ + {{ + ""ipAddress"": ""{expectedIpAddress}"", + ""dedicated"": {expectedDedicated.ToString().ToLower()}, + ""assignedDomainCount"": {expectedAssignedDomainCount}, + ""status"": ""{expectedStatus}"" + }} + ] + }}"; + + var queryParameters = new Dictionary + { + { "domainName", expectedDomainName } + }; + + SetUpGetRequest(EMAIL_DOMAIN_IPS, queryParameters, expectedResponse, 200); + + var emailApi = new EmailApi(configuration); + + void AssertEmailDomainIpResponse(EmailDomainIpResponse emailDomainIpResponse) + { + Assert.IsNotNull(emailDomainIpResponse); + Assert.IsNotNull(emailDomainIpResponse.Result[0]); + Assert.AreEqual(expectedIpAddress, emailDomainIpResponse.Result[0].IpAddress); + Assert.AreEqual(expectedDedicated, emailDomainIpResponse.Result[0].Dedicated); + Assert.AreEqual(expectedAssignedDomainCount, emailDomainIpResponse.Result[0].AssignedDomainCount); + Assert.AreEqual(expectedStatus, emailDomainIpResponse.Result[0].Status); + } + + AssertResponse(emailApi.GetAllDomainIps(expectedDomainName), AssertEmailDomainIpResponse); + AssertResponse(emailApi.GetAllDomainIpsAsync(expectedDomainName).Result, AssertEmailDomainIpResponse); + + AssertResponseWithHttpInfo(emailApi.GetAllDomainIpsWithHttpInfo(expectedDomainName), + AssertEmailDomainIpResponse); + AssertResponseWithHttpInfo(emailApi.GetAllDomainIpsWithHttpInfoAsync(expectedDomainName).Result, + AssertEmailDomainIpResponse); + } + + [TestMethod] + public void ShouldAssignDedicatedIpAddressToProvidedDomainForTheAccountId() + { + var givenDomainName = "domain.com"; + var givenIpAddress = "11.11.11.11"; + + var expectedResult = "OK"; + + var givenRequest = $@" + {{ + ""domainName"": ""{givenDomainName}"", + ""ipAddress"": ""{givenIpAddress}"" + }}"; + + var expectedResponse = $@" + {{ + ""result"": ""{expectedResult}"" + }}"; + + SetUpPostRequest(EMAIL_DOMAIN_IPS, givenRequest, expectedResponse, 200); + + var emailApi = new EmailApi(configuration); + + var emailDomainIpRequest = new EmailDomainIpRequest( + givenDomainName, + givenIpAddress + ); + + void AssertEmailSimpleApiResponse(EmailSimpleApiResponse emailSimpleApiResponse) + { + Assert.IsNotNull(emailSimpleApiResponse); + Assert.AreEqual(expectedResult, emailSimpleApiResponse.Result); + } + + AssertResponse(emailApi.AssignIpToDomain(emailDomainIpRequest), AssertEmailSimpleApiResponse); + AssertResponse(emailApi.AssignIpToDomainAsync(emailDomainIpRequest).Result, AssertEmailSimpleApiResponse); + + AssertResponseWithHttpInfo(emailApi.AssignIpToDomainWithHttpInfo(emailDomainIpRequest), + AssertEmailSimpleApiResponse); + AssertResponseWithHttpInfo(emailApi.AssignIpToDomainWithHttpInfoAsync(emailDomainIpRequest).Result, + AssertEmailSimpleApiResponse); + } + + [TestMethod] + public void ShouldRemoveDedicatedIpAddressFromTheProvidedDomain() + { + var givenDomainName = "domain.com"; + var givenIpAddress = "11.11.11.11"; + + var expectedResult = "OK"; + + var expectedResponse = $@" + {{ + ""result"": ""{expectedResult}"" + }}"; + + var givenQueryParameters = new Dictionary + { + { "domainName", givenDomainName }, + { "ipAddress", givenIpAddress } + }; + + SetUpDeleteRequestWithResponseBody(EMAIL_DOMAIN_IPS, givenQueryParameters, expectedResponse, 200); + + var emailApi = new EmailApi(configuration); + + void AssertEmailSimpleApiResponse(EmailSimpleApiResponse emailSimpleApiResponse) + { + Assert.IsNotNull(emailSimpleApiResponse); + Assert.AreEqual(expectedResult, emailSimpleApiResponse.Result); + } + + AssertResponse(emailApi.RemoveIpFromDomain(givenDomainName, givenIpAddress), AssertEmailSimpleApiResponse); + AssertResponse(emailApi.RemoveIpFromDomainAsync(givenDomainName, givenIpAddress).Result, + AssertEmailSimpleApiResponse); + + AssertResponseWithHttpInfo(emailApi.RemoveIpFromDomainWithHttpInfo(givenDomainName, givenIpAddress), + AssertEmailSimpleApiResponse); + AssertResponseWithHttpInfo(emailApi.RemoveIpFromDomainWithHttpInfoAsync(givenDomainName, givenIpAddress).Result, + AssertEmailSimpleApiResponse); + } + + [DataTestMethod] + [DataRow(0)] + [DataRow(1)] + public void SendEmailErrorResponseTest(int errorResponseIndex) + { + var expectedHttpCode = ErrorResponses[errorResponseIndex].Item1; + var expectedMessageId = ErrorResponses[errorResponseIndex].Item2; + var expectedErrorText = ErrorResponses[errorResponseIndex].Item4; + var expectedErrorPhrase = ErrorResponses[errorResponseIndex].Item3; + + var givenTo = "john.smith@somedomain.com"; + var givenMessageCount = 1; + var givenMessageId = "somexternalMessageId"; + var givenGroupId = 1; + var givenGroupName = "PENDING"; + var givenId = 7; + var givenName = "PENDING_ENROUTE"; + var givenDescription = "Message sent to next instance"; + var givenFrom = "jane.smith@somecompany.com"; + var givenSubject = "Mail subject text"; + var givenMailText = "Mail text"; + + var givenRequest = $@" + {{ + ""messages"": [ + {{ + ""to"": ""{givenTo}"", + ""messageCount"": {givenMessageCount}, + ""messageId"": ""{givenMessageId}"", + ""status"": {{ + ""groupId"": {givenGroupId}, + ""groupName"": ""{givenGroupName}"", + ""id"": {givenId}, + ""name"": ""{givenName}"", + ""description"": ""{givenDescription}"" + }} + }} + ] + }}"; + + var expectedJson = $@" + {{ + ""requestError"": {{ + ""serviceException"": {{ + ""messageId"": ""{expectedMessageId}"", + ""text"": ""{expectedErrorText}"" + }} + }} + }}"; + + var responseHeaders = new Dictionary + { + { "Server", "SMS,API" }, + { "X-Request-ID", "1608758729810312842" }, + { "Content-Type", "application/json; charset=utf-8" } + }; + + var givenParts = new Multimap + { + { "from", givenFrom }, + { "to", givenTo }, + { "subject", givenSubject }, + { "text", givenMailText } + }; + + SetUpMultipartFormRequest(EMAIL_SEND_FULLY_FEATURED_ENDPOINT, givenParts, expectedJson, expectedHttpCode); + + var emailApi = new EmailApi(configuration); + + var toList = new List + { + givenTo + }; + + try + { + var result = emailApi.SendEmail(from: givenFrom, to: toList, subject: givenSubject, text: givenMailText); + } + catch (ApiException ex) + { + Assert.AreEqual(expectedHttpCode, ex.ErrorCode); + Assert.AreEqual(expectedJson, ex.ErrorContent); + Assert.IsInstanceOfType(ex, typeof(ApiException)); + Assert.IsTrue(ex.Message.Contains(expectedErrorPhrase)); + Assert.IsTrue(ex.ErrorContent.ToString()?.Contains(expectedMessageId) == true); + Assert.IsTrue(ex.ErrorContent.ToString()?.Contains(expectedErrorText) == true); + Assert.IsTrue(responseHeaders.All(h => + ex.Headers.ContainsKey(h.Key) && ex.Headers[h.Key].First().Equals(h.Value))); + } + } + + [DataTestMethod] + [DataRow(0)] + [DataRow(1)] + public void GetEmailDeliveryReportsResponseTest(int errorResponseIndex) + { + var expectedHttpCode = DeliveryReportErrorResponses[errorResponseIndex].Item1; + var expectedMessageId = DeliveryReportErrorResponses[errorResponseIndex].Item2; + var expectedErrorPhrase = DeliveryReportErrorResponses[errorResponseIndex].Item3; + var expectedErrorText = DeliveryReportErrorResponses[errorResponseIndex].Item4; + + var givenMessageId = "MSG-TEST-123"; + var givenBulkId = "BULK-1234"; + var givenLimit = 2; + + var expectedJson = $@" + {{ + ""requestError"": {{ + ""serviceException"": {{ + ""messageId"": ""{expectedMessageId}"", + ""text"": ""{expectedErrorPhrase}"", + ""validationErrors"": ""{expectedErrorText}"" + }} + }} + }}"; + + var responseHeaders = new Dictionary + { + { "Server", SERVER_HEADER_VALUE_COMMA }, + { "X-Request-ID", X_REQUEST_ID_HEADER_VALUE }, + { "Content-Type", CONTENT_TYPE_HEADER_VALUE } + }; + + SetUpGetRequest(EMAIL_LOGS_ENDPOINT, expectedJson, expectedHttpCode); + + var emailApi = new EmailApi(configuration); + + try + { + var result = + emailApi.GetEmailDeliveryReports(messageId: givenMessageId, bulkId: givenBulkId, limit: givenLimit); + } + catch (ApiException ex) + { + Assert.AreEqual(expectedHttpCode, ex.ErrorCode); + Assert.AreEqual(expectedJson, ex.ErrorContent); + Assert.IsInstanceOfType(ex, typeof(ApiException)); + Assert.IsTrue(ex.Message.Contains(expectedErrorPhrase)); + Assert.IsTrue(ex.ErrorContent.ToString()?.Contains(expectedMessageId) == true); + Assert.IsTrue(ex.ErrorContent.ToString()?.Contains(expectedErrorText) == true); + Assert.IsTrue(responseHeaders.All(h => + ex.Headers.ContainsKey(h.Key) && ex.Headers[h.Key].First().Equals(h.Value))); + } + } +} \ No newline at end of file diff --git a/ApiClient.Tests/Api/SmsApiTest.cs b/ApiClient.Tests/Api/SmsApiTest.cs new file mode 100644 index 0000000..fdd3259 --- /dev/null +++ b/ApiClient.Tests/Api/SmsApiTest.cs @@ -0,0 +1,1325 @@ +using System.Globalization; +using Infobip.Api.Client.Api; +using Infobip.Api.Client.Model; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json; + +namespace ApiClient.Tests.Api; + +[TestClass] +public class SmsApiTest : ApiTest +{ + protected const string SMS_SEND_TEXT_ADVANCED_ENDPOINT = "/sms/2/text/advanced"; + protected const string SMS_SEND_BINARY_ADVANCED_ENDPOINT = "/sms/2/binary/advanced"; + protected const string SMS_LOGS_ENDPOINT = "/sms/1/logs"; + protected const string SMS_REPORTS_ENDPOINT = "/sms/1/reports"; + protected const string SMS_INBOX_REPORTS_ENDPOINT = "/sms/1/inbox/reports"; + protected const string SMS_SEND_PREVIEW_ENDPOINT = "/sms/1/preview"; + protected const string SMS_BULKS_ENDPOINT = "/sms/1/bulks"; + protected const string SMS_BULKS_STATUS_ENDPOINT = "/sms/1/bulks/status"; + + protected const int PENDING_STATUS_GROUP_ID = 1; + protected const string PENDING_STATUS_GROUP_NAME = "PENDING"; + protected const int PENDING_STATUS_ID = 26; + protected const string PENDING_STATUS_NAME = "MESSAGE_ACCEPTED"; + protected const string PENDING_STATUS_DESCRIPTION = "Message sent to next instance"; + + protected const int DELIVERED_STATUS_GROUP_ID = 3; + protected const string DELIVERED_STATUS_GROUP_NAME = "DELIVERED"; + protected const int DELIVERED_STATUS_ID = 5; + protected const string DELIVERED_STATUS_NAME = "DELIVERED_TO_HANDSET"; + protected const string DELIVERED_STATUS_DESCRIPTION = "Message delivered to handset"; + + protected const int NO_ERROR_GROUP_ID = 0; + protected const string NO_ERROR_GROUP_NAME = "Ok"; + protected const int NO_ERROR_ID = 0; + protected const string NO_ERROR_NAME = "NO_ERROR"; + protected const string NO_ERROR_DESCRIPTION = "No Error"; + protected const bool NO_ERROR_IS_PERMANENT = false; + + [TestMethod] + public void ShouldSendSimpleSms() + { + var givenFlash = false; + var givenFrom = "InfoSMS"; + var givenIntermediateReport = false; + var givenText = "This is a sample message"; + var givenIncludeSmsCountInResponse = false; + + var expectedTo = "41793026727"; + var expectedMessageId = "This is a sample message"; + var expectedBulkId = "2034072219640523072"; + + var givenRequest = $@" + {{ + ""messages"": [ + {{ + ""destinations"": [ + {{ + ""to"": ""{expectedTo}"" + }} + ], + ""flash"":{givenFlash.ToString().ToLower()}, + ""from"": ""{givenFrom}"", + ""intermediateReport"":{givenIntermediateReport.ToString().ToLower()}, + ""text"": ""{givenText}"" + }} + ], + ""includeSmsCountInResponse"":{givenIncludeSmsCountInResponse.ToString().ToLower()} + }}"; + + var expectedResponse = PreparePendingResponse(expectedBulkId, expectedTo, expectedMessageId); + + SetUpPostRequest(SMS_SEND_TEXT_ADVANCED_ENDPOINT, givenRequest, expectedResponse, 200); + + var smsApi = new SmsApi(configuration); + + var destination = new SmsDestination(to: expectedTo); + + var smsMessage = new SmsTextualMessage( + from: givenFrom, + destinations: new List { destination }, + text: givenText + ); + + var smsRequest = new SmsAdvancedTextualRequest( + messages: new List { smsMessage } + ); + + void SmsResponseAssertion(SmsResponse smsResponse) + { + Assert.IsNotNull(smsResponse); + Assert.AreEqual(expectedBulkId, smsResponse.BulkId); + Assert.AreEqual(1, smsResponse.Messages.Count); + Assert.AreEqual(expectedMessageId, smsResponse.Messages[0].MessageId); + Assert.AreEqual(expectedTo, smsResponse.Messages[0].To); + + AssertPendingSmsResponse(smsResponse.Messages[0]); + } + + AssertResponse(smsApi.SendSmsMessage(smsRequest), SmsResponseAssertion); + AssertResponse(smsApi.SendSmsMessageAsync(smsRequest).Result, SmsResponseAssertion); + + AssertResponseWithHttpInfo(smsApi.SendSmsMessageWithHttpInfo(smsRequest), SmsResponseAssertion); + AssertResponseWithHttpInfo(smsApi.SendSmsMessageWithHttpInfoAsync(smsRequest).Result, SmsResponseAssertion); + } + + + [TestMethod] + public void ShouldSendFlashSms() + { + var givenFlash = false; + var givenFrom = "InfoSMS"; + var givenIntermediateReport = false; + var givenText = "This is a sample message"; + var givenIncludeSmsCountInResponse = false; + + var expectedTo = "41793026727"; + var expectedMessageId = "This is a sample message"; + var expectedBulkId = "2034072219640523072"; + + var givenRequest = $@" + {{ + ""messages"": [ + {{ + ""destinations"": [ + {{ + ""to"": ""{expectedTo}"" + }} + ], + ""flash"":{givenFlash.ToString().ToLower()}, + ""from"": ""{givenFrom}"", + ""intermediateReport"":{givenIntermediateReport.ToString().ToLower()}, + ""text"": ""{givenText}"" + }} + ], + ""includeSmsCountInResponse"": {givenIncludeSmsCountInResponse.ToString().ToLower()} + }}"; + + var expectedResponse = PreparePendingResponse(expectedBulkId, expectedTo, expectedMessageId); + + SetUpPostRequest(SMS_SEND_TEXT_ADVANCED_ENDPOINT, givenRequest, expectedResponse, 200); + + var smsApi = new SmsApi(configuration); + + var destination = new SmsDestination(to: expectedTo); + + var smsMessage = new SmsTextualMessage( + from: givenFrom, + destinations: new List { destination }, + text: givenText, + flash: givenFlash + ); + + var smsRequest = new SmsAdvancedTextualRequest( + messages: new List { smsMessage } + ); + + void SmsResponseAssertion(SmsResponse smsResponse) + { + Assert.IsNotNull(smsResponse); + Assert.AreEqual(expectedBulkId, smsResponse.BulkId); + Assert.AreEqual(1, smsResponse.Messages.Count); + Assert.AreEqual(expectedMessageId, smsResponse.Messages[0].MessageId); + Assert.AreEqual(expectedTo, smsResponse.Messages[0].To); + + AssertPendingSmsResponse(smsResponse.Messages[0]); + } + + AssertResponse(smsApi.SendSmsMessage(smsRequest), SmsResponseAssertion); + AssertResponse(smsApi.SendSmsMessageAsync(smsRequest).Result, SmsResponseAssertion); + + AssertResponseWithHttpInfo(smsApi.SendSmsMessageWithHttpInfo(smsRequest), SmsResponseAssertion); + AssertResponseWithHttpInfo(smsApi.SendSmsMessageWithHttpInfoAsync(smsRequest).Result, SmsResponseAssertion); + } + + [TestMethod] + public void ShouldSendFullyFeaturedSmsMessage() + { + var expectedTo1 = "41793026727"; + var expectedMessageId1 = "MESSAGE-ID-123-xyz"; + var expectedAnotherTo1 = "41793026834"; + var givenFrom1 = "InfoSMS"; + var givenText1 = + "Artık Ulusal Dil Tanımlayıcısı ile Türkçe karakterli smslerinizi rahatlıkla iletebilirsiniz."; + var givenFlash1 = false; + var givenLanguageCode1 = "TR"; + var givenTransliteration1 = "TURKISH"; + var givenIntermediateReport1 = true; + var givenNotifyUrl1 = "https://www.example.com/sms/advanced"; + var givenNotifyContentType1 = "application/json"; + var givenCallbackData1 = "DLR callback data"; + var givenValidityPeriod1 = 720L; + + var givenMessage1 = $@" + {{ + ""destinations"": [ + {{ + ""to"": ""{expectedTo1}"", + ""messageId"": ""{expectedMessageId1}"" + }}, + {{ + ""to"": ""{expectedAnotherTo1}"" + }} + ], + ""flash"": {givenFlash1.ToString().ToLower()}, + ""from"": ""{givenFrom1}"", + ""intermediateReport"": {givenIntermediateReport1.ToString().ToLower()}, + ""text"": ""{givenText1}"", + ""language"": {{ + ""languageCode"": ""{givenLanguageCode1}"" + }}, + ""transliteration"": ""{givenTransliteration1}"", + ""notifyUrl"": ""{givenNotifyUrl1}"", + ""notifyContentType"": ""{givenNotifyContentType1}"", + ""callbackData"": ""{givenCallbackData1}"", + ""validityPeriod"": {givenValidityPeriod1} + }}"; + + var expectedTo2 = "41793026700"; + var expectedMessageId2 = "2033247207850523792"; + var givenFlash2 = false; + var givenFrom2 = "41793026700"; + var givenIntermediateReport2 = false; + var givenText2 = "A long time ago, in a galaxy far, far away..."; + var givenSendAt2 = "2021-08-25T16:10:00.000+05:30"; + var givenDeliveryTimeFromHour2 = 6; + var givenDeliveryTimeFromMinute2 = 0; + var givenDeliveryTimeToHour2 = 15; + var givenDeliveryTimeToMinute2 = 30; + var givenDay1 = "MONDAY"; + var givenDay2 = "TUESDAY"; + var givenDay3 = "WEDNESDAY"; + var givenContentTemplateId2 = "contentTemplateId"; + var givenPrincipalEntityId2 = "expectedPrincipalEntityId"; + + var givenMessage2 = $@" + {{ + ""destinations"": [ + {{ + ""to"": ""{expectedTo2}"", + ""messageId"": ""{expectedMessageId2}"", + }} + ], + ""flash"": {givenFlash2.ToString().ToLower()}, + ""from"": ""{givenFrom2}"", + ""intermediateReport"": {givenIntermediateReport2.ToString().ToLower()}, + ""text"": ""{givenText2}"", + ""sendAt"": ""{givenSendAt2}"", + ""deliveryTimeWindow"": {{ + ""from"": {{ + ""hour"": {givenDeliveryTimeFromHour2} + }}, + ""to"": {{ + ""hour"": {givenDeliveryTimeToHour2}, + ""minute"": {givenDeliveryTimeToMinute2} + }}, + ""days"": [ + ""{givenDay1}"", + ""{givenDay2}"", + ""{givenDay3}"" + ] + }}, + ""regional"": {{ + ""indiaDlt"": {{ + ""contentTemplateId"": ""{givenContentTemplateId2}"", + ""principalEntityId"": ""{givenPrincipalEntityId2}"" + }} + }} + }}"; + + var givenBulkId = "BULK-ID-123-xyz"; + var givenTracking = "SMS"; + var givenTrackingType = "MY_CAMPAIGN"; + var givenSendingSpeedLimitAmount = 10; + var givenSendingSpeedLimitTimeUnitString = "HOUR"; + var givenIncludeSmsCountInResponse = false; + + var givenRequest = $@" + {{ + ""messages"": [ + {givenMessage1}, + {givenMessage2} + ], + ""bulkId"": ""{givenBulkId}"", + ""tracking"": {{ + ""track"": ""{givenTracking}"", + ""type"": ""{givenTrackingType}"" + }}, + ""sendingSpeedLimit"": {{ + ""amount"": {givenSendingSpeedLimitAmount}, + ""timeUnit"": ""{givenSendingSpeedLimitTimeUnitString}"" + }}, + ""includeSmsCountInResponse"":{givenIncludeSmsCountInResponse.ToString().ToLower()} + }}"; + + var expectedResponse = PreparePendingResponse(givenBulkId, expectedTo1, expectedMessageId1, + expectedTo2, expectedMessageId2); + SetUpPostRequest(SMS_SEND_TEXT_ADVANCED_ENDPOINT, givenRequest, expectedResponse, 200); + + var smsApi = new SmsApi(configuration); + + var destination1 = new SmsDestination(expectedMessageId1, expectedTo1); + var anotherDestination1 = new SmsDestination(to: expectedAnotherTo1); + + var destination2 = new SmsDestination(expectedMessageId2, expectedTo2); + + var smsMessage1 = new SmsTextualMessage( + from: givenFrom1, + destinations: new List { destination1, anotherDestination1 }, + text: givenText1, + flash: givenFlash1, + language: new SmsLanguage(givenLanguageCode1), + transliteration: givenTransliteration1, + intermediateReport: givenIntermediateReport1, + notifyUrl: givenNotifyUrl1, + notifyContentType: givenNotifyContentType1, + callbackData: givenCallbackData1, + validityPeriod: givenValidityPeriod1 + ); + + var smsMessage2 = new SmsTextualMessage( + from: givenFrom2, + destinations: new List { destination2 }, + text: givenText2, + sendAt: DateTimeOffset.Parse(givenSendAt2), + deliveryTimeWindow: new SmsDeliveryTimeWindow( + new List { SmsDeliveryDay.Monday, SmsDeliveryDay.Tuesday, SmsDeliveryDay.Wednesday }, + new SmsDeliveryTimeFrom(givenDeliveryTimeFromHour2, givenDeliveryTimeFromMinute2), + new SmsDeliveryTimeTo(givenDeliveryTimeToHour2, givenDeliveryTimeToMinute2) + ), + regional: new SmsRegionalOptions( + new SmsIndiaDltOptions(givenContentTemplateId2, givenPrincipalEntityId2) + ) + ); + + var smsRequest = new SmsAdvancedTextualRequest( + messages: new List { smsMessage1, smsMessage2 }, + bulkId: givenBulkId, + tracking: new SmsTracking( + track: givenTracking, + type: givenTrackingType + ), + sendingSpeedLimit: new SmsSendingSpeedLimit( + givenSendingSpeedLimitAmount, + SmsSpeedLimitTimeUnit.Hour + ) + ); + + void SmsResponseAssertion(SmsResponse smsResponse) + { + Assert.IsNotNull(smsResponse); + Assert.AreEqual(givenBulkId, smsResponse.BulkId); + Assert.AreEqual(2, smsResponse.Messages.Count); + + Assert.AreEqual(expectedMessageId1, smsResponse.Messages[0].MessageId); + Assert.AreEqual(expectedTo1, smsResponse.Messages[0].To); + + Assert.AreEqual(expectedMessageId2, smsResponse.Messages[1].MessageId); + Assert.AreEqual(expectedTo2, smsResponse.Messages[1].To); + + AssertPendingSmsResponse(smsResponse.Messages[0]); + AssertPendingSmsResponse(smsResponse.Messages[1]); + } + + AssertResponse(smsApi.SendSmsMessage(smsRequest), SmsResponseAssertion); + AssertResponse(smsApi.SendSmsMessageAsync(smsRequest).Result, SmsResponseAssertion); + + AssertResponseWithHttpInfo(smsApi.SendSmsMessageWithHttpInfo(smsRequest), SmsResponseAssertion); + AssertResponseWithHttpInfo(smsApi.SendSmsMessageWithHttpInfoAsync(smsRequest).Result, SmsResponseAssertion); + } + + [TestMethod] + public void ShouldSendFullyFeaturedBinaryMessage() + { + var expectedTo1 = "41793026727"; + var expectedMessageId1 = "MESSAGE-ID-123-xyz"; + var expectedAnotherTo1 = "41793026834"; + var givenFlash1 = false; + var givenFrom1 = "InfoSMS"; + var givenIntermediateReport1 = true; + var givenHex1 = "54 65 73 74 20 6d 65 73 73 61 67 65 2e"; + var givenDataCoding1 = 0; + var givenEsmClass1 = 0; + var givenNotifyUrl1 = "https://www.example.com/sms/advanced"; + var givenNotifyContentType1 = "application/json"; + var givenCallbackData1 = "DLR callback data"; + var givenValidityPeriod1 = 720L; + + var givenMessage1 = $@" + {{ + ""destinations"": [ + {{ + ""to"": ""{expectedTo1}"", + ""messageId"": ""{expectedMessageId1}"" + }}, + {{ + ""to"": ""{expectedAnotherTo1}"" + }} + ], + ""flash"": {givenFlash1.ToString().ToLower()}, + ""from"": ""{givenFrom1}"", + ""intermediateReport"": {givenIntermediateReport1.ToString().ToLower()}, + ""binary"": {{ + ""hex"": ""{givenHex1}"" + }}, + ""notifyUrl"": ""{givenNotifyUrl1}"", + ""notifyContentType"": ""{givenNotifyContentType1}"", + ""callbackData"": ""{givenCallbackData1}"", + ""validityPeriod"": {givenValidityPeriod1} + }}"; + + var expectedTo2 = "41793026700"; + var expectedMessageId2 = "2033247207850523792"; + var givenFlash2 = false; + var givenFrom2 = "41793026700"; + var givenIntermediateReport2 = false; + var givenHex2 = "54 65 73 74 20 6d 65 73 73 61 67 65 2e"; + var givenDataCoding2 = 0; + var givenEsmClass2 = 0; + var givenSendAt2 = "2021-08-25T16:10:00.000+05:00"; + var givenDeliveryTimeFromHour2 = 6; + var givenDeliveryTimeFromMinute2 = 0; + var givenDeliveryTimeToHour2 = 15; + var givenDeliveryTimeToMinute2 = 30; + var givenDay1 = "MONDAY"; + var givenDay2 = "TUESDAY"; + var givenDay3 = "WEDNESDAY"; + var givenContentTemplateId2 = "contentTemplateId"; + var givenPrincipalEntityId2 = "givenPrincipalEntityId"; + + var givenMessage2 = $@" + {{ + ""destinations"": [ + {{ + ""to"": ""{expectedTo2}"", + ""messageId"": ""{expectedMessageId2}"" + }} + ], + ""flash"": {givenFlash2.ToString().ToLower()}, + ""from"": ""{givenFrom2}"", + ""intermediateReport"": {givenIntermediateReport2.ToString().ToLower()}, + ""binary"": {{ + ""hex"": ""{givenHex2}"" + }}, + ""sendAt"": ""{givenSendAt2}"", + ""deliveryTimeWindow"": {{ + ""from"": {{ + ""hour"": {givenDeliveryTimeFromHour2} + }}, + ""to"": {{ + ""hour"": {givenDeliveryTimeToHour2}, + ""minute"": {givenDeliveryTimeToMinute2} + }}, + ""days"": [ + ""{givenDay1}"", + ""{givenDay2}"", + ""{givenDay3}"" + ] + }}, + ""regional"": {{ + ""indiaDlt"": {{ + ""contentTemplateId"": ""{givenContentTemplateId2}"", + ""principalEntityId"": ""{givenPrincipalEntityId2}"" + }} + }} + }}"; + + var givenBulkId = "BULK-ID-123-xyz"; + var givenSendingSpeedLimitAmount = 10; + var givenSendingSpeedLimitTimeUnitString = "HOUR"; + + var givenRequest = $@" + {{ + ""messages"": [ + {givenMessage1}, + {givenMessage2} + ], + ""bulkId"": ""{givenBulkId}"", + ""sendingSpeedLimit"": {{ + ""amount"": {givenSendingSpeedLimitAmount}, + ""timeUnit"": ""{givenSendingSpeedLimitTimeUnitString}"" + }} + }}"; + + var expectedResponse = PreparePendingResponse(givenBulkId, expectedTo1, expectedMessageId1, + expectedTo2, expectedMessageId2); + SetUpPostRequest(SMS_SEND_BINARY_ADVANCED_ENDPOINT, givenRequest, expectedResponse, 200); + + var smsApi = new SmsApi(configuration); + + var destination1 = new SmsDestination(expectedMessageId1, expectedTo1); + var anotherDestination1 = new SmsDestination(to: expectedAnotherTo1); + + var destination2 = new SmsDestination(expectedMessageId2, expectedTo2); + + var smsMessage1 = new SmsBinaryMessage( + from: givenFrom1, + destinations: new List { destination1, anotherDestination1 }, + binary: new SmsBinaryContent + ( + hex: givenHex1, + dataCoding: givenDataCoding1, + esmClass: givenEsmClass1 + ), + intermediateReport: givenIntermediateReport1, + notifyUrl: givenNotifyUrl1, + notifyContentType: givenNotifyContentType1, + callbackData: givenCallbackData1, + validityPeriod: givenValidityPeriod1 + ); + + var smsMessage2 = new SmsBinaryMessage( + from: givenFrom2, + destinations: new List { destination2 }, + binary: new SmsBinaryContent + ( + hex: givenHex2, + dataCoding: givenDataCoding2, + esmClass: givenEsmClass2 + ), + sendAt: DateTimeOffset.Parse(givenSendAt2), + deliveryTimeWindow: new SmsDeliveryTimeWindow( + new List { SmsDeliveryDay.Monday, SmsDeliveryDay.Tuesday, SmsDeliveryDay.Wednesday }, + new SmsDeliveryTimeFrom(givenDeliveryTimeFromHour2, givenDeliveryTimeFromMinute2), + new SmsDeliveryTimeTo(givenDeliveryTimeToHour2, givenDeliveryTimeToMinute2) + ), + regional: new SmsRegionalOptions( + new SmsIndiaDltOptions(givenContentTemplateId2, givenPrincipalEntityId2) + ) + ); + + var smsRequest = new SmsAdvancedBinaryRequest + ( + messages: new List { smsMessage1, smsMessage2 }, + bulkId: givenBulkId, + sendingSpeedLimit: new SmsSendingSpeedLimit + { + Amount = givenSendingSpeedLimitAmount, + TimeUnit = SmsSpeedLimitTimeUnit.Hour + } + ); + + void SmsResponseAssertion(SmsResponse smsResponse) + { + Assert.IsNotNull(smsResponse); + Assert.AreEqual(givenBulkId, smsResponse.BulkId); + Assert.AreEqual(2, smsResponse.Messages.Count); + + Assert.AreEqual(expectedMessageId1, smsResponse.Messages[0].MessageId); + Assert.AreEqual(expectedTo1, smsResponse.Messages[0].To); + + Assert.AreEqual(expectedMessageId2, smsResponse.Messages[1].MessageId); + Assert.AreEqual(expectedTo2, smsResponse.Messages[1].To); + + AssertPendingSmsResponse(smsResponse.Messages[0]); + AssertPendingSmsResponse(smsResponse.Messages[1]); + } + + AssertResponse(smsApi.SendBinarySmsMessage(smsRequest), SmsResponseAssertion); + AssertResponse(smsApi.SendBinarySmsMessageAsync(smsRequest).Result, SmsResponseAssertion); + + AssertResponseWithHttpInfo(smsApi.SendBinarySmsMessageWithHttpInfo(smsRequest), SmsResponseAssertion); + AssertResponseWithHttpInfo(smsApi.SendBinarySmsMessageWithHttpInfoAsync(smsRequest).Result, + SmsResponseAssertion); + } + + [TestMethod] + public void ShouldSendFlashBinarySms() + { + var expectedBulkId = "2034072219640523072"; + var expectedMessageId = "2250be2d4219-3af1-78856-aabe-1362af1edfd2"; + var expectedTo = "41793026727"; + + var givenFrom = "InfoSMS"; + var givenIntermediateReport = false; + var givenHex = + "0048 0065 006c 006c 006f 0020 0077 006f 0072 006c 0064 002c 0020 039a 03b1 03bb 03b7 03bc 03ad 03c1 03b1 0020 03ba 03cc 03c3 03bc 03b5 002c 0020 30b3 30f3 30cb 30c1 30cf"; + var givenFlash = true; + + var givenRequest = $@" + {{ + ""messages"": [ + {{ + ""destinations"": [ + {{ + ""to"": ""{expectedTo}"" + }} + ], + ""flash"": {givenFlash.ToString().ToLower()}, + ""from"": ""{givenFrom}"", + ""intermediateReport"": {givenIntermediateReport.ToString().ToLower()}, + ""binary"": {{ + ""hex"": ""{givenHex}"" + }} + }} + ] + }}"; + + var expectedResponse = PreparePendingResponse(expectedBulkId, expectedTo, expectedMessageId); + SetUpPostRequest(SMS_SEND_BINARY_ADVANCED_ENDPOINT, givenRequest, expectedResponse, 200); + + var smsApi = new SmsApi(configuration); + + var binaryMessage = new SmsBinaryMessage( + from: givenFrom, + destinations: new List { new(to: expectedTo) }, + binary: new SmsBinaryContent(hex: givenHex), + flash: givenFlash + ); + + var smsRequest = new SmsAdvancedBinaryRequest + ( + messages: new List { binaryMessage } + ); + + void SmsResponseAssertion(SmsResponse smsResponse) + { + Assert.IsNotNull(smsResponse); + Assert.AreEqual(expectedBulkId, smsResponse.BulkId); + Assert.AreEqual(1, smsResponse.Messages.Count); + + Assert.AreEqual(expectedMessageId, smsResponse.Messages[0].MessageId); + Assert.AreEqual(expectedTo, smsResponse.Messages[0].To); + + AssertPendingSmsResponse(smsResponse.Messages[0]); + } + + AssertResponse(smsApi.SendBinarySmsMessage(smsRequest), SmsResponseAssertion); + AssertResponse(smsApi.SendBinarySmsMessageAsync(smsRequest).Result, SmsResponseAssertion); + + AssertResponseWithHttpInfo(smsApi.SendBinarySmsMessageWithHttpInfo(smsRequest), SmsResponseAssertion); + AssertResponseWithHttpInfo(smsApi.SendBinarySmsMessageWithHttpInfoAsync(smsRequest).Result, + SmsResponseAssertion); + } + + [TestMethod] + public void ShouldGetSmsLogs() + { + var expectedBulkId = "BULK-ID-123-xyz"; + var expectedMessageIdMessage1 = "MESSAGE-ID-123-xyz"; + var expectedToMessage1 = "41793026727"; + var expectedSendAtMessage1 = "2019-11-09T16:00:00.000+0530"; + var expectedDoneAtMessage1 = "2019-11-09T16:00:00.000+0530"; + var expectedSmsCountMessage1 = 1; + var expectedPricePerMessageMessage1 = "0.01"; + var expectedCurrencyMessage1 = "EUR"; + + var expectedMessageIdMessage2 = "12db39c3-7822-4e72-a3ec-c87442c0ffc5"; + var expectedToMessage2 = "41793026834"; + var expectedSendAtMessage2 = "2019-11-09T17:00:00.000+0000"; + var expectedDoneAtMessage2 = "2019-11-09T17:00:00.000+0000"; + var expectedSmsCountMessage2 = 5; + var expectedPricePerMessageMessage2 = "0.05"; + var expectedCurrencyMessage2 = "HRK"; + + var expectedResponse = $@" + {{ + ""results"": [ + {{ + ""bulkId"": ""{expectedBulkId}"", + ""messageId"": ""{expectedMessageIdMessage1}"", + ""to"": ""{expectedToMessage1}"", + ""sentAt"": ""{expectedSendAtMessage1}"", + ""doneAt"": ""{expectedDoneAtMessage1}"", + ""smsCount"": {expectedSmsCountMessage1}, + ""price"": + {{ + ""pricePerMessage"": {expectedPricePerMessageMessage1}, + ""currency"": ""{expectedCurrencyMessage1}"" + }}, + ""status"": + {{ + ""groupId"": {DELIVERED_STATUS_GROUP_ID}, + ""groupName"": ""{DELIVERED_STATUS_GROUP_NAME}"", + ""id"": {DELIVERED_STATUS_ID}, + ""name"": ""{DELIVERED_STATUS_NAME}"", + ""description"": ""{DELIVERED_STATUS_DESCRIPTION}"" + + }}, + ""error"": + {{ + ""groupId"": {NO_ERROR_GROUP_ID}, + ""groupName"": ""{NO_ERROR_GROUP_NAME}"", + ""id"": {NO_ERROR_ID}, + ""name"": ""{NO_ERROR_NAME}"", + ""description"": ""{NO_ERROR_DESCRIPTION}"", + ""permanent"": {NO_ERROR_IS_PERMANENT.ToString().ToLower()} + }} + }}, + {{ + ""bulkId"": ""{expectedBulkId}"", + ""messageId"": ""{expectedMessageIdMessage2}"", + ""to"": ""{expectedToMessage2}"", + ""sentAt"": ""{expectedSendAtMessage2}"", + ""doneAt"": ""{expectedDoneAtMessage2}"", + ""smsCount"": {expectedSmsCountMessage2}, + ""price"": + {{ + ""pricePerMessage"": {expectedPricePerMessageMessage2}, + ""currency"": ""{expectedCurrencyMessage2}"" + }}, + ""status"": + {{ + ""groupId"": {DELIVERED_STATUS_GROUP_ID}, + ""groupName"": ""{DELIVERED_STATUS_GROUP_NAME}"", + ""id"": {DELIVERED_STATUS_ID}, + ""name"": ""{DELIVERED_STATUS_NAME}"", + ""description"": ""{DELIVERED_STATUS_DESCRIPTION}"" + + }}, + ""error"": + {{ + ""groupId"": {NO_ERROR_GROUP_ID}, + ""groupName"": ""{NO_ERROR_GROUP_NAME}"", + ""id"": {NO_ERROR_ID}, + ""name"": ""{NO_ERROR_NAME}"", + ""description"": ""{NO_ERROR_DESCRIPTION}"", + ""permanent"": {NO_ERROR_IS_PERMANENT.ToString().ToLower()} + }} + }} + ] + }}"; + + var givenSentSinceString = "2015-02-22T17:42:05.390+0100"; + var searchParams = new Dictionary + { + { "bulkId", expectedBulkId }, + { "sentSince", givenSentSinceString } + }; + + SetUpGetRequest(SMS_LOGS_ENDPOINT, searchParams, expectedResponse, 200); + + void LogsResponseAssertion(SmsLogsResponse logsResponse) + { + Assert.IsNotNull(logsResponse); + List results = logsResponse.Results; + Assert.IsNotNull(results); + Assert.AreEqual(2, results.Count); + + Assert.AreEqual(expectedBulkId, results[0].BulkId); + Assert.AreEqual(expectedMessageIdMessage1, results[0].MessageId); + Assert.AreEqual(expectedToMessage1, results[0].To); + Assert.AreEqual(DateTimeOffset.Parse(expectedSendAtMessage1), results[0].SentAt); + Assert.AreEqual(DateTimeOffset.Parse(expectedDoneAtMessage1), results[0].DoneAt); + Assert.IsNull(results[0].From); + Assert.IsNull(results[0].Text); + Assert.IsNull(results[0].MccMnc); + Assert.AreEqual(decimal.Parse(expectedPricePerMessageMessage1, CultureInfo.InvariantCulture), + results[0].Price.PricePerMessage); + Assert.AreEqual(expectedCurrencyMessage1, results[0].Price.Currency); + AssertDeliveredSmsStatus(results[0].Status); + AssertNoError(results[0].Error); + + Assert.AreEqual(expectedBulkId, results[1].BulkId); + Assert.AreEqual(expectedMessageIdMessage2, results[1].MessageId); + Assert.AreEqual(expectedToMessage2, results[1].To); + Assert.AreEqual(DateTimeOffset.Parse(expectedSendAtMessage2), results[1].SentAt); + Assert.AreEqual(DateTimeOffset.Parse(expectedDoneAtMessage2), results[1].DoneAt); + Assert.IsNull(results[1].From); + Assert.IsNull(results[1].Text); + Assert.IsNull(results[1].MccMnc); + Assert.AreEqual(decimal.Parse(expectedPricePerMessageMessage2, CultureInfo.InvariantCulture), + results[1].Price.PricePerMessage); + Assert.AreEqual(expectedCurrencyMessage2, results[1].Price.Currency); + AssertDeliveredSmsStatus(results[1].Status); + AssertNoError(results[1].Error); + } + + var smsApi = new SmsApi(configuration); + + AssertResponse + ( + smsApi.GetOutboundSmsMessageLogs + ( + sentSince: DateTimeOffset.Parse(givenSentSinceString), + bulkId: new List { expectedBulkId } + ), + LogsResponseAssertion + ); + AssertResponse + ( + smsApi.GetOutboundSmsMessageLogsAsync + ( + sentSince: DateTimeOffset.Parse(givenSentSinceString), + bulkId: new List { expectedBulkId } + ).Result, + LogsResponseAssertion + ); + AssertResponseWithHttpInfo + ( + smsApi.GetOutboundSmsMessageLogsWithHttpInfo + ( + sentSince: DateTimeOffset.Parse(givenSentSinceString), + bulkId: new List { expectedBulkId } + ), + LogsResponseAssertion + ); + AssertResponseWithHttpInfo + ( + smsApi.GetOutboundSmsMessageLogsWithHttpInfoAsync + ( + sentSince: DateTimeOffset.Parse(givenSentSinceString), + bulkId: new List { expectedBulkId } + ).Result, + LogsResponseAssertion + ); + } + + [TestMethod] + public void ShouldGetSmsReports() + { + var expectedBulkId = "BULK-ID-123-xyz"; + var expectedMessageId1 = "MESSAGE-ID-123-xyz"; + var expectedTo1 = "41793026727"; + var expectedSentAt1 = "2019-11-09T16:00:00.000+0000"; + var expectedDoneAt1 = "2019-11-09T16:00:00.000+0000"; + var expectedSmsCount = 1; + var expectedPricePerMessage = "0.01"; + var expectedCurrency = "EUR"; + var expectedEntityId = "promotional-traffic-entity"; + var expectedApplicationId1 = "marketing-automation-application"; + + var expectedMessageId2 = "12db39c3-7822-4e72-a3ec-c87442c0ffc5"; + var expectedTo2 = "41793026834"; + var expectedSentAt2 = "2019-11-09T17:00:00.000+0000"; + var expectedDoneAt2 = "2019-11-09T17:00:00.000+0000"; + var expectedApplicationId2 = "default"; + + var expectedResponse = $@" + {{ + ""results"": [ + {{ + ""bulkId"": ""{expectedBulkId}"", + ""messageId"": ""{expectedMessageId1}"", + ""to"": ""{expectedTo1}"", + ""sentAt"": ""{expectedSentAt1}"", + ""doneAt"": ""{expectedDoneAt1}"", + ""smsCount"": {expectedSmsCount}, + ""price"": {{ + ""pricePerMessage"": {expectedPricePerMessage}, + ""currency"": ""{expectedCurrency}"" + }}, + ""status"": {{ + ""groupId"": {DELIVERED_STATUS_GROUP_ID}, + ""groupName"": ""{DELIVERED_STATUS_GROUP_NAME}"", + ""id"": {DELIVERED_STATUS_ID}, + ""name"": ""{DELIVERED_STATUS_NAME}"", + ""description"": ""{DELIVERED_STATUS_DESCRIPTION}"" + }}, + ""error"": {{ + ""groupId"": {NO_ERROR_GROUP_ID}, + ""groupName"": ""{NO_ERROR_GROUP_NAME}"", + ""id"": {NO_ERROR_ID}, + ""name"": ""{NO_ERROR_NAME}"", + ""description"": ""{NO_ERROR_DESCRIPTION}"", + ""permanent"": {NO_ERROR_IS_PERMANENT.ToString().ToLower()} + }}, + ""entityId"": ""{expectedEntityId}"", + ""applicationId"": ""{expectedApplicationId1}"" + }}, + {{ + ""bulkId"": ""{expectedBulkId}"", + ""messageId"": ""{expectedMessageId2}"", + ""to"": ""{expectedTo2}"", + ""sentAt"": ""{expectedSentAt2}"", + ""doneAt"": ""{expectedDoneAt2}"", + ""smsCount"": {expectedSmsCount}, + ""price"": {{ + ""pricePerMessage"": {expectedPricePerMessage}, + ""currency"": ""{expectedCurrency}"" + }}, + ""status"": {{ + ""groupId"": {DELIVERED_STATUS_GROUP_ID}, + ""groupName"": ""{DELIVERED_STATUS_GROUP_NAME}"", + ""id"": {DELIVERED_STATUS_ID}, + ""name"": ""{DELIVERED_STATUS_NAME}"", + ""description"": ""{DELIVERED_STATUS_DESCRIPTION}"" + }}, + ""error"": {{ + ""groupId"": {NO_ERROR_GROUP_ID}, + ""groupName"": ""{NO_ERROR_GROUP_NAME}"", + ""id"": {NO_ERROR_ID}, + ""name"": ""{NO_ERROR_NAME}"", + ""description"": ""{NO_ERROR_DESCRIPTION}"", + ""permanent"": {NO_ERROR_IS_PERMANENT.ToString().ToLower()} + }}, + ""applicationId"": ""{expectedApplicationId2}"" + }} + ] + }}"; + + var givenLimit = 100; + + var givenQueryParameters = new Dictionary + { + { "bulkId", expectedBulkId }, + { "limit", givenLimit.ToString() } + }; + + SetUpGetRequest(SMS_REPORTS_ENDPOINT, givenQueryParameters, expectedResponse, 200); + + var smsApi = new SmsApi(configuration); + + void AssertSmsDeliveryResult(SmsDeliveryResult smsDeliveryResult) + { + Assert.IsNotNull(smsDeliveryResult); + + Assert.IsNotNull(smsDeliveryResult.Results[0]); + Assert.AreEqual(expectedBulkId, smsDeliveryResult.Results[0].BulkId); + Assert.AreEqual(expectedMessageId1, smsDeliveryResult.Results[0].MessageId); + Assert.AreEqual(expectedTo1, smsDeliveryResult.Results[0].To); + Assert.AreEqual(DateTimeOffset.Parse(expectedSentAt1), smsDeliveryResult.Results[0].SentAt); + Assert.AreEqual(DateTimeOffset.Parse(expectedDoneAt1), smsDeliveryResult.Results[0].DoneAt); + Assert.AreEqual(expectedSmsCount, smsDeliveryResult.Results[0].SmsCount); + Assert.AreEqual(decimal.Parse(expectedPricePerMessage, CultureInfo.InvariantCulture), + smsDeliveryResult.Results[0].Price.PricePerMessage); + Assert.AreEqual(expectedCurrency, smsDeliveryResult.Results[0].Price.Currency); + Assert.AreEqual(DELIVERED_STATUS_GROUP_ID, smsDeliveryResult.Results[0].Status.GroupId); + Assert.AreEqual(DELIVERED_STATUS_GROUP_NAME, smsDeliveryResult.Results[0].Status.GroupName); + Assert.AreEqual(DELIVERED_STATUS_ID, smsDeliveryResult.Results[0].Status.Id); + Assert.AreEqual(DELIVERED_STATUS_NAME, smsDeliveryResult.Results[0].Status.Name); + Assert.AreEqual(DELIVERED_STATUS_DESCRIPTION, smsDeliveryResult.Results[0].Status.Description); + Assert.AreEqual(NO_ERROR_GROUP_ID, smsDeliveryResult.Results[0].Error.GroupId); + Assert.AreEqual(NO_ERROR_GROUP_NAME, smsDeliveryResult.Results[0].Error.GroupName); + Assert.AreEqual(NO_ERROR_ID, smsDeliveryResult.Results[0].Error.Id); + Assert.AreEqual(NO_ERROR_NAME, smsDeliveryResult.Results[0].Error.Name); + Assert.AreEqual(NO_ERROR_DESCRIPTION, smsDeliveryResult.Results[0].Error.Description); + Assert.AreEqual(NO_ERROR_IS_PERMANENT, smsDeliveryResult.Results[0].Error.Permanent); + Assert.AreEqual(expectedEntityId, smsDeliveryResult.Results[0].EntityId); + Assert.AreEqual(expectedApplicationId1, smsDeliveryResult.Results[0].ApplicationId); + + Assert.IsNotNull(smsDeliveryResult.Results[1]); + Assert.AreEqual(expectedBulkId, smsDeliveryResult.Results[1].BulkId); + Assert.AreEqual(expectedMessageId2, smsDeliveryResult.Results[1].MessageId); + Assert.AreEqual(expectedTo2, smsDeliveryResult.Results[1].To); + Assert.AreEqual(smsDeliveryResult.Results[1].SentAt, DateTimeOffset.Parse(expectedSentAt2)); + Assert.AreEqual(smsDeliveryResult.Results[1].DoneAt, DateTimeOffset.Parse(expectedDoneAt2)); + Assert.AreEqual(expectedSmsCount, smsDeliveryResult.Results[1].SmsCount); + Assert.AreEqual(decimal.Parse(expectedPricePerMessage, CultureInfo.InvariantCulture), + smsDeliveryResult.Results[1].Price.PricePerMessage); + Assert.AreEqual(expectedCurrency, smsDeliveryResult.Results[1].Price.Currency); + Assert.AreEqual(DELIVERED_STATUS_GROUP_ID, smsDeliveryResult.Results[1].Status.GroupId); + Assert.AreEqual(DELIVERED_STATUS_GROUP_NAME, smsDeliveryResult.Results[1].Status.GroupName); + Assert.AreEqual(DELIVERED_STATUS_ID, smsDeliveryResult.Results[1].Status.Id); + Assert.AreEqual(DELIVERED_STATUS_NAME, smsDeliveryResult.Results[1].Status.Name); + Assert.AreEqual(DELIVERED_STATUS_DESCRIPTION, smsDeliveryResult.Results[1].Status.Description); + Assert.AreEqual(NO_ERROR_GROUP_ID, smsDeliveryResult.Results[1].Error.GroupId); + Assert.AreEqual(NO_ERROR_GROUP_NAME, smsDeliveryResult.Results[1].Error.GroupName); + Assert.AreEqual(NO_ERROR_ID, smsDeliveryResult.Results[1].Error.Id); + Assert.AreEqual(NO_ERROR_NAME, smsDeliveryResult.Results[1].Error.Name); + Assert.AreEqual(NO_ERROR_DESCRIPTION, smsDeliveryResult.Results[1].Error.Description); + Assert.AreEqual(NO_ERROR_IS_PERMANENT, smsDeliveryResult.Results[1].Error.Permanent); + Assert.AreEqual(expectedApplicationId2, smsDeliveryResult.Results[1].ApplicationId); + } + + AssertResponse(smsApi.GetOutboundSmsMessageDeliveryReports(expectedBulkId, limit: givenLimit), + AssertSmsDeliveryResult); + AssertResponse(smsApi.GetOutboundSmsMessageDeliveryReportsAsync(expectedBulkId, limit: givenLimit).Result, + AssertSmsDeliveryResult); + + AssertResponseWithHttpInfo( + smsApi.GetOutboundSmsMessageDeliveryReportsWithHttpInfo(expectedBulkId, limit: givenLimit), + AssertSmsDeliveryResult); + AssertResponseWithHttpInfo( + smsApi.GetOutboundSmsMessageDeliveryReportsWithHttpInfoAsync(expectedBulkId, limit: givenLimit).Result, + AssertSmsDeliveryResult); + } + + [TestMethod] + public void ShouldGetReceivedSmsMessages() + { + var expectedMessageId = "817790313235066447"; + var expectedFrom = "385916242493"; + var expectedTo = "385921004026"; + var expectedText = "QUIZ Correct answer is Paris"; + var expectedCleanText = "Correct answer is Paris"; + var expectedKeyword = "QUIZ"; + var expectedReceivedAt = "2021-08-25T16:10:00.000+0500"; + var expectedSmsCount = 1; + decimal expectedPricePerMessage = 0; + var expectedCurrency = "EUR"; + var expectedCallbackData = "callbackData"; + var expectedMessageCount = 1; + var expectedPendingMessageCount = 0; + + var expectedResponse = $@" + {{ + ""results"": [ + {{ + ""messageId"": ""{expectedMessageId}"", + ""from"": ""{expectedFrom}"", + ""to"": ""{expectedTo}"", + ""text"": ""{expectedText}"", + ""cleanText"": ""{expectedCleanText}"", + ""keyword"": ""{expectedKeyword}"", + ""receivedAt"": ""{expectedReceivedAt}"", + ""smsCount"": {expectedSmsCount}, + ""price"": {{ + ""pricePerMessage"": {expectedPricePerMessage}, + ""currency"": ""{expectedCurrency}"" + }}, + ""callbackData"": ""{expectedCallbackData}"" + }} + ], + ""messageCount"": {expectedMessageCount}, + ""pendingMessageCount"": {expectedPendingMessageCount} + }}"; + + var givenLimit = 2; + SetUpGetRequest(SMS_INBOX_REPORTS_ENDPOINT, + new Dictionary { { "limit", givenLimit.ToString() } }, expectedResponse, 200); + + void ResultAssertions(SmsInboundMessageResult smsInboundResult) + { + Assert.IsNotNull(smsInboundResult); + Assert.AreEqual(expectedMessageCount, smsInboundResult.MessageCount); + Assert.AreEqual(expectedPendingMessageCount, smsInboundResult.PendingMessageCount); + + Assert.AreEqual(1, smsInboundResult.Results.Count); + var message = smsInboundResult.Results[0]; + Assert.AreEqual(expectedMessageId, message.MessageId); + Assert.AreEqual(expectedFrom, message.From); + Assert.AreEqual(expectedTo, message.To); + Assert.AreEqual(expectedText, message.Text); + Assert.AreEqual(expectedCleanText, message.CleanText); + Assert.AreEqual(expectedKeyword, message.Keyword); + Assert.AreEqual(DateTimeOffset.Parse(expectedReceivedAt), message.ReceivedAt); + Assert.AreEqual(expectedSmsCount, message.SmsCount); + Assert.AreEqual(expectedPricePerMessage, message.Price.PricePerMessage); + Assert.AreEqual(expectedCurrency, message.Price.Currency); + Assert.AreEqual(expectedCallbackData, message.CallbackData); + } + + var receiveApi = new SmsApi(configuration); + + AssertResponse(receiveApi.GetInboundSmsMessages(givenLimit), ResultAssertions); + AssertResponse(receiveApi.GetInboundSmsMessagesAsync(givenLimit).Result, ResultAssertions); + + AssertResponseWithHttpInfo(receiveApi.GetInboundSmsMessagesWithHttpInfo(givenLimit), ResultAssertions); + AssertResponseWithHttpInfo(receiveApi.GetInboundSmsMessagesWithHttpInfoAsync(givenLimit).Result, + ResultAssertions); + } + + [TestMethod] + public void ShouldSendSmsPreview() + { + var givenPreviewText = "Let's see how many characters will remain unused in this message."; + + var givenRequest = $@" + {{ + ""text"": ""{givenPreviewText}"" + + }}"; + + var expectedOriginalText = "Let's see how many characters will remain unused in this message."; + var expectedTextPreview = "Let's see how many characters will remain unused in this message."; + var expectedMessageCount = 1; + var expectedCharactersRemaining = 95; + + var expectedResponse = $@" + {{ + ""originalText"": ""{expectedOriginalText}"", + ""previews"": [ + {{ + ""textPreview"": ""{expectedTextPreview}"", + ""messageCount"": ""{expectedMessageCount}"", + ""charactersRemaining"": {expectedCharactersRemaining}, + ""configuration"": {{ }} + }} + ] + }}"; + + SetUpPostRequest(SMS_SEND_PREVIEW_ENDPOINT, givenRequest, expectedResponse, 200); + + void SmsPreviewAssertions(SmsPreviewResponse response) + { + Assert.IsNotNull(response); + Assert.AreEqual(expectedOriginalText, response.OriginalText); + Assert.AreEqual(1, response.Previews.Count); + var preview = response.Previews[0]; + Assert.AreEqual(expectedTextPreview, preview.TextPreview); + Assert.AreEqual(expectedMessageCount, preview.MessageCount); + Assert.AreEqual(expectedCharactersRemaining, preview.CharactersRemaining); + Assert.AreEqual(expectedOriginalText, response.OriginalText); + var smsLanguage = preview.VarConfiguration; + Assert.IsNotNull(smsLanguage); + Assert.IsNull(smsLanguage.Language); + Assert.IsNull(smsLanguage.Transliteration); + } + + var sendSmsApi = new SmsApi(configuration); + var request = new SmsPreviewRequest(expectedTextPreview); + + AssertResponse(sendSmsApi.PreviewSmsMessage(request), SmsPreviewAssertions); + AssertResponse(sendSmsApi.PreviewSmsMessageAsync(request).Result, SmsPreviewAssertions); + AssertResponseWithHttpInfo(sendSmsApi.PreviewSmsMessageWithHttpInfo(request), SmsPreviewAssertions); + AssertResponseWithHttpInfo(sendSmsApi.PreviewSmsMessageWithHttpInfoAsync(request).Result, SmsPreviewAssertions); + } + + [TestMethod] + public void ShouldGetScheduledSmsMessages() + { + var expectedBulkId = "BULK-ID-123-xyz"; + var expectedSendAt = "2021-02-22T17:42:05.390+0100"; + + var expectedResponse = $@" + {{ + ""bulkId"": ""{expectedBulkId}"", + ""sendAt"": ""{expectedSendAt}"" + }}"; + + SetUpGetRequest(SMS_BULKS_ENDPOINT, new Dictionary { { "bulkId", expectedBulkId } }, + expectedResponse, 200); + + void BulkResponseAssertions(SmsBulkResponse response) + { + Assert.IsNotNull(response); + Assert.AreEqual(expectedBulkId, response.BulkId); + Assert.AreEqual(DateTimeOffset.Parse(expectedSendAt), response.SendAt); + } + + var scheduledSmsApi = new SmsApi(configuration); + + AssertResponse(scheduledSmsApi.GetScheduledSmsMessages(expectedBulkId), BulkResponseAssertions); + AssertResponse(scheduledSmsApi.GetScheduledSmsMessagesAsync(expectedBulkId).Result, BulkResponseAssertions); + AssertResponseWithHttpInfo(scheduledSmsApi.GetScheduledSmsMessagesWithHttpInfo(expectedBulkId), + BulkResponseAssertions); + AssertResponseWithHttpInfo(scheduledSmsApi.GetScheduledSmsMessagesWithHttpInfoAsync(expectedBulkId).Result, + BulkResponseAssertions); + } + + [TestMethod] + public void ShouldRescheduleSmsMessages() + { + var expectedBulkId = "BULK-ID-123-xyz"; + var expectedSendAt = "2021-02-22T17:42:05.390+0100"; + var givenSendAtWithColon = "2021-02-22T17:42:05.390+01:00"; + + var givenRequest = $@" + {{ + ""sendAt"": ""{givenSendAtWithColon}"" + + }}"; + + var expectedResponse = $@" + {{ + ""bulkId"": ""{expectedBulkId}"", + ""sendAt"": ""{expectedSendAt}"" + }}"; + + SetUpPutRequest(SMS_BULKS_ENDPOINT, new Dictionary { { "bulkId", expectedBulkId } }, + givenRequest, expectedResponse, 200); + + void BulkResponseAssertions(SmsBulkResponse response) + { + Assert.IsNotNull(response); + Assert.AreEqual(expectedBulkId, response.BulkId); + Assert.AreEqual(DateTimeOffset.Parse(expectedSendAt), response.SendAt); + } + + var scheduledSmsApi = new SmsApi(configuration); + var bulkRequest = new SmsBulkRequest(DateTimeOffset.Parse(givenSendAtWithColon)); + + AssertResponse(scheduledSmsApi.RescheduleSmsMessages(expectedBulkId, bulkRequest), BulkResponseAssertions); + AssertResponse(scheduledSmsApi.RescheduleSmsMessagesAsync(expectedBulkId, bulkRequest).Result, + BulkResponseAssertions); + AssertResponseWithHttpInfo(scheduledSmsApi.RescheduleSmsMessagesWithHttpInfo(expectedBulkId, bulkRequest), + BulkResponseAssertions); + AssertResponseWithHttpInfo( + scheduledSmsApi.RescheduleSmsMessagesWithHttpInfoAsync(expectedBulkId, bulkRequest).Result, + BulkResponseAssertions); + } + + [TestMethod] + public void ShouldGetScheduledSmsMessagesStatus() + { + var expectedBulkId = "BULK-ID-123-xyz"; + var expectedBulkStatusString = "PAUSED"; + var expectedBulkStatus = SmsBulkStatus.Paused; + + var expectedResponse = $@" + {{ + ""bulkId"": ""{expectedBulkId}"", + ""status"": ""{expectedBulkStatusString}"" + }}"; + + SetUpGetRequest(SMS_BULKS_STATUS_ENDPOINT, new Dictionary { { "bulkId", expectedBulkId } }, + expectedResponse, 200); + + void BulkResponseAssertions(SmsBulkStatusResponse response) + { + Assert.IsNotNull(response); + Assert.AreEqual(expectedBulkId, response.BulkId); + Assert.AreEqual(expectedBulkStatus, response.Status); + } + + var scheduledSmsApi = new SmsApi(configuration); + + AssertResponse(scheduledSmsApi.GetScheduledSmsMessagesStatus(expectedBulkId), BulkResponseAssertions); + AssertResponse(scheduledSmsApi.GetScheduledSmsMessagesStatusAsync(expectedBulkId).Result, + BulkResponseAssertions); + AssertResponseWithHttpInfo(scheduledSmsApi.GetScheduledSmsMessagesStatusWithHttpInfo(expectedBulkId), + BulkResponseAssertions); + AssertResponseWithHttpInfo( + scheduledSmsApi.GetScheduledSmsMessagesStatusWithHttpInfoAsync(expectedBulkId).Result, + BulkResponseAssertions); + } + + + [TestMethod] + public void ShouldUpdateScheduledSmsMessagesStatus() + { + var expectedBulkId = "BULK-ID-123-xyz"; + var expectedBulkStatusString = "PAUSED"; + var expectedBulkStatus = SmsBulkStatus.Paused; + + var givenRequest = $@" + {{ + ""status"": ""{expectedBulkStatusString}"" + + }}"; + + var expectedResponse = $@" + {{ + ""bulkId"": ""{expectedBulkId}"", + ""status"": ""{expectedBulkStatusString}"" + }}"; + + SetUpPutRequest(SMS_BULKS_STATUS_ENDPOINT, new Dictionary { { "bulkId", expectedBulkId } }, + givenRequest, expectedResponse, 200); + + void BulkResponseAssertions(SmsBulkStatusResponse response) + { + Assert.IsNotNull(response); + Assert.AreEqual(expectedBulkId, response.BulkId); + Assert.AreEqual(expectedBulkStatus, response.Status); + } + + var scheduledSmsApi = new SmsApi(configuration); + var updateStatusRequest = new SmsUpdateStatusRequest(SmsBulkStatus.Paused); + + AssertResponse(scheduledSmsApi.UpdateScheduledSmsMessagesStatus(expectedBulkId, updateStatusRequest), + BulkResponseAssertions); + AssertResponse( + scheduledSmsApi.UpdateScheduledSmsMessagesStatusAsync(expectedBulkId, updateStatusRequest).Result, + BulkResponseAssertions); + AssertResponseWithHttpInfo( + scheduledSmsApi.UpdateScheduledSmsMessagesStatusWithHttpInfo(expectedBulkId, updateStatusRequest), + BulkResponseAssertions); + AssertResponseWithHttpInfo( + scheduledSmsApi.UpdateScheduledSmsMessagesStatusWithHttpInfoAsync(expectedBulkId, updateStatusRequest) + .Result, BulkResponseAssertions); + } + + private void AssertDeliveredSmsStatus(MessageStatus status) + { + Assert.AreEqual(DELIVERED_STATUS_GROUP_ID, status.GroupId); + Assert.AreEqual(DELIVERED_STATUS_GROUP_NAME, status.GroupName); + Assert.AreEqual(DELIVERED_STATUS_ID, status.Id); + Assert.AreEqual(DELIVERED_STATUS_NAME, status.Name); + Assert.AreEqual(DELIVERED_STATUS_DESCRIPTION, status.Description); + Assert.IsNull(status.Action); + } + + private void AssertNoError(MessageError error) + { + Assert.AreEqual(NO_ERROR_GROUP_ID, error.GroupId); + Assert.AreEqual(NO_ERROR_GROUP_NAME, error.GroupName); + Assert.AreEqual(NO_ERROR_ID, error.Id); + Assert.AreEqual(NO_ERROR_NAME, error.Name); + Assert.AreEqual(NO_ERROR_DESCRIPTION, error.Description); + Assert.AreEqual(NO_ERROR_IS_PERMANENT, error.Permanent); + } + + private void AssertPendingSmsResponse(SmsResponseDetails responseDetails) + { + Assert.AreEqual(PENDING_STATUS_GROUP_ID, responseDetails.Status.GroupId); + Assert.AreEqual(PENDING_STATUS_GROUP_NAME, responseDetails.Status.GroupName); + Assert.AreEqual(PENDING_STATUS_ID, responseDetails.Status.Id); + Assert.AreEqual(PENDING_STATUS_NAME, responseDetails.Status.Name); + Assert.AreEqual(PENDING_STATUS_DESCRIPTION, responseDetails.Status.Description); + Assert.IsNull(responseDetails.Status.Action); + } + + + private string PreparePendingResponse(string givenBulkId, string givenDestination, string givenMessageId) + { + return $@" + {{ + ""bulkId"": ""{givenBulkId}"", + ""messages"": [ + {PreparePendingResponseDetails(givenDestination, givenMessageId)} + ] + }}"; + } + + private string PreparePendingResponse(string givenBulkId, string givenDestination1, string givenMessageId1, + string givenDestination2, string givenMessageId2) + { + return $@" + {{ + ""bulkId"": ""{givenBulkId}"", + ""messages"": [ + {PreparePendingResponseDetails(givenDestination1, givenMessageId1)}, + {PreparePendingResponseDetails(givenDestination2, givenMessageId2)} + ] + }}"; + } + + private string PreparePendingResponseDetails(string givenDestination, string givenMessageId) + { + return $@" + {{ + ""to"": ""{givenDestination}"", + ""status"": {{ + ""groupId"": 1, + ""groupName"": ""PENDING"", + ""id"": 26, + ""name"": ""MESSAGE_ACCEPTED"", + ""description"": ""Message sent to next instance"" + }}, + ""messageId"": ""{givenMessageId}"" + }}"; + } +} \ No newline at end of file diff --git a/ApiClient.Tests/Api/TfaApiTest.cs b/ApiClient.Tests/Api/TfaApiTest.cs new file mode 100644 index 0000000..0c058f7 --- /dev/null +++ b/ApiClient.Tests/Api/TfaApiTest.cs @@ -0,0 +1,1278 @@ +using System.Globalization; +using Infobip.Api.Client.Api; +using Infobip.Api.Client.Model; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ApiClient.Tests.Api; + +[TestClass] +public class TfaApiTest : ApiTest +{ + protected const string TFA_APPLICATIONS = "/2fa/2/applications"; + protected const string TFA_APPLICATION = "/2fa/2/applications/{appId}"; + protected const string TFA_TEMPLATES = "/2fa/2/applications/{appId}/messages"; + protected const string TFA_TEMPLATE = "/2fa/2/applications/{appId}/messages/{msgId}"; + protected const string TFA_EMAIL_TEMPLATES = "/2fa/2/applications/{appId}/email/messages"; + protected const string TFA_EMAIL_TEMPLATE = "/2fa/2/applications/{appId}/email/messages/{msgId}"; + + protected const string TFA_SEND_PIN = "/2fa/2/pin"; + protected const string TFA_RESEND_PIN = "/2fa/2/pin/{pinId}/resend"; + protected const string TFA_SEND_PIN_VOICE = "/2fa/2/pin/voice"; + protected const string TFA_RESEND_PIN_VOICE = "/2fa/2/pin/{pinId}/resend/voice"; + protected const string TFA_SEND_PIN_EMAIL = "/2fa/2/pin/email"; + protected const string TFA_RESEND_PIN_EMAIL = "/2fa/2/pin/{pinId}/resend/email"; + protected const string TFA_VERIFY_PIN = "/2fa/2/pin/{pinId}/verify"; + protected const string TFA_VERIFICATION_STATUS = "/2fa/2/applications/{appId}/verifications"; + + [TestMethod] + public void ShouldGetTfaApplicationsTest() + { + var expectedApplicationId1 = "0933F3BC087D2A617AC6DCB2EF5B8A61"; + var expectedGetApplicationName1 = "Test application BASIC 1"; + var expectedGetApplicationPinAttempts1 = 10; + var expectedAllowMultiplePinVerifications1 = "true"; + var expectedGetApplicationPinTimeToLive1 = "2h"; + var expectedGetApplicationVerifyPinLimit1 = "1/3s"; + var expectedGetApplicationSendPinPerApplicationLimit1 = "10000/1d"; + var expectedGetApplicationSendPinPerPhoneNumberLimit1 = "3/1d"; + var expectedEnabled1 = "true"; + + var expectedApplicationId2 = "5F04FACFAA4978F62FCAEBA97B37E90F"; + var expectedGetApplicationName2 = "Test application BASIC 2"; + var expectedGetApplicationPinAttempts2 = 12; + var expectedAllowMultiplePinVerifications2 = "true"; + var expectedGetApplicationPinTimeToLive2 = "10m"; + var expectedGetApplicationVerifyPinLimit2 = "2/1s"; + var expectedGetApplicationSendPinPerApplicationLimit2 = "10000/1d"; + var expectedGetApplicationSendPinPerPhoneNumberLimit2 = "5/1h"; + var expectedEnabled2 = "true"; + + var expectedApplicationId3 = "B450F966A8EF017180F148AF22C42642"; + var expectedGetApplicationName3 = "Test application BASIC 3"; + var expectedGetApplicationPinAttempts3 = 15; + var expectedAllowMultiplePinVerifications3 = "true"; + var expectedGetApplicationPinTimeToLive3 = "1h"; + var expectedGetApplicationVerifyPinLimit3 = "30/10s"; + var expectedGetApplicationSendPinPerApplicationLimit3 = "10000/3d"; + var expectedGetApplicationSendPinPerPhoneNumberLimit3 = "10/20m"; + var expectedEnabled3 = "true"; + + var expectedResponse = $@" + [ + {{ + ""applicationId"": ""{expectedApplicationId1}"", + ""name"": ""{expectedGetApplicationName1}"", + ""configuration"": {{ + ""pinAttempts"": {expectedGetApplicationPinAttempts1}, + ""allowMultiplePinVerifications"": {expectedAllowMultiplePinVerifications1}, + ""pinTimeToLive"": ""{expectedGetApplicationPinTimeToLive1}"", + ""verifyPinLimit"": ""{expectedGetApplicationVerifyPinLimit1}"", + ""sendPinPerApplicationLimit"": ""{expectedGetApplicationSendPinPerApplicationLimit1}"", + ""sendPinPerPhoneNumberLimit"": ""{expectedGetApplicationSendPinPerPhoneNumberLimit1}"" + }}, + ""enabled"": {expectedEnabled1} + }}, + {{ + ""applicationId"": ""{expectedApplicationId2}"", + ""name"": ""{expectedGetApplicationName2}"", + ""configuration"": {{ + ""pinAttempts"": {expectedGetApplicationPinAttempts2}, + ""allowMultiplePinVerifications"": {expectedAllowMultiplePinVerifications2}, + ""pinTimeToLive"": ""{expectedGetApplicationPinTimeToLive2}"", + ""verifyPinLimit"": ""{expectedGetApplicationVerifyPinLimit2}"", + ""sendPinPerApplicationLimit"": ""{expectedGetApplicationSendPinPerApplicationLimit2}"", + ""sendPinPerPhoneNumberLimit"": ""{expectedGetApplicationSendPinPerPhoneNumberLimit2}"" + }}, + ""enabled"": {expectedEnabled2} + }}, + {{ + ""applicationId"": ""{expectedApplicationId3}"", + ""name"": ""{expectedGetApplicationName3}"", + ""configuration"": {{ + ""pinAttempts"": {expectedGetApplicationPinAttempts3}, + ""allowMultiplePinVerifications"": {expectedAllowMultiplePinVerifications3}, + ""pinTimeToLive"": ""{expectedGetApplicationPinTimeToLive3}"", + ""verifyPinLimit"": ""{expectedGetApplicationVerifyPinLimit3}"", + ""sendPinPerApplicationLimit"": ""{expectedGetApplicationSendPinPerApplicationLimit3}"", + ""sendPinPerPhoneNumberLimit"": ""{expectedGetApplicationSendPinPerPhoneNumberLimit3}"" + }}, + ""enabled"": {expectedEnabled3} + }} + ]"; + + SetUpGetRequest(TFA_APPLICATIONS, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + void AssertTfaGetApplicationsResponse(List tfaApplicationResponses) + { + Assert.IsNotNull(tfaApplicationResponses); + Assert.IsTrue(tfaApplicationResponses.Count.Equals(3)); + + var tfaApplicationResponse1 = tfaApplicationResponses[0]; + Assert.IsNotNull(tfaApplicationResponse1); + Assert.AreEqual(expectedApplicationId1, tfaApplicationResponse1.ApplicationId); + Assert.AreEqual(expectedGetApplicationName1, tfaApplicationResponse1.Name); + Assert.AreEqual(expectedGetApplicationPinAttempts1, tfaApplicationResponse1.VarConfiguration.PinAttempts); + Assert.AreEqual(bool.Parse(expectedAllowMultiplePinVerifications1), + tfaApplicationResponse1.VarConfiguration.AllowMultiplePinVerifications); + Assert.AreEqual(expectedGetApplicationPinTimeToLive1, + tfaApplicationResponse1.VarConfiguration.PinTimeToLive); + Assert.AreEqual(expectedGetApplicationVerifyPinLimit1, + tfaApplicationResponse1.VarConfiguration.VerifyPinLimit); + Assert.AreEqual(expectedGetApplicationSendPinPerApplicationLimit1, + tfaApplicationResponse1.VarConfiguration.SendPinPerApplicationLimit); + Assert.AreEqual(expectedGetApplicationSendPinPerPhoneNumberLimit1, + tfaApplicationResponse1.VarConfiguration.SendPinPerPhoneNumberLimit); + + var tfaApplicationResponse2 = tfaApplicationResponses[1]; + Assert.IsNotNull(tfaApplicationResponse2); + Assert.AreEqual(expectedApplicationId2, tfaApplicationResponse2.ApplicationId); + Assert.AreEqual(expectedGetApplicationName2, tfaApplicationResponse2.Name); + Assert.AreEqual(expectedGetApplicationPinAttempts2, tfaApplicationResponse2.VarConfiguration.PinAttempts); + Assert.AreEqual(bool.Parse(expectedAllowMultiplePinVerifications2), + tfaApplicationResponse2.VarConfiguration.AllowMultiplePinVerifications); + Assert.AreEqual(expectedGetApplicationPinTimeToLive2, + tfaApplicationResponse2.VarConfiguration.PinTimeToLive); + Assert.AreEqual(expectedGetApplicationVerifyPinLimit2, + tfaApplicationResponse2.VarConfiguration.VerifyPinLimit); + Assert.AreEqual(expectedGetApplicationSendPinPerApplicationLimit2, + tfaApplicationResponse2.VarConfiguration.SendPinPerApplicationLimit); + Assert.AreEqual(expectedGetApplicationSendPinPerPhoneNumberLimit2, + tfaApplicationResponse2.VarConfiguration.SendPinPerPhoneNumberLimit); + + var tfaApplicationResponse3 = tfaApplicationResponses[2]; + Assert.IsNotNull(tfaApplicationResponse3); + Assert.AreEqual(expectedApplicationId3, tfaApplicationResponse3.ApplicationId); + Assert.AreEqual(expectedGetApplicationName3, tfaApplicationResponse3.Name); + Assert.AreEqual(expectedGetApplicationPinAttempts3, tfaApplicationResponse3.VarConfiguration.PinAttempts); + Assert.AreEqual(bool.Parse(expectedAllowMultiplePinVerifications3), + tfaApplicationResponse3.VarConfiguration.AllowMultiplePinVerifications); + Assert.AreEqual(expectedGetApplicationPinTimeToLive3, + tfaApplicationResponse3.VarConfiguration.PinTimeToLive); + Assert.AreEqual(expectedGetApplicationVerifyPinLimit3, + tfaApplicationResponse3.VarConfiguration.VerifyPinLimit); + Assert.AreEqual(expectedGetApplicationSendPinPerApplicationLimit3, + tfaApplicationResponse3.VarConfiguration.SendPinPerApplicationLimit); + Assert.AreEqual(expectedGetApplicationSendPinPerPhoneNumberLimit3, + tfaApplicationResponse3.VarConfiguration.SendPinPerPhoneNumberLimit); + } + + AssertResponse(tfaApi.GetTfaApplications(), AssertTfaGetApplicationsResponse); + AssertResponse(tfaApi.GetTfaApplicationsAsync().Result, AssertTfaGetApplicationsResponse); + + AssertResponseWithHttpInfo(tfaApi.GetTfaApplicationsWithHttpInfo(), AssertTfaGetApplicationsResponse); + AssertResponseWithHttpInfo(tfaApi.GetTfaApplicationsWithHttpInfoAsync().Result, + AssertTfaGetApplicationsResponse); + } + + [TestMethod] + public void ShouldCreateTfaApplicationTest() + { + var expectedApplicationId = "1234567"; + var expectedCreateApplicationName = "2fa application name"; + var expectedCreateApplicationPinAttempts = 5; + var expectedAllowMultiplePinVerifications = "true"; + var expectedCreateApplicationPinTimeToLive = "10m"; + var expectedCreateApplicationVerifyPinLimit = "2/4s"; + var expectedCreateApplicationSendPinPerApplicationLimit = "5000/12h"; + var expectedCreateApplicationSendPinPerPhoneNumberLimit = "2/1d"; + var expectedEnabled = "true"; + + var givenRequest = $@" + {{ + ""name"": ""{expectedCreateApplicationName}"", + ""enabled"": {expectedEnabled}, + ""configuration"": {{ + ""pinAttempts"": {expectedCreateApplicationPinAttempts}, + ""allowMultiplePinVerifications"": {expectedAllowMultiplePinVerifications}, + ""pinTimeToLive"": ""{expectedCreateApplicationPinTimeToLive}"", + ""verifyPinLimit"": ""{expectedCreateApplicationVerifyPinLimit}"", + ""sendPinPerApplicationLimit"": ""{expectedCreateApplicationSendPinPerApplicationLimit}"", + ""sendPinPerPhoneNumberLimit"": ""{expectedCreateApplicationSendPinPerPhoneNumberLimit}"" + }} + }}"; + + var expectedResponse = $@" + {{ + ""applicationId"": ""{expectedApplicationId}"", + ""name"": ""{expectedCreateApplicationName}"", + ""configuration"": {{ + ""pinAttempts"": {expectedCreateApplicationPinAttempts}, + ""allowMultiplePinVerifications"": {expectedAllowMultiplePinVerifications}, + ""pinTimeToLive"": ""{expectedCreateApplicationPinTimeToLive}"", + ""verifyPinLimit"": ""{expectedCreateApplicationVerifyPinLimit}"", + ""sendPinPerApplicationLimit"": ""{expectedCreateApplicationSendPinPerApplicationLimit}"", + ""sendPinPerPhoneNumberLimit"": ""{expectedCreateApplicationSendPinPerPhoneNumberLimit}"" + }}, + ""enabled"": {expectedEnabled} + }}"; + + SetUpPostRequest(TFA_APPLICATIONS, givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var tfaApplicationConfiguration = new TfaApplicationConfiguration + { + PinAttempts = expectedCreateApplicationPinAttempts, + AllowMultiplePinVerifications = bool.Parse(expectedAllowMultiplePinVerifications), + PinTimeToLive = expectedCreateApplicationPinTimeToLive, + VerifyPinLimit = expectedCreateApplicationVerifyPinLimit, + SendPinPerApplicationLimit = expectedCreateApplicationSendPinPerApplicationLimit, + SendPinPerPhoneNumberLimit = expectedCreateApplicationSendPinPerPhoneNumberLimit + }; + + var tfaApplicationRequest = new TfaApplicationRequest( + tfaApplicationConfiguration, + bool.Parse(expectedEnabled), + expectedCreateApplicationName + ); + + void AssertTfaCreateApplicationResponse(TfaApplicationResponse tfaApplicationResponse) + { + Assert.IsNotNull(tfaApplicationResponse); + Assert.AreEqual(expectedApplicationId, tfaApplicationResponse.ApplicationId); + Assert.AreEqual(expectedCreateApplicationName, tfaApplicationResponse.Name); + Assert.AreEqual(tfaApplicationConfiguration, tfaApplicationResponse.VarConfiguration); + Assert.AreEqual(bool.Parse(expectedEnabled), tfaApplicationResponse.Enabled); + } + + AssertResponse(tfaApi.CreateTfaApplication(tfaApplicationRequest), AssertTfaCreateApplicationResponse); + AssertResponse(tfaApi.CreateTfaApplicationAsync(tfaApplicationRequest).Result, + AssertTfaCreateApplicationResponse); + + AssertResponseWithHttpInfo(tfaApi.CreateTfaApplicationWithHttpInfo(tfaApplicationRequest), + AssertTfaCreateApplicationResponse); + AssertResponseWithHttpInfo(tfaApi.CreateTfaApplicationWithHttpInfoAsync(tfaApplicationRequest).Result, + AssertTfaCreateApplicationResponse); + } + + [TestMethod] + public void ShouldGetTfaApplicationTest() + { + var expectedApplicationId = "1234567"; + var expectedGetApplicationName = "2fa application name"; + var expectedGetApplicationPinAttempts = 5; + var expectedAllowMultiplePinVerifications = "true"; + var expectedGetApplicationPinTimeToLive = "10m"; + var expectedGetApplicationVerifyPinLimit = "2/4s"; + var expectedGetApplicationSendPinPerApplicationLimit = "5000/12h"; + var expectedGetApplicationSendPinPerPhoneNumberLimit = "2/1d"; + var expectedEnabled = "true"; + + var expectedResponse = $@" + {{ + ""applicationId"": ""{expectedApplicationId}"", + ""name"": ""{expectedGetApplicationName}"", + ""configuration"": {{ + ""pinAttempts"": {expectedGetApplicationPinAttempts}, + ""allowMultiplePinVerifications"": {expectedAllowMultiplePinVerifications}, + ""pinTimeToLive"": ""{expectedGetApplicationPinTimeToLive}"", + ""verifyPinLimit"": ""{expectedGetApplicationVerifyPinLimit}"", + ""sendPinPerApplicationLimit"": ""{expectedGetApplicationSendPinPerApplicationLimit}"", + ""sendPinPerPhoneNumberLimit"": ""{expectedGetApplicationSendPinPerPhoneNumberLimit}"" + }}, + ""enabled"": {expectedEnabled} + }}"; + + SetUpGetRequest(TFA_APPLICATION.Replace("{appId}", expectedApplicationId), expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + void AssertTfaGetApplicationResponse(TfaApplicationResponse tfaApplicationResponse) + { + var expectedApplicationConfiguration = new TfaApplicationConfiguration + { + PinAttempts = expectedGetApplicationPinAttempts, + AllowMultiplePinVerifications = bool.Parse(expectedAllowMultiplePinVerifications), + PinTimeToLive = expectedGetApplicationPinTimeToLive, + VerifyPinLimit = expectedGetApplicationVerifyPinLimit, + SendPinPerApplicationLimit = expectedGetApplicationSendPinPerApplicationLimit, + SendPinPerPhoneNumberLimit = expectedGetApplicationSendPinPerPhoneNumberLimit + }; + + Assert.IsNotNull(tfaApplicationResponse); + Assert.AreEqual(expectedApplicationId, tfaApplicationResponse.ApplicationId); + Assert.AreEqual(expectedGetApplicationName, tfaApplicationResponse.Name); + Assert.AreEqual(expectedApplicationConfiguration, tfaApplicationResponse.VarConfiguration); + Assert.AreEqual(bool.Parse(expectedEnabled), tfaApplicationResponse.Enabled); + } + + AssertResponse(tfaApi.GetTfaApplication(expectedApplicationId), AssertTfaGetApplicationResponse); + AssertResponse(tfaApi.GetTfaApplicationAsync(expectedApplicationId).Result, AssertTfaGetApplicationResponse); + + AssertResponseWithHttpInfo(tfaApi.GetTfaApplicationWithHttpInfo(expectedApplicationId), + AssertTfaGetApplicationResponse); + AssertResponseWithHttpInfo(tfaApi.GetTfaApplicationWithHttpInfoAsync(expectedApplicationId).Result, + AssertTfaGetApplicationResponse); + } + + [TestMethod] + public void ShouldUpdateTfaApplicationTest() + { + var expectedApplicationId = "1234567"; + var expectedCreateApplicationName = "2fa application name"; + var expectedCreateApplicationPinAttempts = 5; + var expectedAllowMultiplePinVerifications = "true"; + var expectedCreateApplicationPinTimeToLive = "10m"; + var expectedCreateApplicationVerifyPinLimit = "2/4s"; + var expectedCreateApplicationSendPinPerApplicationLimit = "5000/12h"; + var expectedCreateApplicationSendPinPerPhoneNumberLimit = "2/1d"; + var expectedEnabled = "true"; + + var givenRequest = $@" + {{ + ""name"": ""{expectedCreateApplicationName}"", + ""enabled"": {expectedEnabled}, + ""configuration"": {{ + ""pinAttempts"": {expectedCreateApplicationPinAttempts}, + ""allowMultiplePinVerifications"": {expectedAllowMultiplePinVerifications}, + ""pinTimeToLive"": ""{expectedCreateApplicationPinTimeToLive}"", + ""verifyPinLimit"": ""{expectedCreateApplicationVerifyPinLimit}"", + ""sendPinPerApplicationLimit"": ""{expectedCreateApplicationSendPinPerApplicationLimit}"", + ""sendPinPerPhoneNumberLimit"": ""{expectedCreateApplicationSendPinPerPhoneNumberLimit}"" + }} + }}"; + + var expectedResponse = $@" + {{ + ""applicationId"": ""{expectedApplicationId}"", + ""name"": ""{expectedCreateApplicationName}"", + ""configuration"": {{ + ""pinAttempts"": {expectedCreateApplicationPinAttempts}, + ""allowMultiplePinVerifications"": {expectedAllowMultiplePinVerifications}, + ""pinTimeToLive"": ""{expectedCreateApplicationPinTimeToLive}"", + ""verifyPinLimit"": ""{expectedCreateApplicationVerifyPinLimit}"", + ""sendPinPerApplicationLimit"": ""{expectedCreateApplicationSendPinPerApplicationLimit}"", + ""sendPinPerPhoneNumberLimit"": ""{expectedCreateApplicationSendPinPerPhoneNumberLimit}"" + }}, + ""enabled"": {expectedEnabled} + }}"; + + SetUpPutRequest(TFA_APPLICATION.Replace("{appId}", expectedApplicationId), givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var tfaApplicationConfiguration = new TfaApplicationConfiguration + { + PinAttempts = expectedCreateApplicationPinAttempts, + AllowMultiplePinVerifications = bool.Parse(expectedAllowMultiplePinVerifications), + PinTimeToLive = expectedCreateApplicationPinTimeToLive, + VerifyPinLimit = expectedCreateApplicationVerifyPinLimit, + SendPinPerApplicationLimit = expectedCreateApplicationSendPinPerApplicationLimit, + SendPinPerPhoneNumberLimit = expectedCreateApplicationSendPinPerPhoneNumberLimit + }; + + var tfaApplicationRequest = new TfaApplicationRequest( + tfaApplicationConfiguration, + bool.Parse(expectedEnabled), + expectedCreateApplicationName + ); + + void AssertTfaUpdateApplicationResponse(TfaApplicationResponse tfaApplicationResponse) + { + Assert.IsNotNull(tfaApplicationResponse); + Assert.AreEqual(expectedApplicationId, tfaApplicationResponse.ApplicationId); + Assert.AreEqual(expectedCreateApplicationName, tfaApplicationResponse.Name); + Assert.AreEqual(tfaApplicationConfiguration, tfaApplicationResponse.VarConfiguration); + Assert.AreEqual(bool.Parse(expectedEnabled), tfaApplicationResponse.Enabled); + } + + AssertResponse(tfaApi.UpdateTfaApplication(expectedApplicationId, tfaApplicationRequest), + AssertTfaUpdateApplicationResponse); + AssertResponse(tfaApi.UpdateTfaApplicationAsync(expectedApplicationId, tfaApplicationRequest).Result, + AssertTfaUpdateApplicationResponse); + + AssertResponseWithHttpInfo( + tfaApi.UpdateTfaApplicationWithHttpInfo(expectedApplicationId, tfaApplicationRequest), + AssertTfaUpdateApplicationResponse); + AssertResponseWithHttpInfo( + tfaApi.UpdateTfaApplicationWithHttpInfoAsync(expectedApplicationId, tfaApplicationRequest).Result, + AssertTfaUpdateApplicationResponse); + } + + [TestMethod] + public void ShouldGetTfaMessageTemplatesTest() + { + var givenApplicationId = "HJ675435E3A6EA43432G5F37A635KJ8B"; + + var expectedPinPlaceholder = "{{pin}}"; + var expectedMessageText = string.Format("Your PIN is {0}.", expectedPinPlaceholder); + var expectedPinLength = 4; + var expectedPinType = "Alphanumeric"; + var expectedLanguage = "En"; + var expectedSenderId = "Infobip 2FA"; + var expectedRepeatDtmf = "1#"; + double expectedSpeechRate = 1; + + var expectedResponse = $@" + [ + {{ + ""pinPlaceholder"": ""{expectedPinPlaceholder}"", + ""pinType"": ""{expectedPinType}"", + ""messageText"": ""{expectedMessageText}"", + ""pinLength"": {expectedPinLength}, + ""language"": ""{expectedLanguage}"", + ""senderId"": ""{expectedSenderId}"", + ""repeatDTMF"": ""{expectedRepeatDtmf}"", + ""speechRate"": {expectedSpeechRate} + }} + ]"; + + SetUpGetRequest(TFA_TEMPLATES.Replace("{appId}", givenApplicationId), expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + void AssertTfaGetTemplatesResponse(List tfaMessages) + { + Assert.IsNotNull(tfaMessages); + var tfaMessage = tfaMessages[0]; + + Assert.IsNotNull(tfaMessage); + Assert.AreEqual(expectedPinPlaceholder, tfaMessage.PinPlaceholder); + Assert.AreEqual(expectedMessageText, tfaMessage.MessageText); + Assert.AreEqual(expectedPinLength, tfaMessage.PinLength); + Assert.AreEqual(Enum.Parse(expectedPinType), tfaMessage.PinType); + Assert.AreEqual(Enum.Parse(expectedLanguage), tfaMessage.Language); + Assert.AreEqual(expectedSenderId, tfaMessage.SenderId); + Assert.AreEqual(expectedRepeatDtmf, tfaMessage.RepeatDTMF); + Assert.AreEqual(expectedSpeechRate, tfaMessage.SpeechRate); + } + + AssertResponse(tfaApi.GetTfaMessageTemplates(givenApplicationId), AssertTfaGetTemplatesResponse); + AssertResponse(tfaApi.GetTfaMessageTemplatesAsync(givenApplicationId).Result, AssertTfaGetTemplatesResponse); + + AssertResponseWithHttpInfo(tfaApi.GetTfaMessageTemplatesWithHttpInfo(givenApplicationId), + AssertTfaGetTemplatesResponse); + AssertResponseWithHttpInfo(tfaApi.GetTfaMessageTemplatesWithHttpInfoAsync(givenApplicationId).Result, + AssertTfaGetTemplatesResponse); + } + + [TestMethod] + public void ShouldCreateTfaMessageTemplateTest() + { + var givenApplicationId = "HJ675435E3A6EA43432G5F37A635KJ8B"; + + var expectedPinPlaceholder = "{{pin}}"; + var expectedMessageText = string.Format("Your PIN is {0}.", expectedPinPlaceholder); + var expectedPinLength = 4; + var expectedPinType = "Alphanumeric"; + var expectedLanguage = "en"; + var expectedSenderId = "Infobip 2FA"; + var expectedRepeatDtmf = "1#"; + var expectedSpeechRate = "1.0"; + + var givenRequest = $@" + {{ + ""language"": ""{expectedLanguage}"", + ""pinType"": ""{expectedPinType}"", + ""messageText"": ""{expectedMessageText}"", + ""pinLength"": {expectedPinLength}, + ""repeatDTMF"": ""{expectedRepeatDtmf}"", + ""senderId"": ""{expectedSenderId}"", + ""speechRate"": {expectedSpeechRate} + }}"; + + var expectedResponse = $@" + {{ + ""pinPlaceholder"": ""{expectedPinPlaceholder}"", + ""pinType"": ""{expectedPinType}"", + ""messageText"": ""{expectedMessageText}"", + ""pinLength"": {expectedPinLength}, + ""language"": ""{expectedLanguage}"", + ""senderId"": ""{expectedSenderId}"", + ""repeatDTMF"": ""{expectedRepeatDtmf}"", + ""speechRate"": {expectedSpeechRate} + }}"; + + SetUpPostRequest(TFA_TEMPLATES.Replace("{appId}", givenApplicationId), givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var tfaCreateMessageRequest = new TfaCreateMessageRequest( + Enum.Parse(expectedLanguage, true), + expectedMessageText, + expectedPinLength, + Enum.Parse(expectedPinType, true), + repeatDTMF: expectedRepeatDtmf, + senderId: expectedSenderId, + speechRate: double.Parse(expectedSpeechRate, CultureInfo.InvariantCulture) + ); + + void AssertTfaCreateTemplateResponse(TfaMessage tfaMessage) + { + Assert.IsNotNull(tfaMessage); + Assert.AreEqual(expectedPinPlaceholder, tfaMessage.PinPlaceholder); + Assert.AreEqual(expectedMessageText, tfaMessage.MessageText); + Assert.AreEqual(expectedPinLength, tfaMessage.PinLength); + Assert.AreEqual(Enum.Parse(expectedPinType, true), tfaMessage.PinType); + Assert.AreEqual(Enum.Parse(expectedLanguage, true), tfaMessage.Language); + Assert.AreEqual(expectedSenderId, tfaMessage.SenderId); + Assert.AreEqual(expectedRepeatDtmf, tfaMessage.RepeatDTMF); + Assert.AreEqual(double.Parse(expectedSpeechRate, CultureInfo.InvariantCulture), tfaMessage.SpeechRate); + } + + AssertResponse(tfaApi.CreateTfaMessageTemplate(givenApplicationId, tfaCreateMessageRequest), + AssertTfaCreateTemplateResponse); + AssertResponse(tfaApi.CreateTfaMessageTemplateAsync(givenApplicationId, tfaCreateMessageRequest).Result, + AssertTfaCreateTemplateResponse); + + AssertResponseWithHttpInfo( + tfaApi.CreateTfaMessageTemplateWithHttpInfo(givenApplicationId, tfaCreateMessageRequest), + AssertTfaCreateTemplateResponse); + AssertResponseWithHttpInfo( + tfaApi.CreateTfaMessageTemplateWithHttpInfoAsync(givenApplicationId, tfaCreateMessageRequest).Result, + AssertTfaCreateTemplateResponse); + } + + [TestMethod] + public void ShouldGetTfaMessageTemplateTest() + { + var givenApplicationId = "HJ675435E3A6EA43432G5F37A635KJ8B"; + var givenMessageId = "9C815F8AF3328"; + + var expectedPinPlaceholder = "{{pin}}"; + var expectedMessageText = string.Format("Your PIN is {0}.", expectedPinPlaceholder); + var expectedPinLength = 4; + var expectedPinType = "Alphanumeric"; + var expectedLanguage = "En"; + var expectedSenderId = "Infobip 2FA"; + var expectedRepeatDtmf = "1#"; + var expectedSpeechRate = 1.0; + + var expectedResponse = $@" + {{ + ""pinPlaceholder"": ""{expectedPinPlaceholder}"", + ""pinType"": ""{expectedPinType}"", + ""messageText"": ""{expectedMessageText}"", + ""pinLength"": {expectedPinLength}, + ""language"": ""{expectedLanguage}"", + ""senderId"": ""{expectedSenderId}"", + ""repeatDTMF"": ""{expectedRepeatDtmf}"", + ""speechRate"": {expectedSpeechRate} + }}"; + + SetUpGetRequest(TFA_TEMPLATE.Replace("{appId}", givenApplicationId).Replace("{msgId}", givenMessageId), + expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + void AssertTfaGetTemplateResponse(TfaMessage tfaMessage) + { + Assert.IsNotNull(tfaMessage); + Assert.AreEqual(expectedPinPlaceholder, tfaMessage.PinPlaceholder); + Assert.AreEqual(expectedMessageText, tfaMessage.MessageText); + Assert.AreEqual(expectedPinLength, tfaMessage.PinLength); + Assert.AreEqual(Enum.Parse(expectedPinType), tfaMessage.PinType); + Assert.AreEqual(Enum.Parse(expectedLanguage), tfaMessage.Language); + Assert.AreEqual(expectedSenderId, tfaMessage.SenderId); + Assert.AreEqual(expectedRepeatDtmf, tfaMessage.RepeatDTMF); + Assert.AreEqual(expectedSpeechRate, tfaMessage.SpeechRate); + } + + AssertResponse(tfaApi.GetTfaMessageTemplate(givenApplicationId, givenMessageId), AssertTfaGetTemplateResponse); + AssertResponse(tfaApi.GetTfaMessageTemplateAsync(givenApplicationId, givenMessageId).Result, + AssertTfaGetTemplateResponse); + + AssertResponseWithHttpInfo(tfaApi.GetTfaMessageTemplateWithHttpInfo(givenApplicationId, givenMessageId), + AssertTfaGetTemplateResponse); + AssertResponseWithHttpInfo( + tfaApi.GetTfaMessageTemplateWithHttpInfoAsync(givenApplicationId, givenMessageId).Result, + AssertTfaGetTemplateResponse); + } + + [TestMethod] + public void ShouldUpdateTfaMessageTemplateTest() + { + var givenApplicationId = "HJ675435E3A6EA43432G5F37A635KJ8B"; + var givenMessageId = "5E3A6EA43432G5F3"; + + var expectedPinPlaceholder = "{{pin}}"; + var expectedMessageText = string.Format("Your PIN is {0}.", expectedPinPlaceholder); + var expectedPinLength = 4; + var expectedPinType = "Alphanumeric"; + var expectedLanguage = "en"; + var expectedSenderId = "Infobip 2FA"; + var expectedRepeatDtmf = "1#"; + var expectedSpeechRate = "1.0"; + + var givenRequest = $@" + {{ + ""language"": ""{expectedLanguage}"", + ""pinType"": ""{expectedPinType}"", + ""messageText"": ""{expectedMessageText}"", + ""pinLength"": {expectedPinLength}, + ""repeatDTMF"": ""{expectedRepeatDtmf}"", + ""senderId"": ""{expectedSenderId}"", + ""speechRate"": {expectedSpeechRate} + }}"; + + + var expectedResponse = $@" + {{ + ""pinPlaceholder"": ""{expectedPinPlaceholder}"", + ""pinType"": ""{expectedPinType}"", + ""messageText"": ""{expectedMessageText}"", + ""pinLength"": {expectedPinLength}, + ""language"": ""{expectedLanguage}"", + ""senderId"": ""{expectedSenderId}"", + ""repeatDTMF"": ""{expectedRepeatDtmf}"", + ""speechRate"": {expectedSpeechRate} + }}"; + + SetUpPutRequest(TFA_TEMPLATE.Replace("{appId}", givenApplicationId).Replace("{msgId}", givenMessageId), + givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var tfaUpdateMessageRequest = new TfaUpdateMessageRequest( + Enum.Parse(expectedLanguage, true), + expectedMessageText, + expectedPinLength, + Enum.Parse(expectedPinType, true), + repeatDTMF: expectedRepeatDtmf, + senderId: expectedSenderId, + speechRate: double.Parse(expectedSpeechRate, CultureInfo.InvariantCulture) + ); + + void AssertTfaUpdateTemplateResponse(TfaMessage tfaMessage) + { + Assert.IsNotNull(tfaMessage); + Assert.AreEqual(expectedPinPlaceholder, tfaMessage.PinPlaceholder); + Assert.AreEqual(expectedMessageText, tfaMessage.MessageText); + Assert.AreEqual(expectedPinLength, tfaMessage.PinLength); + Assert.AreEqual(Enum.Parse(expectedPinType, true), tfaMessage.PinType); + Assert.AreEqual(Enum.Parse(expectedLanguage, true), tfaMessage.Language); + Assert.AreEqual(expectedSenderId, tfaMessage.SenderId); + Assert.AreEqual(expectedRepeatDtmf, tfaMessage.RepeatDTMF); + Assert.AreEqual(double.Parse(expectedSpeechRate, CultureInfo.InvariantCulture), tfaMessage.SpeechRate); + } + + AssertResponse(tfaApi.UpdateTfaMessageTemplate(givenApplicationId, givenMessageId, tfaUpdateMessageRequest), + AssertTfaUpdateTemplateResponse); + AssertResponse( + tfaApi.UpdateTfaMessageTemplateAsync(givenApplicationId, givenMessageId, tfaUpdateMessageRequest).Result, + AssertTfaUpdateTemplateResponse); + + AssertResponseWithHttpInfo( + tfaApi.UpdateTfaMessageTemplateWithHttpInfo(givenApplicationId, givenMessageId, tfaUpdateMessageRequest), + AssertTfaUpdateTemplateResponse); + AssertResponseWithHttpInfo( + tfaApi.UpdateTfaMessageTemplateWithHttpInfoAsync(givenApplicationId, givenMessageId, + tfaUpdateMessageRequest).Result, AssertTfaUpdateTemplateResponse); + } + + [TestMethod] + public void ShouldCreateTfaEmailMessageTemplateTest() + { + var expectedPinType = TfaPinType.Numeric; + var expectedPinLength = 4; + var expectedFrom = "company@example.com"; + var expectedEmailTemplateId = 1234; + var expectedMessageId = "9C815F8AF3328"; + var expectedApplicationId = "HJ675435E3A6EA43432G5F37A635KJ8B"; + + var givenRequest = $@" + {{ + ""pinType"": ""{expectedPinType}"", + ""pinLength"": {expectedPinLength}, + ""from"": ""{expectedFrom}"", + ""emailTemplateId"": {expectedEmailTemplateId} + }}"; + + var expectedResponse = $@" + {{ + ""messageId"": ""{expectedMessageId}"", + ""applicationId"": ""{expectedApplicationId}"", + ""pinLength"": {expectedPinLength}, + ""pinType"": ""{expectedPinType}"", + ""from"": ""{expectedFrom}"", + ""emailTemplateId"": {expectedEmailTemplateId} + }}"; + + SetUpPostRequest(TFA_EMAIL_TEMPLATES.Replace("{appId}", expectedApplicationId), givenRequest, expectedResponse, + 200); + + var tfaApi = new TfaApi(configuration); + + var tfaCreateEmailMessageRequest = new TfaCreateEmailMessageRequest( + pinType: expectedPinType, + pinLength: expectedPinLength, + from: expectedFrom, + emailTemplateId: expectedEmailTemplateId + ); + + void AssertTfaCreateEmailMessageResponse(TfaEmailMessage tfaEmailMessage) + { + Assert.IsNotNull(tfaEmailMessage); + Assert.AreEqual(expectedMessageId, tfaEmailMessage.MessageId); + Assert.AreEqual(expectedApplicationId, tfaEmailMessage.ApplicationId); + Assert.AreEqual(expectedPinLength, tfaEmailMessage.PinLength); + Assert.AreEqual(expectedPinType, tfaEmailMessage.PinType); + Assert.AreEqual(expectedFrom, tfaEmailMessage.From); + Assert.AreEqual(expectedEmailTemplateId, tfaEmailMessage.EmailTemplateId); + } + + AssertResponse(tfaApi.CreateTfaEmailMessageTemplate(expectedApplicationId, tfaCreateEmailMessageRequest), + AssertTfaCreateEmailMessageResponse); + AssertResponse( + tfaApi.CreateTfaEmailMessageTemplateAsync(expectedApplicationId, tfaCreateEmailMessageRequest).Result, + AssertTfaCreateEmailMessageResponse); + + AssertResponseWithHttpInfo( + tfaApi.CreateTfaEmailMessageTemplateWithHttpInfo(expectedApplicationId, tfaCreateEmailMessageRequest), + AssertTfaCreateEmailMessageResponse); + AssertResponseWithHttpInfo( + tfaApi.CreateTfaEmailMessageTemplateWithHttpInfoAsync(expectedApplicationId, tfaCreateEmailMessageRequest) + .Result, AssertTfaCreateEmailMessageResponse); + } + + [TestMethod] + public void ShouldUpdateTfaEmailMessageTemplateTest() + { + var expectedPinType = TfaPinType.Numeric; + var expectedPinLength = 4; + var expectedFrom = "company@example.com"; + var expectedEmailTemplateId = 1234; + var expectedMessageId = "9C815F8AF3328"; + var expectedApplicationId = "HJ675435E3A6EA43432G5F37A635KJ8B"; + + var givenRequest = $@" + {{ + ""pinType"": ""{expectedPinType}"", + ""pinLength"": {expectedPinLength}, + ""from"": ""{expectedFrom}"", + ""emailTemplateId"": {expectedEmailTemplateId} + }}"; + + var expectedResponse = $@" + {{ + ""messageId"": ""{expectedMessageId}"", + ""applicationId"": ""{expectedApplicationId}"", + ""pinLength"": {expectedPinLength}, + ""pinType"": ""{expectedPinType}"", + ""from"": ""{expectedFrom}"", + ""emailTemplateId"": {expectedEmailTemplateId} + }}"; + + SetUpPutRequest( + TFA_EMAIL_TEMPLATE.Replace("{appId}", expectedApplicationId).Replace("{msgId}", expectedMessageId), + givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var tfaUpdateEmailMessageRequest = new TfaUpdateEmailMessageRequest( + pinType: expectedPinType, + pinLength: expectedPinLength, + from: expectedFrom, + emailTemplateId: expectedEmailTemplateId + ); + + void AssertTfaUpdateEmailMessageResponse(TfaEmailMessage tfaEmailMessage) + { + Assert.IsNotNull(tfaEmailMessage); + Assert.AreEqual(expectedMessageId, tfaEmailMessage.MessageId); + Assert.AreEqual(expectedApplicationId, tfaEmailMessage.ApplicationId); + Assert.AreEqual(expectedPinLength, tfaEmailMessage.PinLength); + Assert.AreEqual(expectedPinType, tfaEmailMessage.PinType); + Assert.AreEqual(expectedFrom, tfaEmailMessage.From); + Assert.AreEqual(expectedEmailTemplateId, tfaEmailMessage.EmailTemplateId); + } + + AssertResponse( + tfaApi.UpdateTfaEmailMessageTemplate(expectedApplicationId, expectedMessageId, + tfaUpdateEmailMessageRequest), AssertTfaUpdateEmailMessageResponse); + AssertResponse( + tfaApi.UpdateTfaEmailMessageTemplateAsync(expectedApplicationId, expectedMessageId, + tfaUpdateEmailMessageRequest).Result, AssertTfaUpdateEmailMessageResponse); + + AssertResponseWithHttpInfo( + tfaApi.UpdateTfaEmailMessageTemplateWithHttpInfo(expectedApplicationId, expectedMessageId, + tfaUpdateEmailMessageRequest), AssertTfaUpdateEmailMessageResponse); + AssertResponseWithHttpInfo( + tfaApi.UpdateTfaEmailMessageTemplateWithHttpInfoAsync(expectedApplicationId, expectedMessageId, + tfaUpdateEmailMessageRequest).Result, AssertTfaUpdateEmailMessageResponse); + } + + [TestMethod] + public void ShouldSendTfaPinCodeViaSmsTest() + { + var givenApplicationId = "1234567"; + var givenMessageId = "7654321"; + var givenFrom = "Sender 1"; + var givenFirstName = "John"; + + var expectedPinId = "9C817C6F8AF3D48F9FE553282AFA2B67"; + var expectedTo = "41793026727"; + var expectedNcStatus = "NC_DESTINATION_REACHABLE"; + var expectedSmsStatus = "MESSAGE_SENT"; + + var givenRequest = $@" + {{ + ""applicationId"": ""{givenApplicationId}"", + ""messageId"": ""{givenMessageId}"", + ""from"": ""{givenFrom}"", + ""to"": ""{expectedTo}"", + ""placeholders"": {{ + ""firstName"": ""{givenFirstName}"" + }} + }}"; + + var expectedResponse = $@" + {{ + ""pinId"": ""{expectedPinId}"", + ""to"": ""{expectedTo}"", + ""ncStatus"": ""{expectedNcStatus}"", + ""smsStatus"": ""{expectedSmsStatus}"" + }}"; + + SetUpPostRequest(TFA_SEND_PIN, givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var givenPlaceholders = new Dictionary { { "firstName", givenFirstName } }; + var tfaStartAuthenticationRequest = new TfaStartAuthenticationRequest( + givenApplicationId, + givenFrom, + givenMessageId, + givenPlaceholders, + expectedTo + ); + + void AssertTfaStartAuthenticationResponse(TfaStartAuthenticationResponse tfaStartAuthenticationResponse) + { + Assert.IsNotNull(tfaStartAuthenticationResponse); + Assert.AreEqual(expectedPinId, tfaStartAuthenticationResponse.PinId); + Assert.AreEqual(expectedTo, tfaStartAuthenticationResponse.To); + Assert.AreEqual(expectedNcStatus, tfaStartAuthenticationResponse.NcStatus); + Assert.AreEqual(expectedSmsStatus, tfaStartAuthenticationResponse.SmsStatus); + } + + AssertResponse(tfaApi.SendTfaPinCodeOverSms(tfaStartAuthenticationRequest), + AssertTfaStartAuthenticationResponse); + AssertResponse(tfaApi.SendTfaPinCodeOverSmsAsync(tfaStartAuthenticationRequest).Result, + AssertTfaStartAuthenticationResponse); + + AssertResponseWithHttpInfo(tfaApi.SendTfaPinCodeOverSmsWithHttpInfo(tfaStartAuthenticationRequest), + AssertTfaStartAuthenticationResponse); + AssertResponseWithHttpInfo(tfaApi.SendTfaPinCodeOverSmsWithHttpInfoAsync(tfaStartAuthenticationRequest).Result, + AssertTfaStartAuthenticationResponse); + } + + [TestMethod] + public void ShouldResendTfaPinCodeViaSmsTest() + { + var givenFirstName = "John"; + + var expectedPinId = "9C817C6F8AF3D48F9FE553282AFA2B67"; + var expectedTo = "41793026727"; + var expectedNcStatus = "NC_DESTINATION_REACHABLE"; + var expectedSmsStatus = "MESSAGE_SENT"; + + var givenRequest = $@" + {{ + ""placeholders"": {{ + ""firstName"": ""{givenFirstName}"" + }} + }}"; + + var expectedResponse = $@" + {{ + ""pinId"": ""{expectedPinId}"", + ""to"": ""{expectedTo}"", + ""ncStatus"": ""{expectedNcStatus}"", + ""smsStatus"": ""{expectedSmsStatus}"" + }}"; + + SetUpPostRequest(TFA_RESEND_PIN.Replace("{pinId}", expectedPinId), givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var tfaResendPinRequest = new TfaResendPinRequest + { + Placeholders = new Dictionary { { "firstName", givenFirstName } } + }; + + void AssertTfaStartAuthenticationResponse(TfaStartAuthenticationResponse tfaStartAuthenticationResponse) + { + Assert.IsNotNull(tfaStartAuthenticationResponse); + Assert.AreEqual(expectedPinId, tfaStartAuthenticationResponse.PinId); + Assert.AreEqual(expectedTo, tfaStartAuthenticationResponse.To); + Assert.AreEqual(expectedNcStatus, tfaStartAuthenticationResponse.NcStatus); + Assert.AreEqual(expectedSmsStatus, tfaStartAuthenticationResponse.SmsStatus); + } + + AssertResponse(tfaApi.ResendTfaPinCodeOverSms(expectedPinId, tfaResendPinRequest), + AssertTfaStartAuthenticationResponse); + AssertResponse(tfaApi.ResendTfaPinCodeOverSmsAsync(expectedPinId, tfaResendPinRequest).Result, + AssertTfaStartAuthenticationResponse); + + AssertResponseWithHttpInfo(tfaApi.ResendTfaPinCodeOverSmsWithHttpInfo(expectedPinId, tfaResendPinRequest), + AssertTfaStartAuthenticationResponse); + AssertResponseWithHttpInfo( + tfaApi.ResendTfaPinCodeOverSmsWithHttpInfoAsync(expectedPinId, tfaResendPinRequest).Result, + AssertTfaStartAuthenticationResponse); + } + + [TestMethod] + public void ShouldSendTfaPinCodeViaVoiceTest() + { + var givenApplicationId = "1234567"; + var givenMessageId = "7654321"; + var givenFrom = "Sender 1"; + var givenFirstName = "John"; + + var expectedPinId = "9C817C6F8AF3D48F9FE553282AFA2B67"; + var expectedTo = "41793026727"; + var expectedCallStatus = "PENDING_ACCEPTED"; + + var givenRequest = $@" + {{ + ""applicationId"": ""{givenApplicationId}"", + ""messageId"": ""{givenMessageId}"", + ""from"": ""{givenFrom}"", + ""to"": ""{expectedTo}"", + ""placeholders"": {{ + ""firstName"": ""{givenFirstName}"" + }} + }}"; + + var expectedResponse = $@" + {{ + ""pinId"": ""{expectedPinId}"", + ""to"": ""{expectedTo}"", + ""callStatus"": ""{expectedCallStatus}"" + }}"; + + SetUpPostRequest(TFA_SEND_PIN_VOICE, givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var givenPlaceholders = new Dictionary { { "firstName", givenFirstName } }; + var tfaStartAuthenticationRequest = new TfaStartAuthenticationRequest( + givenApplicationId, + givenFrom, + givenMessageId, + givenPlaceholders, + expectedTo + ); + + void AssertTfaStartAuthenticationResponse(TfaStartAuthenticationResponse tfaStartAuthenticationResponse) + { + Assert.IsNotNull(tfaStartAuthenticationResponse); + Assert.AreEqual(expectedPinId, tfaStartAuthenticationResponse.PinId); + Assert.AreEqual(expectedTo, tfaStartAuthenticationResponse.To); + Assert.AreEqual(expectedCallStatus, tfaStartAuthenticationResponse.CallStatus); + } + + AssertResponse(tfaApi.SendTfaPinCodeOverVoice(tfaStartAuthenticationRequest), + AssertTfaStartAuthenticationResponse); + AssertResponse(tfaApi.SendTfaPinCodeOverVoiceAsync(tfaStartAuthenticationRequest).Result, + AssertTfaStartAuthenticationResponse); + + AssertResponseWithHttpInfo(tfaApi.SendTfaPinCodeOverVoiceWithHttpInfo(tfaStartAuthenticationRequest), + AssertTfaStartAuthenticationResponse); + AssertResponseWithHttpInfo( + tfaApi.SendTfaPinCodeOverVoiceWithHttpInfoAsync(tfaStartAuthenticationRequest).Result, + AssertTfaStartAuthenticationResponse); + } + + [TestMethod] + public void ShouldResendTfaPinCodeViaVoiceTest() + { + var givenFirstName = "John"; + + var expectedPinId = "9C817C6F8AF3D48F9FE553282AFA2B67"; + var expectedTo = "41793026727"; + var expectedCallStatus = "MESSAGE_SENT"; + + var givenRequest = $@" + {{ + ""placeholders"": {{ + ""firstName"": ""{givenFirstName}"" + }} + }}"; + + var expectedResponse = $@" + {{ + ""pinId"": ""{expectedPinId}"", + ""to"": {expectedTo}, + ""callStatus"": ""{expectedCallStatus}"" + }}"; + + SetUpPostRequest(TFA_RESEND_PIN_VOICE.Replace("{pinId}", expectedPinId), givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var tfaResendPinRequest = new TfaResendPinRequest + { + Placeholders = new Dictionary { { "firstName", givenFirstName } } + }; + + void AssertTfaStartAuthenticationResponse(TfaStartAuthenticationResponse tfaStartAuthenticationResponse) + { + Assert.IsNotNull(tfaStartAuthenticationResponse); + Assert.AreEqual(expectedPinId, tfaStartAuthenticationResponse.PinId); + Assert.AreEqual(expectedTo, tfaStartAuthenticationResponse.To); + Assert.AreEqual(expectedCallStatus, tfaStartAuthenticationResponse.CallStatus); + } + + AssertResponse(tfaApi.ResendTfaPinCodeOverVoice(expectedPinId, tfaResendPinRequest), + AssertTfaStartAuthenticationResponse); + ; + AssertResponse(tfaApi.ResendTfaPinCodeOverVoiceAsync(expectedPinId, tfaResendPinRequest).Result, + AssertTfaStartAuthenticationResponse); + + AssertResponseWithHttpInfo(tfaApi.ResendTfaPinCodeOverVoiceWithHttpInfo(expectedPinId, tfaResendPinRequest), + AssertTfaStartAuthenticationResponse); + AssertResponseWithHttpInfo( + tfaApi.ResendTfaPinCodeOverVoiceWithHttpInfoAsync(expectedPinId, tfaResendPinRequest).Result, + AssertTfaStartAuthenticationResponse); + } + + [TestMethod] + public void ShouldSendTfaPinCodeViaEmailTest() + { + var givenApplicationId = "1234567"; + var givenMessageId = "7654321"; + var givenFirstName = "John"; + + var expectedTo = "john.smith@example.com"; + var expectedPinId = "9C817C6F8AF3D48F9FE553282AFA2B67"; + var expectedEmailStatusName = "PENDING_ACCEPTED"; + var expectedEmailStatusDescription = "Message accepted, pending for delivery."; + + + var givenRequest = $@" + {{ + ""applicationId"": ""{givenApplicationId}"", + ""messageId"": ""{givenMessageId}"", + ""to"": ""{expectedTo}"", + ""placeholders"": {{ + ""firstName"": ""{givenFirstName}"" + }} + }}"; + + var expectedResponse = $@" + {{ + ""pinId"": ""{expectedPinId}"", + ""to"": ""{expectedTo}"", + ""emailStatus"": {{ + ""name"": ""{expectedEmailStatusName}"", + ""description"": ""{expectedEmailStatusDescription}"" + }} + }}"; + + SetUpPostRequest(TFA_SEND_PIN_EMAIL, givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var givenPlaceholders = new Dictionary { { "firstName", givenFirstName } }; + + var tfaStartEmailAuthenticationRequest = new TfaStartEmailAuthenticationRequest( + givenApplicationId, + messageId: givenMessageId, + to: expectedTo, + placeholders: givenPlaceholders + ); + + void AssertTfaStartEmailAuthenticationResponse( + TfaStartEmailAuthenticationResponse tfaStartEmailAuthenticationResponse) + { + Assert.IsNotNull(tfaStartEmailAuthenticationRequest); + Assert.AreEqual(expectedPinId, tfaStartEmailAuthenticationResponse.PinId); + Assert.AreEqual(expectedTo, tfaStartEmailAuthenticationResponse.To); + Assert.AreEqual(expectedEmailStatusName, tfaStartEmailAuthenticationResponse.EmailStatus.Name); + Assert.AreEqual(expectedEmailStatusDescription, + tfaStartEmailAuthenticationResponse.EmailStatus.Description); + } + + AssertResponse(tfaApi.Send2faPinCodeOverEmail(tfaStartEmailAuthenticationRequest), + AssertTfaStartEmailAuthenticationResponse); + AssertResponse(tfaApi.Send2faPinCodeOverEmailAsync(tfaStartEmailAuthenticationRequest).Result, + AssertTfaStartEmailAuthenticationResponse); + + AssertResponseWithHttpInfo(tfaApi.Send2faPinCodeOverEmailWithHttpInfo(tfaStartEmailAuthenticationRequest), + AssertTfaStartEmailAuthenticationResponse); + AssertResponseWithHttpInfo( + tfaApi.Send2faPinCodeOverEmailWithHttpInfoAsync(tfaStartEmailAuthenticationRequest).Result, + AssertTfaStartEmailAuthenticationResponse); + } + + [TestMethod] + public void ShouldResendTfaPinCodeViaEmailTest() + { + var givenFirstName = "John"; + + var expectedPinId = "9C817C6F8AF3D48F9FE553282AFA2B67"; + var expectedTo = "john.smith@example.com"; + var expectedEmailStatusName = "PENDING_ACCEPTED"; + var expectedEmailStatusDescription = "Message accepted, pending for delivery."; + + var givenRequest = $@" + {{ + ""placeholders"": {{ + ""firstName"": ""{givenFirstName}"" + }} + }}"; + + var expectedResponse = $@" + {{ + ""pinId"": ""{expectedPinId}"", + ""to"": ""{expectedTo}"", + ""emailStatus"": {{ + ""name"": ""{expectedEmailStatusName}"", + ""description"": ""{expectedEmailStatusDescription}"" + }} + }}"; + + SetUpPostRequest(TFA_RESEND_PIN_EMAIL.Replace("{pinId}", expectedPinId), givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var tfaResendPinRequest = new TfaResendPinRequest + { + Placeholders = new Dictionary { { "firstName", givenFirstName } } + }; + + void AssertTfaStartAuthenticationResponse( + TfaStartEmailAuthenticationResponse tfaStartEmailAuthenticationResponse) + { + Assert.IsNotNull(tfaStartEmailAuthenticationResponse); + Assert.AreEqual(expectedPinId, tfaStartEmailAuthenticationResponse.PinId); + Assert.AreEqual(expectedTo, tfaStartEmailAuthenticationResponse.To); + Assert.AreEqual(expectedEmailStatusName, tfaStartEmailAuthenticationResponse.EmailStatus.Name); + Assert.AreEqual(expectedEmailStatusDescription, + tfaStartEmailAuthenticationResponse.EmailStatus.Description); + } + + AssertResponse(tfaApi.Resend2faPinCodeOverEmail(expectedPinId, tfaResendPinRequest), + AssertTfaStartAuthenticationResponse); + ; + AssertResponse(tfaApi.Resend2faPinCodeOverEmailAsync(expectedPinId, tfaResendPinRequest).Result, + AssertTfaStartAuthenticationResponse); + + AssertResponseWithHttpInfo(tfaApi.Resend2faPinCodeOverEmailWithHttpInfo(expectedPinId, tfaResendPinRequest), + AssertTfaStartAuthenticationResponse); + AssertResponseWithHttpInfo( + tfaApi.Resend2faPinCodeOverEmailWithHttpInfoAsync(expectedPinId, tfaResendPinRequest).Result, + AssertTfaStartAuthenticationResponse); + } + + [TestMethod] + public void ShouldVerifyTfaCallTest() + { + var givenPin = "1598"; + + var expectedPinId = "9C817C6F8AF3D48F9FE553282AFA2B68"; + var expectedMsisdn = "41793026726"; + var expectedVerified = "true"; + var expectedAttemptsRemaining = 0; + + var givenRequest = $@" + {{ + ""pin"": ""{givenPin}"" + }}"; + + var expectedResponse = $@" + {{ + ""pinId"": ""{expectedPinId}"", + ""msisdn"": ""{expectedMsisdn}"", + ""verified"": {expectedVerified}, + ""attemptsRemaining"": {expectedAttemptsRemaining} + }}"; + + SetUpPostRequest(TFA_VERIFY_PIN.Replace("{pinId}", expectedPinId), givenRequest, expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + var tfaVerifyPinRequest = new TfaVerifyPinRequest(givenPin); + + void AssertTfaVerifyPinResponse(TfaVerifyPinResponse tfaVerifyPinResponse) + { + Assert.IsNotNull(tfaVerifyPinResponse); + Assert.AreEqual(expectedPinId, tfaVerifyPinResponse.PinId); + Assert.AreEqual(expectedMsisdn, tfaVerifyPinResponse.Msisdn); + Assert.AreEqual(bool.Parse(expectedVerified), tfaVerifyPinResponse.Verified); + Assert.AreEqual(expectedAttemptsRemaining, tfaVerifyPinResponse.AttemptsRemaining); + } + + AssertResponse(tfaApi.VerifyTfaPhoneNumber(expectedPinId, tfaVerifyPinRequest), AssertTfaVerifyPinResponse); + ; + AssertResponse(tfaApi.VerifyTfaPhoneNumberAsync(expectedPinId, tfaVerifyPinRequest).Result, + AssertTfaVerifyPinResponse); + + AssertResponseWithHttpInfo(tfaApi.VerifyTfaPhoneNumberWithHttpInfo(expectedPinId, tfaVerifyPinRequest), + AssertTfaVerifyPinResponse); + AssertResponseWithHttpInfo( + tfaApi.VerifyTfaPhoneNumberWithHttpInfoAsync(expectedPinId, tfaVerifyPinRequest).Result, + AssertTfaVerifyPinResponse); + } + + [TestMethod] + public void ShouldGetTfaVerificationStatusTest() + { + var givenApplicationId = "16A8B5FE2BCD6CA716A2D780CB3F3390"; + + var expectedMsisdn = "41793026726"; + var expectedVerified1 = "true"; + var expectedVerifiedAt1 = 1418364366L; + var expectedSentAt1 = 1418364246L; + var expectedVerified2 = "false"; + var expectedVerifiedAt2 = 1418364226L; + var expectedSentAt2 = 1418333246L; + + var expectedResponse = $@" + {{ + ""verifications"": [ + {{ + ""msisdn"": ""{expectedMsisdn}"", + ""verified"": {expectedVerified1}, + ""verifiedAt"": {expectedVerifiedAt1}, + ""sentAt"": {expectedSentAt1} + }}, + {{ + ""msisdn"": ""{expectedMsisdn}"", + ""verified"": {expectedVerified2}, + ""verifiedAt"": {expectedVerifiedAt2}, + ""sentAt"": {expectedSentAt2} + }} + ] + }}"; + + SetUpGetRequest(TFA_VERIFICATION_STATUS.Replace("{appId}", givenApplicationId), expectedResponse, 200); + + var tfaApi = new TfaApi(configuration); + + void AssertTfaVerificationResponse(TfaVerificationResponse tfaVerificationResponse) + { + Assert.IsNotNull(tfaVerificationResponse); + Assert.IsNotNull(tfaVerificationResponse.Verifications); + Assert.IsTrue(tfaVerificationResponse.Verifications.Count.Equals(2)); + + var tfaVerification1 = tfaVerificationResponse.Verifications[0]; + Assert.AreEqual(expectedMsisdn, tfaVerification1.Msisdn); + Assert.AreEqual(bool.Parse(expectedVerified1), tfaVerification1.Verified); + Assert.AreEqual(expectedVerifiedAt1, tfaVerification1.VerifiedAt); + Assert.AreEqual(expectedSentAt1, tfaVerification1.SentAt); + + var tfaVerification2 = tfaVerificationResponse.Verifications[1]; + Assert.AreEqual(expectedMsisdn, tfaVerification2.Msisdn); + Assert.AreEqual(bool.Parse(expectedVerified2), tfaVerification2.Verified); + Assert.AreEqual(expectedVerifiedAt2, tfaVerification2.VerifiedAt); + Assert.AreEqual(expectedSentAt2, tfaVerification2.SentAt); + } + + AssertResponse(tfaApi.GetTfaVerificationStatus(expectedMsisdn, givenApplicationId), + AssertTfaVerificationResponse); + ; + AssertResponse(tfaApi.GetTfaVerificationStatusAsync(expectedMsisdn, givenApplicationId).Result, + AssertTfaVerificationResponse); + + AssertResponseWithHttpInfo(tfaApi.GetTfaVerificationStatusWithHttpInfo(expectedMsisdn, givenApplicationId), + AssertTfaVerificationResponse); + AssertResponseWithHttpInfo( + tfaApi.GetTfaVerificationStatusWithHttpInfoAsync(expectedMsisdn, givenApplicationId).Result, + AssertTfaVerificationResponse); + } +} \ No newline at end of file diff --git a/ApiClient.Tests/ApiClient.Tests.csproj b/ApiClient.Tests/ApiClient.Tests.csproj new file mode 100644 index 0000000..abbb2c1 --- /dev/null +++ b/ApiClient.Tests/ApiClient.Tests.csproj @@ -0,0 +1,23 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + + + + + + + diff --git a/ApiClient.Tests/ApiExceptionTest.cs b/ApiClient.Tests/ApiExceptionTest.cs new file mode 100644 index 0000000..9af435c --- /dev/null +++ b/ApiClient.Tests/ApiExceptionTest.cs @@ -0,0 +1,110 @@ +using ApiClient.Tests.Api; +using Infobip.Api.Client.Api; +using Infobip.Api.Client.Model; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ApiException = Infobip.Api.Client.ApiException; + +namespace ApiClient.Tests; + +[TestClass] +public class ApiExceptionTest : ApiTest +{ + protected const string SMS_SEND_TEXT_ADVANCED_ENDPOINT = "/sms/2/text/advanced"; + + internal static readonly Tuple[] ErrorResponses = + { + Tuple.Create(400, "BAD_REQUEST", "Bad Request", + "[messages[0].destinations : size must be between 1 and 2147483647]"), + Tuple.Create(401, "UNAUTHORIZED", "Unauthorized", "Invalid login details"), + Tuple.Create(403, "UNAUTHORIZED", "Forbidden", "Unauthorized access"), + Tuple.Create(404, "NOT_FOUND", "Not Found", "Requested URL not found: /sms/2/text/advanced"), + Tuple.Create(429, "TOO_MANY_REQUESTS", "Too Many Requests", "Too many requests"), + Tuple.Create(500, "GENERAL_ERROR", "Internal Server Error", "Something went wrong. Please contact support."), + Tuple.Create(503, "0", "Service Unavailable", "Error processing email validation request! Please try again") + }; + + [DataTestMethod] + [DataRow(0)] + [DataRow(1)] + [DataRow(2)] + [DataRow(3)] + [DataRow(4)] + [DataRow(5)] + [DataRow(6)] + public void ErrorResponseTest(int errorResponseIndex) + { + var httpCode = ErrorResponses[errorResponseIndex].Item1; + var messageId = ErrorResponses[errorResponseIndex].Item2; + var errorPhrase = ErrorResponses[errorResponseIndex].Item3; + var errorText = ErrorResponses[errorResponseIndex].Item4; + + var to = "41793026727"; + var from = "InfoSMS"; + var message = "This is a sample message"; + + var responseJson = $@" + {{ + ""requestError"": {{ + ""serviceException"": {{ + ""messageId"": ""{messageId}"", + ""text"": ""{errorText}"" + }} + }} + }}"; + + var expectedRequest = $@" + {{ + ""messages"": [ + {{ + ""destinations"": [ + {{ + ""to"": ""{to}"" + }} + ], + ""flash"":false, + ""from"": ""{from}"", + ""intermediateReport"":false, + ""text"": ""{message}"" + }} + ], + ""includeSmsCountInResponse"":false + }}"; + + var responseHeaders = new Dictionary + { + { "Server", "SMS,API" }, + { "X-Request-ID", "1608758729810312842" }, + { "Content-Type", "application/json; charset=utf-8" } + }; + + SetUpPostRequest(SMS_SEND_TEXT_ADVANCED_ENDPOINT, expectedRequest, responseJson, httpCode); + + var smsApi = new SmsApi(configuration); + + var request = new SmsAdvancedTextualRequest( + messages: new List + { + new( + from: from, text: message, destinations: new List { new(to: to) } + ) + } + ); + + try + { + var result = smsApi.SendSmsMessage(request); + } + catch (ApiException ex) + { + Assert.AreEqual(httpCode, ex.ErrorCode); + Assert.IsNotNull(ex.ErrorContent); + Assert.AreEqual(responseJson, ex.ErrorContent); + Assert.IsInstanceOfType(ex, typeof(ApiException)); + Assert.IsTrue(ex.Message.Contains(errorPhrase)); + Assert.IsTrue(ex.ErrorContent.ToString()?.Contains(messageId) == true); + Assert.IsTrue(ex.ErrorContent.ToString()?.Contains(errorText) == true); + Assert.IsTrue(responseHeaders.All(h => + ex.Headers.ContainsKey(h.Key) && ex.Headers[h.Key].First().Equals(h.Value))); + } + } +} \ No newline at end of file diff --git a/ApiClient.Tests/DateTimeSerializationTest.cs b/ApiClient.Tests/DateTimeSerializationTest.cs new file mode 100644 index 0000000..030d4b2 --- /dev/null +++ b/ApiClient.Tests/DateTimeSerializationTest.cs @@ -0,0 +1,77 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json; + +namespace ApiClient.Tests; + +[TestClass] +public class DateTimeSerializationTest +{ + private const string EXPECTED_DATETIME_FORMAT = "yyyy-MM-ddTHH:mm:ss.fffzzzz"; + private const string EXPECTED_DATE_FORMAT = "yyyy-MM-dd"; + private const string EXPECTED_DATE = "2035-08-18"; + private const long EXPECTED_TICKS = 642066048000000000; + + internal static readonly DateTimeOffset[] DateTimeValues = + { + new(2035, 8, 18, 12, 8, 42, 777, new TimeSpan(0, 0, 0)), + new(2035, 8, 18, 13, 8, 42, 777, new TimeSpan(1, 0, 0)), + new(2035, 8, 18, 11, 8, 42, 777, new TimeSpan(-1, 0, 0)), + new(2035, 8, 18, 17, 8, 42, 777, new TimeSpan(5, 0, 0)), + new(2035, 8, 18, 7, 8, 42, 777, new TimeSpan(-5, 0, 0)), + new(2035, 8, 18, 13, 38, 42, 777, new TimeSpan(1, 30, 0)), + new(2035, 8, 18, 10, 38, 42, 777, new TimeSpan(-1, -30, 0)), + new(2035, 8, 18, 17, 38, 42, 777, new TimeSpan(5, 30, 0)), + new(2035, 8, 18, 6, 38, 42, 777, new TimeSpan(-5, -30, 0)) + }; + + [DataRow("2035-08-18T12:08:42.777+0000", 0)] + [DataRow("2035-08-18T13:08:42.777+0100", 1)] + [DataRow("2035-08-18T11:08:42.777-0100", 2)] + [DataRow("2035-08-18T17:08:42.777+0500", 3)] + [DataRow("2035-08-18T07:08:42.777-0500", 4)] + [DataRow("2035-08-18T13:38:42.777+0130", 5)] + [DataRow("2035-08-18T10:38:42.777-0130", 6)] + [DataRow("2035-08-18T17:38:42.777+0530", 7)] + [DataRow("2035-08-18T06:38:42.777-0530", 8)] + [DataTestMethod] + public void DateTimeFormatDeserializationTest(string dateString, int dateValueIndex) + { + var expected = DateTimeValues[dateValueIndex]; + + var jsonDate = $"{{\"date\":\"{dateString}\"}}"; + + var actual = JsonConvert.DeserializeObject(jsonDate)!; + + Assert.AreEqual(expected, actual.Date); + Assert.AreEqual(expected.Ticks, actual.Date.Ticks); + Assert.AreEqual(expected.Offset, actual.Date.Offset); + Assert.AreEqual(EXPECTED_DATE, actual.Date.ToString(EXPECTED_DATE_FORMAT)); + Assert.AreEqual(EXPECTED_TICKS, actual.Date.Date.Ticks); + Assert.AreEqual(expected.ToString(), actual.Date.ToString()); + Assert.AreEqual(expected.ToString(EXPECTED_DATETIME_FORMAT), actual.Date.ToString(EXPECTED_DATETIME_FORMAT)); + } + + [DataRow(0, "2035-08-18T12:08:42.777+00:00")] + [DataRow(1, "2035-08-18T13:08:42.777+01:00")] + [DataRow(2, "2035-08-18T11:08:42.777-01:00")] + [DataRow(3, "2035-08-18T17:08:42.777+05:00")] + [DataRow(4, "2035-08-18T07:08:42.777-05:00")] + [DataRow(5, "2035-08-18T13:38:42.777+01:30")] + [DataRow(6, "2035-08-18T10:38:42.777-01:30")] + [DataRow(7, "2035-08-18T17:38:42.777+05:30")] + [DataRow(8, "2035-08-18T06:38:42.777-05:30")] + [DataTestMethod] + public void DateTimeFormatSerializationTest(int dateValueIndex, string expected) + { + var initialDate = DateTimeValues[dateValueIndex]; + + var actual = JsonConvert.SerializeObject(initialDate); + + Assert.AreEqual($"\"{expected}\"", actual); + } + + public class TestObject + { + public DateTimeOffset Date { get; set; } + } +} \ No newline at end of file diff --git a/ApiClient.Tests/GeneralSetupTest.cs b/ApiClient.Tests/GeneralSetupTest.cs new file mode 100644 index 0000000..f0aee8e --- /dev/null +++ b/ApiClient.Tests/GeneralSetupTest.cs @@ -0,0 +1,70 @@ +using System.Net; +using ApiClient.Tests.Api; +using Infobip.Api.Client; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using RestSharp; + +namespace ApiClient.Tests; + +[TestClass] +public class GeneralSetupTest : ApiTest +{ + protected const string SMS_SEND_TEXT_ADVANCED_ENDPOINT = "/sms/2/text/advanced"; + + [TestMethod] + public void UsingExampleFromDocs() + { + var givenRequest = @" + { + ""messages"": [ + { + ""from"": ""InfoSMS"", + ""destinations"": [ + { + ""to"": ""41793026727"" + } + ], + ""text"": ""This is a sample message"" + } + ] + }"; + + var expectedResponse = @" + { + ""bulkId"": ""2034072219640523072"", + ""messages"": [ + { + ""to"": ""41793026727"", + ""status"": { + ""groupId"": 1, + ""groupName"": ""PENDING"", + ""id"": 26, + ""name"": ""MESSAGE_ACCEPTED"", + ""description"": ""Message sent to next instance"" + }, + ""messageId"": ""2250be2d4219-3af1-78856-aabe-1362af1edfd2"" + } + ] + }"; + + SetUpPostRequest(SMS_SEND_TEXT_ADVANCED_ENDPOINT, new Dictionary { { "param1", "val1" } }, + givenRequest, expectedResponse, 200); + + var client = new RestClient(configuration!.BasePath + SMS_SEND_TEXT_ADVANCED_ENDPOINT) + { + UserAgent = "infobip-api-client-csharp/" + Configuration.Version, + Timeout = -1 + }; + var request = new RestRequest(Method.POST); + request.AddHeader("Authorization", configuration.ApiKeyWithPrefix); + request.AddHeader("Content-Type", "application/json; charset=utf-8"); + request.AddHeader("Accept", "application/json"); + request.AddQueryParameter("param1", "val1"); + request.AddParameter("application/json", givenRequest, ParameterType.RequestBody); + var response = client.Execute(request); + + Assert.IsNotNull(response); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + Assert.AreEqual(expectedResponse, response.Content); + } +} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5024242..e37a7b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,32 +1,197 @@ -# Getting Involved +# Guidelines For Contributing -Thanks for your interest in the project, we'd love to have you involved! Check out sections below to find out more about what to do next... +✨✨ First off, thanks for taking the time to contribute! ✨✨ -## Submitting an Issue +The following is a set of guidelines for contributing to Infobip API C# Client library, these are mostly guidelines, not rules. You are free to propose changes to this document in a pull request. -If you've seen something that is or may seem like a bug or a mistake in documentation, or you simply have a suggestion for a new feature, please go ahead and open [an issue][issue-link]. -Include as much information as you have. +## 🚩 Issues -Before you submit your issue, please do the archive search first, as there may be a similar question that's already been answered or is pending a response. +How to report a bug? -If you haven't found any related issues among the already asked, feel free to open a new one. +If you've seen something that is or may seem like a bug or a mistake in documentation, or you simply have a suggestion for a new feature, please go ahead and open [an issue][issue-link]. +Include as much information as you have. Before you submit your issue, please do the archive search first, as there may be a similar question that's already been answered or is pending a response. -For new feature requests, any sort of bug, anomaly, issue, etc. please try to provide information, as structured below. +If you haven't found any related issues among the already asked, feel free to open a new one. For new feature requests, any sort of bug, anomaly, issue, etc. please try to provide information, as structured below. You don't have to follow it to the letter, but having it structured like below may save us a lot of time to pinpoint and fix the issue quicker. ### New issue structure (bugs, anomalies, improvements...) + Providing the following information will increase the chances of your issue being dealt with quickly: * **Short TO-THE-POINT Overview** - what seems to be the issue. * **Description** - more detailed explanation of the issue. The stack trace in cases where it is applicable. -* **Which `Infobip.Api.Client` version(s)** - which library version(s) did you use when the issue occurred. -* **Environment** - is this a problem with all development/testing/production environments or only a specific one(s)? +* **Which `infobip-api-csharp-client` version(s)** - which library version(s) you used when the issue occurred. * **Reproducing** - how did it happen? Is it an isolated anomaly, can you recreate it, what are the steps to recreate it? * **Related Issues** - is there something similar to this issue that has been reported before? If so, please tag that issue(s) as a reference. -* **Suggest a Fix** - this code is auto generated, but perhaps you can provide us with your code sample as a fix to the part of the code that is causing the bug. -## Pull requests disclaimer -We will not be accepting any pull requests, as the source code within this repository is **auto generated**. Any change needs to be made by us within the library generation configuration. -Having said that, we still fully encourage you to submit an issue, since that will help us track it and keep you up to date. +If you want to provide the solution to the issue yourself, you are free to do that as well 😊 +We welcome and encourage any effort from the community to take part in solving the issues. +For more details on how to properly provide bugfixes, please check the [Pull request](#%EF%B8%8F-pull-request) section. + +## 🚀 Enhancements/Suggestions/Improvements + +We welcome any suggestion to improve the project! If you have an idea for a new feature or an improvement, +please follow these guidelines to help us understand your proposal and evaluate its feasibility: + +* **Check Existing Issues First** - before suggesting a new enhancement, please search the issue tracker to see if a similar idea or request has already been discussed or proposed. + If you find a related issue, feel free to add a comment to it, offering additional context or your thoughts, instead of opening a new one. +* **Open a New Enhancement Issue** - if your suggestion is new, please open a new issue and prefix it with "ENHANCEMENT" or "SUGGESTION". + Please try to title your issue as clearly as possible to summarize your enhancement idea. +* **Provide a Detailed Description** - in your issue description, try to include as much of the following information: + * **Problem:** What problem does this enhancement solve? Why is this feature needed? + * **Proposed Solution:** Describe the enhancement or feature you’re suggesting. How should it work? Provide as much detail as possible. + * **Alternatives Considered:** Have you thought of other ways to solve the problem? If so, briefly explain why your proposed solution is better. + * **Additional Context:** Share any examples, mockups, screenshots, or links to similar implementations (if applicable). +* **Stay Focused and Specific** - try to keep your enhancement idea focused on a single problem or feature. If you have multiple ideas, consider creating separate issues for each to make the discussion easier to follow. +* **Be Open to Feedback** - we encourage healthy discussion about proposed enhancements. Be open to feedback, as maintainers and other contributors may have questions or alternative suggestions. +* **Contribute the Enhancement** - if you want implement your suggestion or if you're interested in working on the other people's enhancements yourself, please check the [Pull request](#%EF%B8%8F-pull-request) section on how to do that. + +## ℹ️ Asking for General Help + +The [Infobip website](https://www.infobip.com/docs/api) has a list of resources for getting programming help and more. +For any question contributors are available at [DevRel@infobip.com](mailto:DevRel@infobip.com). + +## ⬇️ Pull request + +### 🍴 Step 1: Fork + +Fork the project on GitHub and clone your fork locally: + +```bash +git clone https://github.com//infobip-api-csharp-client.git +cd infobip-api-csharp-client +git remote add upstream https://github.com/infobip/infobip-api-csharp-client.git +git fetch upstream +``` + +### 🛠️ Step 2: Build + +Install all required dependencies & build the project with: + +```bash +dotnet restore +dotnet build --no-restore +``` + +Or simply: + +```bash +dotnet build +``` + +Afterwards, run the tests that are in the project, all tests should pass. + +```bash +dotnet test +``` + +### 🌱 Step 3: Branch + +To keep your development environment organized, create local branches to hold your work. +These should be branched directly off of the master branch. + +```bash +git checkout -b my-branch -t upstream/main +``` + +### 💻 Step 4: Code + +Please follow code structure and naming structure that is already in the repository. +This library uses [CleanupCode Command-Line Tool](https://www.jetbrains.com/help/resharper/CleanupCode.html) from [ReSharper Command Line Tools](https://www.jetbrains.com/resharper/download/#section=commandline) made by JetBrains to format the code. +You can run the cleanup code tool with the following command (Windows): + +```bash +cleanupcode.exe \Infobip.Api.Client.sln +``` + +Or for Linux/masOS (you will need to install `mono` beforehand): +```bash +mono cleanupcode.exe /Infobip.Api.Client.sln +``` + +### ✅ Step 5: Commit + +#### Commit your changes + +It is recommended to keep your changes grouped logically within individual commits. +Many contributors find it easier to review changes that are split across multiple commits. +There is no limit to the number of commits in a pull request. + +```bash +git add my/changed/files +git commit -m "Commit message" +``` + +Note that multiple commits get squashed when the branch is merged to master. +A good commit message should describe what changed and why. +Commit message should: + +* Contain a short description of the change (preferably 50 characters or less, and no more than 72 characters) +* First letter should be capital and rest entirely in lowercase with the exception of proper nouns, acronyms, + and the words that refer to code, like function/variable names + +#### ⚠️ Breaking Changes + +When commit has the breaking change first line of commit text should be BREAKING CHANGE. + +### 📌 Step 6: Rebase + +Once you have committed your changes, it is a good idea to use git rebase (not git merge) to synchronize your work with the main repository. + +```bash +git fetch upstream +git rebase upstream/main +``` + +### 🧪 Step 7: Tests + +Before submitting your changes in a pull request, always run the full test suite. +You can take a look at other tests for inspiration. Bug fixes and features should always come with tests. +Make sure the linter does not report any issues and that all tests pass. Please do not submit patches that fail either check. + +### 🚀 Step 8: Push + +Once your commits are ready to go -- with passing tests and linting -- begin the process of opening a pull request by pushing your working branch to GitHub. + +```bash +git push origin my-branch +``` + +### 📬 Step 9: Opening the Pull Request + +From within GitHub, open new pull request. +Your PR may be delayed in being merged as maintainers seek more information or clarify ambiguities. + +### 🤼 Step 10: Discuss and update + +You will probably get feedback or requests for changes to your pull request. +This is a big part of the submission process so don't be discouraged! + +To make changes to an existing pull request, make the changes to your local branch, +add a new commit with those changes, and push those to your fork. GitHub will automatically update the pull request. + +```bash +git add my/changed/files +git commit -m "Commit message" +git push origin my-branch +``` + +Feel free to post a comment in the pull request to ping reviewers if you are awaiting an answer on something. + +### 🌍 Step 11: Merging + +In order for a pull request to be merged, it needs to be reviewed and approved by at least one repository owner and pass the CI. +After that, if there are no objections from other contributors, the pull request can be merged. + +🎉🎊 Congratulations and thanks for your contribution! 🎊🎉 + +Every pull request is tested on the Continuous Integration (CI) system to confirm that it works. +Ideally, the pull request will pass ("be green") on all of CI's tests. +This means that all tests pass and there are no linting errors. + +## 📚 Further Reading + +For more in-depth guides on developing SDKs, see +[Readme](README.md) and [Infobip's website](https://www.infobip.com/docs/api). -[issue-link]: https://github.com/infobip/infobip-api-csharp-client/issues/new +[issue-link]: https://github.com/infobip/infobip-api-csharp-client/issues/new \ No newline at end of file diff --git a/Infobip.Api.Client.sln b/Infobip.Api.Client.sln index e2058df..9aaf209 100644 --- a/Infobip.Api.Client.sln +++ b/Infobip.Api.Client.sln @@ -1,8 +1,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34031.279 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infobip.Api.Client", "src\Infobip.Api.Client\Infobip.Api.Client.csproj", "{CADD32C6-EEAF-4F62-A44B-F6E35AFEAA0F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infobip.Api.Client", "src\Infobip.Api.Client\Infobip.Api.Client.csproj", "{CADD32C6-EEAF-4F62-A44B-F6E35AFEAA0F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiClient.Tests", "ApiClient.Tests\ApiClient.Tests.csproj", "{3AEFA95F-23A8-4BFB-AEC8-C44296C07D3C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -14,12 +16,15 @@ Global {CADD32C6-EEAF-4F62-A44B-F6E35AFEAA0F}.Debug|Any CPU.Build.0 = Debug|Any CPU {CADD32C6-EEAF-4F62-A44B-F6E35AFEAA0F}.Release|Any CPU.ActiveCfg = Release|Any CPU {CADD32C6-EEAF-4F62-A44B-F6E35AFEAA0F}.Release|Any CPU.Build.0 = Release|Any CPU - {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {19F1DEBC-DE5E-4517-8062-F000CD499087}.Debug|Any CPU.Build.0 = Debug|Any CPU - {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.ActiveCfg = Release|Any CPU - {19F1DEBC-DE5E-4517-8062-F000CD499087}.Release|Any CPU.Build.0 = Release|Any CPU + {3AEFA95F-23A8-4BFB-AEC8-C44296C07D3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AEFA95F-23A8-4BFB-AEC8-C44296C07D3C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AEFA95F-23A8-4BFB-AEC8-C44296C07D3C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AEFA95F-23A8-4BFB-AEC8-C44296C07D3C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection -EndGlobal \ No newline at end of file + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CFCD2192-6FEE-48E8-9099-EF750D54B05C} + EndGlobalSection +EndGlobal