;; lib/dream/tests/headers.sx — security headers + cache-control.

(define dream-hd-pass 0)
(define dream-hd-fail 0)
(define dream-hd-fails (list))

(define
  dream-hd-test
  (fn
    (name actual expected)
    (if
      (= actual expected)
      (set! dream-hd-pass (+ dream-hd-pass 1))
      (begin
        (set! dream-hd-fail (+ dream-hd-fail 1))
        (append! dream-hd-fails {:name name :actual actual :expected expected})))))

(define dream-hd-h (fn (req) (dream-text "body")))
(define dream-hd-req (dream-request "GET" "/" {} ""))

;; ── security headers ───────────────────────────────────────────────
(define dream-hd-sec ((dream-security-headers dream-hd-h) dream-hd-req))
(dream-hd-test
  "nosniff"
  (dream-resp-header dream-hd-sec "x-content-type-options")
  "nosniff")
(dream-hd-test
  "frame deny"
  (dream-resp-header dream-hd-sec "x-frame-options")
  "DENY")
(dream-hd-test
  "referrer policy"
  (dream-resp-header dream-hd-sec "referrer-policy")
  "no-referrer")
(dream-hd-test
  "no hsts by default"
  (dream-resp-header dream-hd-sec "strict-transport-security")
  nil)
(dream-hd-test "body preserved" (dream-resp-body dream-hd-sec) "body")

(define
  dream-hd-hsts
  ((dream-security-headers-with (assoc dream-security-defaults :hsts true))
    dream-hd-h))
(dream-hd-test
  "hsts when enabled"
  (contains?
    (dream-resp-header
      (dream-hd-hsts dream-hd-req)
      "strict-transport-security")
    "max-age=31536000")
  true)

;; ── cache-control ──────────────────────────────────────────────────
(dream-hd-test
  "cache public"
  (dream-resp-header
    (dream-cache (dream-text "x") 60)
    "cache-control")
  "public, max-age=60")
(dream-hd-test
  "private cache"
  (dream-resp-header
    (dream-private-cache (dream-text "x") 30)
    "cache-control")
  "private, max-age=30")
(dream-hd-test
  "no-store"
  (dream-resp-header (dream-no-store (dream-text "x")) "cache-control")
  "no-store")
(dream-hd-test
  "no-cache"
  (dream-resp-header (dream-no-cache (dream-text "x")) "cache-control")
  "no-cache, no-store, must-revalidate")

;; ── cache middleware ───────────────────────────────────────────────
(define dream-hd-capp ((dream-cache-for 300) dream-hd-h))
(dream-hd-test
  "cache-for stamps"
  (dream-resp-header (dream-hd-capp dream-hd-req) "cache-control")
  "public, max-age=300")

;; ── composes around a router ───────────────────────────────────────
(define
  dream-hd-app
  (dream-security-headers
    (dream-router
      (list (dream-get "/" (fn (req) (dream-html "<p>hi</p>")))))))
(dream-hd-test
  "router security header"
  (dream-resp-header (dream-hd-app dream-hd-req) "x-frame-options")
  "DENY")

(define dream-hd-tests-run! (fn () {:total (+ dream-hd-pass dream-hd-fail) :passed dream-hd-pass :failed dream-hd-fail :fails dream-hd-fails}))
