Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chore] Support new UPS carrier account create/update endpoint #574

Merged
merged 10 commits into from
Jul 15, 2024
16 changes: 14 additions & 2 deletions EasyPost.Tests/Fixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ internal static Dictionary<string, object> BasicPickup

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

fixture!.AddOrUpdate("min_datetime", pickupDate);
fixture!.AddOrUpdate("max_datetime", pickupDate);
fixture!.AddOrUpdate(pickupDate, "min_datetime");
fixture!.AddOrUpdate(pickupDate, "max_datetime");

return fixture;
}
Expand Down Expand Up @@ -258,6 +258,18 @@ internal static ParameterSets.CarrierAccount.CreateFedEx CreateFedEx(Dictionary<
ShippingAddressStreet = "345 California St",
};
}

internal static ParameterSets.CarrierAccount.CreateUps CreateUps(Dictionary<string, object>? fixture)
{
fixture ??= new Dictionary<string, object>();

return new ParameterSets.CarrierAccount.CreateUps
{
Description = fixture.GetOrNull<string>("description"),
Reference = fixture.GetOrNull<string>("reference"),
AccountNumber = "123456789",
};
}
}

internal static class CustomsInfo
Expand Down
51 changes: 40 additions & 11 deletions EasyPost.Tests/ServicesTests/CarrierAccountServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Net;
using System.Threading.Tasks;
using EasyPost.Exceptions.API;
using EasyPost.Exceptions.General;
using EasyPost.Http;
using EasyPost.Models.API;
using EasyPost.Tests._Utilities;
Expand Down Expand Up @@ -56,24 +57,20 @@ public async Task TestCreateWithCustomWorkflow()
{
UseVCR("create_with_custom_workflow");

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

CarrierAccount carrierAccount = await Client.CarrierAccount.Create(parameters);
CleanUpAfterTest(carrierAccount.Id);
}
catch (InvalidRequestError e)
catch (InvalidFunctionError e)
{
// 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
Assert.Equal(422, e.StatusCode); // 422 is fine. We don't want a 404 not found
Assert.NotNull(e.Errors);
Assert.Contains(e.Errors, error => error is { Field: "account_number", Message: "must be present and a string" });

// Check the cassette to make sure the endpoint is correct (it should be carrier_accounts/register)
// Function should have been halted due to incompatible carrier account type
Assert.NotNull(e);
}
}

Expand Down Expand Up @@ -128,6 +125,39 @@ public async Task TestUpdate()
Assert.Equal(testDescription, carrierAccount.Description);
}

[Fact]
[CrudOperations.Create]
[Testing.Parameters]
public async Task TestUpdateWithCustomWorkflow()
{
UseMockClient(new List<TestUtils.MockRequest>
{
// Fake retrieving an existing UPS account
new(
new TestUtils.MockRequestMatchRules(Method.Get, @"v2\/carrier_accounts\/ca_123$"),
new TestUtils.MockRequestResponseInfo(HttpStatusCode.OK, data: new CarrierAccount
{
Id = "ca_123",
Type = CarrierAccountType.Ups.Name,
}
)
)
});

// UPS should trigger a function error since not supported by legacy parameter method
try
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
CarrierAccount carrierAccount = await Client.CarrierAccount.Update("ca_123", parameters);
Assert.Fail("Expected an exception to be thrown");
}
catch (InvalidFunctionError e)
{
// Function should have been halted due to incompatible carrier account type
Assert.NotNull(e);
}
}

[Fact]
[CrudOperations.Delete]
[Testing.Function]
Expand Down Expand Up @@ -203,8 +233,7 @@ public async Task TestCarrierFieldsJsonSerialization()
Credentials = new Dictionary<string, CarrierField>
{
{
"account_number",
new CarrierField
"account_number", new CarrierField
{
Visibility = "visible",
Label = "DHL Account Number",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using EasyPost.Exceptions.API;
using EasyPost.Exceptions.General;
using EasyPost.Http;
using EasyPost.Models.API;
using EasyPost.Tests._Utilities;
using EasyPost.Tests._Utilities.Attributes;
Expand Down Expand Up @@ -53,18 +55,18 @@ public async Task TestCreate()
[Fact]
[CrudOperations.Create]
[Testing.Parameters]
public async Task TestCreateWithCustomWorkflow()
public async Task TestCreateFedEx()
{
UseVCR("create_with_custom_workflow");
UseVCR("create_fedex");

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

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

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

[Fact]
[CrudOperations.Create]
[Testing.Parameters]
public async Task TestCreateUps()
{
UseVCR("create_ups");

// UPS should hit the `/ups_oauth_registrations` endpoint
Dictionary<string, object> data = Fixtures.BasicCarrierAccount;

Parameters.CarrierAccount.CreateUps parameters = Fixtures.Parameters.CarrierAccounts.CreateUps(data);

// confirms we can pass in CreateUps parameters to the same Create method because they are children of the generic Create class
CarrierAccount carrierAccount = await Client.CarrierAccount.Create(parameters);
CleanUpAfterTest(carrierAccount.Id);

Assert.IsType<CarrierAccount>(carrierAccount);
Assert.StartsWith("ca_", carrierAccount.Id);
}

[Fact]
[CrudOperations.Create]
[Testing.Exception]
public async Task TestPreventUsersUsingGenericParameterSetWithCustomWorkflow()
public async Task TestPreventUsersUsingGenericParameterSetWithCustomCreateWorkflow()
{
UseVCR("prevent_users_using_generic_parameter_set_with_custom_workflow");
UseVCR("prevent_users_using_generic_parameter_set_with_custom_create_workflow");

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

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

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

// should raise an exception because we're using a generic Create set with a custom workflow type (FedExAccount)
await Assert.ThrowsAsync<InvalidParameterError>(async () => await Client.CarrierAccount.Create(parameters));
await Assert.ThrowsAsync<InvalidParameterError>(async () => await Client.CarrierAccount.Create(standardParameters));

// Specialized CreateFedEx parameter set configured for FedEx
Parameters.CarrierAccount.CreateFedEx fedExParameters = Fixtures.Parameters.CarrierAccounts.CreateFedEx(data);

// Override the type to be a standard type
fedExParameters.Type = "DhlExpressAccount";

// should raise an exception because we're using a FedEx-specific Create set with a standard workflow type (DhlExpressAccount)
await Assert.ThrowsAsync<InvalidParameterError>(async () => await Client.CarrierAccount.Create(fedExParameters));
}

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

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

CarrierAccount carrierAccount = await Client.CarrierAccount.Create(createParameters);
CarrierAccount carrierAccount = await Client.CarrierAccount.Create(createParameters); // DHL Express
CleanUpAfterTest(carrierAccount.Id);

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

[Fact]
[CrudOperations.Update]
[Testing.Parameters]
public async Task TestUpdateUps()
{
UseVCR("update_ups");

Dictionary<string, object> data = Fixtures.BasicCarrierAccount;

Parameters.CarrierAccount.CreateUps createParameters = Fixtures.Parameters.CarrierAccounts.CreateUps(data);

CarrierAccount carrierAccount = await Client.CarrierAccount.Create(createParameters);
CleanUpAfterTest(carrierAccount.Id);

const string testDescription = "my custom description";

Parameters.CarrierAccount.UpdateUps updateParameters = new()
{
Description = testDescription,
};

carrierAccount = await Client.CarrierAccount.Update(carrierAccount.Id, updateParameters);

Assert.IsType<CarrierAccount>(carrierAccount);
Assert.StartsWith("ca_", carrierAccount.Id);
// Assert.Equal(testDescription, carrierAccount.Description); // TODO: Uncomment when the UPS update endpoint is fixed
}

[Fact]
[CrudOperations.Create]
[Testing.Exception]
public async Task TestPreventUsersUsingGenericParameterSetWithCustomUpdateWorkflow()
{
UseMockClient(new List<TestUtils.MockRequest>
{
// Fake retrieving an existing UPS account
new(
new TestUtils.MockRequestMatchRules(Method.Get, @"v2\/carrier_accounts\/ca_123$"),
new TestUtils.MockRequestResponseInfo(HttpStatusCode.OK, data: new CarrierAccount
{
Id = "ca_123",
Type = CarrierAccountType.Ups.Name,
}
)
),
new(
new TestUtils.MockRequestMatchRules(Method.Get, @"v2\/carrier_accounts\/ca_456$"),
new TestUtils.MockRequestResponseInfo(HttpStatusCode.OK, data: new CarrierAccount
{
Id = "ca_456",
Type = CarrierAccountType.FedEx.Name,
}
)
),
});

Parameters.CarrierAccount.Update genericParameters = new();
Parameters.CarrierAccount.UpdateUps upsParameters = new();

// should raise an exception because we're using a generic Create set with a custom workflow type (UpsAccount)
await Assert.ThrowsAsync<InvalidParameterError>(async () => await Client.CarrierAccount.Update("ca_123", genericParameters));

// should raise an exception because we're using a UPS-specific Create set with a standard workflow type (FedExAccount)
await Assert.ThrowsAsync<InvalidParameterError>(async () => await Client.CarrierAccount.Update("ca_456", upsParameters));
}

#endregion

#endregion
Expand Down
Loading
Loading