Skip to content

Commit

Permalink
Merge branch 'master' into precision_shipping
Browse files Browse the repository at this point in the history
  • Loading branch information
nwithan8 authored Jul 3, 2024
2 parents b074ea1 + a27ef94 commit 2b717b8
Show file tree
Hide file tree
Showing 33 changed files with 816 additions and 368 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@
- New `RecommendShipDateForRoute` function to to recommend ship date based on a list of carriers, to/from ZIP codes and a planned ship date (no existing shipment required).
- New model classes as needed for JSON response to new API functions
- Existing SmartRate-related functions and classes in `Shipment` service marked as deprecated and will be removed in a future release
- Enforce one-or-other for `Shipment` and `Batch` parameters in `Pickup.Create` parameter set
- Add internal parameter dependency utility

## v6.5.2 (2024-06-12)

- Fix `Shipment` parameter requirement for `Pickup.Create` parameter set

## v6.5.1 (2024-06-10)

- Fix `Batch` object not allowed to be used in parameter sets due to missing `IBatchParameter` inheritance

## v6.5.0 (2024-06-05)

- Add missing parameters for `CustomsItem.Create` parameter set

## v6.4.0 (2024-05-01)

Expand Down
4 changes: 4 additions & 0 deletions EasyPost.Tests/ExceptionsTests/ExceptionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public void TestExceptionConstructors()
{
const string testMessage = "This is a test message.";
const string testPropertyName = "test_property";
const string testPropertyName2 = "test_property2";
Type testType = typeof(ExceptionsTests);

// Test the base EasyPostError constructor
Expand Down Expand Up @@ -170,6 +171,9 @@ public void TestExceptionConstructors()
InvalidParameterError invalidParameterError = new(testPropertyName);
Assert.Equal($"{string.Format(CultureInfo.InvariantCulture, Constants.ErrorMessages.InvalidParameter, testPropertyName)}. ", invalidParameterError.Message);

InvalidParameterPairError invalidParameterPairError = new(testPropertyName, testPropertyName2);
Assert.Equal($"{string.Format(CultureInfo.InvariantCulture, Constants.ErrorMessages.InvalidParameterPair, testPropertyName, testPropertyName2)}. ", invalidParameterPairError.Message);

JsonDeserializationError jsonDeserializationError = new(testType);
Assert.Equal(string.Format(CultureInfo.InvariantCulture, Constants.ErrorMessages.JsonDeserializationError, testType.FullName), jsonDeserializationError.Message);

Expand Down
229 changes: 208 additions & 21 deletions EasyPost.Tests/ParametersTests/ParametersTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,37 +225,157 @@ public void TestRequiredAndOptionalParameterValidation()
Assert.Throws<Exceptions.General.MissingParameterError>(() => parametersWithOnlyOptionalParameterSet.ToDictionary());
}

private sealed class ParameterSetWithRequiredAndOptionalParameters : Parameters.BaseParameters<EasyPostObject>
[Fact]
[Testing.Exception]
public void TestOneOrOtherDependentTopLevelParameters()
{
[TopLevelRequestParameter(Necessity.Required, "test", "required")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? RequiredParameter { get; set; }
// Either A or B must be set, but not both.

// Should throw exception if both set.
var parametersWithOneOrOtherInterdependenceBothSet = new ParameterSetWithOneOrOtherDependentTopLevelParameters
{
AParam = "A",
BParam = "B",
};

Assert.Throws<Exceptions.General.InvalidParameterPairError>(() => parametersWithOneOrOtherInterdependenceBothSet.ToDictionary());

// Should throw exception if neither set.
var parametersWithOneOrOtherInterdependenceNeitherSet = new ParameterSetWithOneOrOtherDependentTopLevelParameters();

Assert.Throws<Exceptions.General.InvalidParameterPairError>(() => parametersWithOneOrOtherInterdependenceNeitherSet.ToDictionary());

// Should not throw exception if only A is set.
var parametersWithOneOrOtherInterdependenceOnlyASet = new ParameterSetWithOneOrOtherDependentTopLevelParameters
{
AParam = "A",
};

try
{
parametersWithOneOrOtherInterdependenceOnlyASet.ToDictionary();
}
catch (Exceptions.General.InvalidParameterPairError)
{
Assert.Fail("Should not throw exception if only A is set.");
}

// Should not throw exception if only B is set.
var parametersWithOneOrOtherInterdependenceOnlyBSet = new ParameterSetWithOneOrOtherDependentTopLevelParameters
{
BParam = "B",
};

[TopLevelRequestParameter(Necessity.Optional, "test", "optional")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? OptionalParameter { get; set; }
try
{
parametersWithOneOrOtherInterdependenceOnlyBSet.ToDictionary();
}
catch (Exceptions.General.InvalidParameterPairError)
{
Assert.Fail("Should not throw exception if only B is set.");
}
}

private sealed class ParameterSetWithCompetingParameters : Parameters.BaseParameters<EasyPostObject>
[Fact]
[Testing.Exception]
public void TestBothOrNeitherDependentTopLevelParameters()
{
[TopLevelRequestParameter(Necessity.Optional, "location")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? AParam { get; set; }
// Either both A and B must be set, or neither.

// Should throw exception if only A is set.
var parametersWithBothOrNeitherInterdependenceOnlyASet = new ParameterSetWithBothOrNeitherDependentTopLevelParameters
{
AParam = "A",
};

Assert.Throws<Exceptions.General.InvalidParameterPairError>(() => parametersWithBothOrNeitherInterdependenceOnlyASet.ToDictionary());

[TopLevelRequestParameter(Necessity.Optional, "location")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? BParam { get; set; }
// Should throw exception if only B is set.
var parametersWithBothOrNeitherInterdependenceOnlyBSet = new ParameterSetWithBothOrNeitherDependentTopLevelParameters
{
BParam = "B",
};

Assert.Throws<Exceptions.General.InvalidParameterPairError>(() => parametersWithBothOrNeitherInterdependenceOnlyBSet.ToDictionary());

// Should not throw exception if both A and B are set.
var parametersWithBothOrNeitherInterdependenceBothSet = new ParameterSetWithBothOrNeitherDependentTopLevelParameters
{
AParam = "A",
BParam = "B",
};

try
{
parametersWithBothOrNeitherInterdependenceBothSet.ToDictionary();
}
catch (Exceptions.General.InvalidParameterPairError)
{
Assert.Fail("Should not throw exception if both A and B are set.");
}

// Should not throw exception if neither A nor B are set.
var parametersWithBothOrNeitherInterdependenceNeitherSet = new ParameterSetWithBothOrNeitherDependentTopLevelParameters();

try
{
parametersWithBothOrNeitherInterdependenceNeitherSet.ToDictionary();
}
catch (Exceptions.General.InvalidParameterPairError)
{
Assert.Fail("Should not throw exception if neither A nor B are set.");
}
}

private sealed class ParameterSetWithCompetingParametersNonAlphabetic : Parameters.BaseParameters<EasyPostObject>
[Fact]
[Testing.Exception]
public void TestDependentNestedParameters()
{
[TopLevelRequestParameter(Necessity.Optional, "location")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? BParam { get; set; }
// Either A or B must be set, but not both.

// Should throw exception if both set.
var parametersWithInterdependenceBothSet = new ParameterSetWithOneOrOtherDependentTopLevelParameters
{
AParam = "A",
BParam = "B",
};

Assert.Throws<Exceptions.General.InvalidParameterPairError>(() => parametersWithInterdependenceBothSet.ToDictionary());

// Should throw exception if neither set.
var parametersWithInterdependenceNeitherSet = new ParameterSetWithOneOrOtherDependentTopLevelParameters();

Assert.Throws<Exceptions.General.InvalidParameterPairError>(() => parametersWithInterdependenceNeitherSet.ToDictionary());

// Should not throw exception if only A is set.
var parametersWithInterdependenceOnlyASet = new ParameterSetWithOneOrOtherDependentTopLevelParameters
{
AParam = "A",
};

[TopLevelRequestParameter(Necessity.Optional, "location")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? AParam { get; set; }
try
{
parametersWithInterdependenceOnlyASet.ToDictionary();
}
catch (Exceptions.General.InvalidParameterPairError)
{
Assert.Fail("Should not throw exception if only A is set.");
}

// Should not throw exception if only B is set.
var parametersWithInterdependenceOnlyBSet = new ParameterSetWithOneOrOtherDependentTopLevelParameters
{
BParam = "B",
};

try
{
parametersWithInterdependenceOnlyBSet.ToDictionary();
}
catch (Exceptions.General.InvalidParameterPairError)
{
Assert.Fail("Should not throw exception if only B is set.");
}
}

/// <summary>
Expand Down Expand Up @@ -426,6 +546,8 @@ public void TestParameterMatchOverrideFunction()
#endregion
}

#region Fixtures

#pragma warning disable CA1852 // Can be sealed
[SuppressMessage("ReSharper", "UnusedMember.Local")]
internal class ExampleDecoratorParameters : Parameters.BaseParameters<EasyPostObject>
Expand Down Expand Up @@ -460,5 +582,70 @@ internal class ExampleMatchParameters : Parameters.BaseParameters<ExampleMatchPa
public string? Prop1 { get; set; }
}

internal sealed class ParameterSetWithRequiredAndOptionalParameters : Parameters.BaseParameters<EasyPostObject>
{
[TopLevelRequestParameter(Necessity.Required, "test", "required")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? RequiredParameter { get; set; }

[TopLevelRequestParameter(Necessity.Optional, "test", "optional")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? OptionalParameter { get; set; }
}

internal sealed class ParameterSetWithCompetingParameters : Parameters.BaseParameters<EasyPostObject>
{
[TopLevelRequestParameter(Necessity.Optional, "location")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? AParam { get; set; }

[TopLevelRequestParameter(Necessity.Optional, "location")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? BParam { get; set; }
}

internal sealed class ParameterSetWithCompetingParametersNonAlphabetic : Parameters.BaseParameters<EasyPostObject>
{
[TopLevelRequestParameter(Necessity.Optional, "location")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? BParam { get; set; }

[TopLevelRequestParameter(Necessity.Optional, "location")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? AParam { get; set; }
}

internal sealed class ParameterSetWithOneOrOtherDependentTopLevelParameters : Parameters.BaseParameters<EasyPostObject>
{
[TopLevelRequestParameter(Necessity.Optional, "a_param")]
[TopLevelRequestParameterDependents(IndependentStatus.IfSet, DependentStatus.MustNotBeSet, "BParam")]
[TopLevelRequestParameterDependents(IndependentStatus.IfNotSet, DependentStatus.MustBeSet, "BParam")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? AParam { get; set; }

[TopLevelRequestParameter(Necessity.Optional, "b_param")]
[TopLevelRequestParameterDependents(IndependentStatus.IfSet, DependentStatus.MustNotBeSet, "AParam")]
[TopLevelRequestParameterDependents(IndependentStatus.IfNotSet, DependentStatus.MustBeSet, "AParam")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? BParam { get; set; }
}

internal sealed class ParameterSetWithBothOrNeitherDependentTopLevelParameters : Parameters.BaseParameters<EasyPostObject>
{
[TopLevelRequestParameter(Necessity.Optional, "a_param")]
[TopLevelRequestParameterDependents(IndependentStatus.IfSet, DependentStatus.MustBeSet, "BParam")]
[TopLevelRequestParameterDependents(IndependentStatus.IfNotSet, DependentStatus.MustNotBeSet, "BParam")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? AParam { get; set; }

[TopLevelRequestParameter(Necessity.Optional, "b_param")]
[TopLevelRequestParameterDependents(IndependentStatus.IfSet, DependentStatus.MustBeSet, "AParam")]
[TopLevelRequestParameterDependents(IndependentStatus.IfNotSet, DependentStatus.MustNotBeSet, "AParam")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public string? BParam { get; set; }
}

#pragma warning restore CA1852 // Can be sealed

#endregion
}
Loading

0 comments on commit 2b717b8

Please sign in to comment.