Rearrange obsolete tests; test new v4 code
This commit is contained in:
@@ -2,4 +2,6 @@
|
||||
|
||||
This package contains common code shared between [`Giraffe.Htmx`](https://www.nuget.org/packages/Giraffe.Htmx) and [`Giraffe.ViewEngine.Htmx`](https://www.nuget.org/packages/Giraffe.ViewEngine.Htmx), and will be automatically installed when you install either one. It also contains htmx as a static web asset, allowing it to be loaded from your local (or published) project.
|
||||
|
||||
**htmx version: 2.0.8**
|
||||
**htmx version: 4.0.0-alpha6**
|
||||
|
||||
_**NOTE:** Pay special attention to breaking changes highlighted in the packages listed above._
|
||||
@@ -2,16 +2,16 @@
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<VersionPrefix>2.0.8</VersionPrefix>
|
||||
<VersionPrefix>4.0.0</VersionPrefix>
|
||||
<VersionSuffix>alpha6a</VersionSuffix>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageReleaseNotes>- Adds package-provided script (available via Giraffe.Htmx.Common); use app.MapStaticAssets() for publish support, use builder.UseStaticWebAssets() for non-development/non-published execution
|
||||
- [View Engine] Deprecates Script.minified and Script.unminified (use Script.cdnMinified and Script.cdnUnminified instead)
|
||||
- Updates script tags to pull htmx 2.0.8 (no header or attribute changes)
|
||||
- Adds .NET 10 support
|
||||
<PackageReleaseNotes>First htmx 4 alpha release of these libraries
|
||||
- [Server] Marked removed headers as obsolete; added new HX-Source header
|
||||
- [View Engine] Marked removed attributes as obsolete
|
||||
- [View Engine] Added new attributes, modifiers, and support for new hx-partial tag
|
||||
- Updated script tags to pull htmx 4.0.0-alpha6
|
||||
|
||||
See full release notes, including more info about the package-provided script, at https://git.bitbadger.solutions/bit-badger/Giraffe.Htmx/releases/tag/v2.0.8
|
||||
|
||||
NOTE: As of 2.0.6, the CDN for htmx changed from unpkg.com to cdn.jsdelivr.net; sites with Content-Security-Policy headers will want to update their allowed script-src domains accordingly
|
||||
See package READMEs; this is not an update-and-forget-it release
|
||||
</PackageReleaseNotes>
|
||||
<Authors>danieljsummers</Authors>
|
||||
<Company>Bit Badger Solutions</Company>
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
This package enables server-side support for [htmx](https://htmx.org) within [Giraffe](https://giraffe.wiki) and ASP.NET's `HttpContext`.
|
||||
|
||||
**htmx version: 2.0.8**
|
||||
**htmx version: 4.0.0-alpha6**
|
||||
|
||||
_Upgrading from v1.x: the [migration guide](https://htmx.org/migration-guide-htmx-1/) does not currently specify any request or response header changes. This means that there are no required code changes in moving from v1.* to v2.*._
|
||||
_Upgrading from v2.x: the [migration guide](https://four.htmx.org/migration-guide-htmx-4/) lists changes for v4. For this package, the `HX-Trigger` and `HX-Trigger-Name` headers are marked obsolete. They are replaced by `HX-Source`, which provides the triggering tag name and `id` attribute. The `HX-Prompt` header has also been marked as obsolete, as the `hx-prompt` attribute which generated its content has been removed._
|
||||
|
||||
_Obsolete elements will be removed in the first production v4 release._
|
||||
|
||||
### Setup
|
||||
|
||||
@@ -18,9 +20,9 @@ To obtain a request header, using the `IHeaderDictionary` extension properties:
|
||||
```fsharp
|
||||
let myHandler : HttpHander =
|
||||
fun next ctx ->
|
||||
match ctx.HxPrompt with
|
||||
| Some prompt -> ... // do something with the text the user provided
|
||||
| None -> ... // no text provided
|
||||
match ctx.Target with
|
||||
| Some elt -> ... // do something with id of the target element
|
||||
| None -> ... // no target element provided
|
||||
```
|
||||
|
||||
To set a response header:
|
||||
|
||||
@@ -3,7 +3,6 @@ module Htmx
|
||||
open System
|
||||
open Expecto
|
||||
open Giraffe.Htmx
|
||||
open Microsoft.AspNetCore.Html
|
||||
open Microsoft.AspNetCore.Http
|
||||
open NSubstitute
|
||||
|
||||
@@ -74,21 +73,6 @@ let dictExtensions =
|
||||
ctx.Request.Headers.HxHistoryRestoreRequest.Value "The header should have been false"
|
||||
}
|
||||
]
|
||||
testList "HxPrompt" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
|
||||
Expect.isNone ctx.Request.Headers.HxPrompt "There should not have been a header returned"
|
||||
}
|
||||
test "succeeds when the header is present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Prompt", "of course")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
Expect.isSome ctx.Request.Headers.HxPrompt "There should be a header present"
|
||||
Expect.equal ctx.Request.Headers.HxPrompt.Value "of course" "The header value was incorrect"
|
||||
}
|
||||
]
|
||||
testList "HxRequest" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
@@ -112,6 +96,44 @@ let dictExtensions =
|
||||
Expect.isFalse ctx.Request.Headers.HxRequest.Value "The header should have been false"
|
||||
}
|
||||
]
|
||||
testList "HxSource" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
|
||||
Expect.isNone ctx.Request.Headers.HxSource "There should not have been a header returned"
|
||||
}
|
||||
test "succeeds when the header is present and both parts exist" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Source", "button#theId")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
let hdr = ctx.Request.Headers.HxSource
|
||||
Expect.isSome hdr "There should be a header present"
|
||||
Expect.equal (fst hdr.Value) "button" "The source tag was incorrect"
|
||||
Expect.isSome (snd hdr.Value) "There should be a source ID present"
|
||||
Expect.equal (snd hdr.Value).Value "theId" "The source ID was incorrect"
|
||||
}
|
||||
test "succeeds when the header is present and ID is blank" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Source", "a#")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
let hdr = ctx.Request.Headers.HxSource
|
||||
Expect.isSome hdr "There should be a header present"
|
||||
Expect.equal (fst hdr.Value) "a" "The source tag was incorrect"
|
||||
Expect.isNone (snd hdr.Value) "There should not be a source ID present"
|
||||
}
|
||||
test "succeeds when the header is present and ID is missing" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Source", "form")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
let hdr = ctx.Request.Headers.HxSource
|
||||
Expect.isSome hdr "There should be a header present"
|
||||
Expect.equal (fst hdr.Value) "form" "The source tag was incorrect"
|
||||
Expect.isNone (snd hdr.Value) "There should not be a source ID present"
|
||||
}
|
||||
]
|
||||
testList "HxTarget" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
@@ -127,36 +149,6 @@ let dictExtensions =
|
||||
Expect.equal ctx.Request.Headers.HxTarget.Value "#leItem" "The header value was incorrect"
|
||||
}
|
||||
]
|
||||
testList "HxTrigger" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
|
||||
Expect.isNone ctx.Request.Headers.HxTrigger "There should not have been a header returned"
|
||||
}
|
||||
test "succeeds when the header is present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Trigger", "#trig")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
Expect.isSome ctx.Request.Headers.HxTrigger "There should be a header present"
|
||||
Expect.equal ctx.Request.Headers.HxTrigger.Value "#trig" "The header value was incorrect"
|
||||
}
|
||||
]
|
||||
testList "HxTriggerName" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
|
||||
Expect.isNone ctx.Request.Headers.HxTriggerName "There should not have been a header returned"
|
||||
}
|
||||
test "HxTriggerName succeeds when the header is present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Trigger-Name", "click")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
Expect.isSome ctx.Request.Headers.HxTriggerName "There should be a header present"
|
||||
Expect.equal ctx.Request.Headers.HxTriggerName.Value "click" "The header value was incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Tests for the HttpRequest extension properties
|
||||
@@ -366,5 +358,55 @@ let script =
|
||||
}
|
||||
]
|
||||
|
||||
#nowarn 44 // Obsolete items still have tests
|
||||
let dictExtensionsObs =
|
||||
testList "IHeaderDictionaryExtensions (Obsolete)" [
|
||||
testList "HxPrompt" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
|
||||
Expect.isNone ctx.Request.Headers.HxPrompt "There should not have been a header returned"
|
||||
}
|
||||
test "succeeds when the header is present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Prompt", "of course")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
Expect.isSome ctx.Request.Headers.HxPrompt "There should be a header present"
|
||||
Expect.equal ctx.Request.Headers.HxPrompt.Value "of course" "The header value was incorrect"
|
||||
}
|
||||
]
|
||||
testList "HxTrigger" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
ctx.Request.Headers.ReturnsForAnyArgs (HeaderDictionary ()) |> ignore
|
||||
Expect.isNone ctx.Request.Headers.HxTrigger "There should not have been a header returned"
|
||||
}
|
||||
test "succeeds when the header is present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Trigger", "#trig")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
Expect.isSome ctx.Request.Headers.HxTrigger "There should be a header present"
|
||||
Expect.equal ctx.Request.Headers.HxTrigger.Value "#trig" "The header value was incorrect"
|
||||
}
|
||||
]
|
||||
testList "HxTriggerName" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
|
||||
Expect.isNone ctx.Request.Headers.HxTriggerName "There should not have been a header returned"
|
||||
}
|
||||
test "HxTriggerName succeeds when the header is present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Trigger-Name", "click")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
Expect.isSome ctx.Request.Headers.HxTriggerName "There should be a header present"
|
||||
Expect.equal ctx.Request.Headers.HxTriggerName.Value "click" "The header value was incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// All tests for this module
|
||||
let allTests = testList "Htmx" [ dictExtensions; reqExtensions; handlers; script ]
|
||||
let allTests = testList "Htmx" [ dictExtensions; reqExtensions; handlers; script; dictExtensionsObs ]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,41 @@
|
||||
/// <summary>Types and functions supporting htmx attributes in Giraffe View Engine</summary>
|
||||
module Giraffe.ViewEngine.Htmx
|
||||
|
||||
open System.Net.Http
|
||||
/// <summary>Helpers to define <c>hx-config</c> attribute values</summary>
|
||||
/// <seealso href="https://four.htmx.org/attributes/hx-config/">Documentation</seealso>
|
||||
[<RequireQualifiedAccess>]
|
||||
module HxConfig =
|
||||
|
||||
open Giraffe.Htmx.Common
|
||||
|
||||
/// <summary>Configure the request with various options</summary>
|
||||
/// <param name="opts">The options to configure</param>
|
||||
/// <returns>A string with the configured options</returns>
|
||||
let Configure (opts: string list) =
|
||||
opts
|
||||
|> String.concat ", "
|
||||
|> sprintf "{ %s }"
|
||||
|
||||
/// <summary>Set a timeout (in milliseconds)</summary>
|
||||
/// <param name="ms">The milliseconds for the request timeout</param>
|
||||
/// <returns>A string with the configured request timeout</returns>
|
||||
let Timeout (ms: int) =
|
||||
$"\"timeout\": {ms}"
|
||||
|
||||
/// <summary>Include or exclude credentials from the request</summary>
|
||||
/// <param name="send"><c>true</c> if credentials should be sent, <c>false</c> if not</param>
|
||||
/// <returns>A string with the configured credential options</returns>
|
||||
let Credentials send =
|
||||
(toLowerBool >> sprintf "\"credentials\": %s") send
|
||||
|
||||
/// <summary>Exclude or include headers from the request</summary>
|
||||
/// <param name="exclude">
|
||||
/// <c>true</c> if no headers should be sent; <c>false</c> if headers should be sent
|
||||
/// </param>
|
||||
/// <returns>A string with the configured header options</returns>
|
||||
let NoHeaders exclude =
|
||||
(toLowerBool >> sprintf "\"noHeaders\": %s") exclude
|
||||
|
||||
|
||||
/// <summary>Valid values for the <c>hx-encoding</c> attribute</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -289,6 +323,7 @@ module HxHeaders =
|
||||
/// <summary>Values / helpers for the <c>hx-params</c> attribute</summary>
|
||||
/// <seealso href="https://htmx.org/attributes/hx-params/">Documentation</seealso>
|
||||
[<RequireQualifiedAccess>]
|
||||
[<System.Obsolete "Removed in v4; filter parameters via JavaScript in configRequest event">]
|
||||
module HxParams =
|
||||
|
||||
/// <summary>Include all parameters</summary>
|
||||
@@ -315,6 +350,7 @@ module HxParams =
|
||||
/// <summary>Helpers to define <c>hx-request</c> attribute values</summary>
|
||||
/// <seealso href="https://htmx.org/attributes/hx-request/">Documentation</seealso>
|
||||
[<RequireQualifiedAccess>]
|
||||
[<System.Obsolete "Removed in v4; change to HxConfig">]
|
||||
module HxRequest =
|
||||
|
||||
open Giraffe.Htmx.Common
|
||||
@@ -564,6 +600,7 @@ module HxVals =
|
||||
let From = Giraffe.Htmx.Common.toJson
|
||||
|
||||
|
||||
open System.Net.Http
|
||||
open Giraffe.Htmx
|
||||
|
||||
/// <summary>Attributes and flags for htmx</summary>
|
||||
@@ -913,10 +950,10 @@ module HxModifiers =
|
||||
| KeyValue (name, value) -> attr $"{name}:append" value
|
||||
| Boolean name -> flag $"{name}:append"
|
||||
|
||||
/// <summary>Explicity inherit the value for this attribute</summary>
|
||||
/// <summary>Explicitly propagate inheritance for the value for this attribute</summary>
|
||||
/// <param name="attrib">The attribute whose value should be inherited</param>
|
||||
/// <returns>The given attribute with <c>:inherited</c> applied</returns>
|
||||
let hxInherit attrib =
|
||||
let hxInherited attrib =
|
||||
match attrib with
|
||||
| KeyValue (name, value) -> attr $"{name}:inherited" value
|
||||
| Boolean name -> flag $"{name}:inherited"
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
|
||||
This package enables [htmx](https://htmx.org) support within the [Giraffe](https://giraffe.wiki) view engine.
|
||||
|
||||
**htmx version: 2.0.8**
|
||||
**htmx version: 4.0.0-alpha6**
|
||||
|
||||
_Upgrading from v1.x: see [the migration guide](https://htmx.org/migration-guide-htmx-1/) for changes_
|
||||
_Upgrading from v2.x: see [the migration guide](https://four.htmx.org/migration-guide-htmx-4/) for changes, which are plentiful. htmx switches from `XMLHTTPRequest` to `fetch`, and many changes are related to the new event cycle._
|
||||
|
||||
_Inheritance is now explicit; to have an attribute's value inherited to its children, wrap the attribute in `hxInherited` (ex. `hxInherited (_hxTarget "#main")`). Values can be appended to inherited values as well using the `hxAppend` modifier._
|
||||
|
||||
_Several constructs have been marked obsolete in this release, and will be removed from the first production release of v4. With the exception of `_hxDisable`, though (which now functions as the deprecated `_hxDisabledElt` did), this should not introduce compile errors. Rather, this package will raise warnings for deprecated constructs, along with suggestions of what to use instead._
|
||||
|
||||
### Setup
|
||||
|
||||
@@ -21,10 +25,11 @@ let autoload =
|
||||
```
|
||||
|
||||
Support modules include:
|
||||
- `HxConfig` _(new in v4)_
|
||||
- `HxEncoding`
|
||||
- `HxHeaders`
|
||||
- `HxParams`
|
||||
- `HxRequest`
|
||||
- ~~`HxParams`~~ _(removed in v4)_
|
||||
- ~~`HxRequest`~~ _(renamed to `HxConfig`)_
|
||||
- `HxSwap` (requires `open Giraffe.Htmx`)
|
||||
- `HxTrigger`
|
||||
- `HxVals`
|
||||
|
||||
Reference in New Issue
Block a user