http-nu 0.15.0

The surprisingly performant, Nushell-scriptable, cross.stream-powered, Datastar-ready HTTP server that fits in your back pocket.
Documentation
#!/usr/bin/env nu
# Tests for Datastar SSE SDK

use std/assert
use ../src/stdlib/datastar/mod.nu *

# Stub for `to sse` (actual implementation is in http-nu Rust code)
# Skips null values for id, retry, event, data fields
def "to sse" []: record -> string {
  let rec = $in
  mut out = ""
  if ($rec.event? | is-not-empty) { $out = $out + $"event: ($rec.event)\n" }
  if ($rec.id? | is-not-empty) { $out = $out + $"id: ($rec.id)\n" }
  if ($rec.retry? | is-not-empty) { $out = $out + $"retry: ($rec.retry)\n" }
  if ($rec.data? | is-not-empty) {
    let data = $rec.data
    let lines = if ($data | describe | str starts-with "list") {
      $data | each { $in | to text | lines } | flatten
    } else {
      $data | lines
    }
    for line in $lines { $out = $out + $"data: ($line)\n" }
  }
  $out + "\n"
}

# Test patch-elements returns correct record structure
def test_patch_elements_record [] {
  let result = "<div>test</div>" | to datastar-patch-elements --selector "#target"

  assert equal $result.event "datastar-patch-elements"
  assert ("selector #target" in $result.data)
  assert ("elements <div>test</div>" in $result.data)
}

# Test patch-elements with element by ID (no selector)
def test_patch_elements_by_id [] {
  let html = r#'<div id="main">Updated content</div>'#
  let result = $html | to datastar-patch-elements

  assert equal $result.event "datastar-patch-elements"
  assert (r#'elements <div id="main">Updated content</div>'# in $result.data)
  # Default mode is outer, so it should not appear in data
  assert (not ($result.data | any { $in | str starts-with "mode" }))
}

# Test patch-elements with different merge modes
def test_patch_elements_modes [] {
  let prepend = "<div>content</div>" | to datastar-patch-elements --selector "#target" --mode prepend
  assert ("mode prepend" in $prepend.data)

  let append = "<div>content</div>" | to datastar-patch-elements --selector "#target" --mode append
  assert ("mode append" in $append.data)

  let before = "<div>content</div>" | to datastar-patch-elements --selector "#target" --mode before
  assert ("mode before" in $before.data)

  let after = "<div>content</div>" | to datastar-patch-elements --selector "#target" --mode after
  assert ("mode after" in $after.data)

  let remove = "" | to datastar-patch-elements --selector "#target" --mode remove
  assert ("mode remove" in $remove.data)
  assert ("selector #target" in $remove.data)
}

# Test patch-elements with view transition
def test_patch_elements_transition [] {
  let result = "<div>content</div>" | to datastar-patch-elements --selector "#target" --use-view-transition

  assert ("useViewTransition true" in $result.data)
}

# Test patch-elements namespace option
def test_patch_elements_namespace [] {
  # Default namespace (html) should not appear in data
  let html = "<div>content</div>" | to datastar-patch-elements --selector "#target"
  assert (not ($html.data | any { $in | str starts-with "namespace" }))

  # SVG namespace should appear
  let svg = "<circle cx=\"50\" cy=\"50\" r=\"40\"/>" | to datastar-patch-elements --selector "#target" --namespace svg
  assert ("namespace svg" in $svg.data)
}

# Test patch-signals with record input
def test_patch_signals_record [] {
  let signals = {count: 42 name: "Alice"}
  let result = $signals | to datastar-patch-signals

  assert equal $result.event "datastar-patch-signals"
  assert ($result.data | any { str starts-with "signals" })
  assert ($result.data | any { str contains '"count":42' })
  assert ($result.data | any { str contains '"name":"Alice"' })
}

# Test patch-signals with only-if-missing flag
def test_patch_signals_only_if_missing [] {
  let result = {count: 5} | to datastar-patch-signals --only-if-missing

  assert ("onlyIfMissing true" in $result.data)
}

# Test patch-signals with raw string input (multiline)
def test_patch_signals_raw_string [] {
  let raw = "{\n\"one\": 1,\n\"two\": 2}"
  let result = $raw | to datastar-patch-signals

  assert equal $result.event "datastar-patch-signals"
  assert equal ($result.data | length) 3
  assert equal ($result.data | get 0) "signals {"
  assert equal ($result.data | get 1) "signals \"one\": 1,"
  assert equal ($result.data | get 2) "signals \"two\": 2}"
}

# Test execute-script
def test_execute_script [] {
  let script = "console.log('Hello from Datastar')"
  let result = $script | to datastar-execute-script

  # ExecuteScript uses patch-elements event
  assert equal $result.event "datastar-patch-elements"
  assert ("selector body" in $result.data)
  assert ("mode append" in $result.data)
  assert ($result.data | any { str contains "<script" })
  assert ($result.data | any { str contains "console.log" })
  # Default auto-remove is true
  assert ($result.data | any { str contains r#'data-effect="el.remove()"'# })
}

# Test execute-script without auto-remove
def test_execute_script_no_auto_remove [] {
  let result = "alert('test')" | to datastar-execute-script --auto-remove false

  assert ($result.data | any { str contains "<script>alert('test')</script>" })
  assert (not ($result.data | any { str contains "data-effect" }))
}

# Test execute-script with attributes
def test_execute_script_attributes [] {
  let result = "doThing()" | to datastar-execute-script --attributes {type: "module"}

  assert ($result.data | any { str contains r#'type="module"'# })
  assert ($result.data | any { str contains "doThing()" })
}

# Test SSE id field
def test_id_field [] {
  let result = "<div>content</div>" | to datastar-patch-elements --selector "#target" --id "msg-123"

  assert equal $result.id "msg-123"
}

# Test SSE retry-duration field
def test_retry_duration_field [] {
  let result = {count: 1} | to datastar-patch-signals --retry-duration 5000

  assert equal $result.retry 5000
}

# Test from datastar-signals with query string
def test_from_datastar_signals_query [] {
  let req = {
    method: "GET"
    query: {datastar: '{"count":42,"active":true}'}
  }

  let signals = "" | from datastar-signals $req
  assert equal $signals.count 42
  assert equal $signals.active true
}

# Test from datastar-signals with POST body
def test_from_datastar_signals_post [] {
  let req = {method: "POST"}
  let body = '{"username":"alice","score":100}'

  let signals = $body | from datastar-signals $req
  assert equal $signals.username "alice"
  assert equal $signals.score 100
}

# Test from datastar-signals with empty signals
def test_from_datastar_signals_empty [] {
  let req = {
    method: "GET"
    query: {}
  }

  let signals = "" | from datastar-signals $req
  assert equal $signals {}
}

# Test piping to `to sse` produces valid SSE output
def test_to_sse_integration [] {
  let result = "<div>test</div>" | to datastar-patch-elements --selector "#target" | to sse

  assert ($result | str contains "event: datastar-patch-elements")
  assert ($result | str contains "data: selector #target")
  assert ($result | str contains "data: elements <div>test</div>")
}

# Test `to sse` with id and retry-duration fields
def test_to_sse_with_id_retry_duration [] {
  let result = {count: 1} | to datastar-patch-signals --id "evt-1" --retry-duration 3000 | to sse

  assert ($result | str contains "id: evt-1")
  assert ($result | str contains "retry: 3000")
  assert ($result | str contains "event: datastar-patch-signals")
}

# Test redirect helper
def test_redirect [] {
  let result = "/dashboard" | to datastar-redirect

  assert equal $result.event "datastar-patch-elements"
  assert ("selector body" in $result.data)
  assert ("mode append" in $result.data)
  assert ($result.data | any { str contains "window.location.href = '/dashboard'" })
  assert ($result.data | any { str contains "setTimeout" })
}

# Run all tests
def main [] {
  test_patch_elements_record
  test_patch_elements_by_id
  test_patch_elements_modes
  test_patch_elements_transition
  test_patch_elements_namespace
  test_patch_signals_record
  test_patch_signals_only_if_missing
  test_patch_signals_raw_string
  test_execute_script
  test_execute_script_no_auto_remove
  test_execute_script_attributes
  test_id_field
  test_retry_duration_field
  test_from_datastar_signals_query
  test_from_datastar_signals_post
  test_from_datastar_signals_empty
  test_to_sse_integration
  test_to_sse_with_id_retry_duration
  test_redirect
}