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

[feat] Add custom parameter sets for FedEx and UPS account creation #509

Merged
merged 2 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion EasyPost.Tests/ExceptionsTests/ExceptionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public void TestExceptionConstructors()
Assert.Equal(testMessage, invalidObjectError.Message);

InvalidParameterError invalidParameterError = new(testPropertyName);
Assert.Equal(string.Format(CultureInfo.InvariantCulture, Constants.ErrorMessages.InvalidParameter, testPropertyName), invalidParameterError.Message);
Assert.Equal($"{string.Format(CultureInfo.InvariantCulture, Constants.ErrorMessages.InvalidParameter, testPropertyName)}. ", invalidParameterError.Message);

JsonDeserializationError jsonDeserializationError = new(testType);
Assert.Equal(string.Format(CultureInfo.InvariantCulture, Constants.ErrorMessages.JsonDeserializationError, testType.FullName), jsonDeserializationError.Message);
Expand Down
32 changes: 31 additions & 1 deletion EasyPost.Tests/Fixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,36 @@ internal static ParameterSets.CarrierAccount.Create Create(Dictionary<string, ob
RegistrationData = fixture.GetOrNull<Dictionary<string, object?>>("registration_data"),
};
}

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

return new ParameterSets.CarrierAccount.CreateFedEx
{
Description = fixture.GetOrNull<string>("description"),
Reference = fixture.GetOrNull<string>("reference"),
Credentials = fixture.GetOrNull<Dictionary<string, object?>>("credentials"),
TestCredentials = fixture.GetOrNull<Dictionary<string, object?>>("test_credentials"),
AccountNumber = "123456789",
CorporateAddressCity = "San Francisco",
CorporateAddressCountryCode = "US",
CorporateAddressPostalCode = "94105",
CorporateAddressState = "CA",
CorporateAddressStreet = "345 California St",
CorporateCompanyName = "EasyPost",
CorporateEmailAddress = "me@example.com",
CorporateFirstName = "Demo",
CorporateLastName = "User",
CorporateJobTitle = "Developer",
CorporatePhoneNumber = "5555555555",
ShippingAddressCity = "San Francisco",
ShippingAddressCountryCode = "US",
ShippingAddressPostalCode = "94105",
ShippingAddressState = "CA",
ShippingAddressStreet = "345 California St",
};
}
}

internal static class CustomsInfo
Expand Down Expand Up @@ -618,7 +648,7 @@ internal static ParameterSets.Shipment.Create Create(Dictionary<string, object>?
Parcel = Parcels.Create(parcelFixture),
CustomsInfo = CustomsInfo.Create(customsInfoFixture),
Options = Options(optionsFixture),
CarbonOffset = fixture.GetOrDefault<bool>("carbon_offset"), // this will always be true or false, never null
CarbonOffset = fixture.GetOrDefault<bool>("carbon_offset"), // this will always be true or false, never null
CarrierAccountIds = fixture.GetOrNull<List<string>>("carrier_accounts"),
Carrier = fixture.GetOrNull<string>("carrier"),
Service = fixture.GetOrNull<string>("service"),
Expand Down
40 changes: 39 additions & 1 deletion EasyPost.Tests/ParametersTests/ParametersTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,44 @@ public void TestParametersToDictionaryWithSubDictionary()
Assert.Equal(streetB, addressData["street1"]);
}

[Fact]
[Testing.Exception]
public void TestRequiredAndOptionalParameterValidation()
{
var parametersWithBothParameterSet = new ParameterSetWithRequiredAndOptionalParameters
{
RequiredParameter = "required",
OptionalParameter = "optional",
};
// should not throw an exception when serializing to a dictionary
parametersWithBothParameterSet.ToDictionary();

var parametersWithOnlyRequiredParameterSet = new ParameterSetWithRequiredAndOptionalParameters
{
RequiredParameter = "required",
};

// should not throw an exception when serializing to a dictionary
parametersWithOnlyRequiredParameterSet.ToDictionary();

var parametersWithOnlyOptionalParameterSet = new ParameterSetWithRequiredAndOptionalParameters
{
OptionalParameter = "optional",
};

// should throw an exception when serializing to a dictionary
Assert.Throws<Exceptions.General.MissingParameterError>(() => parametersWithOnlyOptionalParameterSet.ToDictionary());
}

private sealed class ParameterSetWithRequiredAndOptionalParameters : Parameters.BaseParameters
{
[TopLevelRequestParameter(Necessity.Required, "test", "required")]
public string? RequiredParameter { get; set; }

[TopLevelRequestParameter(Necessity.Optional, "test", "optional")]
public string? OptionalParameter { get; set; }
}

/// <summary>
/// This test proves that we can reuse the Addresses.Create parameter object,
/// with its serialization logic adapting to whether it is a top-level parameter object
Expand Down Expand Up @@ -200,7 +238,7 @@ public async Task TestDisallowUsingParameterObjectDictionariesInDictionaryFuncti
Street1 = street,
};

Dictionary<string, object> dictionary = addressCreationParameters.ToDictionary(); // this method is "internal", so end-users won't have access to it, for reasons seen below
Dictionary<string, object> dictionary = addressCreationParameters.ToDictionary(); // this method is "internal", so end-users won't have access to it, for reasons seen below

// At this point, the data has already been wrapped properly by the .ToDictionary() method, and this method expects raw (unwrapped) data
// This will cause a double-wrapping, sending malformed data to the API
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost.Exceptions.API;
using EasyPost.Exceptions.General;
using EasyPost.Models.API;
using EasyPost.Tests._Utilities;
using EasyPost.Tests._Utilities.Attributes;
Expand Down Expand Up @@ -57,28 +58,49 @@ public async Task TestCreateWithCustomWorkflow()
UseVCR("create_with_custom_workflow");

// Carriers like FedEx and UPS should hit the `/carrier_accounts/register` endpoint
try
{
Dictionary<string, object> data = Fixtures.BasicCarrierAccount;
data["type"] = "FedexAccount";
data["registration_data"] = new Dictionary<string, object>();
Dictionary<string, object> data = Fixtures.BasicCarrierAccount;

Parameters.CarrierAccount.Create parameters = Fixtures.Parameters.CarrierAccounts.Create(data);
Parameters.CarrierAccount.Create 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
CarrierAccount carrierAccount = await Client.CarrierAccount.Create(parameters);
CleanUpAfterTest(carrierAccount.Id);
}
catch (InvalidRequestError e)

catch (BadRequestError 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.Equal(400, e.StatusCode); // 400 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" });
Assert.Contains(e.Errors, error => error is { Message: "Invalid Customer Account Nbr" });

// Check the cassette to make sure the endpoint is correct (it should be carrier_accounts/register)
// Check the cassette to make sure the "registration_data" key is populated in the request body
}
}

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

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

// Override the type to be a custom type
data["type"] = Constants.CarrierAccountTypes.FedExAccount;
data["registration_data"] = new Dictionary<string, object>();

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

// 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));
}

[Fact]
[CrudOperations.Update]
[Testing.Function]
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading