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:
Joel Kaasinen 2023-02-16 10:26:54 +02:00
parent c8d679c6b3
commit b149c8c5af
2 changed files with 131 additions and 241 deletions

View file

@ -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"]

View file

@ -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]))))))))))))