diff --git a/src/Htmx.Tests/Tests.fs b/src/Htmx.Tests/Tests.fs index 29c002e..556ab93 100644 --- a/src/Htmx.Tests/Tests.fs +++ b/src/Htmx.Tests/Tests.fs @@ -72,4 +72,247 @@ module IHeaderDictionaryExtensions = Option.isSome ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.True Option.get ctx.Request.Headers.HxHistoryRestoreRequest |> Assert.False + [] + let ``HxPrompt succeeds when the header is not present`` () = + let ctx = Substitute.For () + ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore + Option.isNone ctx.Request.Headers.HxPrompt |> Assert.True + + [] + let ``HxPrompt succeeds when the header is present`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + dic.Add ("HX-Prompt", "of course") + ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore + Option.isSome ctx.Request.Headers.HxPrompt |> Assert.True + Assert.Equal("of course", Option.get ctx.Request.Headers.HxPrompt) + + [] + let ``HxRequest succeeds when the header is not present`` () = + let ctx = Substitute.For () + ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore + Option.isNone ctx.Request.Headers.HxRequest |> Assert.True + + [] + let ``HxRequest succeeds when the header is present and true`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + dic.Add ("HX-Request", "true") + ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore + Option.isSome ctx.Request.Headers.HxRequest |> Assert.True + Option.get ctx.Request.Headers.HxRequest |> Assert.True + + [] + let ``HxRequest succeeds when the header is present and false`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + dic.Add ("HX-Request", "false") + ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore + Option.isSome ctx.Request.Headers.HxRequest |> Assert.True + Option.get ctx.Request.Headers.HxRequest |> Assert.False + + [] + let ``HxTarget succeeds when the header is not present`` () = + let ctx = Substitute.For () + ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore + Option.isNone ctx.Request.Headers.HxTarget |> Assert.True + + [] + let ``HxTarget succeeds when the header is present`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + dic.Add ("HX-Target", "#leItem") + ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore + Option.isSome ctx.Request.Headers.HxTarget |> Assert.True + Assert.Equal("#leItem", Option.get ctx.Request.Headers.HxTarget) + + [] + let ``HxTrigger succeeds when the header is not present`` () = + let ctx = Substitute.For () + ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore + Option.isNone ctx.Request.Headers.HxTrigger |> Assert.True + + [] + let ``HxTrigger succeeds when the header is present`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + dic.Add ("HX-Trigger", "#trig") + ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore + Option.isSome ctx.Request.Headers.HxTrigger |> Assert.True + Assert.Equal("#trig", Option.get ctx.Request.Headers.HxTrigger) + + [] + let ``HxTriggerName succeeds when the header is not present`` () = + let ctx = Substitute.For () + ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore + Option.isNone ctx.Request.Headers.HxTriggerName |> Assert.True + + [] + let ``HxTriggerName succeeds when the header is present`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + dic.Add ("HX-Trigger-Name", "click") + ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore + Option.isSome ctx.Request.Headers.HxTriggerName |> Assert.True + Assert.Equal("click", Option.get ctx.Request.Headers.HxTriggerName) + + +/// Tests for the HttpRequest extension properties +module HttpRequestExtensions = + + [] + let ``IsHtmx succeeds when request is not from htmx`` () = + let ctx = Substitute.For () + ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore + Assert.False ctx.Request.IsHtmx + + [] + let ``IsHtmx succeeds when request is from htmx`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + dic.Add ("HX-Request", "true") + ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore + Assert.True ctx.Request.IsHtmx + + [] + let ``IsHtmxRefresh succeeds when request is not from htmx`` () = + let ctx = Substitute.For () + ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore + Assert.False ctx.Request.IsHtmxRefresh + + [] + let ``IsHtmxRefresh succeeds when request is from htmx, but not a refresh`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + dic.Add ("HX-Request", "true") + ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore + Assert.False ctx.Request.IsHtmxRefresh + + [] + let ``IsHtmxRefresh succeeds when request is from htmx and is a refresh`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + dic.Add ("HX-Request", "true") + dic.Add ("HX-History-Restore-Request", "true") + ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore + Assert.True ctx.Request.IsHtmxRefresh + + +/// Tests for the HttpHandler functions provided in the Handlers module +module HandlerTests = + + open System.Threading.Tasks + + /// Dummy "next" parameter to get the pipeline to execute/terminate + let next (ctx : HttpContext) = Task.FromResult (Some ctx) + + [] + let ``withHxPush succeeds`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore + task { + let! _ = withHxPush "/a-new-url" next ctx + Assert.True (dic.ContainsKey "HX-Push") + Assert.Equal ("/a-new-url", dic.["HX-Push"].[0]) + } + + [] + let ``withHxRedirect succeeds`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore + task { + let! _ = withHxRedirect "/somewhere-else" next ctx + Assert.True (dic.ContainsKey "HX-Redirect") + Assert.Equal ("/somewhere-else", dic.["HX-Redirect"].[0]) + } + + [] + let ``withHxRefresh succeeds when set to true`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore + task { + let! _ = withHxRefresh true next ctx + Assert.True (dic.ContainsKey "HX-Refresh") + Assert.Equal ("true", dic.["HX-Refresh"].[0]) + } + + [] + let ``withHxRefresh succeeds when set to false`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore + task { + let! _ = withHxRefresh false next ctx + Assert.True (dic.ContainsKey "HX-Refresh") + Assert.Equal ("false", dic.["HX-Refresh"].[0]) + } + + [] + let ``withHxTrigger succeeds`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore + task { + let! _ = withHxTrigger "doSomething" next ctx + Assert.True (dic.ContainsKey "HX-Trigger") + Assert.Equal ("doSomething", dic.["HX-Trigger"].[0]) + } + + [] + let ``withHxTriggerMany succeeds`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore + task { + let! _ = withHxTriggerMany [ "blah", "foo"; "bleh", "bar" ] next ctx + Assert.True (dic.ContainsKey "HX-Trigger") + Assert.Equal ("""{ "blah": "foo", "bleh": "bar" }""", dic.["HX-Trigger"].[0]) + } + + [] + let ``withHxTriggerAfterSettle succeeds`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore + task { + let! _ = withHxTriggerAfterSettle "byTheWay" next ctx + Assert.True (dic.ContainsKey "HX-Trigger-After-Settle") + Assert.Equal ("byTheWay", dic.["HX-Trigger-After-Settle"].[0]) + } + + [] + let ``withHxTriggerManyAfterSettle succeeds`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore + task { + let! _ = withHxTriggerManyAfterSettle [ "oof", "ouch"; "hmm", "uh" ] next ctx + Assert.True (dic.ContainsKey "HX-Trigger-After-Settle") + Assert.Equal ("""{ "oof": "ouch", "hmm": "uh" }""", dic.["HX-Trigger-After-Settle"].[0]) + } + + [] + let ``withHxTriggerAfterSwap succeeds`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore + task { + let! _ = withHxTriggerAfterSwap "justASec" next ctx + Assert.True (dic.ContainsKey "HX-Trigger-After-Swap") + Assert.Equal ("justASec", dic.["HX-Trigger-After-Swap"].[0]) + } + + [] + let ``withHxTriggerManyAfterSwap succeeds`` () = + let ctx = Substitute.For () + let dic = HeaderDictionary () + ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore + task { + let! _ = withHxTriggerManyAfterSwap [ "this", "1"; "that", "2" ] next ctx + Assert.True (dic.ContainsKey "HX-Trigger-After-Swap") + Assert.Equal ("""{ "this": "1", "that": "2" }""", dic.["HX-Trigger-After-Swap"].[0]) + }