From c45a58236c986d632b9902ac74acc52f99a53141 Mon Sep 17 00:00:00 2001 From: dnaumov Date: Wed, 22 Jul 2020 14:54:50 -0400 Subject: [PATCH] Improve Invoking Actions --- Acumatica REST API Client.sln | 6 ++++ Acumatica.RESTClient/Api/EntityAPI.cs | 43 ++++++++++++++---------- RESTClientTests/ActionLocationTests.cs | 46 ++++++++++++++++++++++++++ RESTClientTests/RESTClientTests.csproj | 44 ++++++++++++++++++++++++ RESTClientTests/app.config | 11 ++++++ RESTClientTests/packages.config | 10 ++++++ 6 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 RESTClientTests/ActionLocationTests.cs create mode 100644 RESTClientTests/RESTClientTests.csproj create mode 100644 RESTClientTests/app.config create mode 100644 RESTClientTests/packages.config diff --git a/Acumatica REST API Client.sln b/Acumatica REST API Client.sln index 2b18cd8c..d89a9c53 100644 --- a/Acumatica REST API Client.sln +++ b/Acumatica REST API Client.sln @@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Acumatica.POS_17.200.001", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Acumatica.ISVCB_19.1", "Acumatica.ISVCB_19.1\Acumatica.ISVCB_19.1.csproj", "{18D5146E-4B20-4343-8A38-AD95EE15B797}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RESTClientTests", "RESTClientTests\RESTClientTests.csproj", "{C56AC405-E788-41DF-B530-D964B55625E7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -71,6 +73,10 @@ Global {18D5146E-4B20-4343-8A38-AD95EE15B797}.Debug|Any CPU.Build.0 = Debug|Any CPU {18D5146E-4B20-4343-8A38-AD95EE15B797}.Release|Any CPU.ActiveCfg = Release|Any CPU {18D5146E-4B20-4343-8A38-AD95EE15B797}.Release|Any CPU.Build.0 = Release|Any CPU + {C56AC405-E788-41DF-B530-D964B55625E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C56AC405-E788-41DF-B530-D964B55625E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C56AC405-E788-41DF-B530-D964B55625E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C56AC405-E788-41DF-B530-D964B55625E7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Acumatica.RESTClient/Api/EntityAPI.cs b/Acumatica.RESTClient/Api/EntityAPI.cs index e97ad0e0..8d06fc1d 100644 --- a/Acumatica.RESTClient/Api/EntityAPI.cs +++ b/Acumatica.RESTClient/Api/EntityAPI.cs @@ -324,36 +324,43 @@ public async System.Threading.Tasks.Task DeleteByIdAsync(Guid? id) #endregion #region Implementation - private struct Location + public struct Location { public string Site; - public string Entity; + public string Status; public string EndpointName; public string EndpointVersion; public string EntityName; public string ActionName; - public string Status; public string ID; } - private Location ParseLocation(string location) + public static Location ParseLocation(string location) { + string entityKeyword = "/entity/"; + char[] pathSeparators = new char[] { '/' }; + var result = new Location(); - - var parts = location.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); - result.Site = parts[0]; - result.Entity = parts[1]; - result.EndpointName = parts[2]; - result.EndpointVersion = parts[3]; - result.EntityName = parts[4]; - if (parts.Length == 6) + var parts = location.Split(pathSeparators, StringSplitOptions.RemoveEmptyEntries); + result.ID = parts[parts.Length - 1]; + + int indexOfEntity = location.IndexOf(entityKeyword, StringComparison.OrdinalIgnoreCase); + if (indexOfEntity < 0) + throw new Exception("Incorrect location"); + if (location.Substring(indexOfEntity + entityKeyword.Length).IndexOf(entityKeyword, StringComparison.OrdinalIgnoreCase) >= 0) + throw new Exception("Location cannot be parsed as it contains more than 1 entity keyword"); + result.Site = location.Substring(0, indexOfEntity); + string restOfLocation = location.Substring(indexOfEntity); + parts = restOfLocation.Split(pathSeparators, StringSplitOptions.RemoveEmptyEntries); + + result.EndpointName = parts[1]; + result.EndpointVersion = parts[2]; + result.EntityName = parts[3]; + if (parts.Length == 7) { - result.ID = parts[5]; - return result; + result.ActionName = parts[4]; + result.Status = parts[5]; } - result.ActionName = parts[5]; - result.Status = parts[6]; - result.ID = parts[7]; return result; } @@ -368,6 +375,8 @@ public int GetProcessStatus(string invokeResult) ThrowMissingParameter("GetProcessStatus", nameof(invokeResult)); var parsedLocation = ParseLocation(invokeResult); + if (parsedLocation.ActionName == null) + return 204; var localVarPath = "/" + parsedLocation.EntityName + "/" + parsedLocation.ActionName + "/" + parsedLocation.Status + "/" + parsedLocation.ID; var localVarFileParams = new Dictionary(); diff --git a/RESTClientTests/ActionLocationTests.cs b/RESTClientTests/ActionLocationTests.cs new file mode 100644 index 00000000..41a3437b --- /dev/null +++ b/RESTClientTests/ActionLocationTests.cs @@ -0,0 +1,46 @@ +using FluentAssertions; +using System.Linq; +using Xunit; +using System; +using System.Globalization; + +using Acumatica.RESTClient.Model; +using Acumatica.RESTClient.Api; + +namespace RESTClientTests +{ + public class ActionLocationTests + { + [Theory] + [InlineData("/demo", "Default", "{0}/entity/{1}/18.200.001/Bill/ReleaseBill/status/9bab77d3-61dd-488a-ba84-d6820f06d114")] + [InlineData("", "Default", "{0}/entity/{1}/18.200.001/Bill/ReleaseBill/status/42e1c8e2-6346-452e-a604-cff94e7d751a")] + [InlineData("/demo/test", "Default", "{0}/entity/{1}/18.200.001/Bill/ReleaseBill/status/1c1a0de3-2bc1-41ea-93fd-c4e3d98e7f03")] + [InlineData("/AcumaticaEntity", "CustomEntityEndpoint", "{0}/entity/{1}/18.200.001/Bill/ReleaseBill/status/1c1a0de3-2bc1-41ea-93fd-c4e3d98e7f03")] + [InlineData("http://localhost:1231", "Default", "{0}/entity/{1}/18.200.001/Bill/ReleaseBill/status/1c1a0de3-2bc1-41ea-93fd-c4e3d98e7f03")] + [InlineData("https://int.acumatica.com/TestsSite", "Default", "{0}/entity/{1}/18.200.001/Bill/ReleaseBill/status/1c1a0de3-2bc1-41ea-93fd-c4e3d98e7f03")] + public void ParseLocationTestWithAction(string expectedSite, string expectedEndpoint, string inputLocation) + { + var parsedLocation = EntityAPI.ParseLocation(string.Format(inputLocation, expectedSite, expectedEndpoint)); + parsedLocation.EndpointName.Should().Be(expectedEndpoint); + parsedLocation.EndpointVersion.Should().Be("18.200.001"); + parsedLocation.ActionName.Should().Be("ReleaseBill"); + parsedLocation.Site.Should().Be(expectedSite); + } + + [Theory] + [InlineData("/demo", "Default", "{0}/entity/{1}/18.200.001/Bill/")] + [InlineData("", "Default", "{0}/entity/{1}/18.200.001/Bill")] + [InlineData("/demo/test", "Default", "{0}/entity/{1}/18.200.001/Bill/")] + [InlineData("/AcumaticaEntity", "CustomEntityEndpoint", "{0}/entity/{1}/18.200.001/Bill")] + [InlineData("http://localhost:1231", "Default", "{0}/entity/{1}/18.200.001/Bill")] + [InlineData("https://int.acumatica.com/TestsSite", "Default", "{0}/entity/{1}/18.200.001/Bill")] + public void ParseLocationTestWithoutAction(string expectedSite, string expectedEndpoint, string inputLocation) + { + var parsedLocation = EntityAPI.ParseLocation(string.Format(inputLocation, expectedSite, expectedEndpoint)); + parsedLocation.EndpointName.Should().Be(expectedEndpoint); + parsedLocation.EndpointVersion.Should().Be("18.200.001"); + parsedLocation.ActionName.Should().BeNull(); + parsedLocation.Site.Should().Be(expectedSite); + } + } +} diff --git a/RESTClientTests/RESTClientTests.csproj b/RESTClientTests/RESTClientTests.csproj new file mode 100644 index 00000000..d8385050 --- /dev/null +++ b/RESTClientTests/RESTClientTests.csproj @@ -0,0 +1,44 @@ + + + net48 + RESTClientTests + RESTClientTests + Copyright © 2020 + bin\$(Configuration)\ + 3 + + + full + + + pdbonly + + + + + + + + + + + + + + + + + + all + + + + + + + + + + + + \ No newline at end of file diff --git a/RESTClientTests/app.config b/RESTClientTests/app.config new file mode 100644 index 00000000..e936cc13 --- /dev/null +++ b/RESTClientTests/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/RESTClientTests/packages.config b/RESTClientTests/packages.config new file mode 100644 index 00000000..b42193f9 --- /dev/null +++ b/RESTClientTests/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file