;; lib/dream/tests/cors.sx — CORS decoration + preflight.

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

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

(define dream-co-h (fn (req) (dream-text "payload")))
(define dream-co-app (dream-cors dream-co-h))

;; ── decoration of normal responses ─────────────────────────────────
(define dream-co-get (dream-co-app (dream-request "GET" "/" {} "")))
(dream-co-test
  "allow-origin star"
  (dream-resp-header dream-co-get "access-control-allow-origin")
  "*")
(dream-co-test "body preserved" (dream-resp-body dream-co-get) "payload")
(dream-co-test "status preserved" (dream-status dream-co-get) 200)
(dream-co-test
  "no credentials by default"
  (dream-resp-header dream-co-get "access-control-allow-credentials")
  nil)

;; ── preflight OPTIONS ──────────────────────────────────────────────
(define
  dream-co-pre
  (dream-co-app (dream-request "OPTIONS" "/" {} "")))
(dream-co-test "preflight 204" (dream-status dream-co-pre) 204)
(dream-co-test
  "preflight origin"
  (dream-resp-header dream-co-pre "access-control-allow-origin")
  "*")
(dream-co-test
  "preflight methods"
  (contains?
    (dream-resp-header dream-co-pre "access-control-allow-methods")
    "POST")
  true)
(dream-co-test
  "preflight headers"
  (dream-resp-header dream-co-pre "access-control-allow-headers")
  "Content-Type")
(dream-co-test
  "preflight max-age"
  (dream-resp-header dream-co-pre "access-control-max-age")
  "86400")

;; ── custom origin ──────────────────────────────────────────────────
(define
  dream-co-custom
  ((dream-cors-origin "https://app.example.com") dream-co-h))
(dream-co-test
  "custom origin"
  (dream-resp-header
    (dream-co-custom (dream-request "GET" "/" {} ""))
    "access-control-allow-origin")
  "https://app.example.com")

;; ── credentials enabled ────────────────────────────────────────────
(define
  dream-co-cred
  ((dream-cors-with (assoc dream-cors-defaults :credentials true))
    dream-co-h))
(dream-co-test
  "credentials header"
  (dream-resp-header
    (dream-co-cred (dream-request "GET" "/" {} ""))
    "access-control-allow-credentials")
  "true")

;; ── composes around a router ───────────────────────────────────────
(define
  dream-co-router
  (dream-cors
    (dream-router (list (dream-get "/api" (fn (req) (dream-json "{}")))))))
(dream-co-test
  "router cors origin"
  (dream-resp-header
    (dream-co-router (dream-request "GET" "/api" {} ""))
    "access-control-allow-origin")
  "*")

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