mirror of
https://github.com/metosin/reitit.git
synced 2025-12-17 08:21:11 +00:00
test: rework openapi3 tests
- DRY out all-parameter-types-test and per-content-type-test - Remove redundant assertions - Run same test for malli/schema/spec - Clean up commented-out code etc.
This commit is contained in:
parent
c8d679c6b3
commit
b149c8c5af
2 changed files with 131 additions and 241 deletions
|
|
@ -105,6 +105,7 @@
|
||||||
[org.clojure/test.check "1.1.1"]
|
[org.clojure/test.check "1.1.1"]
|
||||||
[org.clojure/tools.namespace "1.3.0"]
|
[org.clojure/tools.namespace "1.3.0"]
|
||||||
[com.gfredericks/test.chuck "0.2.13"]
|
[com.gfredericks/test.chuck "0.2.13"]
|
||||||
|
[nubank/matcher-combinators "3.8.3"]
|
||||||
|
|
||||||
[io.pedestal/pedestal.service "0.5.10"]
|
[io.pedestal/pedestal.service "0.5.10"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
(ns reitit.openapi-test
|
(ns reitit.openapi-test
|
||||||
(:require [clojure.test :refer [deftest is testing]]
|
(:require [clojure.test :refer [deftest is testing]]
|
||||||
|
[jsonista.core :as j]
|
||||||
|
[matcher-combinators.test :refer [match?]]
|
||||||
[muuntaja.core :as m]
|
[muuntaja.core :as m]
|
||||||
[reitit.coercion.malli :as malli]
|
[reitit.coercion.malli :as malli]
|
||||||
[reitit.coercion.schema :as schema]
|
[reitit.coercion.schema :as schema]
|
||||||
|
|
@ -96,7 +98,6 @@
|
||||||
rrc/coerce-request-middleware
|
rrc/coerce-request-middleware
|
||||||
rrc/coerce-response-middleware]}})))
|
rrc/coerce-response-middleware]}})))
|
||||||
|
|
||||||
(require '[fipp.edn])
|
|
||||||
(deftest openapi-test
|
(deftest openapi-test
|
||||||
(testing "endpoints work"
|
(testing "endpoints work"
|
||||||
(testing "malli"
|
(testing "malli"
|
||||||
|
|
@ -311,245 +312,133 @@
|
||||||
(-> {:request-method :get :uri "/openapi.json"}
|
(-> {:request-method :get :uri "/openapi.json"}
|
||||||
(app) :body :x-id)))))
|
(app) :body :x-id)))))
|
||||||
|
|
||||||
(deftest malli-all-parameter-types-test
|
(defn- normalize
|
||||||
(let [app (ring/ring-handler
|
"Normalize format of openapi spec by converting it to json and back.
|
||||||
(ring/router
|
Handles differences like :q vs \"q\" in openapi generation."
|
||||||
[["/parameters"
|
[data]
|
||||||
{:post {:coercion malli/coercion
|
(-> data
|
||||||
:parameters {:query [:map
|
j/write-value-as-string
|
||||||
[:q :string]]
|
(j/read-value j/keyword-keys-object-mapper)))
|
||||||
:body [:map
|
|
||||||
[:b :string]]
|
|
||||||
:header [:map
|
|
||||||
[:h :string]]
|
|
||||||
:cookie [:map
|
|
||||||
[:c :string]]
|
|
||||||
:path [:map
|
|
||||||
[:p :string]]}
|
|
||||||
:responses {200 {:body [:map [:ok :string]]}}
|
|
||||||
:handler identity}}]
|
|
||||||
["/openapi.json"
|
|
||||||
{:get {:handler (openapi/create-openapi-handler)
|
|
||||||
:no-doc true}}]]))
|
|
||||||
spec (-> {:request-method :get
|
|
||||||
:uri "/openapi.json"}
|
|
||||||
app
|
|
||||||
:body)]
|
|
||||||
(testing
|
|
||||||
"all non-body parameters"
|
|
||||||
(is (= [{:in "query"
|
|
||||||
:name :q
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}
|
|
||||||
{:in "header"
|
|
||||||
:name :h
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}
|
|
||||||
{:in "cookie"
|
|
||||||
:name :c
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}
|
|
||||||
{:in "path"
|
|
||||||
:name :p
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}]
|
|
||||||
(-> spec
|
|
||||||
(get-in [:paths "/parameters" :post :parameters])
|
|
||||||
#_(doto clojure.pprint/pprint)))))
|
|
||||||
(testing
|
|
||||||
"body parameter"
|
|
||||||
(is (= {"application/json" {:schema {:type "object"
|
|
||||||
:properties {:b {:type "string"}}
|
|
||||||
:additionalProperties false
|
|
||||||
:required [:b]}}}
|
|
||||||
(-> spec
|
|
||||||
(get-in [:paths "/parameters" :post :requestBody :content])
|
|
||||||
#_(doto clojure.pprint/pprint)))))
|
|
||||||
(testing
|
|
||||||
"body response"
|
|
||||||
(is (= {"application/json" {:schema {:type "object"
|
|
||||||
:properties {:ok {:type "string"}}
|
|
||||||
:additionalProperties false
|
|
||||||
:required [:ok]}}}
|
|
||||||
(-> spec
|
|
||||||
(get-in [:paths "/parameters" :post :responses 200 :content])
|
|
||||||
#_(doto clojure.pprint/pprint)))))))
|
|
||||||
|
|
||||||
(deftest malli-all-parameter-types-test-per-content-type
|
|
||||||
(let [app (ring/ring-handler
|
|
||||||
(ring/router
|
|
||||||
[["/parameters"
|
|
||||||
{:post {:coercion malli/coercion
|
|
||||||
:parameters {:query [:map
|
|
||||||
[:q :string]]
|
|
||||||
:request {:content {"application/json" [:map
|
|
||||||
[:b :string]]}}
|
|
||||||
:header [:map
|
|
||||||
[:h :string]]
|
|
||||||
:cookie [:map
|
|
||||||
[:c :string]]
|
|
||||||
:path [:map
|
|
||||||
[:p :string]]}
|
|
||||||
:responses {200 {:content {"application/json" [:map [:ok :string]]}}}
|
|
||||||
:handler identity}}]
|
|
||||||
["/openapi.json"
|
|
||||||
{:get {:handler (openapi/create-openapi-handler)
|
|
||||||
:no-doc true}}]]))
|
|
||||||
spec (-> {:request-method :get
|
|
||||||
:uri "/openapi.json"}
|
|
||||||
app
|
|
||||||
:body)]
|
|
||||||
(testing
|
|
||||||
"all non-body parameters"
|
|
||||||
(is (= [{:in "query"
|
|
||||||
:name :q
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}
|
|
||||||
{:in "header"
|
|
||||||
:name :h
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}
|
|
||||||
{:in "cookie"
|
|
||||||
:name :c
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}
|
|
||||||
{:in "path"
|
|
||||||
:name :p
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}]
|
|
||||||
(-> spec
|
|
||||||
(get-in [:paths "/parameters" :post :parameters])
|
|
||||||
#_(doto clojure.pprint/pprint)))))
|
|
||||||
(testing
|
|
||||||
"body parameter"
|
|
||||||
(is (= {"application/json" {:schema {:type "object"
|
|
||||||
:properties {:b {:type "string"}}
|
|
||||||
:additionalProperties false
|
|
||||||
:required [:b]}}}
|
|
||||||
(-> spec
|
|
||||||
(get-in [:paths "/parameters" :post :requestBody :content])
|
|
||||||
#_(doto clojure.pprint/pprint)))))
|
|
||||||
(testing
|
|
||||||
"body response"
|
|
||||||
(is (= {"application/json" {:schema {:type "object"
|
|
||||||
:properties {:ok {:type "string"}}
|
|
||||||
:additionalProperties false
|
|
||||||
:required [:ok]}}}
|
|
||||||
(-> spec
|
|
||||||
(get-in [:paths "/parameters" :post :responses 200 :content])
|
|
||||||
#_(doto clojure.pprint/pprint)))))))
|
|
||||||
|
|
||||||
|
|
||||||
(deftest schema-all-parameter-types-test-per-content-type
|
|
||||||
(let [app (ring/ring-handler
|
|
||||||
(ring/router
|
|
||||||
[["/parameters"
|
|
||||||
{:post {:coercion schema/coercion
|
|
||||||
:parameters {:query {:q s/Str}
|
|
||||||
:request {:content {"application/json" {:b s/Str}}}
|
|
||||||
:header {:h s/Str}
|
|
||||||
:cookie {:c s/Str}
|
|
||||||
:path {:p s/Str}}
|
|
||||||
:responses {200 {:content {"application/json" {:ok s/Str}}}}
|
|
||||||
:handler identity}}]
|
|
||||||
["/openapi.json"
|
|
||||||
{:get {:handler (openapi/create-openapi-handler)
|
|
||||||
:no-doc true}}]]))
|
|
||||||
spec (-> {:request-method :get
|
|
||||||
:uri "/openapi.json"}
|
|
||||||
app
|
|
||||||
:body)]
|
|
||||||
(testing
|
|
||||||
"all non-body parameters"
|
|
||||||
(is (= [{:description ""
|
|
||||||
:in "query"
|
|
||||||
:name "q"
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}
|
|
||||||
{:description ""
|
|
||||||
:in "header"
|
|
||||||
:name "h"
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}
|
|
||||||
{:description ""
|
|
||||||
:in "cookie"
|
|
||||||
:name "c"
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}
|
|
||||||
{:description ""
|
|
||||||
:in "path"
|
|
||||||
:name "p"
|
|
||||||
:required true
|
|
||||||
:schema {:type "string"}}]
|
|
||||||
(-> spec
|
|
||||||
(get-in [:paths "/parameters" :post :parameters])
|
|
||||||
#_(doto clojure.pprint/pprint)))))
|
|
||||||
(testing
|
|
||||||
"body parameter"
|
|
||||||
(is (= {"application/json" {:schema {:additionalProperties false
|
|
||||||
:properties {"b" {:type "string"}}
|
|
||||||
:required ["b"]
|
|
||||||
:type "object"}}}
|
|
||||||
(-> spec
|
|
||||||
(get-in [:paths "/parameters" :post :requestBody :content])
|
|
||||||
#_(doto clojure.pprint/pprint)))))
|
|
||||||
(testing
|
|
||||||
"body response"
|
|
||||||
(is (= {"application/json" {:schema {:additionalProperties false
|
|
||||||
:properties {"ok" {:type "string"}}
|
|
||||||
:required ["ok"]
|
|
||||||
:type "object"}}}
|
|
||||||
(-> spec
|
|
||||||
(get-in [:paths "/parameters" :post :responses 200 :content])
|
|
||||||
#_(doto clojure.pprint/pprint)))))))
|
|
||||||
(deftest all-parameter-types-test
|
(deftest all-parameter-types-test
|
||||||
(let [app (ring/ring-handler
|
(doseq [[coercion ->schema]
|
||||||
(ring/router
|
[[#'malli/coercion (fn [nom] [:map [nom :string]])]
|
||||||
[["/parameters"
|
[#'schema/coercion (fn [nom] {nom s/Str})]
|
||||||
{:post {:coercion spec/coercion
|
[#'spec/coercion (fn [nom] {nom string?})]]]
|
||||||
:parameters {:query {:q string?}
|
(testing coercion
|
||||||
:body {:b string?}
|
(let [app (ring/ring-handler
|
||||||
:cookies {:c string?}
|
(ring/router
|
||||||
:header {:h string?}
|
[["/parameters"
|
||||||
:path {:p string?}}
|
{:post {:coercion @coercion
|
||||||
:responses {200 {:body {:ok string?}}}
|
:parameters {:query (->schema :q)
|
||||||
:handler identity}}]
|
:body (->schema :b)
|
||||||
["/openapi.json"
|
:header (->schema :h)
|
||||||
{:get {:no-doc true
|
:cookie (->schema :c)
|
||||||
:handler (openapi/create-openapi-handler)}}]]))
|
:path (->schema :p)}
|
||||||
spec (:body (app {:request-method :get, :uri "/openapi.json"}))]
|
:responses {200 {:body (->schema :ok)}}
|
||||||
(is (= [{:description ""
|
:handler identity}}]
|
||||||
:in "query"
|
["/openapi.json"
|
||||||
:name "q"
|
{:get {:handler (openapi/create-openapi-handler)
|
||||||
:required true
|
:no-doc true}}]]))
|
||||||
:schema {:type "string"}}
|
spec (-> {:request-method :get
|
||||||
{:description ""
|
:uri "/openapi.json"}
|
||||||
:in "cookies"
|
app
|
||||||
:name "c"
|
:body)]
|
||||||
:required true
|
(testing "all non-body parameters"
|
||||||
:schema {:type "string"}}
|
(is (match? [{:in "query"
|
||||||
{:description ""
|
:name "q"
|
||||||
:in "header"
|
:required true
|
||||||
:name "h"
|
:schema {:type "string"}}
|
||||||
:required true
|
{:in "header"
|
||||||
:schema {:type "string"}}
|
:name "h"
|
||||||
{:description ""
|
:required true
|
||||||
:in "path"
|
:schema {:type "string"}}
|
||||||
:name "p"
|
{:in "cookie"
|
||||||
:required true
|
:name "c"
|
||||||
:schema {:type "string"}}]
|
:required true
|
||||||
(-> spec
|
:schema {:type "string"}}
|
||||||
(get-in [:paths "/parameters" :post :parameters])
|
{:in "path"
|
||||||
#_(doto clojure.pprint/pprint))))
|
:name "p"
|
||||||
(is (= {"application/json" {:schema {:properties {"b" {:type "string"}}
|
:required true
|
||||||
:required ["b"]
|
:schema {:type "string"}}]
|
||||||
:type "object"}}}
|
(-> spec
|
||||||
(-> spec
|
(get-in [:paths "/parameters" :post :parameters])
|
||||||
(get-in [:paths "/parameters" :post :requestBody :content])
|
normalize))))
|
||||||
#_(doto clojure.pprint/pprint))))
|
(testing "body parameter"
|
||||||
(is (= {"application/json" {:schema {:properties {"ok" {:type "string"}}
|
(is (match? {:schema {:type "object"
|
||||||
:required ["ok"]
|
:properties {:b {:type "string"}}
|
||||||
:type "object"}}}
|
#_#_:additionalProperties false ;; not present for spec
|
||||||
(-> spec
|
:required ["b"]}}
|
||||||
(get-in [:paths "/parameters" :post :responses 200 :content])
|
(-> spec
|
||||||
#_(doto clojure.pprint/pprint))))))
|
(get-in [:paths "/parameters" :post :requestBody :content "application/json"])
|
||||||
|
normalize))))
|
||||||
|
(testing "body response"
|
||||||
|
(is (match? {:schema {:type "object"
|
||||||
|
:properties {:ok {:type "string"}}
|
||||||
|
#_#_:additionalProperties false ;; not present for spec
|
||||||
|
:required ["ok"]}}
|
||||||
|
(-> spec
|
||||||
|
(get-in [:paths "/parameters" :post :responses 200 :content "application/json"])
|
||||||
|
normalize))))))))
|
||||||
|
|
||||||
|
(deftest per-content-type-test
|
||||||
|
(doseq [[coercion ->schema]
|
||||||
|
[[#'malli/coercion (fn [nom] [:map [nom :string]])]
|
||||||
|
[#'schema/coercion (fn [nom] {nom s/Str})]
|
||||||
|
#_ ;; Doesn't work yet
|
||||||
|
[#'spec/coercion (fn [nom] {nom string?})]]]
|
||||||
|
(testing coercion
|
||||||
|
(let [app (ring/ring-handler
|
||||||
|
(ring/router
|
||||||
|
[["/parameters"
|
||||||
|
{:post {:coercion @coercion
|
||||||
|
:parameters {:request {:content {"application/json" (->schema :b)}}}
|
||||||
|
:responses {200 {:content {"application/json" (->schema :ok)}}}
|
||||||
|
:handler (fn [req]
|
||||||
|
{:status 200
|
||||||
|
:body (-> req :parameters :request)})}}]
|
||||||
|
["/openapi.json"
|
||||||
|
{:get {:handler (openapi/create-openapi-handler)
|
||||||
|
:no-doc true}}]]
|
||||||
|
{:data {:middleware [rrc/coerce-request-middleware
|
||||||
|
rrc/coerce-response-middleware]}}))
|
||||||
|
spec (-> {:request-method :get
|
||||||
|
:uri "/openapi.json"}
|
||||||
|
app
|
||||||
|
:body)]
|
||||||
|
(testing "body parameter"
|
||||||
|
(is (= {:schema {:type "object"
|
||||||
|
:properties {:b {:type "string"}}
|
||||||
|
:additionalProperties false
|
||||||
|
:required ["b"]}}
|
||||||
|
(-> spec
|
||||||
|
(get-in [:paths "/parameters" :post :requestBody :content "application/json"])
|
||||||
|
normalize))))
|
||||||
|
(testing "body response"
|
||||||
|
(is (= {:schema {:type "object"
|
||||||
|
:properties {:ok {:type "string"}}
|
||||||
|
:additionalProperties false
|
||||||
|
:required ["ok"]}}
|
||||||
|
(-> spec
|
||||||
|
(get-in [:paths "/parameters" :post :responses 200 :content "application/json"])
|
||||||
|
normalize))))
|
||||||
|
(testing "validation"
|
||||||
|
(let [valid-query {:request-method :post
|
||||||
|
:uri "/parameters"
|
||||||
|
:muuntaja/request {:format "application/json"}
|
||||||
|
:muuntaja/response {:format "application/json"}
|
||||||
|
:body-params {:b "x"}}]
|
||||||
|
(testing "of output"
|
||||||
|
(is (= {:type :reitit.coercion/response-coercion
|
||||||
|
:in [:response :body]}
|
||||||
|
(try
|
||||||
|
(app (assoc valid-query :body-params {:b "x"}))
|
||||||
|
(catch clojure.lang.ExceptionInfo e
|
||||||
|
(select-keys (ex-data e) [:type :in]))))))
|
||||||
|
(testing "of input"
|
||||||
|
(is (= {:type :reitit.coercion/request-coercion
|
||||||
|
:in [:request :body-params]}
|
||||||
|
(try
|
||||||
|
(app (assoc valid-query :body-params {:z 1}))
|
||||||
|
(catch clojure.lang.ExceptionInfo e
|
||||||
|
(select-keys (ex-data e) [:type :in]))))))))))))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue