Skip to content

Commit 7a6b3b7

Browse files
authored
[chore] Support new UPS carrier account create/update endpoint (#574)
- Consolidate dictionary serialization process for easier re-usability - Add UPS-specific carrier account creation parameters - Mark legacy (dictionary) carrier account creation function as deprecated (does not support FedEx and UPS registrations) - Introduce new error type raised if invalid function called (guard clause for legacy carrier account creation function) - Add and update unit tests for carrier account creation + FedEx and UPS-specific tests - Add support for UPS carrier account update deviating flow - New parameter sets for UPS update - Add and update unit tests for carrier account updates - Add/re-record cassettes as needed - Add init-examples-submodule Make step - Update examples submodule
1 parent a27ef94 commit 7a6b3b7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1800
-727
lines changed

Diff for: EasyPost.Tests/Fixture.cs

+14-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ internal static Dictionary<string, object> BasicPickup
5656

5757
const string pickupDate = "2024-04-08";
5858

59-
fixture!.AddOrUpdate("min_datetime", pickupDate);
60-
fixture!.AddOrUpdate("max_datetime", pickupDate);
59+
fixture!.AddOrUpdate(pickupDate, "min_datetime");
60+
fixture!.AddOrUpdate(pickupDate, "max_datetime");
6161

6262
return fixture;
6363
}
@@ -258,6 +258,18 @@ internal static ParameterSets.CarrierAccount.CreateFedEx CreateFedEx(Dictionary<
258258
ShippingAddressStreet = "345 California St",
259259
};
260260
}
261+
262+
internal static ParameterSets.CarrierAccount.CreateUps CreateUps(Dictionary<string, object>? fixture)
263+
{
264+
fixture ??= new Dictionary<string, object>();
265+
266+
return new ParameterSets.CarrierAccount.CreateUps
267+
{
268+
Description = fixture.GetOrNull<string>("description"),
269+
Reference = fixture.GetOrNull<string>("reference"),
270+
AccountNumber = "123456789",
271+
};
272+
}
261273
}
262274

263275
internal static class CustomsInfo

Diff for: EasyPost.Tests/ServicesTests/CarrierAccountServiceTest.cs

+40-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Net;
44
using System.Threading.Tasks;
55
using EasyPost.Exceptions.API;
6+
using EasyPost.Exceptions.General;
67
using EasyPost.Http;
78
using EasyPost.Models.API;
89
using EasyPost.Tests._Utilities;
@@ -56,24 +57,20 @@ public async Task TestCreateWithCustomWorkflow()
5657
{
5758
UseVCR("create_with_custom_workflow");
5859

59-
// Carriers like FedEx and UPS should hit the `/carrier_accounts/register` endpoint
60+
// FedEx or UPS should trigger a function error since not supported by legacy parameter method
6061
try
6162
{
6263
Dictionary<string, object> parameters = Fixtures.BasicCarrierAccount;
63-
parameters["type"] = "FedexAccount";
64+
parameters["type"] = CarrierAccountType.FedEx.Name;
6465
parameters["registration_data"] = new Dictionary<string, object>();
6566

6667
CarrierAccount carrierAccount = await Client.CarrierAccount.Create(parameters);
6768
CleanUpAfterTest(carrierAccount.Id);
6869
}
69-
catch (InvalidRequestError e)
70+
catch (InvalidFunctionError e)
7071
{
71-
// the data we're sending is invalid, we want to check that the API error is because of malformed data and not due to the endpoint
72-
Assert.Equal(422, e.StatusCode); // 422 is fine. We don't want a 404 not found
73-
Assert.NotNull(e.Errors);
74-
Assert.Contains(e.Errors, error => error is { Field: "account_number", Message: "must be present and a string" });
75-
76-
// Check the cassette to make sure the endpoint is correct (it should be carrier_accounts/register)
72+
// Function should have been halted due to incompatible carrier account type
73+
Assert.NotNull(e);
7774
}
7875
}
7976

@@ -128,6 +125,39 @@ public async Task TestUpdate()
128125
Assert.Equal(testDescription, carrierAccount.Description);
129126
}
130127

128+
[Fact]
129+
[CrudOperations.Create]
130+
[Testing.Parameters]
131+
public async Task TestUpdateWithCustomWorkflow()
132+
{
133+
UseMockClient(new List<TestUtils.MockRequest>
134+
{
135+
// Fake retrieving an existing UPS account
136+
new(
137+
new TestUtils.MockRequestMatchRules(Method.Get, @"v2\/carrier_accounts\/ca_123$"),
138+
new TestUtils.MockRequestResponseInfo(HttpStatusCode.OK, data: new CarrierAccount
139+
{
140+
Id = "ca_123",
141+
Type = CarrierAccountType.Ups.Name,
142+
}
143+
)
144+
)
145+
});
146+
147+
// UPS should trigger a function error since not supported by legacy parameter method
148+
try
149+
{
150+
Dictionary<string, object> parameters = new Dictionary<string, object>();
151+
CarrierAccount carrierAccount = await Client.CarrierAccount.Update("ca_123", parameters);
152+
Assert.Fail("Expected an exception to be thrown");
153+
}
154+
catch (InvalidFunctionError e)
155+
{
156+
// Function should have been halted due to incompatible carrier account type
157+
Assert.NotNull(e);
158+
}
159+
}
160+
131161
[Fact]
132162
[CrudOperations.Delete]
133163
[Testing.Function]
@@ -203,8 +233,7 @@ public async Task TestCarrierFieldsJsonSerialization()
203233
Credentials = new Dictionary<string, CarrierField>
204234
{
205235
{
206-
"account_number",
207-
new CarrierField
236+
"account_number", new CarrierField
208237
{
209238
Visibility = "visible",
210239
Label = "DHL Account Number",

Diff for: EasyPost.Tests/ServicesTests/WithParameters/CarrierAccountServiceTest.cs

+109-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System.Collections.Generic;
2+
using System.Net;
23
using System.Threading.Tasks;
34
using EasyPost.Exceptions.API;
45
using EasyPost.Exceptions.General;
6+
using EasyPost.Http;
57
using EasyPost.Models.API;
68
using EasyPost.Tests._Utilities;
79
using EasyPost.Tests._Utilities.Attributes;
@@ -53,18 +55,18 @@ public async Task TestCreate()
5355
[Fact]
5456
[CrudOperations.Create]
5557
[Testing.Parameters]
56-
public async Task TestCreateWithCustomWorkflow()
58+
public async Task TestCreateFedEx()
5759
{
58-
UseVCR("create_with_custom_workflow");
60+
UseVCR("create_fedex");
5961

60-
// Carriers like FedEx and UPS should hit the `/carrier_accounts/register` endpoint
62+
// FedEx should hit the `/carrier_accounts/register` endpoint
6163
Dictionary<string, object> data = Fixtures.BasicCarrierAccount;
6264

6365
Parameters.CarrierAccount.CreateFedEx parameters = Fixtures.Parameters.CarrierAccounts.CreateFedEx(data);
6466

6567
try
6668
{
67-
// confirms we can pass in CreateFedEx and CreateUps parameters to the same Create method because they are children of the generic Create class
69+
// confirms we can pass in CreateFedEx parameters to the same Create method because they are children of the generic Create class
6870
CarrierAccount carrierAccount = await Client.CarrierAccount.Create(parameters);
6971
CleanUpAfterTest(carrierAccount.Id);
7072
}
@@ -81,24 +83,52 @@ public async Task TestCreateWithCustomWorkflow()
8183
}
8284
}
8385

86+
[Fact]
87+
[CrudOperations.Create]
88+
[Testing.Parameters]
89+
public async Task TestCreateUps()
90+
{
91+
UseVCR("create_ups");
92+
93+
// UPS should hit the `/ups_oauth_registrations` endpoint
94+
Dictionary<string, object> data = Fixtures.BasicCarrierAccount;
95+
96+
Parameters.CarrierAccount.CreateUps parameters = Fixtures.Parameters.CarrierAccounts.CreateUps(data);
97+
98+
// confirms we can pass in CreateUps parameters to the same Create method because they are children of the generic Create class
99+
CarrierAccount carrierAccount = await Client.CarrierAccount.Create(parameters);
100+
CleanUpAfterTest(carrierAccount.Id);
101+
102+
Assert.IsType<CarrierAccount>(carrierAccount);
103+
Assert.StartsWith("ca_", carrierAccount.Id);
104+
}
105+
84106
[Fact]
85107
[CrudOperations.Create]
86108
[Testing.Exception]
87-
public async Task TestPreventUsersUsingGenericParameterSetWithCustomWorkflow()
109+
public async Task TestPreventUsersUsingGenericParameterSetWithCustomCreateWorkflow()
88110
{
89-
UseVCR("prevent_users_using_generic_parameter_set_with_custom_workflow");
111+
UseVCR("prevent_users_using_generic_parameter_set_with_custom_create_workflow");
90112

91-
// Generic Create parameter set configured for DHL
92113
Dictionary<string, object> data = Fixtures.BasicCarrierAccount;
93114

94-
// Override the type to be a custom type
95-
data["type"] = CarrierAccountType.FedEx.Name;
96-
data["registration_data"] = new Dictionary<string, object>();
115+
// Generic Create parameter set configured for DHL
116+
Parameters.CarrierAccount.Create standardParameters = Fixtures.Parameters.CarrierAccounts.Create(data);
97117

98-
Parameters.CarrierAccount.Create parameters = Fixtures.Parameters.CarrierAccounts.Create(data);
118+
// Override the type to be a custom type
119+
standardParameters.Type = CarrierAccountType.FedEx.Name;
99120

100121
// should raise an exception because we're using a generic Create set with a custom workflow type (FedExAccount)
101-
await Assert.ThrowsAsync<InvalidParameterError>(async () => await Client.CarrierAccount.Create(parameters));
122+
await Assert.ThrowsAsync<InvalidParameterError>(async () => await Client.CarrierAccount.Create(standardParameters));
123+
124+
// Specialized CreateFedEx parameter set configured for FedEx
125+
Parameters.CarrierAccount.CreateFedEx fedExParameters = Fixtures.Parameters.CarrierAccounts.CreateFedEx(data);
126+
127+
// Override the type to be a standard type
128+
fedExParameters.Type = "DhlExpressAccount";
129+
130+
// should raise an exception because we're using a FedEx-specific Create set with a standard workflow type (DhlExpressAccount)
131+
await Assert.ThrowsAsync<InvalidParameterError>(async () => await Client.CarrierAccount.Create(fedExParameters));
102132
}
103133

104134
[Fact]
@@ -112,7 +142,7 @@ public async Task TestUpdate()
112142

113143
Parameters.CarrierAccount.Create createParameters = Fixtures.Parameters.CarrierAccounts.Create(data);
114144

115-
CarrierAccount carrierAccount = await Client.CarrierAccount.Create(createParameters);
145+
CarrierAccount carrierAccount = await Client.CarrierAccount.Create(createParameters); // DHL Express
116146
CleanUpAfterTest(carrierAccount.Id);
117147

118148
const string testDescription = "my custom description";
@@ -129,6 +159,72 @@ public async Task TestUpdate()
129159
Assert.Equal(testDescription, carrierAccount.Description);
130160
}
131161

162+
[Fact]
163+
[CrudOperations.Update]
164+
[Testing.Parameters]
165+
public async Task TestUpdateUps()
166+
{
167+
UseVCR("update_ups");
168+
169+
Dictionary<string, object> data = Fixtures.BasicCarrierAccount;
170+
171+
Parameters.CarrierAccount.CreateUps createParameters = Fixtures.Parameters.CarrierAccounts.CreateUps(data);
172+
173+
CarrierAccount carrierAccount = await Client.CarrierAccount.Create(createParameters);
174+
CleanUpAfterTest(carrierAccount.Id);
175+
176+
const string testDescription = "my custom description";
177+
178+
Parameters.CarrierAccount.UpdateUps updateParameters = new()
179+
{
180+
Description = testDescription,
181+
};
182+
183+
carrierAccount = await Client.CarrierAccount.Update(carrierAccount.Id, updateParameters);
184+
185+
Assert.IsType<CarrierAccount>(carrierAccount);
186+
Assert.StartsWith("ca_", carrierAccount.Id);
187+
// Assert.Equal(testDescription, carrierAccount.Description); // TODO: Uncomment when the UPS update endpoint is fixed
188+
}
189+
190+
[Fact]
191+
[CrudOperations.Create]
192+
[Testing.Exception]
193+
public async Task TestPreventUsersUsingGenericParameterSetWithCustomUpdateWorkflow()
194+
{
195+
UseMockClient(new List<TestUtils.MockRequest>
196+
{
197+
// Fake retrieving an existing UPS account
198+
new(
199+
new TestUtils.MockRequestMatchRules(Method.Get, @"v2\/carrier_accounts\/ca_123$"),
200+
new TestUtils.MockRequestResponseInfo(HttpStatusCode.OK, data: new CarrierAccount
201+
{
202+
Id = "ca_123",
203+
Type = CarrierAccountType.Ups.Name,
204+
}
205+
)
206+
),
207+
new(
208+
new TestUtils.MockRequestMatchRules(Method.Get, @"v2\/carrier_accounts\/ca_456$"),
209+
new TestUtils.MockRequestResponseInfo(HttpStatusCode.OK, data: new CarrierAccount
210+
{
211+
Id = "ca_456",
212+
Type = CarrierAccountType.FedEx.Name,
213+
}
214+
)
215+
),
216+
});
217+
218+
Parameters.CarrierAccount.Update genericParameters = new();
219+
Parameters.CarrierAccount.UpdateUps upsParameters = new();
220+
221+
// should raise an exception because we're using a generic Create set with a custom workflow type (UpsAccount)
222+
await Assert.ThrowsAsync<InvalidParameterError>(async () => await Client.CarrierAccount.Update("ca_123", genericParameters));
223+
224+
// should raise an exception because we're using a UPS-specific Create set with a standard workflow type (FedExAccount)
225+
await Assert.ThrowsAsync<InvalidParameterError>(async () => await Client.CarrierAccount.Update("ca_456", upsParameters));
226+
}
227+
132228
#endregion
133229

134230
#endregion

0 commit comments

Comments
 (0)