diff --git a/ErsatzTV.Tests/Controllers/OpenApiPagingContractTests.cs b/ErsatzTV.Tests/Controllers/OpenApiPagingContractTests.cs index 3f1ccedf9..bb7e9ebf2 100644 --- a/ErsatzTV.Tests/Controllers/OpenApiPagingContractTests.cs +++ b/ErsatzTV.Tests/Controllers/OpenApiPagingContractTests.cs @@ -129,11 +129,19 @@ public class OpenApiPagingContractTests foreach ((string key, int cap) in expectedCaps) { - // Match the number as a WHOLE token, not a substring: "capped at 1000" contains - // "capped at 100", so a plain ShouldContain would pass a cap-100 endpoint whose - // description claims 1000 — the exact wrong-cap defect this test exists to catch. - Regex.IsMatch(Description(key, "pageSize"), $@"capped at {cap}(?!\d)", RegexOptions.IgnoreCase) - .ShouldBeTrue($"{key} pageSize should document a cap of exactly {cap}"); + // Enumerate EVERY cap claim in the description and require the set to be exactly one + // number, the right one. Two weaker forms were rejected on the way here: + // - ShouldContain("capped at 100") is satisfied by the string "capped at 1000", so a + // cap-100 endpoint claiming 1000 passed — the very defect this test exists to catch. + // - Matching one occurrence as a whole token ("capped at 100(?!\d)") fixes that, but + // still passes a description that names a wrong cap somewhere ELSE in the sentence + // and the right one later. Presence of a true claim is not absence of a false one. + List claimedCaps = Regex + .Matches(Description(key, "pageSize"), @"capped at (\d+)", RegexOptions.IgnoreCase) + .Select(match => int.Parse(match.Groups[1].Value)) + .ToList(); + + claimedCaps.ShouldBe([cap], $"{key} pageSize should make exactly one cap claim, of {cap}"); } }