Skip to content
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
154 changes: 154 additions & 0 deletions EasyPost.Tests/ServicesTests/FedExRegistrationServiceTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using EasyPost.Http;
using EasyPost.Models.API;
using EasyPost.Tests._Utilities;
using Xunit;

namespace EasyPost.Tests.ServicesTests
{
public class FedExRegistrationServiceTests : UnitTest
{
public FedExRegistrationServiceTests() : base("fedex_registration_service", TestUtils.ApiKey.Production)
{
}

protected override IEnumerable<TestUtils.MockRequest> MockRequests
{
get
{
return new List<TestUtils.MockRequest>
{
new(
new TestUtils.MockRequestMatchRules(Method.Post, @"v2\/fedex_registrations\/\S*\/address$"),
new TestUtils.MockRequestResponseInfo(HttpStatusCode.OK, data: new FedExAccountValidationResponse
{
EmailAddress = "test@example.com",
PhoneNumber = "5555555555",
Options = new List<string> { "SMS", "CALL", "INVOICE" },
})
),
new(
new TestUtils.MockRequestMatchRules(Method.Post, @"v2\/fedex_registrations\/\S*\/pin$"),
new TestUtils.MockRequestResponseInfo(HttpStatusCode.OK, data: new FedExRequestPinResponse
{
Message = "Your secured PIN has been sent to your phone.",
})
),
new(
new TestUtils.MockRequestMatchRules(Method.Post, @"v2\/fedex_registrations\/\S*\/pin\/validate$"),
new TestUtils.MockRequestResponseInfo(HttpStatusCode.OK, data: new FedExAccountValidationResponse
{
Id = "ca_test123",
ObjectType = "CarrierAccount",
Type = "FedexAccount",
Credentials = new Dictionary<string, string>
{
{ "account_number", "123456789" },
{ "mfa_key", "test_mfa_key" },
},
})
),
new(
new TestUtils.MockRequestMatchRules(Method.Post, @"v2\/fedex_registrations\/\S*\/invoice$"),
new TestUtils.MockRequestResponseInfo(HttpStatusCode.OK, data: new FedExAccountValidationResponse
{
Id = "ca_test123",
ObjectType = "CarrierAccount",
Type = "FedexAccount",
Credentials = new Dictionary<string, string>
{
{ "account_number", "123456789" },
{ "mfa_key", "test_mfa_key" },
},
})
),
};
}
}

#region Tests

[Fact]
public async Task TestRegisterAddress()
{
UseMockClient();

Parameters.FedExRegistration.RegisterAddress parameters = new Parameters.FedExRegistration.RegisterAddress
{
Name = "test_name",
Company = "test_company",
Street1 = "test_street",
City = "test_city",
State = "test_state",
Zip = "test_zip",
Country = "US",
Phone = "test_phone",
};

FedExAccountValidationResponse response = await Client.FedExRegistration.RegisterAddress("123456789", parameters);

Assert.NotNull(response);
Assert.NotNull(response.Options);
Assert.Contains("SMS", response.Options);
Assert.Contains("CALL", response.Options);
Assert.Contains("INVOICE", response.Options);
Assert.NotNull(response.PhoneNumber);
}

[Fact]
public async Task TestRequestPin()
{
UseMockClient();

FedExRequestPinResponse response = await Client.FedExRegistration.RequestPin("123456789", "SMS");

Assert.NotNull(response);
Assert.NotNull(response.Message);
Assert.Contains("secured PIN", response.Message);
}

[Fact]
public async Task TestValidatePin()
{
UseMockClient();

Parameters.FedExRegistration.ValidatePin parameters = new Parameters.FedExRegistration.ValidatePin
{
Name = "test_name",
Pin = "123456",
};

FedExAccountValidationResponse response = await Client.FedExRegistration.ValidatePin("123456789", parameters);

Assert.NotNull(response);
Assert.NotNull(response.Credentials);
Assert.True(response.Credentials.ContainsKey("account_number"));
Assert.True(response.Credentials.ContainsKey("mfa_key"));
}

[Fact]
public async Task TestSubmitInvoice()
{
UseMockClient();

Parameters.FedExRegistration.SubmitInvoice parameters = new Parameters.FedExRegistration.SubmitInvoice
{
Name = "test_name",
InvoiceNumber = "test_invoice",
InvoiceAmount = "100.00",
InvoiceDate = "2023-01-01",
};

FedExAccountValidationResponse response = await Client.FedExRegistration.SubmitInvoice("123456789", parameters);

Assert.NotNull(response);
Assert.NotNull(response.Credentials);
Assert.True(response.Credentials.ContainsKey("account_number"));
Assert.True(response.Credentials.ContainsKey("mfa_key"));
}

#endregion
}
}
5 changes: 5 additions & 0 deletions EasyPost/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ public class Client : EasyPostClient
/// </summary>
public EventService Event => new EventService(this);

/// <summary>
/// Access FedEx Registration-related functionality.
/// </summary>
public FedExRegistrationService FedExRegistration => new FedExRegistrationService(this);

/// <summary>
/// Access Insurance-related functionality.
/// </summary>
Expand Down
58 changes: 58 additions & 0 deletions EasyPost/Models/API/FedExAccountValidationResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System.Collections.Generic;
using EasyPost._base;
using Newtonsoft.Json;

namespace EasyPost.Models.API
{
/// <summary>
/// Represents a FedEx account validation response.
/// </summary>
public class FedExAccountValidationResponse : EphemeralEasyPostObject
{
#region JSON Properties

/// <summary>
/// Gets or sets the email address for PIN delivery.
/// </summary>
[JsonProperty("email_address")]
public string? EmailAddress { get; set; }

/// <summary>
/// Gets or sets the available PIN delivery options.
/// </summary>
[JsonProperty("options")]
public List<string>? Options { get; set; }

/// <summary>
/// Gets or sets the phone number for PIN delivery.
/// </summary>
[JsonProperty("phone_number")]
public string? PhoneNumber { get; set; }

/// <summary>
/// Gets or sets the ID.
/// </summary>
[JsonProperty("id")]
public string? Id { get; set; }

/// <summary>
/// Gets or sets the object type.
/// </summary>
[JsonProperty("object")]
public string? ObjectType { get; set; }

/// <summary>
/// Gets or sets the type.
/// </summary>
[JsonProperty("type")]
public string? Type { get; set; }

/// <summary>
/// Gets or sets the credentials.
/// </summary>
[JsonProperty("credentials")]
public Dictionary<string, string>? Credentials { get; set; }

#endregion
}
}
21 changes: 21 additions & 0 deletions EasyPost/Models/API/FedExRequestPinResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using EasyPost._base;
using Newtonsoft.Json;

namespace EasyPost.Models.API
{
/// <summary>
/// Represents a FedEx request PIN response.
/// </summary>
public class FedExRequestPinResponse : EphemeralEasyPostObject
{
#region JSON Properties

/// <summary>
/// Gets or sets the message.
/// </summary>
[JsonProperty("message")]
public string? Message { get; set; }

#endregion
}
}
99 changes: 99 additions & 0 deletions EasyPost/Parameters/FedExRegistration/RegisterAddress.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System;
using System.Diagnostics.CodeAnalysis;
using EasyPost.Utilities.Internal.Attributes;

namespace EasyPost.Parameters.FedExRegistration
{
/// <summary>
/// Parameters for <see cref="EasyPost.Services.FedExRegistrationService.RegisterAddress(string, RegisterAddress, System.Threading.CancellationToken)"/> API calls.
/// </summary>
[ExcludeFromCodeCoverage]
public class RegisterAddress : BaseParameters<Models.API.FedExAccountValidationResponse>, IFedExRegistrationParameter
{
#region Request Parameters

/// <summary>
/// Name for the FedEx registration.
/// If not provided, a UUID will be auto-generated.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "address_validation", "name")]
public string? Name { get; set; }

/// <summary>
/// Company name for the FedEx registration.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "address_validation", "company")]
public string? Company { get; set; }

/// <summary>
/// First street line for the FedEx registration.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "address_validation", "street1")]
public string? Street1 { get; set; }

/// <summary>
/// Second street line for the FedEx registration.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "address_validation", "street2")]
public string? Street2 { get; set; }

/// <summary>
/// City for the FedEx registration.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "address_validation", "city")]
public string? City { get; set; }

/// <summary>
/// State for the FedEx registration.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "address_validation", "state")]
public string? State { get; set; }

/// <summary>
/// ZIP code for the FedEx registration.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "address_validation", "zip")]
public string? Zip { get; set; }

/// <summary>
/// Country code for the FedEx registration.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "address_validation", "country")]
public string? Country { get; set; }

/// <summary>
/// Phone number for the FedEx registration.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "address_validation", "phone")]
public string? Phone { get; set; }

/// <summary>
/// Email address for the FedEx registration.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "address_validation", "email")]
public string? Email { get; set; }

/// <summary>
/// Carrier account ID for the FedEx registration.
/// </summary>
[TopLevelRequestParameter(Necessity.Optional, "easypost_details", "carrier_account_id")]
public string? CarrierAccountId { get; set; }

#endregion

/// <summary>
/// Override the default <see cref="BaseParameters{TMatchInputType}.ToDictionary"/> method to ensure the "name" field exists.
/// If not present, generates a UUID (with hyphens removed) as the name.
/// </summary>
/// <returns>A <see cref="System.Collections.Generic.Dictionary{TKey,TValue}"/>.</returns>
public override System.Collections.Generic.Dictionary<string, object> ToDictionary()
{
if (string.IsNullOrWhiteSpace(Name))
{
Name = Guid.NewGuid().ToString().Replace("-", string.Empty);
}

return base.ToDictionary();
}
}
}
Loading
Loading