Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

192 řádky
7.3KB

  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.False(report.IsConsistent);
  24. Assert.Equal(0, report.ProviderCount);
  25. Assert.Equal(0, report.TotalRecords);
  26. Assert.Equal(0, report.FailedRecords);
  27. Assert.Equal(100.0, report.ConsistencyPercentage);
  28. Assert.Empty(report.Failures);
  29. Assert.Equal(FixedNow, report.CheckedAt);
  30. }
  31. // ── AC #4 — consistent records produce clean report ──────────────────────
  32. [Fact]
  33. public async Task CheckAsync_AllValidLinks_Reports100PercentConsistency_AC4()
  34. {
  35. var data = new InMemoryLegacyDataAccess(
  36. jurisdictions:
  37. [
  38. new("FAIR01", "Fairview", null, null, null, null),
  39. new("LAKE02", "Lake", null, null, null, null),
  40. ]);
  41. var provider = new StubProvider(
  42. [
  43. new StubRecord("MunicipalityProfile", "mp-001", LegacyLinkReference.ForJurisdiction("FAIR01")),
  44. new StubRecord("MunicipalityProfile", "mp-002", LegacyLinkReference.ForJurisdiction("LAKE02")),
  45. ]);
  46. var sut = BuildSut(data, provider);
  47. var report = await sut.CheckAsync();
  48. Assert.True(report.IsConsistent);
  49. Assert.Equal(1, report.ProviderCount);
  50. Assert.Equal(2, report.TotalRecords);
  51. Assert.Equal(2, report.ConsistentRecords);
  52. Assert.Equal(0, report.FailedRecords);
  53. Assert.Equal(100.0, report.ConsistencyPercentage);
  54. Assert.Empty(report.Failures);
  55. }
  56. // ── AC #4 — failing links are flagged with descriptive reason ────────────
  57. [Fact]
  58. public async Task CheckAsync_InvalidLink_FlagsRecordWithReason_AC4()
  59. {
  60. var data = new InMemoryLegacyDataAccess(jurisdictions: []);
  61. var provider = new StubProvider(
  62. [
  63. new StubRecord("MunicipalityProfile", "mp-ghost", LegacyLinkReference.ForJurisdiction("GONE01")),
  64. ]);
  65. var sut = BuildSut(data, provider);
  66. var report = await sut.CheckAsync();
  67. Assert.False(report.IsConsistent);
  68. Assert.Equal(1, report.ProviderCount);
  69. Assert.Equal(1, report.TotalRecords);
  70. Assert.Equal(0, report.ConsistentRecords);
  71. Assert.Equal(1, report.FailedRecords);
  72. Assert.Single(report.Failures);
  73. var failure = report.Failures[0];
  74. Assert.Equal("MunicipalityProfile", failure.RecordType);
  75. Assert.Equal("mp-ghost", failure.RecordId);
  76. Assert.Equal(LegacyLinkType.JurisdictionJCode, failure.Reference.Type);
  77. Assert.Equal("GONE01", failure.Reference.Value);
  78. Assert.Contains("GONE01", failure.Reason);
  79. }
  80. [Fact]
  81. public async Task CheckAsync_MixedValidity_ReportsCorrectConsistencyPercentage_AC4()
  82. {
  83. var data = new InMemoryLegacyDataAccess(
  84. jurisdictions: [new("GOOD01", "Good", null, null, null, null)]);
  85. var provider = new StubProvider(
  86. [
  87. new StubRecord("MunicipalityProfile", "mp-good", LegacyLinkReference.ForJurisdiction("GOOD01")),
  88. new StubRecord("MunicipalityProfile", "mp-bad", LegacyLinkReference.ForJurisdiction("MISSING")),
  89. ]);
  90. var sut = BuildSut(data, provider);
  91. var report = await sut.CheckAsync();
  92. Assert.False(report.IsConsistent);
  93. Assert.Equal(2, report.TotalRecords);
  94. Assert.Equal(1, report.ConsistentRecords);
  95. Assert.Equal(1, report.FailedRecords);
  96. Assert.Equal(50.0, report.ConsistencyPercentage);
  97. }
  98. // ── AC #4 — multiple providers aggregate correctly ───────────────────────
  99. [Fact]
  100. public async Task CheckAsync_MultipleProviders_AggregatesAllRecords_AC4()
  101. {
  102. var data = new InMemoryLegacyDataAccess(
  103. jurisdictions: [new("FAIR01", "Fairview", null, null, null, null)],
  104. kits: [new LegacyKit(101, "FAIR01", null, null, null, null, false, false, null, null, null, null, null, null)]);
  105. var providerA = new StubProvider(
  106. [
  107. new StubRecord("MunicipalityProfile", "mp-001", LegacyLinkReference.ForJurisdiction("FAIR01")),
  108. ]);
  109. var providerB = new StubProvider(
  110. [
  111. new StubRecord("ElectionJob", "ej-001", LegacyLinkReference.ForKit(101)),
  112. ]);
  113. var sut = BuildSut(data, providerA, providerB);
  114. var report = await sut.CheckAsync();
  115. Assert.True(report.IsConsistent);
  116. Assert.Equal(2, report.ProviderCount);
  117. Assert.Equal(2, report.TotalRecords);
  118. Assert.Equal(0, report.FailedRecords);
  119. }
  120. [Fact]
  121. public async Task CheckAsync_DuplicateActiveLinks_FlagsAmbiguousJoin_AC2_AC4()
  122. {
  123. var data = new InMemoryLegacyDataAccess(
  124. jurisdictions: [new("FAIR01", "Fairview", null, null, null, null)]);
  125. var provider = new StubProvider(
  126. [
  127. new StubRecord("MunicipalityProfile", "mp-001", LegacyLinkReference.ForJurisdiction("FAIR01")),
  128. new StubRecord("ElectionJob", "ej-001", LegacyLinkReference.ForJurisdiction("FAIR01")),
  129. ]);
  130. var sut = BuildSut(data, provider);
  131. var report = await sut.CheckAsync();
  132. Assert.False(report.IsConsistent);
  133. Assert.Equal(2, report.TotalRecords);
  134. Assert.Equal(1, report.FailedRecords);
  135. Assert.Contains(report.Failures, failure =>
  136. failure.Reason.Contains("ambiguous", StringComparison.OrdinalIgnoreCase));
  137. }
  138. // ── Helpers ───────────────────────────────────────────────────────────────
  139. private sealed class StubRecord(string recordType, string recordId, LegacyLinkReference link)
  140. : ILegacyLinkedRecord
  141. {
  142. public string RecordType => recordType;
  143. public string RecordId => recordId;
  144. public LegacyLinkReference LegacyLink => link;
  145. }
  146. private sealed class StubProvider(IReadOnlyList<ILegacyLinkedRecord> records)
  147. : ILegacyLinkedRecordProvider
  148. {
  149. public Task<IReadOnlyList<ILegacyLinkedRecord>> GetAllAsync(CancellationToken cancellationToken = default)
  150. => Task.FromResult(records);
  151. }
  152. private sealed class FakeTimeProvider(DateTimeOffset utcNow) : TimeProvider
  153. {
  154. public override DateTimeOffset GetUtcNow() => utcNow;
  155. }
  156. }

Powered by TurnKey Linux.