using Campaign_Tracker.Server.ExtensionData; using Campaign_Tracker.Server.LegacyData; using Campaign_Tracker.Server.LegacyData.Models; namespace Campaign_Tracker.Server.Tests; public sealed class LegacyLinkValidatorTests { // ── AC #2 — ACL join returns correct record with no ambiguity ──────────── [Fact] public async Task ValidateAsync_JurisdictionJCode_ExistingRecord_ReturnsSuccess_AC2() { var data = new InMemoryLegacyDataAccess( jurisdictions: [new("FAIR01", "Fairview Borough", null, null, null, null)]); var sut = new LegacyLinkValidator(data); var result = await sut.ValidateAsync(LegacyLinkReference.ForJurisdiction("FAIR01")); Assert.True(result.IsValid); Assert.Null(result.Error); } [Fact] public async Task ValidateAsync_KitId_ExistingRecord_ReturnsSuccess_AC2() { var kit = new LegacyKit(101, "FAIR01", null, null, null, null, false, false, null, null, null, null, null, null); var data = new InMemoryLegacyDataAccess(kits: [kit]); var sut = new LegacyLinkValidator(data); var result = await sut.ValidateAsync(LegacyLinkReference.ForKit(101)); Assert.True(result.IsValid); } [Fact] public async Task ValidateAsync_ContactId_ExistingRecord_ReturnsSuccess_AC2() { var contact = new LegacyContact(1, "FAIR01", "Jane Doe", null, null, null, null, null, null, null, null, null, null, null, null); var data = new InMemoryLegacyDataAccess(contacts: [contact]); var sut = new LegacyLinkValidator(data); var result = await sut.ValidateAsync(LegacyLinkReference.ForContact(1)); Assert.True(result.IsValid); } [Fact] public async Task ValidateAsync_JurisdictionJCode_IsCaseInsensitive_AC2() { var data = new InMemoryLegacyDataAccess( jurisdictions: [new("FAIR01", "Fairview Borough", null, null, null, null)]); var sut = new LegacyLinkValidator(data); var result = await sut.ValidateAsync(LegacyLinkReference.ForJurisdiction("fair01")); Assert.True(result.IsValid); } // ── AC #3 — invalid/non-existent reference rejected with descriptive error ─ [Fact] public async Task ValidateAsync_JurisdictionJCode_NotFound_ReturnsFailureWithDescription_AC3() { var data = new InMemoryLegacyDataAccess(jurisdictions: []); var sut = new LegacyLinkValidator(data); var result = await sut.ValidateAsync(LegacyLinkReference.ForJurisdiction("UNKNOWN")); Assert.False(result.IsValid); Assert.NotNull(result.Error); Assert.Contains("UNKNOWN", result.Error); Assert.Contains("jurisdiction", result.Error, StringComparison.OrdinalIgnoreCase); } [Fact] public async Task ValidateAsync_KitId_NotFound_ReturnsFailureWithDescription_AC3() { var data = new InMemoryLegacyDataAccess(kits: []); var sut = new LegacyLinkValidator(data); var result = await sut.ValidateAsync(LegacyLinkReference.ForKit(9999)); Assert.False(result.IsValid); Assert.NotNull(result.Error); Assert.Contains("9999", result.Error); Assert.Contains("kit", result.Error, StringComparison.OrdinalIgnoreCase); } [Fact] public async Task ValidateAsync_ContactId_NotFound_ReturnsFailureWithDescription_AC3() { var data = new InMemoryLegacyDataAccess(contacts: []); var sut = new LegacyLinkValidator(data); var result = await sut.ValidateAsync(LegacyLinkReference.ForContact(9999)); Assert.False(result.IsValid); Assert.NotNull(result.Error); Assert.Contains("9999", result.Error); Assert.Contains("contact", result.Error, StringComparison.OrdinalIgnoreCase); } [Fact] public async Task ValidateAsync_BlankJCode_ReturnsFailureWithDescription_AC3() { var data = new InMemoryLegacyDataAccess(); var sut = new LegacyLinkValidator(data); var result = await sut.ValidateAsync(new LegacyLinkReference(LegacyLinkType.JurisdictionJCode, " ")); Assert.False(result.IsValid); Assert.NotNull(result.Error); Assert.Contains("required", result.Error, StringComparison.OrdinalIgnoreCase); } [Fact] public async Task ValidateAsync_KitId_NonIntegerValue_ReturnsFailureWithDescription_AC3() { var data = new InMemoryLegacyDataAccess(); var sut = new LegacyLinkValidator(data); var result = await sut.ValidateAsync(new LegacyLinkReference(LegacyLinkType.KitId, "not-a-number")); Assert.False(result.IsValid); Assert.NotNull(result.Error); Assert.Contains("not-a-number", result.Error); } [Fact] public async Task ValidateAsync_ContactId_NonIntegerValue_ReturnsFailureWithDescription_AC3() { var data = new InMemoryLegacyDataAccess(); var sut = new LegacyLinkValidator(data); var result = await sut.ValidateAsync(new LegacyLinkReference(LegacyLinkType.ContactId, "abc")); Assert.False(result.IsValid); Assert.NotNull(result.Error); } // ── AC #1 — factory methods produce correct link type and value ─────────── [Fact] public void ForJurisdiction_SetsCorrectTypeAndValue_AC1() { var ref_ = LegacyLinkReference.ForJurisdiction("LAKE02"); Assert.Equal(LegacyLinkType.JurisdictionJCode, ref_.Type); Assert.Equal("LAKE02", ref_.Value); } [Fact] public void ForKit_SetsCorrectTypeAndValue_AC1() { var ref_ = LegacyLinkReference.ForKit(101); Assert.Equal(LegacyLinkType.KitId, ref_.Type); Assert.Equal("101", ref_.Value); } [Fact] public void ForContact_SetsCorrectTypeAndValue_AC1() { var ref_ = LegacyLinkReference.ForContact(42); Assert.Equal(LegacyLinkType.ContactId, ref_.Type); Assert.Equal("42", ref_.Value); } [Fact] public void ForJurisdiction_BlankJCode_Throws_AC1() { Assert.Throws(() => LegacyLinkReference.ForJurisdiction("")); Assert.Throws(() => LegacyLinkReference.ForJurisdiction(" ")); } }