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