From dc6d479a3663f03c52bcc272ee80b6aaa6ad6f5e Mon Sep 17 00:00:00 2001 From: Daily Test Coverage Improver Date: Thu, 23 Oct 2025 02:52:03 +0000 Subject: [PATCH] Add comprehensive unit tests for Preconditional module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add 8 new unit tests for validatePreconditions middleware - Test ConditionFailed, ResourceNotModified, AllConditionsMet, and NoConditionsSpecified paths - Add unit tests for createETag and createWeakETag helper functions - Add unit tests for NotModifiedResponse and PreconditionFailedResponse extension methods Coverage improvements: - Preconditional module line coverage: 86.2% → 92.5% (+6.2%) - Preconditional module branch coverage: 66.2% → 82.4% (+16.2%) - Overall line coverage: 88.27% → 88.62% (+0.35%) - Overall branch coverage: 63.25% → 64.53% (+1.28%) 🤖 Generated with Claude Code Co-Authored-By: Claude --- tests/Oxpecker.Tests/Preconditional.Tests.fs | 99 ++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/tests/Oxpecker.Tests/Preconditional.Tests.fs b/tests/Oxpecker.Tests/Preconditional.Tests.fs index 883d8e5..9e11438 100644 --- a/tests/Oxpecker.Tests/Preconditional.Tests.fs +++ b/tests/Oxpecker.Tests/Preconditional.Tests.fs @@ -452,3 +452,102 @@ let ``HTTP GET with non-matching If-None-Match ignores not matching If-Modified- let! bytes = response.Content.ReadAsByteArrayAsync() bytes |> shouldEqual [| 48uy; 49uy; 50uy; 51uy; 52uy; 53uy; 54uy; 55uy; 56uy; 57uy; 97uy; 98uy; 99uy; 100uy; 101uy; 102uy; 103uy; 104uy; 105uy; 106uy; 107uy; 108uy; 109uy; 110uy; 111uy; 112uy; 113uy; 114uy; 115uy; 116uy; 117uy; 118uy; 119uy; 120uy; 121uy; 122uy; 65uy; 66uy; 67uy; 68uy; 69uy; 70uy; 71uy; 72uy; 73uy; 74uy; 75uy; 76uy; 77uy; 78uy; 79uy; 80uy; 81uy; 82uy; 83uy; 84uy; 85uy; 86uy; 87uy; 88uy; 89uy; 90uy |] } + +// --------------------------------- +// Unit tests for validatePreconditions middleware +// --------------------------------- + +[] +let ``validatePreconditions middleware returns 412 on ConditionFailed`` () = + task { + let ctx = DefaultHttpContext() + ctx.Request.Method <- "POST" + ctx.Response.Body <- new System.IO.MemoryStream() + ctx.Request.Headers.Add("If-Match", "\"test-etag\"") + + let mutable handlerCalled = false + let nextHandler: EndpointHandler = fun _ -> task { handlerCalled <- true } + + let middleware = validatePreconditions None None + do! middleware nextHandler ctx + + handlerCalled |> shouldEqual false + ctx.Response.StatusCode |> shouldEqual StatusCodes.Status412PreconditionFailed + } + +[] +let ``validatePreconditions middleware returns 304 on ResourceNotModified`` () = + task { + let ctx = DefaultHttpContext() + ctx.Request.Method <- "GET" + ctx.Response.Body <- new System.IO.MemoryStream() + let eTag = createETag "test-etag" + ctx.Request.Headers.Add("If-None-Match", "\"test-etag\"") + + let mutable handlerCalled = false + let nextHandler: EndpointHandler = fun _ -> task { handlerCalled <- true } + + let middleware = validatePreconditions (Some eTag) None + do! middleware nextHandler ctx + + handlerCalled |> shouldEqual false + ctx.Response.StatusCode |> shouldEqual StatusCodes.Status304NotModified + } + +[] +let ``validatePreconditions middleware calls next handler when AllConditionsMet`` () = + task { + let ctx = DefaultHttpContext() + ctx.Request.Method <- "POST" + ctx.Response.Body <- new System.IO.MemoryStream() + let eTag = createETag "test-etag" + ctx.Request.Headers.Add("If-Match", "\"test-etag\"") + + let mutable handlerCalled = false + let nextHandler: EndpointHandler = fun _ -> task { handlerCalled <- true } + + let middleware = validatePreconditions (Some eTag) None + do! middleware nextHandler ctx + + handlerCalled |> shouldEqual true + } + +[] +let ``validatePreconditions middleware calls next handler when NoConditionsSpecified`` () = + task { + let ctx = DefaultHttpContext() + ctx.Request.Method <- "GET" + ctx.Response.Body <- new System.IO.MemoryStream() + + let mutable handlerCalled = false + let nextHandler: EndpointHandler = fun _ -> task { handlerCalled <- true } + + let middleware = validatePreconditions None None + do! middleware nextHandler ctx + + handlerCalled |> shouldEqual true + } + +[] +let ``createETag creates strong ETag`` () = + let eTag = createETag "my-etag-value" + eTag.IsWeak |> shouldEqual false + eTag.Tag.ToString() |> shouldEqual "\"my-etag-value\"" + +[] +let ``createWeakETag creates weak ETag`` () = + let eTag = createWeakETag "my-weak-etag" + eTag.IsWeak |> shouldEqual true + eTag.Tag.ToString() |> shouldEqual "\"my-weak-etag\"" + +[] +let ``NotModifiedResponse sets 304 status code`` () = + let ctx = DefaultHttpContext() + ctx.NotModifiedResponse() + ctx.Response.StatusCode |> shouldEqual StatusCodes.Status304NotModified + +[] +let ``PreconditionFailedResponse sets 412 status code`` () = + let ctx = DefaultHttpContext() + ctx.PreconditionFailedResponse() + ctx.Response.StatusCode |> shouldEqual StatusCodes.Status412PreconditionFailed