[Clojure] Add model generation and conforming (#122)

* [Clojure] Add model generation and verification

- Generate clojure.specs from models
- Optionally validate them at runtime (validation is active if
  orchestra.spec.test/instrument is called after specs are imported)
- Coerce the results of the API calls to get objects that conform
  to the spec (e.g. get Date objects for dates and time instead of strings)

* [Clojure] Make model conforming configurable and opt-out

* [Clojure] Move specs from a single file to a ns per model

So that the order of the forms will be resolved by the compiler,
otherwise we'd have to implement a topological ordering.

* [Clojure] Update petstore sample and set automatic decoding off

* [Clojure] Stop testing Clojure generator on Java7

* [Clojure] Fix tests and handling of multiple arity

* [Clojure] Fix tests and add testing for the new decoding feature

* [Clojure] Capitalize names of generated models

* [Clojure] Rename petstore specs to be capitalized

* Revert to lowercase spec names, and postfix the data specs
This commit is contained in:
Fabrizio Ferrai 2018-08-13 09:04:25 +02:00 committed by William Cheng
parent aed8e38584
commit 74d70121d1
18 changed files with 529 additions and 154 deletions

View File

@ -837,7 +837,6 @@
<module>samples/client/petstore/scala-akka</module> <module>samples/client/petstore/scala-akka</module>
<module>samples/client/petstore/scala-httpclient</module> <module>samples/client/petstore/scala-httpclient</module>
<module>samples/client/petstore/scalaz</module> <module>samples/client/petstore/scalaz</module>
<module>samples/client/petstore/clojure</module>
<module>samples/client/petstore/java/feign</module> <module>samples/client/petstore/java/feign</module>
<module>samples/client/petstore/java/jersey1</module> <module>samples/client/petstore/java/jersey1</module>
<module>samples/client/petstore/java/jersey2</module> <module>samples/client/petstore/java/jersey2</module>

View File

@ -17,23 +17,16 @@
package org.openapitools.codegen.languages; package org.openapitools.codegen.languages;
import org.openapitools.codegen.CliOption; import org.openapitools.codegen.*;
import org.openapitools.codegen.CodegenConfig;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.DefaultCodegen;
import org.openapitools.codegen.SupportingFile;
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.*; import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.oas.models.info.*; import io.swagger.v3.oas.models.info.*;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.utils.ModelUtils;
import java.io.File; import java.io.File;
import java.util.Map; import java.util.*;
import java.util.List;
public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfig { public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final String PROJECT_NAME = "projectName"; private static final String PROJECT_NAME = "projectName";
@ -44,23 +37,29 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
private static final String PROJECT_LICENSE_URL = "projectLicenseUrl"; private static final String PROJECT_LICENSE_URL = "projectLicenseUrl";
private static final String BASE_NAMESPACE = "baseNamespace"; private static final String BASE_NAMESPACE = "baseNamespace";
static final String X_BASE_SPEC = "x-baseSpec";
static final String X_MODELS = "x-models";
protected String projectName; protected String projectName;
protected String projectDescription; protected String projectDescription;
protected String projectVersion; protected String projectVersion;
protected String baseNamespace; protected String baseNamespace;
protected Set<String> baseSpecs;
protected Set<String> models = new HashSet<>();
protected String sourceFolder = "src"; protected String sourceFolder = "src";
public ClojureClientCodegen() { public ClojureClientCodegen() {
super(); super();
outputFolder = "generated-code" + File.separator + "clojure"; outputFolder = "generated-code" + File.separator + "clojure";
modelTemplateFiles.put("spec.mustache", ".clj");
apiTemplateFiles.put("api.mustache", ".clj"); apiTemplateFiles.put("api.mustache", ".clj");
embeddedTemplateDir = templateDir = "clojure"; embeddedTemplateDir = templateDir = "clojure";
cliOptions.add(new CliOption(PROJECT_NAME, cliOptions.add(new CliOption(PROJECT_NAME,
"name of the project (Default: generated from info.title or \"openapi-clj-client\")")); "name of the project (Default: generated from info.title or \"openapi-clj-client\")"));
cliOptions.add(new CliOption(PROJECT_DESCRIPTION, cliOptions.add(new CliOption(PROJECT_DESCRIPTION,
"description of the project (Default: using info.description or \"Client library of <projectNname>\")")); "description of the project (Default: using info.description or \"Client library of <projectName>\")"));
cliOptions.add(new CliOption(PROJECT_VERSION, cliOptions.add(new CliOption(PROJECT_VERSION,
"version of the project (Default: using info.version or \"1.0.0\")")); "version of the project (Default: using info.version or \"1.0.0\")"));
cliOptions.add(new CliOption(PROJECT_URL, cliOptions.add(new CliOption(PROJECT_URL,
@ -71,6 +70,49 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
"URL of the license the project uses (Default: using info.license.url or not included in project.clj)")); "URL of the license the project uses (Default: using info.license.url or not included in project.clj)"));
cliOptions.add(new CliOption(BASE_NAMESPACE, cliOptions.add(new CliOption(BASE_NAMESPACE,
"the base/top namespace (Default: generated from projectName)")); "the base/top namespace (Default: generated from projectName)"));
typeMapping.clear();
// We have specs for most of the types:
typeMapping.put("integer", "int?");
typeMapping.put("long", "int?");
typeMapping.put("short", "int?");
typeMapping.put("number", "float?");
typeMapping.put("float", "float?");
typeMapping.put("double", "float?");
typeMapping.put("array", "list?");
typeMapping.put("map", "map?");
typeMapping.put("boolean", "boolean?");
typeMapping.put("string", "string?");
typeMapping.put("char", "char?");
typeMapping.put("date", "inst?");
typeMapping.put("DateTime", "inst?");
typeMapping.put("UUID", "uuid?");
// But some type mappings are not really worth/meaningful to check for:
typeMapping.put("object", "any?"); // Like, everything is an object.
typeMapping.put("file", "any?"); // We don't really have specs for files,
typeMapping.put("binary", "any?"); // nor binary.
// And while there is a way to easily check if something is a bytearray,
// (https://stackoverflow.com/questions/14796964/), it's not possible
// to conform it yet, so we leave it as is.
typeMapping.put("ByteArray", "any?");
// Set of base specs that don't need to be imported
baseSpecs = new HashSet<>(
Arrays.asList(
"int?",
"float?",
"list?",
"map?",
"boolean?",
"string?",
"char?",
"inst?",
"uuid?",
"any?"
)
);
} }
@Override @Override
@ -88,6 +130,75 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
return "Generates a Clojure client library."; return "Generates a Clojure client library.";
} }
@Override
public String getTypeDeclaration(Schema p) {
if (p instanceof ArraySchema) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return "(s/coll-of " + getTypeDeclaration(inner) + ")";
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = (Schema) p.getAdditionalProperties();
return "(s/map-of string? " + getTypeDeclaration(inner) + ")";
}
// If it's a type we defined, we want to append the spec suffix
if (!typeMapping.containsKey(super.getSchemaType(p))) {
return super.getTypeDeclaration(p) + "-spec";
} else {
return super.getTypeDeclaration(p);
}
}
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
if (typeMapping.containsKey(openAPIType)) {
return typeMapping.get(openAPIType);
} else {
return toModelName(openAPIType);
}
}
@Override
public String toModelName(String name) {
return dashize(name);
}
@Override
public String toVarName(String name) {
name = name.replaceAll("[^a-zA-Z0-9_-]+", ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
return name;
}
@Override
public CodegenModel fromModel(String name, Schema mod, Map<String, Schema> allDefinitions) {
CodegenModel model = super.fromModel(name, mod, allDefinitions);
// If a var is a base spec we won't need to import it
for (CodegenProperty var : model.vars) {
if (baseSpecs.contains(var.complexType)) {
var.vendorExtensions.put(X_BASE_SPEC, true);
} else {
var.vendorExtensions.put(X_BASE_SPEC, false);
}
if (var.items != null) {
if (baseSpecs.contains(var.items.complexType)) {
var.items.vendorExtensions.put(X_BASE_SPEC, true);
} else {
var.items.vendorExtensions.put(X_BASE_SPEC, false);
}
}
}
// We also add all models to our model list so we can import them e.g. in operations
models.add(model.classname);
return model;
}
@Override @Override
public void preprocessOpenAPI(OpenAPI openAPI) { public void preprocessOpenAPI(OpenAPI openAPI) {
super.preprocessOpenAPI(openAPI); super.preprocessOpenAPI(openAPI);
@ -151,12 +262,14 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
baseNamespace = dashize(projectName); baseNamespace = dashize(projectName);
} }
apiPackage = baseNamespace + ".api"; apiPackage = baseNamespace + ".api";
modelPackage = baseNamespace + ".specs";
additionalProperties.put(PROJECT_NAME, projectName); additionalProperties.put(PROJECT_NAME, projectName);
additionalProperties.put(PROJECT_DESCRIPTION, escapeText(projectDescription)); additionalProperties.put(PROJECT_DESCRIPTION, escapeText(projectDescription));
additionalProperties.put(PROJECT_VERSION, projectVersion); additionalProperties.put(PROJECT_VERSION, projectVersion);
additionalProperties.put(BASE_NAMESPACE, baseNamespace); additionalProperties.put(BASE_NAMESPACE, baseNamespace);
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage); additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
final String baseNamespaceFolder = sourceFolder + File.separator + namespaceToFolder(baseNamespace); final String baseNamespaceFolder = sourceFolder + File.separator + namespaceToFolder(baseNamespace);
supportingFiles.add(new SupportingFile("project.mustache", "", "project.clj")); supportingFiles.add(new SupportingFile("project.mustache", "", "project.clj"));
@ -175,6 +288,11 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
return outputFolder + File.separator + sourceFolder + File.separator + namespaceToFolder(apiPackage); return outputFolder + File.separator + sourceFolder + File.separator + namespaceToFolder(apiPackage);
} }
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + namespaceToFolder(modelPackage);
}
@Override @Override
public String toOperationId(String operationId) { public String toOperationId(String operationId) {
// throw exception if method name is empty // throw exception if method name is empty
@ -190,6 +308,11 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
return underscore(toApiName(name)); return underscore(toApiName(name));
} }
@Override
public String toModelFilename(String name) {
return underscore(toModelName(name));
}
@Override @Override
public String toApiName(String name) { public String toApiName(String name) {
return dashize(name); return dashize(name);
@ -200,13 +323,6 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
return toVarName(name); return toVarName(name);
} }
@Override
public String toVarName(String name) {
name = name.replaceAll("[^a-zA-Z0-9_-]+", ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
name = dashize(name);
return name;
}
@Override @Override
public String escapeText(String input) { public String escapeText(String input) {
if (input == null) { if (input == null) {
@ -222,6 +338,8 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
for (CodegenOperation op : ops) { for (CodegenOperation op : ops) {
// Convert httpMethod to lower case, e.g. "get", "post" // Convert httpMethod to lower case, e.g. "get", "post"
op.httpMethod = op.httpMethod.toLowerCase(); op.httpMethod = op.httpMethod.toLowerCase();
op.vendorExtensions.put(X_MODELS, models);
} }
return operations; return operations;
} }

View File

@ -1,12 +1,18 @@
{{=< >=}}(ns <package>.<classname> {{=< >=}}(ns <package>.<classname>
(:require [<baseNamespace>.core :refer [call-api check-required-params with-collection-format]]) (:require [<baseNamespace>.core :refer [call-api check-required-params with-collection-format *api-context*]]
[clojure.spec.alpha :as s]
[spec-tools.core :as st]
[orchestra.core :refer [defn-spec]]
<#operations><#operation><#-first><#vendorExtensions.x-models>[<modelPackage>.<.> :refer :all]
</vendorExtensions.x-models></-first></operation></operations>)
(:import (java.io File))) (:import (java.io File)))
<#operations><#operation> <#operations><#operation>
(defn <operationId>-with-http-info (defn-spec <operationId>-with-http-info any?
"<&summary><#notes> "<&summary><#notes>
<&notes></notes>"<#hasOptionalParams> <&notes></notes>"<#hasOptionalParams>
([<#allParams><#required><#isFile>^File </isFile><paramName> </required></allParams>] (<operationId>-with-http-info<#allParams><#required> <paramName></required></allParams> nil))</hasOptionalParams> ([<#allParams><#required><#isFile>^File </isFile><paramName> <dataType><#hasMore>, </hasMore></required></allParams>] (<operationId>-with-http-info<#allParams><#required> <paramName></required></allParams> nil))</hasOptionalParams>
<#hasOptionalParams>(</hasOptionalParams>[<#allParams><#required><#isFile>^File </isFile><paramName> </required></allParams><#hasOptionalParams>{:keys [<#allParams><^required><#isFile>^File </isFile><paramName> </required></allParams>]}</hasOptionalParams>]<#hasRequiredParams> <#hasOptionalParams>(</hasOptionalParams>[<#allParams><#required><#isFile>^File </isFile><paramName> <dataType><#hasMore>, </hasMore></required></allParams><#hasOptionalParams>{:keys [<#allParams><^required><#isFile>^File </isFile><paramName><#hasMore> </hasMore></required></allParams>]} (s/map-of keyword? any?)</hasOptionalParams>]<#hasRequiredParams>
<#hasOptionalParams> </hasOptionalParams>(check-required-params<#allParams><#required> <paramName></required></allParams>)</hasRequiredParams> <#hasOptionalParams> </hasOptionalParams>(check-required-params<#allParams><#required> <paramName></required></allParams>)</hasRequiredParams>
<#hasOptionalParams> </hasOptionalParams>(call-api "<path>" :<httpMethod> <#hasOptionalParams> </hasOptionalParams>(call-api "<path>" :<httpMethod>
<#hasOptionalParams> </hasOptionalParams> {:path-params {<#pathParams>"<baseName>" <#collectionFormat>(with-collection-format <paramName> :<collectionFormat>)</collectionFormat><^collectionFormat><paramName></collectionFormat> </pathParams>} <#hasOptionalParams> </hasOptionalParams> {:path-params {<#pathParams>"<baseName>" <#collectionFormat>(with-collection-format <paramName> :<collectionFormat>)</collectionFormat><^collectionFormat><paramName></collectionFormat> </pathParams>}
@ -18,10 +24,14 @@
<#hasOptionalParams> </hasOptionalParams> :accepts [<#produces>"<& mediaType>"<#hasMore> </hasMore></produces>] <#hasOptionalParams> </hasOptionalParams> :accepts [<#produces>"<& mediaType>"<#hasMore> </hasMore></produces>]
<#hasOptionalParams> </hasOptionalParams> :auth-names [<#authMethods>"<&name>"<#hasMore> </hasMore></authMethods>]})<#hasOptionalParams>)</hasOptionalParams>) <#hasOptionalParams> </hasOptionalParams> :auth-names [<#authMethods>"<&name>"<#hasMore> </hasMore></authMethods>]})<#hasOptionalParams>)</hasOptionalParams>)
(defn <operationId> (defn-spec <operationId> <#returnType><returnType></returnType><^returnType>any?</returnType>
"<&summary><#notes> "<&summary><#notes>
<&notes></notes>"<#hasOptionalParams> <&notes></notes>"<#hasOptionalParams>
([<#allParams><#required><#isFile>^File </isFile><paramName> </required></allParams>] (<operationId><#allParams><#required> <paramName></required></allParams> nil))</hasOptionalParams> ([<#allParams><#required><#isFile>^File </isFile><paramName> <dataType><#hasMore>, </hasMore></required></allParams>] (<operationId><#allParams><#required> <paramName></required></allParams> nil))</hasOptionalParams>
<#hasOptionalParams>(</hasOptionalParams>[<#allParams><#required><#isFile>^File </isFile><paramName> </required></allParams><#hasOptionalParams>optional-params</hasOptionalParams>] <#hasOptionalParams>(</hasOptionalParams>[<#allParams><#required><#isFile>^File </isFile><paramName> <dataType><#hasMore>, </hasMore></required></allParams><#hasOptionalParams>optional-params any?</hasOptionalParams>]
<#hasOptionalParams> </hasOptionalParams>(:data (<operationId>-with-http-info<#allParams><#required> <paramName></required></allParams><#hasOptionalParams> optional-params</hasOptionalParams>))<#hasOptionalParams>)</hasOptionalParams>) <#hasOptionalParams> </hasOptionalParams>(let [res (:data (<operationId>-with-http-info<#allParams><#required> <paramName></required></allParams><#hasOptionalParams> optional-params</hasOptionalParams>))]
<#hasOptionalParams> </hasOptionalParams> (if (:decode-models *api-context*)
<#hasOptionalParams> </hasOptionalParams> (st/decode <#returnType><returnType></returnType><^returnType>any?</returnType> res st/string-transformer)
<#hasOptionalParams> </hasOptionalParams> res))<#hasOptionalParams>)</hasOptionalParams>)
</operation></operations> </operation></operations>

View File

@ -16,6 +16,7 @@
{:base-url "<&basePath>" {:base-url "<&basePath>"
:date-format "yyyy-MM-dd" :date-format "yyyy-MM-dd"
:datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" :datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
:decode-models false
:debug false :debug false
:auths {<#authMethods>"<&name>" nil<#hasMore> :auths {<#authMethods>"<&name>" nil<#hasMore>
</hasMore></authMethods>}}) </hasMore></authMethods>}})

View File

@ -3,6 +3,8 @@
:url "<&projectUrl>"</projectUrl><#projectLicenseName> :url "<&projectUrl>"</projectUrl><#projectLicenseName>
:license {:name "<&projectLicenseName>"<#projectLicenseUrl> :license {:name "<&projectLicenseName>"<#projectLicenseUrl>
:url "<&projectLicenseUrl>"</projectLicenseUrl>}</projectLicenseName> :url "<&projectLicenseUrl>"</projectLicenseUrl>}</projectLicenseName>
:dependencies [[org.clojure/clojure "1.7.0"] :dependencies [[org.clojure/clojure "1.9.0"]
[clj-http "3.6.0"] [metosin/spec-tools "0.7.0"]
[cheshire "5.5.0"]]) [clj-http "3.8.0"]
[orchestra "2017.11.12-1"]
[cheshire "5.8.0"]])

View File

@ -0,0 +1,19 @@
{{=< >=}}(ns <package>.<classname>
(:require [clojure.spec.alpha :as s]
[spec-tools.data-spec :as ds]
<#models><#model><#vars><^isContainer><^vendorExtensions.x-baseSpec>[<package>.<complexType> :refer :all]
</vendorExtensions.x-baseSpec></isContainer><#isContainer><^vendorExtensions.x-baseSpec>[<package>.<complexType> :refer :all]
</vendorExtensions.x-baseSpec></isContainer></vars></model></models>)
(:import (java.io File)))
<#models><#model>
(def <classname>-data
{<#vars>
(ds/<#required>req</required><^required>opt</required> :<name>) <datatype></vars>
})
(def <classname>-spec
(ds/spec
{:name ::<classname>
:spec <classname>-data}))
</model></models>

View File

@ -2,6 +2,8 @@
:description "This is a sample server Petstore server. For this sample, you can use the api key \"special-key\" to test the authorization filters" :description "This is a sample server Petstore server. For this sample, you can use the api key \"special-key\" to test the authorization filters"
:license {:name "Apache-2.0" :license {:name "Apache-2.0"
:url "http://www.apache.org/licenses/LICENSE-2.0.html"} :url "http://www.apache.org/licenses/LICENSE-2.0.html"}
:dependencies [[org.clojure/clojure "1.7.0"] :dependencies [[org.clojure/clojure "1.9.0"]
[clj-http "3.6.0"] [metosin/spec-tools "0.7.0"]
[cheshire "5.5.0"]]) [clj-http "3.8.0"]
[orchestra "2017.11.12-1"]
[cheshire "5.8.0"]])

View File

@ -1,11 +1,21 @@
(ns open-api-petstore.api.pet (ns open-api-petstore.api.pet
(:require [open-api-petstore.core :refer [call-api check-required-params with-collection-format]]) (:require [open-api-petstore.core :refer [call-api check-required-params with-collection-format *api-context*]]
[clojure.spec.alpha :as s]
[spec-tools.core :as st]
[orchestra.core :refer [defn-spec]]
[open-api-petstore.specs.tag :refer :all]
[open-api-petstore.specs.category :refer :all]
[open-api-petstore.specs.user :refer :all]
[open-api-petstore.specs.pet :refer :all]
[open-api-petstore.specs.order :refer :all]
)
(:import (java.io File))) (:import (java.io File)))
(defn add-pet-with-http-info
(defn-spec add-pet-with-http-info any?
"Add a new pet to the store" "Add a new pet to the store"
([] (add-pet-with-http-info nil)) ([] (add-pet-with-http-info nil))
([{:keys [pet ]}] ([{:keys [pet]} (s/map-of keyword? any?)]
(call-api "/pet" :post (call-api "/pet" :post
{:path-params {} {:path-params {}
:header-params {} :header-params {}
@ -16,37 +26,45 @@
:accepts [] :accepts []
:auth-names ["petstore_auth"]}))) :auth-names ["petstore_auth"]})))
(defn add-pet (defn-spec add-pet any?
"Add a new pet to the store" "Add a new pet to the store"
([] (add-pet nil)) ([] (add-pet nil))
([optional-params] ([optional-params any?]
(:data (add-pet-with-http-info optional-params)))) (let [res (:data (add-pet-with-http-info optional-params))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res))))
(defn delete-pet-with-http-info
(defn-spec delete-pet-with-http-info any?
"Deletes a pet" "Deletes a pet"
([pet-id ] (delete-pet-with-http-info pet-id nil)) ([petId int?, ] (delete-pet-with-http-info petId nil))
([pet-id {:keys [api-key ]}] ([petId int?, {:keys [api_key]} (s/map-of keyword? any?)]
(check-required-params pet-id) (check-required-params petId)
(call-api "/pet/{petId}" :delete (call-api "/pet/{petId}" :delete
{:path-params {"petId" pet-id } {:path-params {"petId" petId }
:header-params {"api_key" api-key } :header-params {"api_key" api_key }
:query-params {} :query-params {}
:form-params {} :form-params {}
:content-types [] :content-types []
:accepts [] :accepts []
:auth-names ["petstore_auth"]}))) :auth-names ["petstore_auth"]})))
(defn delete-pet (defn-spec delete-pet any?
"Deletes a pet" "Deletes a pet"
([pet-id ] (delete-pet pet-id nil)) ([petId int?, ] (delete-pet petId nil))
([pet-id optional-params] ([petId int?, optional-params any?]
(:data (delete-pet-with-http-info pet-id optional-params)))) (let [res (:data (delete-pet-with-http-info petId optional-params))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res))))
(defn find-pets-by-status-with-http-info
(defn-spec find-pets-by-status-with-http-info any?
"Finds Pets by status "Finds Pets by status
Multiple status values can be provided with comma separated strings" Multiple status values can be provided with comma separated strings"
([] (find-pets-by-status-with-http-info nil)) ([] (find-pets-by-status-with-http-info nil))
([{:keys [status ]}] ([{:keys [status]} (s/map-of keyword? any?)]
(call-api "/pet/findByStatus" :get (call-api "/pet/findByStatus" :get
{:path-params {} {:path-params {}
:header-params {} :header-params {}
@ -56,18 +74,22 @@
:accepts ["application/json" "application/xml"] :accepts ["application/json" "application/xml"]
:auth-names ["petstore_auth"]}))) :auth-names ["petstore_auth"]})))
(defn find-pets-by-status (defn-spec find-pets-by-status (s/coll-of pet-spec)
"Finds Pets by status "Finds Pets by status
Multiple status values can be provided with comma separated strings" Multiple status values can be provided with comma separated strings"
([] (find-pets-by-status nil)) ([] (find-pets-by-status nil))
([optional-params] ([optional-params any?]
(:data (find-pets-by-status-with-http-info optional-params)))) (let [res (:data (find-pets-by-status-with-http-info optional-params))]
(if (:decode-models *api-context*)
(st/decode (s/coll-of pet-spec) res st/string-transformer)
res))))
(defn find-pets-by-tags-with-http-info
(defn-spec find-pets-by-tags-with-http-info any?
"Finds Pets by tags "Finds Pets by tags
Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing." Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing."
([] (find-pets-by-tags-with-http-info nil)) ([] (find-pets-by-tags-with-http-info nil))
([{:keys [tags ]}] ([{:keys [tags]} (s/map-of keyword? any?)]
(call-api "/pet/findByTags" :get (call-api "/pet/findByTags" :get
{:path-params {} {:path-params {}
:header-params {} :header-params {}
@ -77,20 +99,24 @@
:accepts ["application/json" "application/xml"] :accepts ["application/json" "application/xml"]
:auth-names ["petstore_auth"]}))) :auth-names ["petstore_auth"]})))
(defn find-pets-by-tags (defn-spec find-pets-by-tags (s/coll-of pet-spec)
"Finds Pets by tags "Finds Pets by tags
Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing." Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing."
([] (find-pets-by-tags nil)) ([] (find-pets-by-tags nil))
([optional-params] ([optional-params any?]
(:data (find-pets-by-tags-with-http-info optional-params)))) (let [res (:data (find-pets-by-tags-with-http-info optional-params))]
(if (:decode-models *api-context*)
(st/decode (s/coll-of pet-spec) res st/string-transformer)
res))))
(defn get-pet-by-id-with-http-info
(defn-spec get-pet-by-id-with-http-info any?
"Find pet by ID "Find pet by ID
Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions" Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions"
[pet-id ] [petId int?]
(check-required-params pet-id) (check-required-params petId)
(call-api "/pet/{petId}" :get (call-api "/pet/{petId}" :get
{:path-params {"petId" pet-id } {:path-params {"petId" petId }
:header-params {} :header-params {}
:query-params {} :query-params {}
:form-params {} :form-params {}
@ -98,16 +124,20 @@
:accepts ["application/json" "application/xml"] :accepts ["application/json" "application/xml"]
:auth-names ["api_key" "petstore_auth"]})) :auth-names ["api_key" "petstore_auth"]}))
(defn get-pet-by-id (defn-spec get-pet-by-id pet-spec
"Find pet by ID "Find pet by ID
Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions" Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions"
[pet-id ] [petId int?]
(:data (get-pet-by-id-with-http-info pet-id))) (let [res (:data (get-pet-by-id-with-http-info petId))]
(if (:decode-models *api-context*)
(st/decode pet-spec res st/string-transformer)
res)))
(defn update-pet-with-http-info
(defn-spec update-pet-with-http-info any?
"Update an existing pet" "Update an existing pet"
([] (update-pet-with-http-info nil)) ([] (update-pet-with-http-info nil))
([{:keys [pet ]}] ([{:keys [pet]} (s/map-of keyword? any?)]
(call-api "/pet" :put (call-api "/pet" :put
{:path-params {} {:path-params {}
:header-params {} :header-params {}
@ -118,19 +148,23 @@
:accepts [] :accepts []
:auth-names ["petstore_auth"]}))) :auth-names ["petstore_auth"]})))
(defn update-pet (defn-spec update-pet any?
"Update an existing pet" "Update an existing pet"
([] (update-pet nil)) ([] (update-pet nil))
([optional-params] ([optional-params any?]
(:data (update-pet-with-http-info optional-params)))) (let [res (:data (update-pet-with-http-info optional-params))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res))))
(defn update-pet-with-form-with-http-info
(defn-spec update-pet-with-form-with-http-info any?
"Updates a pet in the store with form data" "Updates a pet in the store with form data"
([pet-id ] (update-pet-with-form-with-http-info pet-id nil)) ([petId string?, ] (update-pet-with-form-with-http-info petId nil))
([pet-id {:keys [name status ]}] ([petId string?, {:keys [name status]} (s/map-of keyword? any?)]
(check-required-params pet-id) (check-required-params petId)
(call-api "/pet/{petId}" :post (call-api "/pet/{petId}" :post
{:path-params {"petId" pet-id } {:path-params {"petId" petId }
:header-params {} :header-params {}
:query-params {} :query-params {}
:form-params {"name" name "status" status } :form-params {"name" name "status" status }
@ -138,29 +172,37 @@
:accepts [] :accepts []
:auth-names ["petstore_auth"]}))) :auth-names ["petstore_auth"]})))
(defn update-pet-with-form (defn-spec update-pet-with-form any?
"Updates a pet in the store with form data" "Updates a pet in the store with form data"
([pet-id ] (update-pet-with-form pet-id nil)) ([petId string?, ] (update-pet-with-form petId nil))
([pet-id optional-params] ([petId string?, optional-params any?]
(:data (update-pet-with-form-with-http-info pet-id optional-params)))) (let [res (:data (update-pet-with-form-with-http-info petId optional-params))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res))))
(defn upload-file-with-http-info
(defn-spec upload-file-with-http-info any?
"uploads an image" "uploads an image"
([pet-id ] (upload-file-with-http-info pet-id nil)) ([petId int?, ] (upload-file-with-http-info petId nil))
([pet-id {:keys [additional-metadata ^File file ]}] ([petId int?, {:keys [additionalMetadata ^File file]} (s/map-of keyword? any?)]
(check-required-params pet-id) (check-required-params petId)
(call-api "/pet/{petId}/uploadImage" :post (call-api "/pet/{petId}/uploadImage" :post
{:path-params {"petId" pet-id } {:path-params {"petId" petId }
:header-params {} :header-params {}
:query-params {} :query-params {}
:form-params {"additionalMetadata" additional-metadata "file" file } :form-params {"additionalMetadata" additionalMetadata "file" file }
:content-types ["multipart/form-data"] :content-types ["multipart/form-data"]
:accepts [] :accepts []
:auth-names ["petstore_auth"]}))) :auth-names ["petstore_auth"]})))
(defn upload-file (defn-spec upload-file any?
"uploads an image" "uploads an image"
([pet-id ] (upload-file pet-id nil)) ([petId int?, ] (upload-file petId nil))
([pet-id optional-params] ([petId int?, optional-params any?]
(:data (upload-file-with-http-info pet-id optional-params)))) (let [res (:data (upload-file-with-http-info petId optional-params))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res))))

View File

@ -1,14 +1,24 @@
(ns open-api-petstore.api.store (ns open-api-petstore.api.store
(:require [open-api-petstore.core :refer [call-api check-required-params with-collection-format]]) (:require [open-api-petstore.core :refer [call-api check-required-params with-collection-format *api-context*]]
[clojure.spec.alpha :as s]
[spec-tools.core :as st]
[orchestra.core :refer [defn-spec]]
[open-api-petstore.specs.tag :refer :all]
[open-api-petstore.specs.category :refer :all]
[open-api-petstore.specs.user :refer :all]
[open-api-petstore.specs.pet :refer :all]
[open-api-petstore.specs.order :refer :all]
)
(:import (java.io File))) (:import (java.io File)))
(defn delete-order-with-http-info
(defn-spec delete-order-with-http-info any?
"Delete purchase order by ID "Delete purchase order by ID
For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors" For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors"
[order-id ] [orderId string?]
(check-required-params order-id) (check-required-params orderId)
(call-api "/store/order/{orderId}" :delete (call-api "/store/order/{orderId}" :delete
{:path-params {"orderId" order-id } {:path-params {"orderId" orderId }
:header-params {} :header-params {}
:query-params {} :query-params {}
:form-params {} :form-params {}
@ -16,13 +26,17 @@
:accepts [] :accepts []
:auth-names []})) :auth-names []}))
(defn delete-order (defn-spec delete-order any?
"Delete purchase order by ID "Delete purchase order by ID
For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors" For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors"
[order-id ] [orderId string?]
(:data (delete-order-with-http-info order-id))) (let [res (:data (delete-order-with-http-info orderId))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res)))
(defn get-inventory-with-http-info
(defn-spec get-inventory-with-http-info any?
"Returns pet inventories by status "Returns pet inventories by status
Returns a map of status codes to quantities" Returns a map of status codes to quantities"
[] []
@ -35,19 +49,23 @@
:accepts ["application/json" "application/xml"] :accepts ["application/json" "application/xml"]
:auth-names ["api_key"]})) :auth-names ["api_key"]}))
(defn get-inventory (defn-spec get-inventory (s/map-of string? int?)
"Returns pet inventories by status "Returns pet inventories by status
Returns a map of status codes to quantities" Returns a map of status codes to quantities"
[] []
(:data (get-inventory-with-http-info))) (let [res (:data (get-inventory-with-http-info))]
(if (:decode-models *api-context*)
(st/decode (s/map-of string? int?) res st/string-transformer)
res)))
(defn get-order-by-id-with-http-info
(defn-spec get-order-by-id-with-http-info any?
"Find purchase order by ID "Find purchase order by ID
For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions" For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions"
[order-id ] [orderId string?]
(check-required-params order-id) (check-required-params orderId)
(call-api "/store/order/{orderId}" :get (call-api "/store/order/{orderId}" :get
{:path-params {"orderId" order-id } {:path-params {"orderId" orderId }
:header-params {} :header-params {}
:query-params {} :query-params {}
:form-params {} :form-params {}
@ -55,16 +73,20 @@
:accepts ["application/json" "application/xml"] :accepts ["application/json" "application/xml"]
:auth-names []})) :auth-names []}))
(defn get-order-by-id (defn-spec get-order-by-id order-spec
"Find purchase order by ID "Find purchase order by ID
For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions" For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions"
[order-id ] [orderId string?]
(:data (get-order-by-id-with-http-info order-id))) (let [res (:data (get-order-by-id-with-http-info orderId))]
(if (:decode-models *api-context*)
(st/decode order-spec res st/string-transformer)
res)))
(defn place-order-with-http-info
(defn-spec place-order-with-http-info any?
"Place an order for a pet" "Place an order for a pet"
([] (place-order-with-http-info nil)) ([] (place-order-with-http-info nil))
([{:keys [order ]}] ([{:keys [order]} (s/map-of keyword? any?)]
(call-api "/store/order" :post (call-api "/store/order" :post
{:path-params {} {:path-params {}
:header-params {} :header-params {}
@ -75,9 +97,13 @@
:accepts ["application/json" "application/xml"] :accepts ["application/json" "application/xml"]
:auth-names []}))) :auth-names []})))
(defn place-order (defn-spec place-order order-spec
"Place an order for a pet" "Place an order for a pet"
([] (place-order nil)) ([] (place-order nil))
([optional-params] ([optional-params any?]
(:data (place-order-with-http-info optional-params)))) (let [res (:data (place-order-with-http-info optional-params))]
(if (:decode-models *api-context*)
(st/decode order-spec res st/string-transformer)
res))))

View File

@ -1,12 +1,22 @@
(ns open-api-petstore.api.user (ns open-api-petstore.api.user
(:require [open-api-petstore.core :refer [call-api check-required-params with-collection-format]]) (:require [open-api-petstore.core :refer [call-api check-required-params with-collection-format *api-context*]]
[clojure.spec.alpha :as s]
[spec-tools.core :as st]
[orchestra.core :refer [defn-spec]]
[open-api-petstore.specs.tag :refer :all]
[open-api-petstore.specs.category :refer :all]
[open-api-petstore.specs.user :refer :all]
[open-api-petstore.specs.pet :refer :all]
[open-api-petstore.specs.order :refer :all]
)
(:import (java.io File))) (:import (java.io File)))
(defn create-user-with-http-info
(defn-spec create-user-with-http-info any?
"Create user "Create user
This can only be done by the logged in user." This can only be done by the logged in user."
([] (create-user-with-http-info nil)) ([] (create-user-with-http-info nil))
([{:keys [user ]}] ([{:keys [user]} (s/map-of keyword? any?)]
(call-api "/user" :post (call-api "/user" :post
{:path-params {} {:path-params {}
:header-params {} :header-params {}
@ -17,17 +27,21 @@
:accepts [] :accepts []
:auth-names []}))) :auth-names []})))
(defn create-user (defn-spec create-user any?
"Create user "Create user
This can only be done by the logged in user." This can only be done by the logged in user."
([] (create-user nil)) ([] (create-user nil))
([optional-params] ([optional-params any?]
(:data (create-user-with-http-info optional-params)))) (let [res (:data (create-user-with-http-info optional-params))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res))))
(defn create-users-with-array-input-with-http-info
(defn-spec create-users-with-array-input-with-http-info any?
"Creates list of users with given input array" "Creates list of users with given input array"
([] (create-users-with-array-input-with-http-info nil)) ([] (create-users-with-array-input-with-http-info nil))
([{:keys [user ]}] ([{:keys [user]} (s/map-of keyword? any?)]
(call-api "/user/createWithArray" :post (call-api "/user/createWithArray" :post
{:path-params {} {:path-params {}
:header-params {} :header-params {}
@ -38,16 +52,20 @@
:accepts [] :accepts []
:auth-names []}))) :auth-names []})))
(defn create-users-with-array-input (defn-spec create-users-with-array-input any?
"Creates list of users with given input array" "Creates list of users with given input array"
([] (create-users-with-array-input nil)) ([] (create-users-with-array-input nil))
([optional-params] ([optional-params any?]
(:data (create-users-with-array-input-with-http-info optional-params)))) (let [res (:data (create-users-with-array-input-with-http-info optional-params))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res))))
(defn create-users-with-list-input-with-http-info
(defn-spec create-users-with-list-input-with-http-info any?
"Creates list of users with given input array" "Creates list of users with given input array"
([] (create-users-with-list-input-with-http-info nil)) ([] (create-users-with-list-input-with-http-info nil))
([{:keys [user ]}] ([{:keys [user]} (s/map-of keyword? any?)]
(call-api "/user/createWithList" :post (call-api "/user/createWithList" :post
{:path-params {} {:path-params {}
:header-params {} :header-params {}
@ -58,16 +76,20 @@
:accepts [] :accepts []
:auth-names []}))) :auth-names []})))
(defn create-users-with-list-input (defn-spec create-users-with-list-input any?
"Creates list of users with given input array" "Creates list of users with given input array"
([] (create-users-with-list-input nil)) ([] (create-users-with-list-input nil))
([optional-params] ([optional-params any?]
(:data (create-users-with-list-input-with-http-info optional-params)))) (let [res (:data (create-users-with-list-input-with-http-info optional-params))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res))))
(defn delete-user-with-http-info
(defn-spec delete-user-with-http-info any?
"Delete user "Delete user
This can only be done by the logged in user." This can only be done by the logged in user."
[username ] [username string?]
(check-required-params username) (check-required-params username)
(call-api "/user/{username}" :delete (call-api "/user/{username}" :delete
{:path-params {"username" username } {:path-params {"username" username }
@ -78,15 +100,19 @@
:accepts [] :accepts []
:auth-names []})) :auth-names []}))
(defn delete-user (defn-spec delete-user any?
"Delete user "Delete user
This can only be done by the logged in user." This can only be done by the logged in user."
[username ] [username string?]
(:data (delete-user-with-http-info username))) (let [res (:data (delete-user-with-http-info username))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res)))
(defn get-user-by-name-with-http-info
(defn-spec get-user-by-name-with-http-info any?
"Get user by user name" "Get user by user name"
[username ] [username string?]
(check-required-params username) (check-required-params username)
(call-api "/user/{username}" :get (call-api "/user/{username}" :get
{:path-params {"username" username } {:path-params {"username" username }
@ -97,15 +123,19 @@
:accepts ["application/json" "application/xml"] :accepts ["application/json" "application/xml"]
:auth-names []})) :auth-names []}))
(defn get-user-by-name (defn-spec get-user-by-name user-spec
"Get user by user name" "Get user by user name"
[username ] [username string?]
(:data (get-user-by-name-with-http-info username))) (let [res (:data (get-user-by-name-with-http-info username))]
(if (:decode-models *api-context*)
(st/decode user-spec res st/string-transformer)
res)))
(defn login-user-with-http-info
(defn-spec login-user-with-http-info any?
"Logs user into the system" "Logs user into the system"
([] (login-user-with-http-info nil)) ([] (login-user-with-http-info nil))
([{:keys [username password ]}] ([{:keys [username password]} (s/map-of keyword? any?)]
(call-api "/user/login" :get (call-api "/user/login" :get
{:path-params {} {:path-params {}
:header-params {} :header-params {}
@ -115,13 +145,17 @@
:accepts ["application/json" "application/xml"] :accepts ["application/json" "application/xml"]
:auth-names []}))) :auth-names []})))
(defn login-user (defn-spec login-user string?
"Logs user into the system" "Logs user into the system"
([] (login-user nil)) ([] (login-user nil))
([optional-params] ([optional-params any?]
(:data (login-user-with-http-info optional-params)))) (let [res (:data (login-user-with-http-info optional-params))]
(if (:decode-models *api-context*)
(st/decode string? res st/string-transformer)
res))))
(defn logout-user-with-http-info
(defn-spec logout-user-with-http-info any?
"Logs out current logged in user session" "Logs out current logged in user session"
[] []
(call-api "/user/logout" :get (call-api "/user/logout" :get
@ -133,16 +167,20 @@
:accepts [] :accepts []
:auth-names []})) :auth-names []}))
(defn logout-user (defn-spec logout-user any?
"Logs out current logged in user session" "Logs out current logged in user session"
[] []
(:data (logout-user-with-http-info))) (let [res (:data (logout-user-with-http-info))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res)))
(defn update-user-with-http-info
(defn-spec update-user-with-http-info any?
"Updated user "Updated user
This can only be done by the logged in user." This can only be done by the logged in user."
([username ] (update-user-with-http-info username nil)) ([username string?, ] (update-user-with-http-info username nil))
([username {:keys [user ]}] ([username string?, {:keys [user]} (s/map-of keyword? any?)]
(check-required-params username) (check-required-params username)
(call-api "/user/{username}" :put (call-api "/user/{username}" :put
{:path-params {"username" username } {:path-params {"username" username }
@ -154,10 +192,14 @@
:accepts [] :accepts []
:auth-names []}))) :auth-names []})))
(defn update-user (defn-spec update-user any?
"Updated user "Updated user
This can only be done by the logged in user." This can only be done by the logged in user."
([username ] (update-user username nil)) ([username string?, ] (update-user username nil))
([username optional-params] ([username string?, optional-params any?]
(:data (update-user-with-http-info username optional-params)))) (let [res (:data (update-user-with-http-info username optional-params))]
(if (:decode-models *api-context*)
(st/decode any? res st/string-transformer)
res))))

View File

@ -16,6 +16,7 @@
{:base-url "http://petstore.swagger.io/v2" {:base-url "http://petstore.swagger.io/v2"
:date-format "yyyy-MM-dd" :date-format "yyyy-MM-dd"
:datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" :datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
:decode-models false
:debug false :debug false
:auths {"api_key" nil :auths {"api_key" nil
"petstore_auth" nil}}) "petstore_auth" nil}})

View File

@ -0,0 +1,17 @@
(ns open-api-petstore.specs.category
(:require [clojure.spec.alpha :as s]
[spec-tools.data-spec :as ds]
)
(:import (java.io File)))
(def category-data
{
(ds/opt :id) int?
(ds/opt :name) string?
})
(def category-spec
(ds/spec
{:name ::category
:spec category-data}))

View File

@ -0,0 +1,21 @@
(ns open-api-petstore.specs.order
(:require [clojure.spec.alpha :as s]
[spec-tools.data-spec :as ds]
)
(:import (java.io File)))
(def order-data
{
(ds/opt :id) int?
(ds/opt :petId) int?
(ds/opt :quantity) int?
(ds/opt :shipDate) inst?
(ds/opt :status) string?
(ds/opt :complete) boolean?
})
(def order-spec
(ds/spec
{:name ::order
:spec order-data}))

View File

@ -0,0 +1,23 @@
(ns open-api-petstore.specs.pet
(:require [clojure.spec.alpha :as s]
[spec-tools.data-spec :as ds]
[open-api-petstore.specs.category :refer :all]
[open-api-petstore.specs.tag :refer :all]
)
(:import (java.io File)))
(def pet-data
{
(ds/opt :id) int?
(ds/opt :category) category-spec
(ds/req :name) string?
(ds/req :photoUrls) (s/coll-of string?)
(ds/opt :tags) (s/coll-of tag-spec)
(ds/opt :status) string?
})
(def pet-spec
(ds/spec
{:name ::pet
:spec pet-data}))

View File

@ -0,0 +1,17 @@
(ns open-api-petstore.specs.tag
(:require [clojure.spec.alpha :as s]
[spec-tools.data-spec :as ds]
)
(:import (java.io File)))
(def tag-data
{
(ds/opt :id) int?
(ds/opt :name) string?
})
(def tag-spec
(ds/spec
{:name ::tag
:spec tag-data}))

View File

@ -0,0 +1,23 @@
(ns open-api-petstore.specs.user
(:require [clojure.spec.alpha :as s]
[spec-tools.data-spec :as ds]
)
(:import (java.io File)))
(def user-data
{
(ds/opt :id) int?
(ds/opt :username) string?
(ds/opt :firstName) string?
(ds/opt :lastName) string?
(ds/opt :email) string?
(ds/opt :password) string?
(ds/opt :phone) string?
(ds/opt :userStatus) int?
})
(def user-spec
(ds/spec
{:name ::user
:spec user-data}))

View File

@ -32,3 +32,11 @@
(delete-order order-id) (delete-order order-id)
(comment "it seems that delete-order does not really delete the order" (comment "it seems that delete-order does not really delete the order"
(is (thrown? RuntimeException (get-order-by-id order-id)))))) (is (thrown? RuntimeException (get-order-by-id order-id))))))
(deftest test-order-spec-conforming
(with-api-context {:decode-models true}
(let [order (make-random-order)
order-id (:id order)
_ (place-order {:order order})
fetched (get-order-by-id order-id)]
(is (= order fetched)))))

View File

@ -9,6 +9,7 @@
(is (= {:base-url "http://petstore.swagger.io/v2" (is (= {:base-url "http://petstore.swagger.io/v2"
:date-format "yyyy-MM-dd" :date-format "yyyy-MM-dd"
:datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" :datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
:decode-models false
:debug false :debug false
:auths {"api_key" nil :auths {"api_key" nil
"petstore_auth" nil}} "petstore_auth" nil}}
@ -24,6 +25,7 @@
(is (= {:base-url "http://localhost" (is (= {:base-url "http://localhost"
:date-format "yyyy-MM-dd" :date-format "yyyy-MM-dd"
:datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" :datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
:decode-models false
:debug true :debug true
:auths (merge (:auths default-api-context) :auths (merge (:auths default-api-context)
{"api_key" "key1" {"api_key" "key1"
@ -35,6 +37,7 @@
(is (= {:base-url "http://localhost" (is (= {:base-url "http://localhost"
:date-format "yyyy-MM-dd" :date-format "yyyy-MM-dd"
:datetime-format "yyyy-MM-dd HH:mm:ss" :datetime-format "yyyy-MM-dd HH:mm:ss"
:decode-models false
:debug true :debug true
:auths (merge (:auths default-api-context) :auths (merge (:auths default-api-context)
{"api_key" "key2" {"api_key" "key2"
@ -44,6 +47,7 @@
(is (= {:base-url "http://petstore.swagger.io/v2" (is (= {:base-url "http://petstore.swagger.io/v2"
:date-format "yyyy-MM-dd" :date-format "yyyy-MM-dd"
:datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" :datetime-format "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
:decode-models false
:debug false :debug false
:auths {"api_key" nil :auths {"api_key" nil
"petstore_auth" nil}} "petstore_auth" nil}}