From 67eac90b9a70082c2772058d8a8292d359433095 Mon Sep 17 00:00:00 2001 From: "Michael H. Siemaszko" <mhs@into.software> Date: Sun, 17 Oct 2021 20:14:36 +0200 Subject: [PATCH 01/13] Further K6 OpenAPI generator enhancements * request body example data extraction * request grouping and ordering * response visibility * request data extraction for chaining requests Signed-off-by: Michael H. Siemaszko <mhs@into.software> --- .../codegen/CodegenOperation.java | 13 + .../codegen/languages/K6ClientCodegen.java | 503 ++++++++++++++++-- .../src/main/resources/k6/script.mustache | 83 +-- 3 files changed, 516 insertions(+), 83 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java index 0a8e7b31991..07197e209a3 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java @@ -69,6 +69,10 @@ public class CodegenOperation { return params != null && params.size() > 0; } + private static boolean nonempty(Map<?, ?> params) { + return params != null && params.size() > 0; + } + /** * Check if there's at least one body parameter * @@ -177,6 +181,15 @@ public class CodegenOperation { return responses.stream().filter(response -> response.isDefault).findFirst().isPresent(); } + /** + * Check if there's at least one vendor extension + * + * @return true if vendor extensions exists, false otherwise + */ + public boolean getHasVendorExtensions() { + return nonempty(vendorExtensions); + } + /** * Check if act as Restful index method * diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java index dfc6efdd69b..45956976a00 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java @@ -28,11 +28,15 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; +import java.util.OptionalInt; import java.util.Set; +import java.util.TreeMap; import java.util.TreeSet; import java.util.stream.Collectors; @@ -43,6 +47,7 @@ import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CodegenConfig; import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; import org.openapitools.codegen.CodegenParameter; import org.openapitools.codegen.CodegenProperty; import org.openapitools.codegen.CodegenResponse; @@ -55,11 +60,14 @@ import org.openapitools.codegen.utils.ModelUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.ImmutableMap.Builder; import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Mustache.Lambda; import com.samskivert.mustache.Template; +import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; @@ -73,12 +81,30 @@ import io.swagger.v3.oas.models.servers.Server; public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { + // K6 vendor extension - operation grouping - group operations and define their + // ordering, to allow for e.g. scenario testing + private static final String X_OPERATION_GROUPING = "x-k6-openapi-operation-grouping"; + + // K6 vendor extension - operation response - for now, allows to hide given + // operation response, so that in case of multiple 2xx responses, generated + // script checks only against e.g. code 200 responses + private static final String X_OPERATION_RESPONSE = "x-k6-openapi-operation-response"; + private static final String X_OPERATION_RESPONSE_HIDE = "hide"; + + // K6 vendor extension - extract data from operation - allows to specify path to + // value in body of response which should be extracted and assigned to variable + // for later use by other operations + private static final String X_OPERATION_DATAEXTRACT = "x-k6-openapi-operation-dataextract"; + private static final String X_OPERATION_DATAEXTRACT_OPERATION_ID = "operationId"; // denotes ID of operation whose response body contains value to be extracted + private static final String X_OPERATION_DATAEXTRACT_VALUE_PATH = "valuePath"; // denotes path to value in body of response which should be extracted + private static final String X_OPERATION_DATAEXTRACT_PARAMETER_NAME = "parameterName"; // denotes name of parameter to which extracted value should be assigned + public K6ClientCodegen() { super(); generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata) .stability(Stability.BETA) - .build(); + .build(); } @@ -86,6 +112,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { String key; Object value; boolean hasExample; + boolean initialize; public Parameter(String key, Object value) { this.key = key; @@ -97,6 +124,11 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { this.value = exampleValue; this.hasExample = hasExample; } + + public Parameter(String key, boolean initialize) { + this.key = key; + this.initialize = initialize; + } @Override public int hashCode() { @@ -110,10 +142,35 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { if (obj == null || getClass() != obj.getClass()) return false; Parameter p = (Parameter) obj; - return key.equals(p.key) && value.equals(p.value) && hasExample == p.hasExample; + return key.equals(p.key) && value.equals(p.value) && hasExample == p.hasExample + && initialize == p.initialize; } } - + + // Stores information specified in `X_OPERATION_GROUPING` K6 vendor extension + static class OperationGrouping { + String groupName; + int order; + + public OperationGrouping(String groupName, int order) { + this.groupName = groupName; + this.order = order; + } + } + + // Stores information specified in `X_OPERATION_DATAEXTRACT` K6 vendor extension + static class DataExtractSubstituteParameter { + String operationId; + String valuePath; + String paramName; + + public DataExtractSubstituteParameter(String operationId, String valuePath, String paramName) { + this.operationId = operationId; + this.valuePath = valuePath; + this.paramName = paramName; + } + } + static class ParameterValueLambda implements Mustache.Lambda { private static final String NO_EXAMPLE_PARAM_VALUE_PREFIX = "TODO_EDIT_THE_"; @@ -138,10 +195,10 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { @SuppressWarnings("unchecked") Set<String> exampleValues = ((Map<String, Example>) rawValue).values().stream() - .map(x -> quoteExample( - StringEscapeUtils.escapeEcmaScript( - String.valueOf(x.getValue())))) - .collect(Collectors.toCollection(() -> new TreeSet<String>())); + .map(x -> quoteExample( + StringEscapeUtils.escapeEcmaScript( + String.valueOf(x.getValue())))) + .collect(Collectors.toCollection(() -> new TreeSet<String>())); if (!exampleValues.isEmpty()) { @@ -160,11 +217,20 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { quoteExample( StringEscapeUtils.escapeEcmaScript( String.valueOf( - ((K6ClientCodegen.Parameter) fragment.context()).value))), + ((K6ClientCodegen.Parameter) fragment.context()).value))), ";", " // extracted from 'example' field defined at the parameter level of OpenAPI spec")); } + // param needs to be initialized for subsequent data extraction - see `X_OPERATION_DATAEXTRACT` K6 vendor extension + } else if (fragment.context() instanceof K6ClientCodegen.Parameter + && ((K6ClientCodegen.Parameter) fragment.context()).initialize) { + + writer.write(String.join("", + "null", + ";", + " // parameter initialized for subsequent data extraction")); + } else { writer.write(noExampleParamValue); } @@ -231,25 +297,33 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { static class HTTPRequest { String method; + boolean isDelete; String path; @Nullable List<Parameter> query; @Nullable HTTPBody body; + boolean hasBodyExample; @Nullable HTTPParameters params; @Nullable List<k6Check> k6Checks; + @Nullable + DataExtractSubstituteParameter dataExtract; public HTTPRequest(String method, String path, @Nullable List<Parameter> query, @Nullable HTTPBody body, - @Nullable HTTPParameters params, @Nullable List<k6Check> k6Checks) { + boolean hasBodyExample, @Nullable HTTPParameters params, @Nullable List<k6Check> k6Checks, + DataExtractSubstituteParameter dataExtract) { // NOTE: https://k6.io/docs/javascript-api/k6-http/del-url-body-params this.method = method.equals("delete") ? "del" : method; + this.isDelete = method.equals("delete") ? true : false; this.path = path; this.query = query; this.body = body; + this.hasBodyExample = hasBodyExample; this.params = params; this.k6Checks = k6Checks; + this.dataExtract = dataExtract; } } @@ -257,14 +331,29 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { String groupName; Set<Parameter> variables; // query and path parameters List<HTTPRequest> requests; + private Map<Integer, HTTPRequest> requestsMap; - public HTTPRequestGroup(String groupName, Set<Parameter> variables, List<HTTPRequest> requests) { + public HTTPRequestGroup(String groupName, Set<Parameter> variables, Map<Integer, HTTPRequest> requestsMap) { this.groupName = groupName; this.variables = variables; - this.requests = requests; + this.requestsMap = requestsMap; + this.requests = sortRequests(requestsMap); + } + + private void addRequests(Map<Integer, HTTPRequest> moreRequests) { + this.requestsMap.putAll(moreRequests); + this.requests = sortRequests(this.requestsMap); } - } + private void addVariables(Set<Parameter> moreVariables) { + this.variables.addAll(moreVariables); + } + + private List<HTTPRequest> sortRequests(Map<Integer, HTTPRequest> requestsMap) { + return new ArrayList<>(new TreeMap<Integer, HTTPRequest>(requestsMap).values()); + } + } + private final Logger LOGGER = LoggerFactory.getLogger(K6ClientCodegen.class); public static final String PROJECT_NAME = "projectName"; @@ -336,7 +425,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { boolean preserveLeadingParamChar = convertPropertyToBooleanAndWriteBack(PRESERVE_LEADING_PARAM_CHAR); this.setPreserveLeadingParamChar(preserveLeadingParamChar); } - + @Override public void preprocessOpenAPI(OpenAPI openAPI) { super.preprocessOpenAPI(openAPI); @@ -397,17 +486,24 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { } } additionalProperties.put(BASE_URL, baseURL); + + // if data is to be extracted from any of the operations' responses, this has to + // be known prior to executing processing of OpenAPI spec further down + Map<String, DataExtractSubstituteParameter> dataExtractSubstituteParams = getDataExtractSubstituteParameters( + openAPI); - List<HTTPRequestGroup> requestGroups = new ArrayList<>(); + Map<String, HTTPRequestGroup> requestGroups = new HashMap<>(); Set<Parameter> extraParameters = new HashSet<>(); Map<String, Set<Parameter>> pathVariables = new HashMap<>(); for (String path : openAPI.getPaths().keySet()) { - List<HTTPRequest> requests = new ArrayList<>(); + Map<Integer, HTTPRequest> requests = new HashMap<>(); Set<Parameter> variables = new HashSet<>(); + String groupName = path; + for (Map.Entry<PathItem.HttpMethod, Operation> methodOperation : openAPI.getPaths().get(path). - readOperationsMap().entrySet()) { + readOperationsMap().entrySet()) { List<Parameter> httpParams = new ArrayList<>(); List<Parameter> queryParams = new ArrayList<>(); List<Parameter> bodyOrFormParams = new ArrayList<>(); @@ -416,11 +512,33 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { final Operation operation = methodOperation.getValue(); final PathItem.HttpMethod method = methodOperation.getKey(); + OptionalInt operationGroupingOrder = OptionalInt.empty(); + + final CodegenOperation cgOperation = super.fromOperation(path, method.name(), operation, null); + + String operationId = operation.getOperationId(); + + boolean hasRequestBodyExample = false; + + // optionally group and order operations - see `X_OPERATION_GROUPING` K6 vendor + // extension + Optional<OperationGrouping> operationGrouping = extractOperationGrouping(cgOperation); + if (operationGrouping.isPresent()) { + groupName = operationGrouping.get().groupName; + operationGroupingOrder = OptionalInt.of(operationGrouping.get().order); + } for (Map.Entry<String, ApiResponse> resp : operation.getResponses().entrySet()) { String statusData = resp.getKey().equals("default") ? "200" : resp.getKey(); + + // optionally hide given response - see `X_OPERATION_RESPONSE` K6 vendor + // extension + // i.e. in case of multiple 2xx responses, generated script checks only against + // e.g. code 200 responses + boolean hideOperationResponse = shouldHideOperationResponse(resp.getValue()); + int status = Integer.parseInt(statusData); - if (status >= 200 && status < 300) { + if (!hideOperationResponse && (status >= 200 && status < 300)) { k6Checks.add(new k6Check(status, resp.getValue().getDescription())); } } @@ -435,6 +553,12 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { httpParams.add(contentType); RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, operation.getRequestBody()); + + // extract request body example, if present + hasRequestBodyExample = hasRequestBodyExample(requestBody, contentTypeValue); + if (hasRequestBodyExample) { + extractRequestBodyExample(requestBody, contentTypeValue, bodyOrFormParams); + } for (Map.Entry<String, ApiResponse> responseEntry : operation.getResponses().entrySet()) { CodegenResponse r = fromResponse(responseEntry.getKey(), responseEntry.getValue()); @@ -444,31 +568,35 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { imports.add(r.baseType); } } + + // if we have at least one request body example, we do not need to construct these dummies + if (!hasRequestBodyExample) { + List<CodegenParameter> formParameters = fromRequestBodyToFormParameters(requestBody, imports); + for (CodegenParameter parameter : formParameters) { + String reference = ""; + if (parameter.isModel) { + Schema nestedSchema = ModelUtils.getSchema(openAPI, parameter.baseType); + CodegenModel model = fromModel(parameter.paramName, nestedSchema); + reference = generateNestedModelTemplate(model); + if (parameter.dataType.equals("List")) { + reference = "[" + reference + "]"; + } + } - List<CodegenParameter> formParameters = fromRequestBodyToFormParameters(requestBody, imports); - for (CodegenParameter parameter : formParameters) { - String reference = ""; - if (parameter.isModel) { - Schema nestedSchema = ModelUtils.getSchema(openAPI, parameter.baseType); - CodegenModel model = fromModel(parameter.paramName, nestedSchema); - reference = generateNestedModelTemplate(model); - if (parameter.dataType.equals("List")) { - reference = "[" + reference + "]"; + Parameter k6Parameter; + if (parameter.dataType.equals("File")) { + k6Parameter = new Parameter(parameter.paramName, + "http.file(open(\"/path/to/file.bin\", \"b\"), \"test.bin\")"); + } else { + k6Parameter = new Parameter(parameter.paramName, !reference.isEmpty() ? reference + : getDoubleQuotedString(parameter.dataType.toLowerCase(Locale.ROOT))); } - } - Parameter k6Parameter; - if (parameter.dataType.equals("File")) { - k6Parameter = new Parameter(parameter.paramName, - "http.file(open(\"/path/to/file.bin\", \"b\"), \"test.bin\")"); - } else { - k6Parameter = new Parameter(parameter.paramName, !reference.isEmpty() ? reference - : getDoubleQuotedString(parameter.dataType.toLowerCase(Locale.ROOT))); + bodyOrFormParams.add(k6Parameter); } - - bodyOrFormParams.add(k6Parameter); } } + String accepts = getAccept(openAPI, operation); String responseType = getDoubleQuotedString(accepts); @@ -510,29 +638,43 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { } - pathVariables.put(path, variables); + pathVariables.put(groupName, variables); final HTTPParameters params = new HTTPParameters(null, null, httpParams, null, null, null, null, null, responseType.length() > 0 ? responseType : null); assert params.headers != null; - requests.add(new HTTPRequest(method.toString().toLowerCase(Locale.ROOT), path, + + // check if data needs to be extracted from response of this operation + Optional<DataExtractSubstituteParameter> dataExtract = getDataExtractSubstituteParameter( + dataExtractSubstituteParams, operationId); + + // calculate order for this current request + Integer requestOrder = calculateRequestOrder(operationGroupingOrder, requests.size()); + + requests.put(requestOrder, new HTTPRequest(method.toString().toLowerCase(Locale.ROOT), path, queryParams.size() > 0 ? queryParams : null, - bodyOrFormParams.size() > 0 ? new HTTPBody(bodyOrFormParams) : null, - params.headers.size() > 0 ? params : null, k6Checks.size() > 0 ? k6Checks : null)); + bodyOrFormParams.size() > 0 ? new HTTPBody(bodyOrFormParams) : null, hasRequestBodyExample, + params.headers.size() > 0 ? params : null, k6Checks.size() > 0 ? k6Checks : null, + dataExtract.isPresent() ? dataExtract.get() : null)); } - requestGroups.add(new HTTPRequestGroup(path, pathVariables.get(path), requests)); + + addOrUpdateRequestGroup(requestGroups, groupName, pathVariables.get(groupName), requests); } - for (HTTPRequestGroup requestGroup : requestGroups) { + for (HTTPRequestGroup requestGroup : requestGroups.values()) { for (HTTPRequest request : requestGroup.requests) { if (request.path.contains("/{")) { request.path = request.path.replace("/{", "/${"); } } + + // any variables not defined yet but used for subsequent data extraction must be + // initialized + initializeDataExtractSubstituteParameters(dataExtractSubstituteParams, requestGroup); } - additionalProperties.put("requestGroups", requestGroups); + additionalProperties.put("requestGroups", requestGroups.values()); additionalProperties.put("extra", extraParameters); for (String[] supportingTemplateFile : JAVASCRIPT_SUPPORTING_FILES) { @@ -547,7 +689,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { supportingFiles.add(new SupportingFile(templateFile, folder, supportingTemplateFile[1])); } } - + private String generateNestedModelTemplate(CodegenModel model) { StringBuilder reference = new StringBuilder(); int modelEntrySetSize = model.getAllVars().size(); @@ -749,4 +891,277 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { protected Builder<String, Lambda> addMustacheLambdas() { return super.addMustacheLambdas().put("handleParamValue", new ParameterValueLambda()); } + + /** + * We're iterating over paths but grouping requests across paths, therefore + * these need to be aggregated. + * + * @param requestGroups + * @param groupName + * @param variables + * @param requests + */ + private void addOrUpdateRequestGroup(Map<String, HTTPRequestGroup> requestGroups, String groupName, + Set<Parameter> variables, Map<Integer, HTTPRequest> requests) { + if (requestGroups.containsKey(groupName)) { + HTTPRequestGroup existingHTTPRequestGroup = requestGroups.get(groupName); + existingHTTPRequestGroup.addRequests(requests); + existingHTTPRequestGroup.addVariables(variables); + } else { + requestGroups.put(groupName, new HTTPRequestGroup(groupName, variables, requests)); + } + } + + /** + * If `X_OPERATION_DATAEXTRACT` K6 vendor extension is present, extract info + * from it. + * + * @param openAPI + * @return + */ + private Map<String, DataExtractSubstituteParameter> getDataExtractSubstituteParameters(OpenAPI openAPI) { + Map<String, DataExtractSubstituteParameter> dataExtractSubstituteParams = new HashMap<>(); + + for (String path : openAPI.getPaths().keySet()) { + for (Map.Entry<PathItem.HttpMethod, Operation> methodOperation : openAPI.getPaths().get(path) + .readOperationsMap().entrySet()) { + + final PathItem.HttpMethod method = methodOperation.getKey(); + final Operation operation = methodOperation.getValue(); + final CodegenOperation cgOperation = super.fromOperation(path, method.name(), operation, null); + + if (cgOperation.getHasVendorExtensions() + && cgOperation.vendorExtensions.containsKey(X_OPERATION_DATAEXTRACT) + && cgOperation.vendorExtensions.get(X_OPERATION_DATAEXTRACT) instanceof java.util.Map) { + + Optional<DataExtractSubstituteParameter> dataExtractSubstituteParameter = getDataExtractSubstituteParameter( + (Map<?, ?>) cgOperation.vendorExtensions.get(X_OPERATION_DATAEXTRACT)); + + // TODO: add support for extracting data for multiple params + if (dataExtractSubstituteParameter.isPresent()) { + dataExtractSubstituteParams.put(dataExtractSubstituteParameter.get().operationId, + dataExtractSubstituteParameter.get()); + } + } + + } + } + + return dataExtractSubstituteParams; + } + + /** + * Optionally, retrieve information specified in the `X_OPERATION_DATAEXTRACT` + * K6 vendor extension + * + * @param xOperationDataExtractProperties + * @return optional as only returned if all required info is present + */ + private Optional<DataExtractSubstituteParameter> getDataExtractSubstituteParameter( + Map<?, ?> xOperationDataExtractProperties) { + + Optional<String> operationId = Optional.empty(); + Optional<String> valuePath = Optional.empty(); + Optional<String> parameterName = Optional.empty(); + + for (Map.Entry<?, ?> xOperationDataExtractPropertiesEntry : xOperationDataExtractProperties.entrySet()) { + + switch (String.valueOf(xOperationDataExtractPropertiesEntry.getKey())) { + case X_OPERATION_DATAEXTRACT_OPERATION_ID: + operationId = Optional.of(String.valueOf(xOperationDataExtractPropertiesEntry.getValue())); + continue; + + case X_OPERATION_DATAEXTRACT_VALUE_PATH: + valuePath = Optional.of(String.valueOf(xOperationDataExtractPropertiesEntry.getValue())); + continue; + + case X_OPERATION_DATAEXTRACT_PARAMETER_NAME: + parameterName = Optional.of(String.valueOf(xOperationDataExtractPropertiesEntry.getValue())); + continue; + } + } + + if (operationId.isPresent() && valuePath.isPresent() && parameterName.isPresent()) { + return Optional + .of(new DataExtractSubstituteParameter(operationId.get(), valuePath.get(), parameterName.get())); + + } else { + return Optional.empty(); + } + } + + /** + * Optionally, retrieve data extraction properties for given operation + * + * @param dataExtractSubstituteParams + * @param operationId + * @return optional as only returned if present for given operation + */ + private Optional<DataExtractSubstituteParameter> getDataExtractSubstituteParameter( + Map<String, DataExtractSubstituteParameter> dataExtractSubstituteParams, String operationId) { + + return (!dataExtractSubstituteParams.isEmpty() && dataExtractSubstituteParams.containsKey(operationId)) + ? Optional.of(dataExtractSubstituteParams.get(operationId)) + : Optional.empty(); + } + + /** + * Optionally, retrieve information specified in the `X_OPERATION_GROUPING` K6 + * vendor extension + * + * @param cgOperation + * @return optional as only returned if required info is present + */ + private Optional<OperationGrouping> extractOperationGrouping(CodegenOperation cgOperation) { + Optional<OperationGrouping> operationGrouping = Optional.empty(); + + if (cgOperation.getHasVendorExtensions() && cgOperation.vendorExtensions.containsKey(X_OPERATION_GROUPING) + && cgOperation.vendorExtensions.get(X_OPERATION_GROUPING) instanceof java.util.Map) { + + Map.Entry<?, ?> operationGroupingEntry = ((Map<?, ?>) cgOperation.vendorExtensions + .get(X_OPERATION_GROUPING)).entrySet().stream().findFirst().get(); + + return Optional.of(new OperationGrouping(String.valueOf(operationGroupingEntry.getKey()), + Integer.parseInt(String.valueOf(operationGroupingEntry.getValue())))); + } + + return operationGrouping; + } + + /** + * If `X_OPERATION_RESPONSE` K6 vendor extension is present, check if given + * operation response should be hidden. + * + * @param resp + * @return true if should be hidden, false otherwise + */ + private boolean shouldHideOperationResponse(ApiResponse resp) { + boolean hideOperationResponse = false; + + if (Objects.nonNull(resp.getExtensions()) && !resp.getExtensions().isEmpty() + && resp.getExtensions().containsKey(X_OPERATION_RESPONSE)) { + + Map<?, ?> respExtensions = (Map<?, ?>) resp.getExtensions().get(X_OPERATION_RESPONSE); + + for (Map.Entry<?, ?> respExtensionEntry : respExtensions.entrySet()) { + + switch (String.valueOf(respExtensionEntry.getKey())) { + case X_OPERATION_RESPONSE_HIDE: + hideOperationResponse = Boolean.valueOf(respExtensionEntry.getValue().toString()); + continue; + } + } + } + + return hideOperationResponse; + } + + /** + * Check if example is present for given request body and content type. + * + * @param requestBody + * @param contentTypeValue + * @return true if present, false otherwise + */ + private boolean hasRequestBodyExample(RequestBody requestBody, String contentTypeValue) { + return (Objects.nonNull(requestBody.getContent()) && requestBody.getContent().containsKey(contentTypeValue) + && Objects.nonNull(requestBody.getContent().get(contentTypeValue).getExamples()) + && !requestBody.getContent().get(contentTypeValue).getExamples().isEmpty()); + } + + /** + * Extract example for given request body. + * + * @param requestBody + * @param contentTypeValue + * @param bodyOrFormParams + */ + private void extractRequestBodyExample(RequestBody requestBody, String contentTypeValue, + List<Parameter> bodyOrFormParams) { + + Optional<Map.Entry<String, Example>> requestBodyExampleEntry = requestBody.getContent().get(contentTypeValue) + .getExamples().entrySet().stream().findFirst(); + + if (requestBodyExampleEntry.isPresent()) { + + Example requestBodyExample = requestBodyExampleEntry.get().getValue(); + + try { + JsonNode requestBodyExampleValueJsonNode = Json.mapper() + .readTree(String.valueOf(requestBodyExample.getValue())); + + Iterator<Map.Entry<String, JsonNode>> fields = requestBodyExampleValueJsonNode.fields(); + while (fields.hasNext()) { + Map.Entry<String, JsonNode> fieldsEntry = fields.next(); + + JsonNode exampleValueAsJsonNode = fieldsEntry.getValue(); + + Parameter k6Parameter = new Parameter(fieldsEntry.getKey(), + exampleValueAsJsonNode.isNumber() ? exampleValueAsJsonNode.asText() + : exampleValueAsJsonNode.toString()); + + bodyOrFormParams.add(k6Parameter); + } + + } catch (JsonProcessingException e) { + LOGGER.error(e.getMessage(), e); + } + } + } + + /** + * Calculate order for this current request + * + * @param operationGroupingOrder + * @param requests + * @return request order + */ + private Integer calculateRequestOrder(OptionalInt operationGroupingOrder, int requestsSize) { + int requestOrder = 0; + + if (operationGroupingOrder.isPresent()) { + requestOrder = Integer.valueOf(operationGroupingOrder.getAsInt() - 1); + + } else { + switch (requestsSize) { + case 0: + case 1: + requestOrder = requestsSize; + break; + + default: + requestOrder = (requestsSize - 1); + break; + } + } + + return Integer.valueOf(requestOrder); + } + + // + /** + * Any variables not defined yet but used for subsequent data extraction must be + * initialized + * + * @param dataExtractSubstituteParams + * @param requestGroup + */ + private void initializeDataExtractSubstituteParameters( + Map<String, DataExtractSubstituteParameter> dataExtractSubstituteParams, HTTPRequestGroup requestGroup) { + + if (!dataExtractSubstituteParams.isEmpty()) { + List<String> existingVariablesNames = requestGroup.variables.stream().map(v -> v.key) + .collect(Collectors.toList()); + + Set<DataExtractSubstituteParameter> initializeVariables = dataExtractSubstituteParams.values().stream() + .filter(p -> !existingVariablesNames.contains(toVarName(p.paramName))).collect(Collectors.toSet()); + + if (!initializeVariables.isEmpty()) { + for (DataExtractSubstituteParameter initializeVariable : initializeVariables) { + requestGroup.variables.add(new Parameter(toVarName(initializeVariable.paramName), true)); + } + } + } + } + } diff --git a/modules/openapi-generator/src/main/resources/k6/script.mustache b/modules/openapi-generator/src/main/resources/k6/script.mustache index cac3381de01..4138e10a029 100644 --- a/modules/openapi-generator/src/main/resources/k6/script.mustache +++ b/modules/openapi-generator/src/main/resources/k6/script.mustache @@ -19,47 +19,52 @@ export default function() { let {{{key}}} = {{#lambda.handleParamValue}}{{value}}{{/lambda.handleParamValue}} {{/variables}} {{#requests}} - {{#-first}} - let url = BASE_URL + `{{{path}}}{{=<% %>=}}<%#query%><%#-first%>?<%/-first%><%& key%>=<%& value%><%^-last%>&<%/-last%><%/query%><%={{ }}=%>`; + // Request No. {{-index}} - {{#body}} - // TODO: edit the parameters of the request body. - let body = {{#body}}{{=<% %>=}}{<%#parameters%>"<%& key%>": <%& value%><%^-last%>, <%/-last%><%/parameters%>}<%={{ }}=%>{{/body}}; - {{/body}} - {{#params}} - let params = {{#params}}{{=<% %>=}}{headers: {<%# headers%>"<%& key%>": <%& value%><%^-last%>, <%/-last%><%/headers%><%#responseType%>, "Accept": <%& responseType%><%/responseType%>}<%# auth%>, auth: "<%& auth%>"<%/auth%>}<%={{ }}=%>{{/params}}; - {{/params}} - let request = http.{{method}}(url{{#body}}, body{{/body}}{{#params}}, params{{/params}}); - {{#k6Checks}} - {{=<% %>=}} - check(request, { + { + let url = BASE_URL + `{{{path}}}{{=<% %>=}}<%#query%><%#-first%>?<%/-first%><%& key%>=<%& value%><%^-last%>&<%/-last%><%/query%><%={{ }}=%>`; + {{#body}} + {{^hasBodyExample}} + // TODO: edit the parameters of the request body. + {{/hasBodyExample}} + let body = {{#body}}{{=<% %>=}}{<%#parameters%>"<%& key%>": <%& value%><%^-last%>, <%/-last%><%/parameters%>}<%={{ }}=%>{{/body}}; + {{/body}} + + {{#params}} + let params = {{#params}}{{=<% %>=}}{headers: {<%# headers%>"<%& key%>": <%& value%><%^-last%>, <%/-last%><%/headers%><%#responseType%>, "Accept": <%& responseType%><%/responseType%>}<%# auth%>, auth: "<%& auth%>"<%/auth%>}<%={{ }}=%>{{/params}}; + {{/params}} + + {{#isDelete}} + {{#params}} + // this is a DELETE method request - if params are also set, empty body must be passed + let request = http.{{method}}(url, {} {{#params}}, params{{/params}}); + {{/params}} + {{^params}} + let request = http.{{method}}(url); + {{/params}} + {{/isDelete}} + + {{^isDelete}} + let request = http.{{method}}(url{{#body}}, JSON.stringify(body){{/body}}{{#params}}, params{{/params}}); + {{/isDelete}} + + {{#k6Checks}} + {{=<% %>=}} + check(request, { "<%& description%>": (r) => r.status === <%& status%> - }); - <%={{ }}=%> - {{/k6Checks}} - {{/-first}} - {{^-first}} - // Request No. {{-index}} - {{#body}} - // TODO: edit the parameters of the request body. - body = {{#body}}{{=<% %>=}}{<%#parameters%>"<%& key%>": <%& value%><%^-last%>, <%/-last%><%/parameters%>}<%={{ }}=%>{{/body}}; - {{/body}} - {{#params}} - params = {{#params}}{{=<% %>=}}{headers: {<%# headers%>"<%& key%>": <%& value%><%^-last%>, <%/-last%><%/headers%>}<%# auth%>, auth: "<%& auth%>"<%/auth%>}<%={{ }}=%>{{/params}}; - {{/params}} - request = http.{{method}}(url{{#body}}, body{{/body}}{{#params}}, params{{/params}}); - {{#k6Checks}} - {{=<% %>=}} - check(request, { - "<%& description%>": (r) => r.status === <%& status%> - }); - <%={{ }}=%> - {{/k6Checks}} - {{/-first}} - sleep(SLEEP_DURATION); - {{^-last}} - - {{/-last}} + }); + <%={{ }}=%> + {{/k6Checks}} + + {{#dataExtract}} + {{{paramName}}} = JSON.parse(request.body).{{{valuePath}}}; // extract data for subsequent use + {{/dataExtract}} + + {{^-last}} + sleep(SLEEP_DURATION); + {{/-last}} + } + {{/requests}} }); {{/requestGroups}} -- GitLab From 809daddf5f5c0fe3962a09864fc9b2d01188ea13 Mon Sep 17 00:00:00 2001 From: "Michael H. Siemaszko" <mhs@into.software> Date: Sun, 17 Oct 2021 20:16:01 +0200 Subject: [PATCH 02/13] Further K6 OpenAPI generator enhancements - regenerated samples Signed-off-by: Michael H. Siemaszko <mhs@into.software> --- .../petstore/k6/.openapi-generator/FILES | 2 + samples/client/petstore/k6/script.js | 417 ++++++++++++------ 2 files changed, 287 insertions(+), 132 deletions(-) create mode 100644 samples/client/petstore/k6/.openapi-generator/FILES diff --git a/samples/client/petstore/k6/.openapi-generator/FILES b/samples/client/petstore/k6/.openapi-generator/FILES new file mode 100644 index 00000000000..343cd1bd1f8 --- /dev/null +++ b/samples/client/petstore/k6/.openapi-generator/FILES @@ -0,0 +1,2 @@ +README.md +script.js diff --git a/samples/client/petstore/k6/script.js b/samples/client/petstore/k6/script.js index 6988d6417da..966e67a6132 100644 --- a/samples/client/petstore/k6/script.js +++ b/samples/client/petstore/k6/script.js @@ -23,182 +23,335 @@ let apiKey = "TODO_EDIT_THE_API_KEY"; export default function() { group("/pet", () => { - let url = BASE_URL + `/pet`; + // Request No. 1 - // TODO: edit the parameters of the request body. - let body = {"id": "long", "category": {"id": "long", "name": "string"}, "name": "string", "photoUrls": "list", "tags": [{"id": "long", "name": "string"}], "status": "string"}; - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - let request = http.put(url, body, params); - sleep(SLEEP_DURATION); - + { + let url = BASE_URL + `/pet`; + // TODO: edit the parameters of the request body. + let body = {"id": "long", "category": {"id": "long", "name": "string"}, "name": "string", "photoUrls": "list", "tags": "list", "status": "string"}; + + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + + + let request = http.put(url, JSON.stringify(body), params); + + + + sleep(SLEEP_DURATION); + } + + // Request No. 2 - // TODO: edit the parameters of the request body. - body = {"id": "long", "category": {"id": "long", "name": "string"}, "name": "string", "photoUrls": "list", "tags": [{"id": "long", "name": "string"}], "status": "string"}; - params = {headers: {"Content-Type": "application/json"}}; - request = http.post(url, body, params); - sleep(SLEEP_DURATION); + { + let url = BASE_URL + `/pet`; + // TODO: edit the parameters of the request body. + let body = {"id": "long", "category": {"id": "long", "name": "string"}, "name": "string", "photoUrls": "list", "tags": "list", "status": "string"}; + + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + + + let request = http.post(url, JSON.stringify(body), params); + + + + } + }); - group("/pet/findByStatus", () => { - let status = 'TODO_EDIT_THE_STATUS'; // specify value as there is no example value for this parameter in OpenAPI spec - let url = BASE_URL + `/pet/findByStatus?status=${status}`; + group("/user/{username}", () => { + let username = 'TODO_EDIT_THE_USERNAME'; // specify value as there is no example value for this parameter in OpenAPI spec + // Request No. 1 - let request = http.get(url); - check(request, { + { + let url = BASE_URL + `/user/${username}`; + + + + let request = http.get(url); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); + }); + + + sleep(SLEEP_DURATION); + } + + + // Request No. 2 + { + let url = BASE_URL + `/user/${username}`; + + + let request = http.del(url); + + + + + } + }); - group("/pet/findByTags", () => { - let tags = 'TODO_EDIT_THE_TAGS'; // specify value as there is no example value for this parameter in OpenAPI spec - let url = BASE_URL + `/pet/findByTags?tags=${tags}`; + group("/pet/findByStatus", () => { + let status = 'TODO_EDIT_THE_STATUS'; // specify value as there is no example value for this parameter in OpenAPI spec + // Request No. 1 - let request = http.get(url); - check(request, { + { + let url = BASE_URL + `/pet/findByStatus?status=${status}`; + + + + let request = http.get(url); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); + }); + + + } + }); - group("/pet/{petId}", () => { - let petId = 'TODO_EDIT_THE_PETID'; // specify value as there is no example value for this parameter in OpenAPI spec - let url = BASE_URL + `/pet/${petId}`; + group("/user/createWithList", () => { + // Request No. 1 - let request = http.get(url); - check(request, { + { + let url = BASE_URL + `/user/createWithList`; + + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + + + let request = http.post(url, params); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); - - // Request No. 2 - // TODO: edit the parameters of the request body. - body = {"name": "string", "status": "string"}; - params = {headers: {"Content-Type": "application/x-www-form-urlencoded"}}; - request = http.post(url, body, params); - sleep(SLEEP_DURATION); - - // Request No. 3 - params = {headers: {"api_key": `${apiKey}`}}; - request = http.del(url, params); - sleep(SLEEP_DURATION); + }); + + + } + }); group("/pet/{petId}/uploadImage", () => { let petId = 'TODO_EDIT_THE_PETID'; // specify value as there is no example value for this parameter in OpenAPI spec - let url = BASE_URL + `/pet/${petId}/uploadImage`; + // Request No. 1 - // TODO: edit the parameters of the request body. - let body = {"additionalMetadata": "string", "file": http.file(open("/path/to/file.bin", "b"), "test.bin")}; - let params = {headers: {"Content-Type": "multipart/form-data", "Accept": "application/json"}}; - let request = http.post(url, body, params); - check(request, { + { + let url = BASE_URL + `/pet/${petId}/uploadImage`; + // TODO: edit the parameters of the request body. + let body = {"additionalMetadata": "string", "file": http.file(open("/path/to/file.bin", "b"), "test.bin")}; + + let params = {headers: {"Content-Type": "multipart/form-data", "Accept": "application/json"}}; + + + let request = http.post(url, JSON.stringify(body), params); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); + }); + + + } + }); group("/store/inventory", () => { - let url = BASE_URL + `/store/inventory`; + // Request No. 1 - let request = http.get(url); - check(request, { + { + let url = BASE_URL + `/store/inventory`; + + + + let request = http.get(url); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); + }); + + + } + }); - group("/store/order", () => { - let url = BASE_URL + `/store/order`; - // Request No. 1 - // TODO: edit the parameters of the request body. - let body = {"id": "long", "petId": "long", "quantity": "integer", "shipDate": "date", "status": "string", "complete": "boolean"}; - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - let request = http.post(url, body, params); - check(request, { - "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); - }); - group("/store/order/{orderId}", () => { - let orderId = 'TODO_EDIT_THE_ORDERID'; // specify value as there is no example value for this parameter in OpenAPI spec - let url = BASE_URL + `/store/order/${orderId}`; + group("/user/login", () => { + let password = 'TODO_EDIT_THE_PASSWORD'; // specify value as there is no example value for this parameter in OpenAPI spec + let username = 'TODO_EDIT_THE_USERNAME'; // specify value as there is no example value for this parameter in OpenAPI spec + // Request No. 1 - let request = http.get(url); - check(request, { + { + let url = BASE_URL + `/user/login?username=${username}&password=${password}`; + + + + let request = http.get(url); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); - - // Request No. 2 - request = http.del(url); - sleep(SLEEP_DURATION); + }); + + + } + }); group("/user", () => { - let url = BASE_URL + `/user`; + // Request No. 1 - // TODO: edit the parameters of the request body. - let body = {"id": "long", "username": "string", "firstName": "string", "lastName": "string", "email": "string", "password": "string", "phone": "string", "userStatus": "integer"}; - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - let request = http.post(url, body, params); - check(request, { + { + let url = BASE_URL + `/user`; + // TODO: edit the parameters of the request body. + let body = {"id": "long", "username": "string", "firstName": "string", "lastName": "string", "email": "string", "password": "string", "phone": "string", "userStatus": "integer"}; + + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + + + let request = http.post(url, JSON.stringify(body), params); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); + }); + + + } + }); group("/user/createWithArray", () => { - let url = BASE_URL + `/user/createWithArray`; + // Request No. 1 - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - let request = http.post(url, params); - check(request, { + { + let url = BASE_URL + `/user/createWithArray`; + + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + + + let request = http.post(url, params); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); + }); + + + } + }); - group("/user/createWithList", () => { - let url = BASE_URL + `/user/createWithList`; + group("/pet/findByTags", () => { + let tags = 'TODO_EDIT_THE_TAGS'; // specify value as there is no example value for this parameter in OpenAPI spec + // Request No. 1 - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - let request = http.post(url, params); - check(request, { + { + let url = BASE_URL + `/pet/findByTags?tags=${tags}`; + + + + let request = http.get(url); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); + }); + + + } + }); - group("/user/login", () => { - let password = 'TODO_EDIT_THE_PASSWORD'; // specify value as there is no example value for this parameter in OpenAPI spec - let username = 'TODO_EDIT_THE_USERNAME'; // specify value as there is no example value for this parameter in OpenAPI spec - let url = BASE_URL + `/user/login?username=${username}&password=${password}`; + group("/store/order", () => { + // Request No. 1 - let request = http.get(url); - check(request, { + { + let url = BASE_URL + `/store/order`; + // TODO: edit the parameters of the request body. + let body = {"id": "long", "petId": "long", "quantity": "integer", "shipDate": "date", "status": "string", "complete": "boolean"}; + + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + + + let request = http.post(url, JSON.stringify(body), params); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); + }); + + + } + }); group("/user/logout", () => { - let url = BASE_URL + `/user/logout`; + // Request No. 1 - let request = http.get(url); - check(request, { + { + let url = BASE_URL + `/user/logout`; + + + + let request = http.get(url); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); + }); + + + } + }); - group("/user/{username}", () => { - let username = 'TODO_EDIT_THE_USERNAME'; // specify value as there is no example value for this parameter in OpenAPI spec - let url = BASE_URL + `/user/${username}`; + group("/pet/{petId}", () => { + let petId = 'TODO_EDIT_THE_PETID'; // specify value as there is no example value for this parameter in OpenAPI spec + // Request No. 1 - let request = http.get(url); - check(request, { + { + let url = BASE_URL + `/pet/${petId}`; + + + + let request = http.get(url); + + check(request, { "successful operation": (r) => r.status === 200 - }); - sleep(SLEEP_DURATION); - + }); + + + sleep(SLEEP_DURATION); + } + + // Request No. 2 - // TODO: edit the parameters of the request body. - body = {"id": "long", "username": "string", "firstName": "string", "lastName": "string", "email": "string", "password": "string", "phone": "string", "userStatus": "integer"}; - params = {headers: {"Content-Type": "application/json"}}; - request = http.put(url, body, params); - sleep(SLEEP_DURATION); - - // Request No. 3 - request = http.del(url); - sleep(SLEEP_DURATION); + { + let url = BASE_URL + `/pet/${petId}`; + + let params = {headers: {"api_key": `${apiKey}`, "Accept": "application/json"}}; + + // this is a DELETE method request - if params are also set, empty body must be passed + let request = http.del(url, {} , params); + + + + + } + + }); + group("/store/order/{orderId}", () => { + let orderId = 'TODO_EDIT_THE_ORDERID'; // specify value as there is no example value for this parameter in OpenAPI spec + + // Request No. 1 + { + let url = BASE_URL + `/store/order/${orderId}`; + + + + let request = http.get(url); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + + + sleep(SLEEP_DURATION); + } + + + // Request No. 2 + { + let url = BASE_URL + `/store/order/${orderId}`; + + + let request = http.del(url); + + + + + } + }); } -- GitLab From 66dc3ed72fa2203e3814df1510c2e4114437461d Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafa@loadimpact.com> Date: Tue, 7 Dec 2021 13:11:16 +0100 Subject: [PATCH 03/13] Fix suggested changes by linter --- .../codegen/languages/K6ClientCodegen.java | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java index df3739a0154..dedd1d26ec3 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java @@ -198,7 +198,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { .map(x -> quoteExample( StringEscapeUtils.escapeEcmaScript( String.valueOf(x.getValue())))) - .collect(Collectors.toCollection(() -> new TreeSet<String>())); + .collect(Collectors.toCollection(TreeSet::new)); if (!exampleValues.isEmpty()) { @@ -316,7 +316,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { DataExtractSubstituteParameter dataExtract) { // NOTE: https://k6.io/docs/javascript-api/k6-http/del-url-body-params this.method = method.equals("delete") ? "del" : method; - this.isDelete = method.equals("delete") ? true : false; + this.isDelete = method.equals("delete"); this.path = path; this.query = query; this.body = body; @@ -331,7 +331,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { String groupName; Set<Parameter> variables; // query and path parameters List<HTTPRequest> requests; - private Map<Integer, HTTPRequest> requestsMap; + private final Map<Integer, HTTPRequest> requestsMap; public HTTPRequestGroup(String groupName, Set<Parameter> variables, Map<Integer, HTTPRequest> requestsMap) { this.groupName = groupName; @@ -350,7 +350,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { } private List<HTTPRequest> sortRequests(Map<Integer, HTTPRequest> requestsMap) { - return new ArrayList<>(new TreeMap<Integer, HTTPRequest>(requestsMap).values()); + return new ArrayList<>(new TreeMap<>(requestsMap).values()); } } @@ -508,7 +508,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { List<Parameter> queryParams = new ArrayList<>(); List<Parameter> bodyOrFormParams = new ArrayList<>(); List<k6Check> k6Checks = new ArrayList<>(); - Set<String> imports = new HashSet<String>(); + Set<String> imports = new HashSet<>(); final Operation operation = methodOperation.getValue(); final PathItem.HttpMethod method = methodOperation.getKey(); @@ -546,7 +546,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { if (hasBodyParameter(openAPI, operation) || hasFormParameter(openAPI, operation)) { String defaultContentType = hasFormParameter(openAPI, operation) ? "application/x-www-form-urlencoded" : "application/json"; List<String> consumes = new ArrayList<>(getConsumesInfo(openAPI, operation)); - String contentTypeValue = consumes == null || consumes.isEmpty() ? defaultContentType : consumes.get(0); + String contentTypeValue = consumes.isEmpty() ? defaultContentType : consumes.get(0); if (contentTypeValue.equals("*/*")) contentTypeValue = "application/json"; Parameter contentType = new Parameter("Content-Type", getDoubleQuotedString(contentTypeValue)); @@ -634,7 +634,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { break; } } - } catch (NullPointerException e) { + } catch (NullPointerException ignored) { } @@ -656,7 +656,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { queryParams.size() > 0 ? queryParams : null, bodyOrFormParams.size() > 0 ? new HTTPBody(bodyOrFormParams) : null, hasRequestBodyExample, params.headers.size() > 0 ? params : null, k6Checks.size() > 0 ? k6Checks : null, - dataExtract.isPresent() ? dataExtract.get() : null)); + dataExtract.orElse(null))); } addOrUpdateRequestGroup(requestGroups, groupName, pathVariables.get(groupName), requests); @@ -938,10 +938,8 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { (Map<?, ?>) cgOperation.vendorExtensions.get(X_OPERATION_DATAEXTRACT)); // TODO: add support for extracting data for multiple params - if (dataExtractSubstituteParameter.isPresent()) { - dataExtractSubstituteParams.put(dataExtractSubstituteParameter.get().operationId, - dataExtractSubstituteParameter.get()); - } + dataExtractSubstituteParameter.ifPresent(extractSubstituteParameter -> dataExtractSubstituteParams.put(extractSubstituteParameter.operationId, + extractSubstituteParameter)); } } @@ -977,7 +975,6 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { case X_OPERATION_DATAEXTRACT_PARAMETER_NAME: parameterName = Optional.of(String.valueOf(xOperationDataExtractPropertiesEntry.getValue())); - continue; } } @@ -1045,10 +1042,8 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { for (Map.Entry<?, ?> respExtensionEntry : respExtensions.entrySet()) { - switch (String.valueOf(respExtensionEntry.getKey())) { - case X_OPERATION_RESPONSE_HIDE: - hideOperationResponse = Boolean.valueOf(respExtensionEntry.getValue().toString()); - continue; + if (X_OPERATION_RESPONSE_HIDE.equals(String.valueOf(respExtensionEntry.getKey()))) { + hideOperationResponse = Boolean.parseBoolean(respExtensionEntry.getValue().toString()); } } } @@ -1113,14 +1108,14 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { * Calculate order for this current request * * @param operationGroupingOrder - * @param requests + * @param requestsSize * @return request order */ private Integer calculateRequestOrder(OptionalInt operationGroupingOrder, int requestsSize) { - int requestOrder = 0; + int requestOrder; if (operationGroupingOrder.isPresent()) { - requestOrder = Integer.valueOf(operationGroupingOrder.getAsInt() - 1); + requestOrder = operationGroupingOrder.getAsInt() - 1; } else { switch (requestsSize) { @@ -1135,7 +1130,7 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { } } - return Integer.valueOf(requestOrder); + return requestOrder; } // -- GitLab From a79d0c7a3f1ef99139605fa5b39fc9ce341b2623 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafa@loadimpact.com> Date: Tue, 7 Dec 2021 14:37:13 +0100 Subject: [PATCH 04/13] Fix extra spaces in the template --- .../src/main/resources/k6/script.mustache | 83 +++++++++---------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/k6/script.mustache b/modules/openapi-generator/src/main/resources/k6/script.mustache index 4138e10a029..ed5269a4fec 100644 --- a/modules/openapi-generator/src/main/resources/k6/script.mustache +++ b/modules/openapi-generator/src/main/resources/k6/script.mustache @@ -19,53 +19,50 @@ export default function() { let {{{key}}} = {{#lambda.handleParamValue}}{{value}}{{/lambda.handleParamValue}} {{/variables}} {{#requests}} - + // Request No. {{-index}} { - let url = BASE_URL + `{{{path}}}{{=<% %>=}}<%#query%><%#-first%>?<%/-first%><%& key%>=<%& value%><%^-last%>&<%/-last%><%/query%><%={{ }}=%>`; - {{#body}} - {{^hasBodyExample}} - // TODO: edit the parameters of the request body. - {{/hasBodyExample}} - let body = {{#body}}{{=<% %>=}}{<%#parameters%>"<%& key%>": <%& value%><%^-last%>, <%/-last%><%/parameters%>}<%={{ }}=%>{{/body}}; - {{/body}} - - {{#params}} - let params = {{#params}}{{=<% %>=}}{headers: {<%# headers%>"<%& key%>": <%& value%><%^-last%>, <%/-last%><%/headers%><%#responseType%>, "Accept": <%& responseType%><%/responseType%>}<%# auth%>, auth: "<%& auth%>"<%/auth%>}<%={{ }}=%>{{/params}}; - {{/params}} - - {{#isDelete}} - {{#params}} - // this is a DELETE method request - if params are also set, empty body must be passed - let request = http.{{method}}(url, {} {{#params}}, params{{/params}}); - {{/params}} - {{^params}} - let request = http.{{method}}(url); - {{/params}} - {{/isDelete}} - - {{^isDelete}} - let request = http.{{method}}(url{{#body}}, JSON.stringify(body){{/body}}{{#params}}, params{{/params}}); - {{/isDelete}} - - {{#k6Checks}} - {{=<% %>=}} - check(request, { - "<%& description%>": (r) => r.status === <%& status%> - }); - <%={{ }}=%> - {{/k6Checks}} - - {{#dataExtract}} - {{{paramName}}} = JSON.parse(request.body).{{{valuePath}}}; // extract data for subsequent use - {{/dataExtract}} - - {{^-last}} - sleep(SLEEP_DURATION); - {{/-last}} + let url = BASE_URL + `{{{path}}}{{=<% %>=}}<%#query%><%#-first%>?<%/-first%><%& key%>=<%& value%><%^-last%>&<%/-last%><%/query%><%={{ }}=%>`; + {{#body}} + {{^hasBodyExample}} + // TODO: edit the parameters of the request body. + {{/hasBodyExample}} + let body = {{#body}}{{=<% %>=}}{<%#parameters%>"<%& key%>": <%& value%><%^-last%>, <%/-last%><%/parameters%>}<%={{ }}=%>{{/body}}; + {{/body}} + {{#params}} + let params = {{#params}}{{=<% %>=}}{headers: {<%# headers%>"<%& key%>": <%& value%><%^-last%>, <%/-last%><%/headers%><%#responseType%>, "Accept": <%& responseType%><%/responseType%>}<%# auth%>, auth: "<%& auth%>"<%/auth%>}<%={{ }}=%>{{/params}}; + {{/params}} + {{#isDelete}} + {{#params}} + // this is a DELETE method request - if params are also set, empty body must be passed + let request = http.{{method}}(url, {} {{#params}}, params{{/params}}); + {{/params}} + {{^params}} + let request = http.{{method}}(url); + {{/params}} + {{/isDelete}} + {{^isDelete}} + let request = http.{{method}}(url{{#body}}, JSON.stringify(body){{/body}}{{#params}}, params{{/params}}); + {{/isDelete}} + + {{#k6Checks}} + {{=<% %>=}} + check(request, { + "<%& description%>": (r) => r.status === <%& status%> + }); + <%={{ }}=%> + {{/k6Checks}} + {{#dataExtract}} + + {{{paramName}}} = JSON.parse(request.body).{{{valuePath}}}; // extract data for subsequent use + {{/dataExtract}} + {{^-last}} + + sleep(SLEEP_DURATION); + {{/-last}} } - {{/requests}} }); + {{/requestGroups}} } -- GitLab From 5d281808d964b078ee187c4cad7ee1fb9d76c995 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafa@loadimpact.com> Date: Tue, 14 Dec 2021 10:19:25 +0100 Subject: [PATCH 05/13] Log exception --- .../org/openapitools/codegen/languages/K6ClientCodegen.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java index 6f3cef5b285..64d086156df 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java @@ -634,8 +634,8 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { break; } } - } catch (NullPointerException ignored) { - + } catch (NullPointerException e) { + LOGGER.error(e.getMessage(), e); } pathVariables.put(groupName, variables); -- GitLab From d9e10b8ef3f358baefa09a89d1900eb7924ced1f Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafa@loadimpact.com> Date: Tue, 14 Dec 2021 10:21:17 +0100 Subject: [PATCH 06/13] Rename function signature to camelCase --- .../codegen/CodegenOperation.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java index 943b23772ca..ca0cca500cd 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenOperation.java @@ -66,11 +66,11 @@ public class CodegenOperation { * * @return true if parameter exists, false otherwise */ - private static boolean nonempty(List<?> params) { + private static boolean nonEmpty(List<?> params) { return params != null && params.size() > 0; } - private static boolean nonempty(Map<?, ?> params) { + private static boolean nonEmpty(Map<?, ?> params) { return params != null && params.size() > 0; } @@ -80,7 +80,7 @@ public class CodegenOperation { * @return true if body parameter exists, false otherwise */ public boolean getHasBodyParam() { - return nonempty(bodyParams); + return nonEmpty(bodyParams); } /** @@ -89,7 +89,7 @@ public class CodegenOperation { * @return true if query parameter exists, false otherwise */ public boolean getHasQueryParams() { - return nonempty(queryParams); + return nonEmpty(queryParams); } /** @@ -107,7 +107,7 @@ public class CodegenOperation { * @return true if header parameter exists, false otherwise */ public boolean getHasHeaderParams() { - return nonempty(headerParams); + return nonEmpty(headerParams); } /** @@ -116,7 +116,7 @@ public class CodegenOperation { * @return true if path parameter exists, false otherwise */ public boolean getHasPathParams() { - return nonempty(pathParams); + return nonEmpty(pathParams); } /** @@ -125,7 +125,7 @@ public class CodegenOperation { * @return true if any form parameter exists, false otherwise */ public boolean getHasFormParams() { - return nonempty(formParams); + return nonEmpty(formParams); } /** @@ -143,7 +143,7 @@ public class CodegenOperation { * @return true if any cookie parameter exists, false otherwise */ public boolean getHasCookieParams() { - return nonempty(cookieParams); + return nonEmpty(cookieParams); } /** @@ -152,7 +152,7 @@ public class CodegenOperation { * @return true if any optional parameter exists, false otherwise */ public boolean getHasOptionalParams() { - return nonempty(optionalParams); + return nonEmpty(optionalParams); } /** @@ -161,7 +161,7 @@ public class CodegenOperation { * @return true if any optional parameter exists, false otherwise */ public boolean getHasRequiredParams() { - return nonempty(requiredParams); + return nonEmpty(requiredParams); } /** @@ -170,7 +170,7 @@ public class CodegenOperation { * @return true if header response exists, false otherwise */ public boolean getHasResponseHeaders() { - return nonempty(responseHeaders); + return nonEmpty(responseHeaders); } /** @@ -179,7 +179,7 @@ public class CodegenOperation { * @return true if examples parameter exists, false otherwise */ public boolean getHasExamples() { - return nonempty(examples); + return nonEmpty(examples); } /** @@ -197,7 +197,7 @@ public class CodegenOperation { * @return true if vendor extensions exists, false otherwise */ public boolean getHasVendorExtensions() { - return nonempty(vendorExtensions); + return nonEmpty(vendorExtensions); } /** -- GitLab From 6e106dff1ce7c8eacd932b025715c5479ee8b1d8 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafa@loadimpact.com> Date: Tue, 14 Dec 2021 10:34:45 +0100 Subject: [PATCH 07/13] Address comments on Big-O --- .../codegen/languages/K6ClientCodegen.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java index 64d086156df..237285eeb52 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java @@ -1145,16 +1145,14 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { Map<String, DataExtractSubstituteParameter> dataExtractSubstituteParams, HTTPRequestGroup requestGroup) { if (!dataExtractSubstituteParams.isEmpty()) { - List<String> existingVariablesNames = requestGroup.variables.stream().map(v -> v.key) - .collect(Collectors.toList()); + Set<String> existingVariablesNames = requestGroup.variables.stream().map(v -> v.key) + .collect(Collectors.toSet()); Set<DataExtractSubstituteParameter> initializeVariables = dataExtractSubstituteParams.values().stream() .filter(p -> !existingVariablesNames.contains(toVarName(p.paramName))).collect(Collectors.toSet()); - if (!initializeVariables.isEmpty()) { - for (DataExtractSubstituteParameter initializeVariable : initializeVariables) { - requestGroup.variables.add(new Parameter(toVarName(initializeVariable.paramName), true)); - } + for (DataExtractSubstituteParameter initializeVariable : initializeVariables) { + requestGroup.variables.add(new Parameter(toVarName(initializeVariable.paramName), true)); } } } -- GitLab From 4cb1819a04cba8dfa2ebf37b4a65478f038116ab Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafa@loadimpact.com> Date: Tue, 14 Dec 2021 11:26:57 +0100 Subject: [PATCH 08/13] Move declaration of variable near the usage --- .../org/openapitools/codegen/languages/K6ClientCodegen.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java index 237285eeb52..253f1f6b972 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java @@ -514,14 +514,13 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { final PathItem.HttpMethod method = methodOperation.getKey(); OptionalInt operationGroupingOrder = OptionalInt.empty(); - final CodegenOperation cgOperation = super.fromOperation(path, method.name(), operation, null); - String operationId = operation.getOperationId(); boolean hasRequestBodyExample = false; // optionally group and order operations - see `X_OPERATION_GROUPING` K6 vendor // extension + final CodegenOperation cgOperation = super.fromOperation(path, method.name(), operation, null); Optional<OperationGrouping> operationGrouping = extractOperationGrouping(cgOperation); if (operationGrouping.isPresent()) { groupName = operationGrouping.get().groupName; -- GitLab From fd19b3324a379c309a284b9cbe0ea203dc7d1709 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafa@loadimpact.com> Date: Tue, 14 Dec 2021 11:36:29 +0100 Subject: [PATCH 09/13] Add config file for generating k6 script --- bin/configs/k6.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 bin/configs/k6.yaml diff --git a/bin/configs/k6.yaml b/bin/configs/k6.yaml new file mode 100644 index 00000000000..9933744e314 --- /dev/null +++ b/bin/configs/k6.yaml @@ -0,0 +1,6 @@ +generatorName: k6 +outputDir: samples/client/petstore/k6 +inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml +templateDir: modules/openapi-generator/src/main/resources/k6 +additionalProperties: + appName: PetstoreClient -- GitLab From a42d924c5e4ba1867b753bf4778b437da82724fa Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafa@loadimpact.com> Date: Tue, 14 Dec 2021 11:36:43 +0100 Subject: [PATCH 10/13] Regenerate k6 script --- .../petstore/k6/.openapi-generator/VERSION | 2 +- samples/client/petstore/k6/script.js | 775 +++++++++++------- 2 files changed, 498 insertions(+), 279 deletions(-) diff --git a/samples/client/petstore/k6/.openapi-generator/VERSION b/samples/client/petstore/k6/.openapi-generator/VERSION index 4b448de535c..4077803655c 100644 --- a/samples/client/petstore/k6/.openapi-generator/VERSION +++ b/samples/client/petstore/k6/.openapi-generator/VERSION @@ -1 +1 @@ -5.3.0-SNAPSHOT \ No newline at end of file +5.3.1-SNAPSHOT \ No newline at end of file diff --git a/samples/client/petstore/k6/script.js b/samples/client/petstore/k6/script.js index 966e67a6132..7ae1bf14532 100644 --- a/samples/client/petstore/k6/script.js +++ b/samples/client/petstore/k6/script.js @@ -1,357 +1,576 @@ /* * OpenAPI Petstore - * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ * * OpenAPI spec version: 1.0.0 * * NOTE: This class is auto generated by OpenAPI Generator. * https://github.com/OpenAPITools/openapi-generator * - * OpenAPI generator version: 5.3.0-SNAPSHOT + * OpenAPI generator version: 5.3.1-SNAPSHOT */ import http from "k6/http"; import { group, check, sleep } from "k6"; -const BASE_URL = "http://petstore.swagger.io/v2"; +const BASE_URL = "https://127.0.0.1/no_varaible"; // Sleep duration between successive requests. // You might want to edit the value of this variable or remove calls to the sleep function on the script. const SLEEP_DURATION = 0.1; // Global variables should be initialized. +let booleanGroup = "TODO_EDIT_THE_BOOLEAN_GROUP"; +let header1 = "TODO_EDIT_THE_HEADER_1"; let apiKey = "TODO_EDIT_THE_API_KEY"; +let requiredBooleanGroup = "TODO_EDIT_THE_REQUIRED_BOOLEAN_GROUP"; +let enumHeaderStringArray = "TODO_EDIT_THE_ENUM_HEADER_STRING_ARRAY"; +let enumHeaderString = "TODO_EDIT_THE_ENUM_HEADER_STRING"; export default function() { + group("/fake", () => { + let enumQueryInteger = 'TODO_EDIT_THE_ENUM_QUERY_INTEGER'; // specify value as there is no example value for this parameter in OpenAPI spec + let enumQueryString = 'TODO_EDIT_THE_ENUM_QUERY_STRING'; // specify value as there is no example value for this parameter in OpenAPI spec + let enumQueryStringArray = 'TODO_EDIT_THE_ENUM_QUERY_STRING_ARRAY'; // specify value as there is no example value for this parameter in OpenAPI spec + let enumQueryDouble = 'TODO_EDIT_THE_ENUM_QUERY_DOUBLE'; // specify value as there is no example value for this parameter in OpenAPI spec + + // Request No. 1 + { + let url = BASE_URL + `/fake?enum_query_string_array=${enum_query_string_array}&enum_query_string=${enum_query_string}&enum_query_integer=${enum_query_integer}&enum_query_double=${enum_query_double}`; + // TODO: edit the parameters of the request body. + let body = {"enumFormStringArray": "list", "enumFormString": "string"}; + let params = {headers: {"Content-Type": "application/x-www-form-urlencoded", "enum_header_string_array": `${enumHeaderStringArray}`, "enum_header_string": `${enumHeaderString}`, "Accept": "application/json"}}; + let request = http.get(url, JSON.stringify(body), params); + + + sleep(SLEEP_DURATION); + } + + // Request No. 2 + { + let url = BASE_URL + `/fake`; + // TODO: edit the parameters of the request body. + let body = {"client": "string"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.patch(url, JSON.stringify(body), params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } + }); + + group("/fake/outer/boolean", () => { + + // Request No. 1 + { + let url = BASE_URL + `/fake/outer/boolean`; + let params = {headers: {"Content-Type": "application/json", "Accept": "*/*"}}; + let request = http.post(url, params); + + check(request, { + "Output boolean": (r) => r.status === 200 + }); + } + }); + + group("/another-fake/dummy", () => { + + // Request No. 1 + { + let url = BASE_URL + `/another-fake/dummy`; + // TODO: edit the parameters of the request body. + let body = {"client": "string"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.patch(url, JSON.stringify(body), params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } + }); + group("/pet", () => { - - // Request No. 1 - { - let url = BASE_URL + `/pet`; - // TODO: edit the parameters of the request body. - let body = {"id": "long", "category": {"id": "long", "name": "string"}, "name": "string", "photoUrls": "list", "tags": "list", "status": "string"}; - - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - - - let request = http.put(url, JSON.stringify(body), params); - - - - sleep(SLEEP_DURATION); - } - - + + // Request No. 1 + { + let url = BASE_URL + `/pet`; + // TODO: edit the parameters of the request body. + let body = {"id": "long", "category": {"id": "long", "name": "string"}, "name": "string", "photoUrls": "set", "tags": "list", "status": "string"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.put(url, JSON.stringify(body), params); + + check(request, { + "Successful operation": (r) => r.status === 200 + }); + + sleep(SLEEP_DURATION); + } + // Request No. 2 { - let url = BASE_URL + `/pet`; - // TODO: edit the parameters of the request body. - let body = {"id": "long", "category": {"id": "long", "name": "string"}, "name": "string", "photoUrls": "list", "tags": "list", "status": "string"}; - - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - - - let request = http.post(url, JSON.stringify(body), params); - - - + let url = BASE_URL + `/pet`; + // TODO: edit the parameters of the request body. + let body = {"id": "long", "category": {"id": "long", "name": "string"}, "name": "string", "photoUrls": "set", "tags": "list", "status": "string"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.post(url, JSON.stringify(body), params); + + check(request, { + "Successful operation": (r) => r.status === 200 + }); } - }); + group("/user/{username}", () => { let username = 'TODO_EDIT_THE_USERNAME'; // specify value as there is no example value for this parameter in OpenAPI spec - - // Request No. 1 - { - let url = BASE_URL + `/user/${username}`; - - - - let request = http.get(url); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - - sleep(SLEEP_DURATION); - } - - + + // Request No. 1 + { + let url = BASE_URL + `/user/${username}`; + let request = http.get(url); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + + sleep(SLEEP_DURATION); + } + // Request No. 2 { - let url = BASE_URL + `/user/${username}`; - - - let request = http.del(url); - - - - + let url = BASE_URL + `/user/${username}`; + let request = http.del(url); + } - }); - group("/pet/findByStatus", () => { - let status = 'TODO_EDIT_THE_STATUS'; // specify value as there is no example value for this parameter in OpenAPI spec - + + group("/fake/body-with-binary", () => { + + // Request No. 1 + { + let url = BASE_URL + `/fake/body-with-binary`; + let params = {headers: {"Content-Type": "image/png", "Accept": "application/json"}}; + let request = http.put(url, params); + + check(request, { + "Success": (r) => r.status === 200 + }); + } + }); + + group("/fake_classname_test", () => { + // Request No. 1 { - let url = BASE_URL + `/pet/findByStatus?status=${status}`; - - - - let request = http.get(url); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - + let url = BASE_URL + `/fake_classname_test`; + // TODO: edit the parameters of the request body. + let body = {"client": "string"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.patch(url, JSON.stringify(body), params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); } - }); + group("/user/createWithList", () => { - + // Request No. 1 { - let url = BASE_URL + `/user/createWithList`; - - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - - - let request = http.post(url, params); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - + let url = BASE_URL + `/user/createWithList`; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.post(url, params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); } - }); - group("/pet/{petId}/uploadImage", () => { - let petId = 'TODO_EDIT_THE_PETID'; // specify value as there is no example value for this parameter in OpenAPI spec - - // Request No. 1 - { - let url = BASE_URL + `/pet/${petId}/uploadImage`; - // TODO: edit the parameters of the request body. - let body = {"additionalMetadata": "string", "file": http.file(open("/path/to/file.bin", "b"), "test.bin")}; - - let params = {headers: {"Content-Type": "multipart/form-data", "Accept": "application/json"}}; - - - let request = http.post(url, JSON.stringify(body), params); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - - } - + + group("/fake/inline-additionalProperties", () => { + + // Request No. 1 + { + let url = BASE_URL + `/fake/inline-additionalProperties`; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.post(url, params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } }); + group("/store/inventory", () => { - + // Request No. 1 { - let url = BASE_URL + `/store/inventory`; - - - - let request = http.get(url); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - + let url = BASE_URL + `/store/inventory`; + let request = http.get(url); + + check(request, { + "successful operation": (r) => r.status === 200 + }); } - }); + group("/user/login", () => { let password = 'TODO_EDIT_THE_PASSWORD'; // specify value as there is no example value for this parameter in OpenAPI spec let username = 'TODO_EDIT_THE_USERNAME'; // specify value as there is no example value for this parameter in OpenAPI spec - + + // Request No. 1 + { + let url = BASE_URL + `/user/login?username=${username}&password=${password}`; + let request = http.get(url); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } + }); + + group("/fake/outer/composite", () => { + + // Request No. 1 + { + let url = BASE_URL + `/fake/outer/composite`; + // TODO: edit the parameters of the request body. + let body = {"myNumber": "bigdecimal", "myString": "string", "myBoolean": "boolean"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "*/*"}}; + let request = http.post(url, JSON.stringify(body), params); + + check(request, { + "Output composite": (r) => r.status === 200 + }); + } + }); + + group("/fake/jsonFormData", () => { + + // Request No. 1 + { + let url = BASE_URL + `/fake/jsonFormData`; + // TODO: edit the parameters of the request body. + let body = {"param": "string", "param2": "string"}; + let params = {headers: {"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}}; + let request = http.get(url, JSON.stringify(body), params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } + }); + + group("/fake/{petId}/uploadImageWithRequiredFile", () => { + let petId = 'TODO_EDIT_THE_PETID'; // specify value as there is no example value for this parameter in OpenAPI spec + + // Request No. 1 + { + let url = BASE_URL + `/fake/${petId}/uploadImageWithRequiredFile`; + // TODO: edit the parameters of the request body. + let body = {"additionalMetadata": "string", "requiredFile": http.file(open("/path/to/file.bin", "b"), "test.bin")}; + let params = {headers: {"Content-Type": "multipart/form-data", "Accept": "application/json"}}; + let request = http.post(url, JSON.stringify(body), params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } + }); + + group("/pet/{petId}", () => { + let petId = 'TODO_EDIT_THE_PETID'; // specify value as there is no example value for this parameter in OpenAPI spec + + // Request No. 1 + { + let url = BASE_URL + `/pet/${petId}`; + let request = http.get(url); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + + sleep(SLEEP_DURATION); + } + + // Request No. 2 + { + let url = BASE_URL + `/pet/${petId}`; + let params = {headers: {"api_key": `${apiKey}`, "Accept": "application/json"}}; + // this is a DELETE method request - if params are also set, empty body must be passed + let request = http.del(url, {} , params); + + check(request, { + "Successful operation": (r) => r.status === 200 + }); + } + }); + + group("/foo", () => { + // Request No. 1 { - let url = BASE_URL + `/user/login?username=${username}&password=${password}`; - - - - let request = http.get(url); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - + let url = BASE_URL + `/foo`; + let request = http.get(url); + + check(request, { + "response": (r) => r.status === 200 + }); } - }); + + group("/fake/outer/string", () => { + + // Request No. 1 + { + let url = BASE_URL + `/fake/outer/string`; + let params = {headers: {"Content-Type": "application/json", "Accept": "*/*"}}; + let request = http.post(url, params); + + check(request, { + "Output string": (r) => r.status === 200 + }); + } + }); + + group("/fake/test-query-parameters", () => { + let allowEmpty = 'TODO_EDIT_THE_ALLOWEMPTY'; // specify value as there is no example value for this parameter in OpenAPI spec + let ioutil = 'TODO_EDIT_THE_IOUTIL'; // specify value as there is no example value for this parameter in OpenAPI spec + let context = 'TODO_EDIT_THE_CONTEXT'; // specify value as there is no example value for this parameter in OpenAPI spec + let http = 'TODO_EDIT_THE_HTTP'; // specify value as there is no example value for this parameter in OpenAPI spec + let pipe = 'TODO_EDIT_THE_PIPE'; // specify value as there is no example value for this parameter in OpenAPI spec + let language = 'TODO_EDIT_THE_LANGUAGE'; // specify value as there is no example value for this parameter in OpenAPI spec + let url = 'TODO_EDIT_THE_URL'; // specify value as there is no example value for this parameter in OpenAPI spec + + // Request No. 1 + { + let url = BASE_URL + `/fake/test-query-parameters?pipe=${pipe}&ioutil=${ioutil}&http=${http}&url=${url}&context=${context}&language=${language}&allowEmpty=${allowEmpty}`; + let request = http.put(url); + + check(request, { + "Success": (r) => r.status === 200 + }); + } + }); + + group("/store/order/{order_id}", () => { + let orderId = 'TODO_EDIT_THE_ORDER_ID'; // specify value as there is no example value for this parameter in OpenAPI spec + + // Request No. 1 + { + let url = BASE_URL + `/store/order/${order_id}`; + let request = http.get(url); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + + sleep(SLEEP_DURATION); + } + + // Request No. 2 + { + let url = BASE_URL + `/store/order/${order_id}`; + let request = http.del(url); + + } + }); + + group("/pet/findByStatus", () => { + let status = 'TODO_EDIT_THE_STATUS'; // specify value as there is no example value for this parameter in OpenAPI spec + + // Request No. 1 + { + let url = BASE_URL + `/pet/findByStatus?status=${status}`; + let request = http.get(url); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } + }); + + group("/fake/body-with-query-params", () => { + let query = 'TODO_EDIT_THE_QUERY'; // specify value as there is no example value for this parameter in OpenAPI spec + + // Request No. 1 + { + let url = BASE_URL + `/fake/body-with-query-params?query=${query}`; + // TODO: edit the parameters of the request body. + let body = {"id": "long", "username": "string", "firstName": "string", "lastName": "string", "email": "string", "password": "string", "phone": "string", "userStatus": "integer"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.put(url, JSON.stringify(body), params); + + check(request, { + "Success": (r) => r.status === 200 + }); + } + }); + + group("/pet/{petId}/uploadImage", () => { + let petId = 'TODO_EDIT_THE_PETID'; // specify value as there is no example value for this parameter in OpenAPI spec + + // Request No. 1 + { + let url = BASE_URL + `/pet/${petId}/uploadImage`; + // TODO: edit the parameters of the request body. + let body = {"additionalMetadata": "string", "file": http.file(open("/path/to/file.bin", "b"), "test.bin")}; + let params = {headers: {"Content-Type": "multipart/form-data", "Accept": "application/json"}}; + let request = http.post(url, JSON.stringify(body), params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } + }); + + group("/fake/http-signature-test", () => { + let query1 = 'TODO_EDIT_THE_QUERY_1'; // specify value as there is no example value for this parameter in OpenAPI spec + + // Request No. 1 + { + let url = BASE_URL + `/fake/http-signature-test?query_1=${query_1}`; + // TODO: edit the parameters of the request body. + let body = {"id": "long", "category": {"id": "long", "name": "string"}, "name": "string", "photoUrls": "set", "tags": "list", "status": "string"}; + let params = {headers: {"Content-Type": "application/json", "header_1": `${header1}`, "Accept": "application/json"}}; + let request = http.get(url, JSON.stringify(body), params); + + check(request, { + "The instance started successfully": (r) => r.status === 200 + }); + } + }); + group("/user", () => { - - // Request No. 1 - { - let url = BASE_URL + `/user`; - // TODO: edit the parameters of the request body. - let body = {"id": "long", "username": "string", "firstName": "string", "lastName": "string", "email": "string", "password": "string", "phone": "string", "userStatus": "integer"}; - - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - - - let request = http.post(url, JSON.stringify(body), params); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - - } - + + // Request No. 1 + { + let url = BASE_URL + `/user`; + // TODO: edit the parameters of the request body. + let body = {"id": "long", "username": "string", "firstName": "string", "lastName": "string", "email": "string", "password": "string", "phone": "string", "userStatus": "integer"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.post(url, JSON.stringify(body), params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } + }); + + group("/fake/property/enum-int", () => { + + // Request No. 1 + { + let url = BASE_URL + `/fake/property/enum-int`; + // TODO: edit the parameters of the request body. + let body = {"value": "outerenuminteger"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "*/*"}}; + let request = http.post(url, JSON.stringify(body), params); + + check(request, { + "Output enum (int)": (r) => r.status === 200 + }); + } }); + group("/user/createWithArray", () => { - + + // Request No. 1 + { + let url = BASE_URL + `/user/createWithArray`; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.post(url, params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } + }); + + group("/fake/body-with-file-schema", () => { + // Request No. 1 { - let url = BASE_URL + `/user/createWithArray`; - - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - - - let request = http.post(url, params); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - + let url = BASE_URL + `/fake/body-with-file-schema`; + // TODO: edit the parameters of the request body. + let body = {"file": http.file(open("/path/to/file.bin", "b"), "test.bin"), "files": "list"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.put(url, JSON.stringify(body), params); + + check(request, { + "Success": (r) => r.status === 200 + }); } - }); + group("/pet/findByTags", () => { let tags = 'TODO_EDIT_THE_TAGS'; // specify value as there is no example value for this parameter in OpenAPI spec - + // Request No. 1 { - let url = BASE_URL + `/pet/findByTags?tags=${tags}`; - - - - let request = http.get(url); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - + let url = BASE_URL + `/pet/findByTags?tags=${tags}`; + let request = http.get(url); + + check(request, { + "successful operation": (r) => r.status === 200 + }); } - }); + group("/store/order", () => { - - // Request No. 1 - { - let url = BASE_URL + `/store/order`; - // TODO: edit the parameters of the request body. - let body = {"id": "long", "petId": "long", "quantity": "integer", "shipDate": "date", "status": "string", "complete": "boolean"}; - - let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; - - - let request = http.post(url, JSON.stringify(body), params); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - - } - + + // Request No. 1 + { + let url = BASE_URL + `/store/order`; + // TODO: edit the parameters of the request body. + let body = {"id": "long", "petId": "long", "quantity": "integer", "shipDate": "date", "status": "string", "complete": "boolean"}; + let params = {headers: {"Content-Type": "application/json", "Accept": "application/json"}}; + let request = http.post(url, JSON.stringify(body), params); + + check(request, { + "successful operation": (r) => r.status === 200 + }); + } }); + group("/user/logout", () => { - + // Request No. 1 { - let url = BASE_URL + `/user/logout`; - - - - let request = http.get(url); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - + let url = BASE_URL + `/user/logout`; + let request = http.get(url); + + check(request, { + "successful operation": (r) => r.status === 200 + }); } - }); - group("/pet/{petId}", () => { - let petId = 'TODO_EDIT_THE_PETID'; // specify value as there is no example value for this parameter in OpenAPI spec - - // Request No. 1 - { - let url = BASE_URL + `/pet/${petId}`; - - - - let request = http.get(url); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - - sleep(SLEEP_DURATION); - } - - - // Request No. 2 + + group("/fake/health", () => { + + // Request No. 1 { - let url = BASE_URL + `/pet/${petId}`; - - let params = {headers: {"api_key": `${apiKey}`, "Accept": "application/json"}}; - - // this is a DELETE method request - if params are also set, empty body must be passed - let request = http.del(url, {} , params); - - - - - } - - }); - group("/store/order/{orderId}", () => { - let orderId = 'TODO_EDIT_THE_ORDERID'; // specify value as there is no example value for this parameter in OpenAPI spec - - // Request No. 1 - { - let url = BASE_URL + `/store/order/${orderId}`; - - - - let request = http.get(url); - - check(request, { - "successful operation": (r) => r.status === 200 - }); - - - sleep(SLEEP_DURATION); - } - - - // Request No. 2 + let url = BASE_URL + `/fake/health`; + let request = http.get(url); + + check(request, { + "The instance started successfully": (r) => r.status === 200 + }); + } + }); + + group("/fake/outer/number", () => { + + // Request No. 1 { - let url = BASE_URL + `/store/order/${orderId}`; - - - let request = http.del(url); - - - - + let url = BASE_URL + `/fake/outer/number`; + let params = {headers: {"Content-Type": "application/json", "Accept": "*/*"}}; + let request = http.post(url, params); + + check(request, { + "Output number": (r) => r.status === 200 + }); } - }); + } -- GitLab From 070f73064fc119148819616d73c6034907f6ed88 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafamoradian0@gmail.com> Date: Tue, 14 Dec 2021 12:16:16 +0100 Subject: [PATCH 11/13] Regenerate samples --- .../kotlin/vertx/.openapi-generator/FILES | 2 +- .../server/petstore/kotlin/vertx/README.md | 2 +- .../server/api/model/ModelApiResponse.kt | 34 +++++++++++++++++++ .../server/api/verticle/PetApi.kt | 4 +-- .../api/verticle/PetApiVertxProxyHandler.kt | 2 +- 5 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/ModelApiResponse.kt diff --git a/samples/server/petstore/kotlin/vertx/.openapi-generator/FILES b/samples/server/petstore/kotlin/vertx/.openapi-generator/FILES index cf01966a4dd..bfa6fd2a60c 100644 --- a/samples/server/petstore/kotlin/vertx/.openapi-generator/FILES +++ b/samples/server/petstore/kotlin/vertx/.openapi-generator/FILES @@ -1,7 +1,7 @@ README.md pom.xml -src/main/kotlin/org/openapitools/server/api/model/ApiResponse.kt src/main/kotlin/org/openapitools/server/api/model/Category.kt +src/main/kotlin/org/openapitools/server/api/model/ModelApiResponse.kt src/main/kotlin/org/openapitools/server/api/model/Order.kt src/main/kotlin/org/openapitools/server/api/model/Pet.kt src/main/kotlin/org/openapitools/server/api/model/Tag.kt diff --git a/samples/server/petstore/kotlin/vertx/README.md b/samples/server/petstore/kotlin/vertx/README.md index 4e9992d66cb..47e035f66db 100644 --- a/samples/server/petstore/kotlin/vertx/README.md +++ b/samples/server/petstore/kotlin/vertx/README.md @@ -51,8 +51,8 @@ This runs all tests and packages the library. <a name="documentation-for-models"></a> ## Documentation for Models - - [org.openapitools.server.api.model.ApiResponse](docs/ApiResponse.md) - [org.openapitools.server.api.model.Category](docs/Category.md) + - [org.openapitools.server.api.model.ModelApiResponse](docs/ModelApiResponse.md) - [org.openapitools.server.api.model.Order](docs/Order.md) - [org.openapitools.server.api.model.Pet](docs/Pet.md) - [org.openapitools.server.api.model.Tag](docs/Tag.md) diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/ModelApiResponse.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/ModelApiResponse.kt new file mode 100644 index 00000000000..ce832696033 --- /dev/null +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/model/ModelApiResponse.kt @@ -0,0 +1,34 @@ +/** +* OpenAPI Petstore +* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. +* +* The version of the OpenAPI document: 1.0.0 +* +* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). +* https://openapi-generator.tech +* Do not edit the class manually. +*/ +package org.openapitools.server.api.model + + + +import com.google.gson.annotations.SerializedName +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonInclude +/** + * Describes the result of uploading an image resource + * @param code + * @param type + * @param message + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +data class ModelApiResponse ( + var code: kotlin.Int? = null, + var type: kotlin.String? = null, + var message: kotlin.String? = null +) { + +} + diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApi.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApi.kt index 07f92471774..5968aa12cac 100644 --- a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApi.kt +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApi.kt @@ -1,6 +1,6 @@ package org.openapitools.server.api.verticle -import org.openapitools.server.api.model.ApiResponse +import org.openapitools.server.api.model.ModelApiResponse import org.openapitools.server.api.model.Pet import io.vertx.core.Vertx import io.vertx.core.json.JsonObject @@ -41,7 +41,7 @@ interface PetApi { suspend fun updatePetWithForm(petId:kotlin.Long?,name:kotlin.String?,status:kotlin.String?,context:OperationRequest):Response<Void> /* uploadFile * uploads an image */ - suspend fun uploadFile(petId:kotlin.Long?,additionalMetadata:kotlin.String?,file:kotlin.collections.List<java.io.File>?,context:OperationRequest):Response<ApiResponse> + suspend fun uploadFile(petId:kotlin.Long?,additionalMetadata:kotlin.String?,file:kotlin.collections.List<java.io.File>?,context:OperationRequest):Response<ModelApiResponse> companion object { const val address = "PetApi-service" suspend fun createRouterFactory(vertx: Vertx,path:String): io.vertx.ext.web.api.contract.openapi3.OpenAPI3RouterFactory { diff --git a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVertxProxyHandler.kt b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVertxProxyHandler.kt index 6d4fcafa98b..644fc1cee83 100644 --- a/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVertxProxyHandler.kt +++ b/samples/server/petstore/kotlin/vertx/src/main/kotlin/org/openapitools/server/api/verticle/PetApiVertxProxyHandler.kt @@ -16,7 +16,7 @@ import io.vertx.core.json.Json import io.vertx.core.json.JsonArray import com.google.gson.reflect.TypeToken import com.google.gson.Gson -import org.openapitools.server.api.model.ApiResponse +import org.openapitools.server.api.model.ModelApiResponse import org.openapitools.server.api.model.Pet class PetApiVertxProxyHandler(private val vertx: Vertx, private val service: PetApi, topLevel: Boolean, private val timeoutSeconds: Long) : ProxyHandler() { -- GitLab From 8788910a90551ad1f72724de32d34b06f4fa0d97 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafamoradian0@gmail.com> Date: Tue, 14 Dec 2021 14:36:04 +0100 Subject: [PATCH 12/13] Fix predicate --- .../codegen/languages/K6ClientCodegen.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java index 253f1f6b972..624456c0a5f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java @@ -1038,16 +1038,14 @@ public class K6ClientCodegen extends DefaultCodegen implements CodegenConfig { && resp.getExtensions().containsKey(X_OPERATION_RESPONSE)) { Map<?, ?> respExtensions = (Map<?, ?>) resp.getExtensions().get(X_OPERATION_RESPONSE); + Entry<?, ?> entry = respExtensions.entrySet().stream().findFirst().orElse(null); - for (Map.Entry<?, ?> respExtensionEntry : respExtensions.entrySet()) { - - if (X_OPERATION_RESPONSE_HIDE.equals(String.valueOf(respExtensionEntry.getKey()))) { - hideOperationResponse = Boolean.parseBoolean(respExtensionEntry.getValue().toString()); - } + if (entry.getKey().equals(X_OPERATION_RESPONSE_HIDE)) { + return Boolean.parseBoolean(String.valueOf(entry.getValue())); } } - return hideOperationResponse; + return false; } /** -- GitLab From e79063b8d3152cb652343cb7d48f5ec024b66bc5 Mon Sep 17 00:00:00 2001 From: Mostafa Moradian <mostafamoradian0@gmail.com> Date: Tue, 14 Dec 2021 14:39:42 +0100 Subject: [PATCH 13/13] Fix missing import --- .../java/org/openapitools/codegen/languages/K6ClientCodegen.java | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java index 624456c0a5f..681594ea8eb 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/K6ClientCodegen.java @@ -38,6 +38,7 @@ import java.util.OptionalInt; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; +import java.util.Map.Entry; import java.util.stream.Collectors; import javax.annotation.Nullable; -- GitLab