[
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Tests\non: [push, pull_request]\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Prepare java\n        uses: actions/setup-java@v4\n        with:\n          distribution: 'zulu'\n          java-version: '11'\n\n      - name: Install clojure tools\n        uses: DeLaGuardo/setup-clojure@13.4\n        with:\n          lein: 2.11.2\n\n      - name: Cache clojure dependencies\n        uses: actions/cache@v4\n        with:\n          path: ~/.m2/repository\n          key: cljdeps-${{ hashFiles('project.clj') }}\n          restore-keys: cljdeps-\n\n      - name: Run tests\n        run: lein test-all\n"
  },
  {
    "path": ".gitignore",
    "content": "/target\n/lib\n/classes\n/checkouts\n/codox\npom.xml\npom.xml.asc\n*.jar\n*.class\n.lein-deps-sum\n.lein-failures\n.lein-plugins\n.lein-env\n.lein-repl-history\n/.cpcache\n/.clj-kondo\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing Guidelines\n\n**Do** follow [the seven rules of a great Git commit message][1].\n\n**Do** follow [the Clojure Style Guide][2].\n\n**Do** include tests for your change when appropriate.\n\n**Do** ensure that the CI checks pass.\n\n**Do** squash the commits in your PR to remove corrections\nirrelevant to the code history, once the PR has been reviewed.\n\n**Do** feel free to pester the project maintainers about the PR if it\nhasn't been responded to. Sometimes notifications can be missed.\n\n**Don't** include more than one feature or fix in a single PR.\n\n**Don't** include changes unrelated to the purpose of the PR. This\nincludes changing the project version number, adding lines to the\n`.gitignore` file, or changing the indentation or formatting.\n\n**Don't** open a new PR if changes are requested. Just push to the\nsame branch and the PR will be updated.\n\n**Don't** overuse vertical whitespace; avoid multiple sequential blank\nlines.\n\n**Don't** docstring private vars or functions.\n\n[1]: https://chris.beams.io/posts/git-commit/#seven-rules\n[2]: https://github.com/bbatsov/clojure-style-guide\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2009-2010 Mark McGranaghan\nCopyright (c) 2009-2018 James Reeves\n \nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n \nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n \nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Ring-Mock [![Build Status](https://github.com/ring-clojure/ring-mock/actions/workflows/test.yml/badge.svg)](https://github.com/ring-clojure/ring-mock/actions/workflows/test.yml)\n\nRing-Mock is a library for creating [Ring][] request maps for testing\npurposes.\n\n[ring]: https://github.com/ring-clojure/ring\n\n## Installation\n\nAdd the following dependency to your deps.edn file:\n\n    ring/ring-mock {:mvn/version \"0.6.2\"}\n\nOr to your Leiningen project file:\n\n    [ring/ring-mock \"0.6.2\"]\n\n## Documentation\n\n* [API Documentation](https://ring-clojure.github.io/ring-mock/ring.mock.request.html)\n\n## Example\n\n```clojure\n(ns your-app.core-test\n  (:require [clojure.test :refer :all]\n            [your-app.core :refer :all]\n            [ring.mock.request :as mock]))\n\n(deftest your-handler-test\n  (is (= (your-handler (mock/request :get \"/doc/10\"))\n         {:status  200\n          :headers {\"content-type\" \"text/plain\"}\n          :body    \"Your expected result\"})))\n\n(deftest your-json-handler-test\n  (is (= (your-handler (-> (mock/request :post \"/api/endpoint\")\n                           (mock/json-body {:foo \"bar\"})))\n         {:status  201\n          :headers {\"content-type\" \"application/json\"}\n          :body    {:key \"your expected result\"}})))\n```\n\n## License\n\nCopyright © 2025 James Reeves\n\nDistributed under the MIT License.\n"
  },
  {
    "path": "project.clj",
    "content": "(defproject ring/ring-mock \"0.6.2\"\n  :description \"A library for creating mock Ring request maps\"\n  :url \"https://github.com/ring-clojure/ring-mock\"\n  :license {:name \"The MIT License\"\n            :url \"http://opensource.org/licenses/MIT\"}\n  :dependencies [[org.clojure/clojure \"1.9.0\"]\n                 [cheshire \"6.0.0\"]\n                 [org.apache.httpcomponents.client5/httpclient5 \"5.5\"]\n                 [ring/ring-codec \"1.3.0\"]\n                 [ring/ring-core \"1.14.2\"]]\n  :plugins [[lein-codox \"0.10.8\"]]\n  :codox\n  {:project     {:name \"Ring-Mock\"}\n   :output-path \"codox\"\n   :source-uri  \"https://github.com/ring-clojure/ring-mock/blob/{version}/{filepath}#L{line}\"}\n  :aliases {\"test-all\" [\"with-profile\" \"default:+1.10:+1.11:+1.12\" \"test\"]}\n  :profiles\n  {:1.10 {:dependencies [[org.clojure/clojure \"1.10.0\"]\n                         [ring/ring-spec \"0.0.4\"]]}\n   :1.11 {:dependencies [[org.clojure/clojure \"1.11.0\"]\n                         [ring/ring-spec \"0.0.4\"]]}\n   :1.12 {:dependencies [[org.clojure/clojure \"1.12.0\"]\n                         [ring/ring-spec \"0.0.4\"]]}})\n"
  },
  {
    "path": "src/ring/mock/request.clj",
    "content": "(ns ring.mock.request\n  \"Functions to create mock request maps.\"\n  (:require [cheshire.core :as json]\n            [clojure.string :as string]\n            [ring.util.codec :as codec]\n            [ring.util.mime-type :as mime])\n  (:import [java.io ByteArrayInputStream ByteArrayOutputStream File InputStream]\n           [java.net URI]\n           [java.nio.charset Charset]\n           [java.util Map]\n           [org.apache.hc.core5.http ContentType HttpEntity]\n           [org.apache.hc.client5.http.entity.mime MultipartEntityBuilder]))\n\n(defn- encode-params [params]\n  (when params (codec/form-encode params)))\n\n(defn header\n  \"Add a HTTP header to the request map.\"\n  [request header value]\n  (let [header (string/lower-case (name header))]\n    (assoc-in request [:headers header] (str value))))\n\n(defn cookie\n  \"Add a cookie to the request headers map\"\n  [request cookie-name value]\n  (let [cookie-name (name cookie-name)\n        cookie-string (str cookie-name \"=\" value)]\n    (update-in request [:headers \"cookie\"]\n               (fn [cookie-header]\n                 (if cookie-header\n                   (str cookie-header \"; \" cookie-string)\n                   cookie-string)))))\n\n(defn content-type\n  \"Set the content type of the request map.\"\n  [request mime-type]\n  (-> request\n      (assoc :content-type mime-type)\n      (header :content-type mime-type)))\n\n(defn content-length\n  \"Set the content length of the request map.\"\n  [request length]\n  (-> request\n      (assoc :content-length length)\n      (header :content-length length)))\n\n(defn- combined-query [request params]\n  (let [query (:query-string request)]\n    (when (or query params)\n      (string/join \"&\"\n        (remove string/blank?\n                [query (encode-params params)])))))\n\n(defn- merge-query [request params]\n  (if-let [qs (combined-query request params)]\n    (assoc request :query-string qs)\n    request))\n\n(defn query-string\n  \"Set the query string of the request to a string or a map of parameters.\"\n  [request params]\n  (cond\n    (nil? params) request\n    (map? params) (assoc request :query-string (encode-params params))\n    :else (assoc request :query-string params)))\n\n(defmulti body\n  \"Set the body of the request. The supplied body value can be a string or\n  a map of parameters to be url-encoded.\"\n  {:arglists '([request body-value])}\n  (fn [_request x] (type x)))\n\n(defmethod body String [request ^String string]\n  (body request (.getBytes string)))\n\n(defmethod body (class (byte-array 0)) [request bytes]\n  (-> request\n      (content-length (count bytes))\n      (assoc :body (ByteArrayInputStream. bytes))))\n\n(defmethod body Map [request params]\n  (-> request\n      (content-type \"application/x-www-form-urlencoded\")\n      (body (encode-params params))))\n\n(defmethod body nil [request _params]\n  request)\n\n(defn json-body\n  \"Set the body of the request to a JSON structure. The supplied body value\n  should be a map of parameters to be converted to JSON.\"\n  [request body-value]\n  (-> request\n      (content-type \"application/json\")\n      (body (json/generate-string body-value))))\n\n(def ^:private default-charset\n  (Charset/forName \"UTF-8\"))\n\n(defn- file? [f]\n  (instance? File f))\n\n(defn- str->bytes ^bytes [^String s]\n  (.getBytes s ^Charset default-charset))\n\n(defn- add-binary-body\n  [^MultipartEntityBuilder builder key value ^ContentType mimetype\n   ^String filename]\n  (let [k (name key)]\n    (cond\n      (string? value)\n      (.addBinaryBody builder k (str->bytes value) mimetype filename)\n      (bytes? value)\n      (.addBinaryBody builder k ^bytes value mimetype filename)\n      (file? value)\n      (.addBinaryBody builder k ^File value mimetype filename)\n      (instance? InputStream value)\n      (.addBinaryBody builder k ^InputStream value mimetype filename)\n      :else\n      (throw (IllegalArgumentException.\n               (str \"Cannot encode a value of type \" (type value)\n                    \" as a multipart body.\"))))))\n\n(defn- add-multipart-part [^MultipartEntityBuilder builder k v]\n  (let [param    (if (map? v) v {:value v})\n        value    (if (map? v) (:value v) v)\n        mimetype (ContentType/parse\n                  (or (:content-type param)\n                      (when (file? value)\n                        (mime/ext-mime-type (.getName ^File value)))\n                      (if (string? (:value param))\n                        \"text/plain; charset=UTF-8\"\n                        \"application/octet-stream\")))\n        filename (or (:filename param)\n                     (when (file? value) (.getName ^File value)))]\n    (add-binary-body builder (name k) value mimetype filename)))\n\n(defn- multipart-entity ^HttpEntity [params]\n  (let [builder (MultipartEntityBuilder/create)]\n    (.setCharset builder ^Charset default-charset)\n    (doseq [[k v] params]\n      (add-multipart-part builder k v))\n    (.build builder)))\n\n(defn multipart-body\n  \"Set the body of the request to a map of parameters encoded as a multipart\n  form. The parameters are supplied as a map. The keys should be keywords or\n  strings. The values should be maps that contain the following keys:\n\n    :value        - a string, byte array, File or InputStream\n    :filename     - the name of the file the value came from (optional)\n    :content-type - the content type of the value (optional)\n\n  The value may also be a string, byte array, File or InputStream instead of a\n  map. In that case, it will be treated as if it were a map with a single :value\n  key.\"\n  [request params]\n  (let [entity (multipart-entity params)\n        out    (ByteArrayOutputStream.)]\n    (.writeTo entity out)\n    (.close out)\n    (-> request\n        (content-length (.getContentLength entity))\n        (content-type (.getContentType entity))\n        (assoc :body (ByteArrayInputStream. (.toByteArray out))))))\n\n(def default-port\n  \"A map of the default ports for a scheme.\"\n  {:http 80\n   :https 443})\n\n(defn request\n  \"Create a minimal valid request map from a HTTP method keyword, a string\n  containing a URI, and an optional map of parameters that will be added to\n  the query string of the URI. The URI can be relative or absolute. Relative\n  URIs are assumed to go to http://localhost.\"\n  ([method uri]\n     (request method uri nil))\n  ([method uri params]\n     (let [uri    (URI. uri)\n           scheme (keyword (or (.getScheme uri) \"http\"))\n           host   (or (.getHost uri) \"localhost\")\n           port   (when (not= (.getPort uri) -1) (.getPort uri))\n           path   (.getRawPath uri)\n           query  (.getRawQuery uri)\n           request {:protocol       \"HTTP/1.1\"\n                    :server-port    (or port (default-port scheme))\n                    :server-name    host\n                    :remote-addr    \"127.0.0.1\"\n                    :uri            (if (string/blank? path) \"/\" path)\n                    :scheme         scheme\n                    :request-method method\n                    :headers        {\"host\" (if port\n                                              (str host \":\" port)\n                                              host)}}\n           request (if query\n                     (assoc request :query-string query)\n                     request)]\n       (if (#{:get :head :delete} method)\n         (merge-query request params)\n         (body request params)))))\n"
  },
  {
    "path": "test/ring/mock/request_test.clj",
    "content": "(ns ring.mock.request-test\n  (:require [clojure.java.io :as io]\n            [clojure.spec.alpha :as s]\n            [clojure.test :refer [deftest is testing]]\n            [ring.mock.request :refer [body content-length content-type cookie\n                                       header json-body multipart-body\n                                       query-string request]])\n  (:import [java.io InputStream]))\n\n(deftest test-request\n  (testing \"relative uri\"\n    (is (= (request :get \"/foo\")\n           {:protocol \"HTTP/1.1\"\n            :server-port 80\n            :server-name \"localhost\"\n            :remote-addr \"127.0.0.1\"\n            :uri \"/foo\"\n            :scheme :http\n            :request-method :get\n            :headers {\"host\" \"localhost\"}})))\n  (testing \"absolute uri\"\n    (let [request (request :post \"https://example.com:8443/foo?bar=baz\" {\"quux\" \"zot\"})\n          literal-request (dissoc request :body)\n          body (:body request)]\n      (is (= literal-request\n             {:protocol \"HTTP/1.1\"\n              :server-port 8443\n              :server-name \"example.com\"\n              :remote-addr \"127.0.0.1\"\n              :uri \"/foo\"\n              :query-string \"bar=baz\"\n              :scheme :https\n              :request-method :post\n              :content-type \"application/x-www-form-urlencoded\"\n              :content-length 8\n              :headers {\"host\" \"example.com:8443\"\n                        \"content-type\" \"application/x-www-form-urlencoded\"\n                        \"content-length\" \"8\"}}))\n      (is (= (slurp body) \"quux=zot\"))))\n  (testing \"absolute http uri with implicit port\"\n    (let [{:keys [headers server-port]} (request :get \"http://example.test\")]\n      (is (= server-port 80))\n      (is (= (get headers \"host\") \"example.test\"))))\n  (testing \"absolute https uri with implicit port\"\n    (let [{:keys [headers server-port]} (request :get \"https://example.test\")]\n      (is (= server-port 443))\n      (is (= (get headers \"host\") \"example.test\"))))\n  (testing \"nil path\"\n    (is (= (:uri (request :get \"http://example.com\")) \"/\")))\n  (testing \"only params in :get\"\n    (is (= (:query-string (request :get \"/?a=b\"))\n           \"a=b\")))\n  (testing \"added params in :get\"\n    (is (= (:query-string (request :get \"/\" (array-map :x \"y\" :z \"n\")))\n           \"x=y&z=n\"))\n    (is (= (:query-string (request :get \"/?a=b\" {:x \"y\"}))\n           \"a=b&x=y\"))\n    (is (= (:query-string (request :get \"/?\" {:x \"y\"}))\n           \"x=y\"))\n    (is (= (:query-string (request :get \"/\" {:x \"a b\"}))\n           \"x=a+b\")))\n  (testing \"added params in :delete\"\n    (is (= (:query-string (request :delete \"/\" (array-map :x \"y\" :z \"n\")))\n           \"x=y&z=n\")))\n  (testing \"added params in :post\"\n    (let [req (request :post \"/\" (array-map :x \"y\" :z \"n\"))]\n      (is (= (slurp (:body req))\n             \"x=y&z=n\"))\n      (is (not (contains? req :query-string))))\n    (let [req (request :post \"/?a=b\" {:x \"y\"})]\n      (is (= (slurp (:body req))\n             \"x=y\"))\n      (is (= (:query-string req)\n             \"a=b\")))\n    (let [req (request :post \"/?\" {:x \"y\"})]\n      (is (= (slurp (:body req))\n             \"x=y\"))\n      (is (= (:query-string req)\n             \"\")))\n    (let [req (request :post \"/\" {:x \"a b\"})]\n      (is (= (slurp (:body req))\n             \"x=a+b\"))\n      (is (nil? (:query-string req))))\n    (let [req (request :post \"/?a=b\")]\n      (is (nil? (:body req)))\n      (is (= (:query-string req)\n             \"a=b\"))))\n  (testing \"added params in :put\"\n    (let [req (request :put \"/\" (array-map :x \"y\" :z \"n\"))]\n      (is (= (slurp (:body req)) \"x=y&z=n\")))))\n\n(deftest test-header\n  (is (= (header {} \"X-Foo\" \"Bar\")\n         {:headers {\"x-foo\" \"Bar\"}}))\n  (is (= (header {} :x-foo \"Bar\")\n         {:headers {\"x-foo\" \"Bar\"}})))\n\n(deftest test-cookie\n  (is (= (cookie {} \"Foo\" \"Bar\")\n         {:headers {\"cookie\" \"Foo=Bar\"}}))\n  (is (= (cookie {:headers {\"cookie\" \"a=b\"}} \"c\" \"d\")\n         {:headers {\"cookie\" \"a=b; c=d\"}}))\n  (is (= (cookie {} :foo \"bar\")\n         {:headers {\"cookie\" \"foo=bar\"}})))\n\n(deftest test-content-type\n  (is (= (content-type {} \"text/html\")\n         {:content-type \"text/html\"\n          :headers {\"content-type\" \"text/html\"}})))\n\n(deftest test-content-length\n  (is (= (content-length {} 10)\n         {:content-length 10\n          :headers {\"content-length\" \"10\"}})))\n\n(deftest test-query-string\n  (testing \"nil\"\n    (is (= (query-string {} nil)\n           {})))\n  (testing \"string\"\n    (is (= (query-string {} \"a=b\")\n           {:query-string \"a=b\"})))\n  (testing \"map of params\"\n    (is (= (query-string {} {:a \"b\"})\n           {:query-string \"a=b\"})))\n  (testing \"overwriting\"\n    (is (= (-> {}\n               (query-string {:a \"b\"})\n               (query-string {:c \"d\"}))\n           {:query-string \"c=d\"}))))\n\n(deftest test-body\n  (testing \"string body\"\n    (let [resp (body {} \"Hello World\")]\n      (is (instance? InputStream (:body resp)))\n      (is (= (slurp (:body resp)) \"Hello World\"))\n      (is (= (:content-length resp) 11))))\n  (testing \"map body\"\n    (let [resp (body {} (array-map :foo \"bar\" :fi [\"fi\" \"fo\" \"fum\"]))]\n      (is (instance? InputStream (:body resp)))\n      (is (= (slurp (:body resp)) \"foo=bar&fi=fi&fi=fo&fi=fum\"))\n      (is (= (:content-length resp) 26))\n      (is (= (:content-type resp)\n             \"application/x-www-form-urlencoded\"))))\n  (testing \"bytes body\"\n    (let [resp (body {} (.getBytes \"foo\"))]\n      (is (instance? InputStream (:body resp)))\n      (is (= (slurp (:body resp)) \"foo\"))\n      (is (= (:content-length resp) 3)))))\n\n(deftest test-json-body\n  (testing \"json body\"\n    (let [resp (json-body {} {:baz [\"qu\" \"qi\" \"qo\"]})]\n      (is (= (:content-type resp) \"application/json\"))\n      (is (instance? InputStream (:body resp)))\n      (is (= (slurp (:body resp))\n             \"{\\\"baz\\\":[\\\"qu\\\",\\\"qi\\\",\\\"qo\\\"]}\"))\n      (is (= (:content-length resp) 24)))))\n\n(defn- get-boundary [{:keys [content-type]}]\n  (re-find #\"(?<=boundary=)[^;]*\" content-type))\n\n(deftest test-multipart-body\n  (testing \"string values\"\n    (let [response (multipart-body {} {:foo \"a\"\n                                       :bar {:value \"b\"}\n                                       :baz {:value \"<html></html>\"\n                                             :content-type \"text/html\"}})\n          boundary (get-boundary response)]\n      (is (= (:content-length response)\n             (+ 284 (* 4 (count boundary)))))\n      (is (= (:content-type response)\n             (str \"multipart/form-data; charset=ISO-8859-1; \"\n                  \"boundary=\" boundary)))\n      (is (= (slurp (:body response))\n             (str \"--\" boundary \"\\r\\n\"\n                  \"Content-Disposition: form-data; name=\\\"foo\\\"\\r\\n\"\n                  \"Content-Type: text/plain; charset=UTF-8\\r\\n\\r\\n\"\n                  \"a\\r\\n\"\n                  \"--\" boundary \"\\r\\n\"\n                  \"Content-Disposition: form-data; name=\\\"bar\\\"\\r\\n\"\n                  \"Content-Type: text/plain; charset=UTF-8\\r\\n\\r\\n\"\n                  \"b\\r\\n\"\n                  \"--\" boundary \"\\r\\n\"\n                  \"Content-Disposition: form-data; name=\\\"baz\\\"\\r\\n\"\n                  \"Content-Type: text/html\\r\\n\\r\\n\"\n                  \"<html></html>\\r\\n\"\n                  \"--\" boundary \"--\\r\\n\")))))\n  (testing \"byte array values\"\n    (let [response (multipart-body {} {:foo (.getBytes \"a\" \"UTF-8\")\n                                       :bar {:value (.getBytes \"b\" \"UTF-8\")\n                                             :content-type \"image/png\"\n                                             :filename \"bee.png\"}})\n          boundary (get-boundary response)]\n      (is (= (:content-length response)\n             (+ 197 (* 3 (count boundary)))))\n      (is (= (:content-type response)\n             (str \"multipart/form-data; charset=ISO-8859-1; \"\n                  \"boundary=\" boundary)))\n      (is (= (slurp (:body response))\n             (str \"--\" boundary \"\\r\\n\"\n                  \"Content-Disposition: form-data; name=\\\"foo\\\"\\r\\n\"\n                  \"Content-Type: application/octet-stream\\r\\n\\r\\n\"\n                  \"a\\r\\n\"\n                  \"--\" boundary \"\\r\\n\"\n                  \"Content-Disposition: form-data; name=\\\"bar\\\"; \"\n                  \"filename=\\\"bee.png\\\"\\r\\n\"\n                  \"Content-Type: image/png\\r\\n\\r\\n\"\n                  \"b\\r\\n\"\n                  \"--\" boundary \"--\\r\\n\")))))\n  (testing \"file values\"\n    (let [test-file (io/file (io/resource \"ring/mock/test.txt\"))\n          response  (multipart-body {} {:foo test-file\n                                        :bar {:value test-file\n                                              :content-type \"text/html\"\n                                              :filename \"test.html\"}})\n          boundary  (get-boundary response)]\n      (is (= (:content-length response)\n             (+ 208 (* 3 (count boundary)))))\n      (is (= (:content-type response)\n             (str \"multipart/form-data; charset=ISO-8859-1; \"\n                  \"boundary=\" boundary)))\n      (is (= (slurp (:body response))\n             (str \"--\" boundary \"\\r\\n\"\n                  \"Content-Disposition: form-data; name=\\\"foo\\\"; \"\n                  \"filename=\\\"test.txt\\\"\\r\\n\"\n                  \"Content-Type: text/plain\\r\\n\\r\\n\"\n                  \"a\\n\\r\\n\"\n                  \"--\" boundary \"\\r\\n\"\n                  \"Content-Disposition: form-data; name=\\\"bar\\\"; \"\n                  \"filename=\\\"test.html\\\"\\r\\n\"\n                  \"Content-Type: text/html\\r\\n\\r\\n\"\n                  \"a\\n\\r\\n\"\n                  \"--\" boundary \"--\\r\\n\")))))\n  (testing \"not supported type\"\n    (try\n      (multipart-body {} {:foo :keyword\n                          :bar {:value        :keyword\n                                :content-type \"text/html\"\n                                :filename     \"test.html\"}})\n      (catch Exception e\n        (let [expected-message \"Cannot encode a value of type class clojure.lang.Keyword as a multipart body.\"]\n          (is (= expected-message (.getMessage ^Exception e))))))))\n\n(defmacro when-clojure-spec\n  [& body]\n  (when (try\n          (require '[clojure.spec :as s])\n          true\n          (catch Exception _\n            (binding [*out* *err*]\n              (println \"ring-mock: Skipping ring-spec tests.\"))\n            false))\n    `(do\n       (require 'ring.core.spec)\n       ~@body)))\n\n(deftest test-specs\n  (when-clojure-spec\n   (doseq [req [(-> (request :get \"/foo/bar\") (query-string nil))\n                (request :put \"/foo/bar\")\n                (request :something \"/foo\" {:params true})]]\n     (is (s/valid? :ring/request req)\n         (s/explain-str :ring/request req)))))\n"
  },
  {
    "path": "test/ring/mock/test.txt",
    "content": "a\n"
  }
]