test: 补齐 GB/CA 字母数字邮编前缀、精确与闭区间匹配
All checks were successful
Build and Deploy / deploy (push) Successful in 1m2s

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-10-05 16:30:18 +08:00
parent 74a71991b2
commit c91d8ca0e6

View File

@ -118,6 +118,110 @@ public class GeoPartitionMatcherTests
act.Should().Throw<InvalidOperationException>().WithMessage("*州*");
}
[Theory]
[InlineData("BT9 7AA", "BT97AA")]
[InlineData("bt97aa", "BT97AA")]
[InlineData("BT9-7AA", "BT97AA")]
[InlineData("B46 3AB", "B463AB")]
[InlineData(" b46 3ab ", "B463AB")]
public void NormalizeZip_AlphanumericWithSpaces_ShouldStripAndUpper(string raw, string expected)
{
GeoPartitionMatcher.NormalizeZip(raw).Should().Be(expected);
}
[Fact]
public void Gb_Bt97aa_LongerOutwardPrefixWins()
{
var rules = CompileEntities(
Zip("GB", "BT"),
Zip("GB", "BT9"),
Zip("GB", "BT97"),
Zip("GB", "B"));
var hit = GeoPartitionMatcher.MatchEntity(rules, "GB", "NIR", "Belfast", "BT9 7AA");
hit!.LeftPostcode.Should().Be("BT97");
GeoPartitionMatcher.MatchEntity(rules, "gb", null, null, "BT97AA")!.LeftPostcode.Should().Be("BT97");
}
[Fact]
public void Gb_Bt97aa_ExactIgnoresSpaces()
{
var rules = CompileEntities(Exact("GB", "BT9 7AA"));
GeoPartitionMatcher.IsHit(rules, "GB", null, null, "BT97AA").Should().BeTrue();
GeoPartitionMatcher.IsHit(rules, "GB", null, null, "BT9 7AA").Should().BeTrue();
GeoPartitionMatcher.IsHit(rules, "GB", null, null, "BT9 7AB").Should().BeFalse();
GeoPartitionMatcher.IsHit(rules, "GB", null, null, "BT98AA").Should().BeFalse();
}
[Fact]
public void Gb_Bt97aa_ClosedAlphanumericRange()
{
var rules = CompileEntities(Range("GB", "BT90AA", "BT99ZZ"));
GeoPartitionMatcher.IsHit(rules, "GB", null, null, "BT97AA").Should().BeTrue();
GeoPartitionMatcher.IsHit(rules, "GB", null, null, "BT9 7AA").Should().BeTrue();
GeoPartitionMatcher.IsHit(rules, "GB", null, null, "BT90AA").Should().BeTrue();
GeoPartitionMatcher.IsHit(rules, "GB", null, null, "BT99ZZ").Should().BeTrue();
GeoPartitionMatcher.IsHit(rules, "GB", null, null, "BT8 1AA").Should().BeFalse();
GeoPartitionMatcher.IsHit(rules, "GB", null, null, "E1 6AN").Should().BeFalse();
}
[Fact]
public void Ca_B463ab_PrefixAndSpaceVariants()
{
var rules = CompileEntities(
Zip("CA", "B"),
Zip("CA", "B4"),
Zip("CA", "B46"),
Zip("CA", "B463"));
var hit = GeoPartitionMatcher.MatchEntity(rules, "CA", "ON", "Toronto", "B46 3AB");
hit!.LeftPostcode.Should().Be("B463");
GeoPartitionMatcher.IsHit(rules, "CA", null, null, "B463AB").Should().BeTrue();
GeoPartitionMatcher.MatchEntity(rules, "CA", null, null, "B47 3AB")!.LeftPostcode.Should().Be("B4");
GeoPartitionMatcher.IsHit(rules, "CA", null, null, "M5V 2T6").Should().BeFalse();
}
[Fact]
public void Ca_B463ab_ExactAndRange()
{
var exact = CompileEntities(Exact("CA", "B46 3AB"));
var range = CompileEntities(Range("CA", "B460AA", "B469ZZ"));
GeoPartitionMatcher.IsHit(exact, "CA", null, null, "B46 3AB").Should().BeTrue();
GeoPartitionMatcher.IsHit(exact, "CA", null, null, "B463AB").Should().BeTrue();
GeoPartitionMatcher.IsHit(exact, "CA", null, null, "B46 3AC").Should().BeFalse();
GeoPartitionMatcher.IsHit(range, "CA", null, null, "B46 3AB").Should().BeTrue();
GeoPartitionMatcher.IsHit(range, "CA", null, null, "B46 0AA").Should().BeTrue();
GeoPartitionMatcher.IsHit(range, "CA", null, null, "B47 3AB").Should().BeFalse();
}
[Fact]
public void GbAndCa_SameLookingPostcode_CountryMustMatch()
{
var gb = CompileEntities(Zip("GB", "B46"), Exact("GB", "BT97AA"));
var ca = CompileEntities(Zip("CA", "B46"));
GeoPartitionMatcher.IsHit(gb, "GB", null, null, "B46 3AB").Should().BeTrue();
GeoPartitionMatcher.IsHit(gb, "CA", null, null, "B46 3AB").Should().BeFalse();
GeoPartitionMatcher.IsHit(ca, "CA", null, null, "B46 3AB").Should().BeTrue();
GeoPartitionMatcher.IsHit(ca, "GB", null, null, "BT97AA").Should().BeFalse();
GeoPartitionMatcher.IsHit(gb, "GB", null, null, "BT97AA").Should().BeTrue();
}
[Fact]
public void Gb_Bt97aa_ZipPresent_ShouldSkipState()
{
var rules = CompileEntities(
State("GB", "NIR"),
Zip("GB", "BT1"));
GeoPartitionMatcher.MatchEntity(rules, "GB", "NIR", "Belfast", "BT97AA").Should().BeNull();
GeoPartitionMatcher.MatchEntity(rules, "GB", "NIR", "Belfast", null)!.Province.Should().Be("NIR");
}
private static List<KpiAreaInfo> CompileEntities(params KpiAreaInfo[] items)
{
foreach (var item in items)
@ -131,6 +235,9 @@ public class GeoPartitionMatcherTests
private static KpiAreaInfo Zip(string country, string prefix) =>
new() { CountryCode = country, LeftPostcode = prefix };
private static KpiAreaInfo Exact(string country, string postcode) =>
new() { CountryCode = country, LeftPostcode = postcode, RightPostcode = postcode };
private static KpiAreaInfo Range(string country, string left, string right) =>
new() { CountryCode = country, LeftPostcode = left, RightPostcode = right };