Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

162 lines
6.1KB

  1. using Campaign_Tracker.Server.ExtensionData;
  2. using Campaign_Tracker.Server.LegacyData;
  3. using Campaign_Tracker.Server.LegacyData.Models;
  4. namespace Campaign_Tracker.Server.Tests;
  5. public sealed class LegacyLinkIntegrityServiceTests
  6. {
  7. private static readonly DateTimeOffset FixedNow =
  8. new(2026, 5, 6, 12, 0, 0, TimeSpan.Zero);
  9. private static LegacyLinkIntegrityService BuildSut(
  10. ILegacyDataAccess data,
  11. params ILegacyLinkedRecordProvider[] providers)
  12. {
  13. var validator = new LegacyLinkValidator(data);
  14. var time = new FakeTimeProvider(FixedNow);
  15. return new LegacyLinkIntegrityService(providers, validator, time);
  16. }
  17. // ── AC #4 — nightly integrity check with no extension records ────────────
  18. [Fact]
  19. public async Task CheckAsync_NoProviders_ReturnsFullyConsistentReport_AC4()
  20. {
  21. var sut = BuildSut(new InMemoryLegacyDataAccess());
  22. var report = await sut.CheckAsync();
  23. Assert.True(report.IsConsistent);
  24. Assert.Equal(0, report.TotalRecords);
  25. Assert.Equal(0, report.FailedRecords);
  26. Assert.Equal(100.0, report.ConsistencyPercentage);
  27. Assert.Empty(report.Failures);
  28. Assert.Equal(FixedNow, report.CheckedAt);
  29. }
  30. // ── AC #4 — consistent records produce clean report ──────────────────────
  31. [Fact]
  32. public async Task CheckAsync_AllValidLinks_Reports100PercentConsistency_AC4()
  33. {
  34. var data = new InMemoryLegacyDataAccess(
  35. jurisdictions: [new("FAIR01", "Fairview", null, null, null, null)]);
  36. var provider = new StubProvider(
  37. [
  38. new StubRecord("MunicipalityProfile", "mp-001", LegacyLinkReference.ForJurisdiction("FAIR01")),
  39. new StubRecord("MunicipalityProfile", "mp-002", LegacyLinkReference.ForJurisdiction("FAIR01")),
  40. ]);
  41. var sut = BuildSut(data, provider);
  42. var report = await sut.CheckAsync();
  43. Assert.True(report.IsConsistent);
  44. Assert.Equal(2, report.TotalRecords);
  45. Assert.Equal(2, report.ConsistentRecords);
  46. Assert.Equal(0, report.FailedRecords);
  47. Assert.Equal(100.0, report.ConsistencyPercentage);
  48. Assert.Empty(report.Failures);
  49. }
  50. // ── AC #4 — failing links are flagged with descriptive reason ────────────
  51. [Fact]
  52. public async Task CheckAsync_InvalidLink_FlagsRecordWithReason_AC4()
  53. {
  54. var data = new InMemoryLegacyDataAccess(jurisdictions: []);
  55. var provider = new StubProvider(
  56. [
  57. new StubRecord("MunicipalityProfile", "mp-ghost", LegacyLinkReference.ForJurisdiction("GONE01")),
  58. ]);
  59. var sut = BuildSut(data, provider);
  60. var report = await sut.CheckAsync();
  61. Assert.False(report.IsConsistent);
  62. Assert.Equal(1, report.TotalRecords);
  63. Assert.Equal(0, report.ConsistentRecords);
  64. Assert.Equal(1, report.FailedRecords);
  65. Assert.Single(report.Failures);
  66. var failure = report.Failures[0];
  67. Assert.Equal("MunicipalityProfile", failure.RecordType);
  68. Assert.Equal("mp-ghost", failure.RecordId);
  69. Assert.Equal(LegacyLinkType.JurisdictionJCode, failure.Reference.Type);
  70. Assert.Equal("GONE01", failure.Reference.Value);
  71. Assert.Contains("GONE01", failure.Reason);
  72. }
  73. [Fact]
  74. public async Task CheckAsync_MixedValidity_ReportsCorrectConsistencyPercentage_AC4()
  75. {
  76. var data = new InMemoryLegacyDataAccess(
  77. jurisdictions: [new("GOOD01", "Good", null, null, null, null)]);
  78. var provider = new StubProvider(
  79. [
  80. new StubRecord("MunicipalityProfile", "mp-good", LegacyLinkReference.ForJurisdiction("GOOD01")),
  81. new StubRecord("MunicipalityProfile", "mp-bad", LegacyLinkReference.ForJurisdiction("MISSING")),
  82. ]);
  83. var sut = BuildSut(data, provider);
  84. var report = await sut.CheckAsync();
  85. Assert.False(report.IsConsistent);
  86. Assert.Equal(2, report.TotalRecords);
  87. Assert.Equal(1, report.ConsistentRecords);
  88. Assert.Equal(1, report.FailedRecords);
  89. Assert.Equal(50.0, report.ConsistencyPercentage);
  90. }
  91. // ── AC #4 — multiple providers aggregate correctly ───────────────────────
  92. [Fact]
  93. public async Task CheckAsync_MultipleProviders_AggregatesAllRecords_AC4()
  94. {
  95. var data = new InMemoryLegacyDataAccess(
  96. jurisdictions: [new("FAIR01", "Fairview", null, null, null, null)],
  97. kits: [new LegacyKit(101, "FAIR01", null, null, null, null, false, false, null, null, null, null, null, null)]);
  98. var providerA = new StubProvider(
  99. [
  100. new StubRecord("MunicipalityProfile", "mp-001", LegacyLinkReference.ForJurisdiction("FAIR01")),
  101. ]);
  102. var providerB = new StubProvider(
  103. [
  104. new StubRecord("ElectionJob", "ej-001", LegacyLinkReference.ForKit(101)),
  105. ]);
  106. var sut = BuildSut(data, providerA, providerB);
  107. var report = await sut.CheckAsync();
  108. Assert.True(report.IsConsistent);
  109. Assert.Equal(2, report.TotalRecords);
  110. Assert.Equal(0, report.FailedRecords);
  111. }
  112. // ── Helpers ───────────────────────────────────────────────────────────────
  113. private sealed class StubRecord(string recordType, string recordId, LegacyLinkReference link)
  114. : ILegacyLinkedRecord
  115. {
  116. public string RecordType => recordType;
  117. public string RecordId => recordId;
  118. public LegacyLinkReference LegacyLink => link;
  119. }
  120. private sealed class StubProvider(IReadOnlyList<ILegacyLinkedRecord> records)
  121. : ILegacyLinkedRecordProvider
  122. {
  123. public Task<IReadOnlyList<ILegacyLinkedRecord>> GetAllAsync(CancellationToken cancellationToken = default)
  124. => Task.FromResult(records);
  125. }
  126. private sealed class FakeTimeProvider(DateTimeOffset utcNow) : TimeProvider
  127. {
  128. public override DateTimeOffset GetUtcNow() => utcNow;
  129. }
  130. }

Powered by TurnKey Linux.