forked from loafle/openapi-generator-original
[k6] OpenAPI code generator for k6 API load-testing tool (ES5.1+) (#5300)
* Add generator for converting OpenAPI spec to k6 script * Fixed names and URL * Add @wing328's proposed changes to fix the builds
This commit is contained in:
@@ -0,0 +1,547 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.info.License;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.oas.models.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.models.servers.Server;
|
||||
import org.openapitools.codegen.*;
|
||||
import io.swagger.v3.oas.models.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import static org.openapitools.codegen.utils.StringUtils.*;
|
||||
|
||||
public class k6Codegen extends DefaultCodegen implements CodegenConfig {
|
||||
|
||||
static class Parameter {
|
||||
String key;
|
||||
Object value;
|
||||
|
||||
public Parameter(String key, Object value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return key.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
Parameter p = (Parameter) obj;
|
||||
return key.equals(p.key) && value.equals((String) p.value);
|
||||
}
|
||||
}
|
||||
|
||||
static class HTTPBody {
|
||||
List<Parameter> parameters;
|
||||
|
||||
public HTTPBody(List<Parameter> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
}
|
||||
|
||||
static class HTTPParameters {
|
||||
@Nullable
|
||||
String auth;
|
||||
@Nullable
|
||||
List<Parameter> cookies;
|
||||
@Nullable
|
||||
List<Parameter> headers;
|
||||
@Nullable
|
||||
List<Parameter> jar;
|
||||
@Nullable
|
||||
Integer redirects;
|
||||
@Nullable
|
||||
List<Parameter> tags;
|
||||
@Nullable
|
||||
Integer timeout;
|
||||
@Nullable
|
||||
String compression;
|
||||
@Nullable
|
||||
String responseType;
|
||||
|
||||
public HTTPParameters(@Nullable String auth, @Nullable List<Parameter> cookies,
|
||||
@Nullable List<Parameter> headers, @Nullable List<Parameter> jar, @Nullable Integer redirects,
|
||||
@Nullable List<Parameter> tags, @Nullable Integer timeout, @Nullable String compression,
|
||||
@Nullable String responseType) {
|
||||
this.auth = auth;
|
||||
this.cookies = cookies;
|
||||
this.headers = headers;
|
||||
this.jar = jar;
|
||||
this.redirects = redirects;
|
||||
this.tags = tags;
|
||||
this.timeout = timeout;
|
||||
this.compression = compression;
|
||||
this.responseType = responseType;
|
||||
}
|
||||
}
|
||||
|
||||
static class k6Check {
|
||||
Integer status;
|
||||
String description;
|
||||
|
||||
public k6Check(Integer status, String description) {
|
||||
this.status = status;
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
||||
static class HTTPRequest {
|
||||
String method;
|
||||
String path;
|
||||
@Nullable
|
||||
List<Parameter> query;
|
||||
@Nullable
|
||||
HTTPBody body;
|
||||
@Nullable
|
||||
HTTPParameters params;
|
||||
@Nullable
|
||||
List<k6Check> k6Checks;
|
||||
|
||||
public HTTPRequest(String method, String path, @Nullable List<Parameter> query, @Nullable HTTPBody body,
|
||||
@Nullable HTTPParameters params, @Nullable List<k6Check> k6Checks) {
|
||||
this.method = method;
|
||||
this.path = path;
|
||||
this.query = query;
|
||||
this.body = body;
|
||||
this.params = params;
|
||||
this.k6Checks = k6Checks;
|
||||
}
|
||||
}
|
||||
|
||||
static public class HTTPRequestGroup {
|
||||
String groupName;
|
||||
Set<Parameter> variables; // query and path parameters
|
||||
List<HTTPRequest> requests;
|
||||
|
||||
public HTTPRequestGroup(String groupName, Set<Parameter> variables, List<HTTPRequest> requests) {
|
||||
this.groupName = groupName;
|
||||
this.variables = variables;
|
||||
this.requests = requests;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JavascriptClientCodegen.class);
|
||||
|
||||
public static final String PROJECT_NAME = "projectName";
|
||||
public static final String MODULE_NAME = "moduleName";
|
||||
public static final String PROJECT_DESCRIPTION = "projectDescription";
|
||||
public static final String PROJECT_VERSION = "projectVersion";
|
||||
public static final String BASE_URL = "baseURL";
|
||||
public static final String PRESERVE_LEADING_PARAM_CHAR = "preserveLeadingParamChar";
|
||||
static final Collection<String> INVOKER_PKG_SUPPORTING_FILES = Arrays.asList("script.mustache", "README.mustache");
|
||||
static final String[][] JAVASCRIPT_SUPPORTING_FILES = new String[][] {
|
||||
new String[] { "script.mustache", "script.js" }, new String[] { "README.mustache", "README.md" } };
|
||||
|
||||
protected String projectName;
|
||||
protected String moduleName;
|
||||
protected String projectDescription;
|
||||
protected String projectVersion;
|
||||
protected String licenseName;
|
||||
|
||||
protected String invokerPackage;
|
||||
protected String sourceFolder = "";
|
||||
protected String localVariablePrefix = "";
|
||||
private String modelPropertyNaming = "camelCase";
|
||||
protected boolean preserveLeadingParamChar = false;
|
||||
|
||||
@Override
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "k6";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelp() {
|
||||
return "Generates k6 script.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
embeddedTemplateDir = templateDir = "k6";
|
||||
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(PROJECT_NAME)) {
|
||||
setProjectName(((String) additionalProperties.get(PROJECT_NAME)));
|
||||
}
|
||||
if (additionalProperties.containsKey(MODULE_NAME)) {
|
||||
setModuleName(((String) additionalProperties.get(MODULE_NAME)));
|
||||
}
|
||||
if (additionalProperties.containsKey(PROJECT_DESCRIPTION)) {
|
||||
setProjectDescription(((String) additionalProperties.get(PROJECT_DESCRIPTION)));
|
||||
}
|
||||
if (additionalProperties.containsKey(PROJECT_VERSION)) {
|
||||
setProjectVersion(((String) additionalProperties.get(PROJECT_VERSION)));
|
||||
}
|
||||
if (additionalProperties.containsKey(CodegenConstants.LICENSE_NAME)) {
|
||||
setLicenseName(((String) additionalProperties.get(CodegenConstants.LICENSE_NAME)));
|
||||
}
|
||||
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
|
||||
setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
|
||||
}
|
||||
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
|
||||
setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
|
||||
}
|
||||
if (additionalProperties.containsKey(CodegenConstants.MODEL_PROPERTY_NAMING)) {
|
||||
setModelPropertyNaming((String) additionalProperties.get(CodegenConstants.MODEL_PROPERTY_NAMING));
|
||||
}
|
||||
boolean preserveLeadingParamChar = convertPropertyToBooleanAndWriteBack(PRESERVE_LEADING_PARAM_CHAR);
|
||||
this.setPreserveLeadingParamChar(preserveLeadingParamChar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preprocessOpenAPI(OpenAPI openAPI) {
|
||||
super.preprocessOpenAPI(openAPI);
|
||||
|
||||
if (openAPI.getInfo() != null) {
|
||||
Info info = openAPI.getInfo();
|
||||
if (StringUtils.isBlank(projectName) && info.getTitle() != null) {
|
||||
// when projectName is not specified, generate it from info.title
|
||||
projectName = sanitizeName(dashize(info.getTitle()));
|
||||
}
|
||||
if (StringUtils.isBlank(projectVersion)) {
|
||||
// when projectVersion is not specified, use info.version
|
||||
projectVersion = escapeUnsafeCharacters(escapeQuotationMark(info.getVersion()));
|
||||
}
|
||||
if (projectDescription == null) {
|
||||
// when projectDescription is not specified, use info.description
|
||||
projectDescription = sanitizeName(info.getDescription());
|
||||
}
|
||||
|
||||
// when licenceName is not specified, use info.license
|
||||
if (additionalProperties.get(CodegenConstants.LICENSE_NAME) == null && info.getLicense() != null) {
|
||||
License license = info.getLicense();
|
||||
licenseName = license.getName();
|
||||
}
|
||||
}
|
||||
|
||||
// default values
|
||||
if (StringUtils.isBlank(projectName)) {
|
||||
projectName = "swagger-k6-client";
|
||||
}
|
||||
if (StringUtils.isBlank(moduleName)) {
|
||||
moduleName = camelize(underscore(projectName));
|
||||
}
|
||||
if (StringUtils.isBlank(projectVersion)) {
|
||||
projectVersion = "1.0.0";
|
||||
}
|
||||
if (projectDescription == null) {
|
||||
projectDescription = "Client library of " + projectName;
|
||||
}
|
||||
if (StringUtils.isBlank(licenseName)) {
|
||||
licenseName = "Unlicense";
|
||||
}
|
||||
|
||||
additionalProperties.put(PROJECT_NAME, projectName);
|
||||
additionalProperties.put(MODULE_NAME, moduleName);
|
||||
additionalProperties.put(PROJECT_DESCRIPTION, escapeText(projectDescription));
|
||||
additionalProperties.put(PROJECT_VERSION, projectVersion);
|
||||
additionalProperties.put(CodegenConstants.LICENSE_NAME, licenseName);
|
||||
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
|
||||
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
|
||||
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
|
||||
additionalProperties.put(CodegenConstants.SOURCE_FOLDER, sourceFolder);
|
||||
|
||||
String baseURL = openAPI.getServers().get(0).getUrl();
|
||||
for (Server server : openAPI.getServers()) {
|
||||
if (server.getUrl().contains("https://")) {
|
||||
baseURL = server.getUrl();
|
||||
}
|
||||
}
|
||||
additionalProperties.put(BASE_URL, baseURL);
|
||||
|
||||
List<HTTPRequestGroup> requestGroups = new ArrayList<>();
|
||||
Set<Parameter> extraParameters = new HashSet<>();
|
||||
Map<String, Set<Parameter>> pathVariables = new HashMap<>();
|
||||
|
||||
for (String path : openAPI.getPaths().keySet()) {
|
||||
List<HTTPRequest> requests = new ArrayList<>();
|
||||
Set<Parameter> variables = new HashSet<>();
|
||||
|
||||
for (Map.Entry<PathItem.HttpMethod, Operation> methodOperation : openAPI.getPaths().get(path).
|
||||
readOperationsMap().entrySet()) {
|
||||
List<Parameter> httpParams = new ArrayList<>();
|
||||
List<Parameter> queryParams = new ArrayList<>();
|
||||
List<Parameter> bodyOrFormParams = new ArrayList<>();
|
||||
List<k6Check> k6Checks = new ArrayList<>();
|
||||
Set<String> imports = new HashSet<String>();
|
||||
|
||||
final Operation operation = methodOperation.getValue();
|
||||
final PathItem.HttpMethod method = methodOperation.getKey();
|
||||
|
||||
for (Map.Entry<String, ApiResponse> resp : operation.getResponses().entrySet()) {
|
||||
String statusData = resp.getKey().equals("default") ? "200" : resp.getKey();
|
||||
int status = Integer.parseInt(statusData);
|
||||
if (status >= 200 && status < 300) {
|
||||
k6Checks.add(new k6Check(status, resp.getValue().getDescription()));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (contentTypeValue.equals("*/*"))
|
||||
contentTypeValue = "application/json";
|
||||
Parameter contentType = new Parameter("Content-Type", getDoubleQuotedString(contentTypeValue));
|
||||
httpParams.add(contentType);
|
||||
|
||||
RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, operation.getRequestBody());
|
||||
|
||||
for (Map.Entry<String, ApiResponse> responseEntry : operation.getResponses().entrySet()) {
|
||||
CodegenResponse r = fromResponse(responseEntry.getKey(), responseEntry.getValue());
|
||||
if (r.baseType != null &&
|
||||
!defaultIncludes.contains(r.baseType) &&
|
||||
!languageSpecificPrimitives.contains(r.baseType)) {
|
||||
imports.add(r.baseType);
|
||||
}
|
||||
}
|
||||
|
||||
List<CodegenParameter> formParameteres = fromRequestBodyToFormParameters(requestBody, imports);
|
||||
for (CodegenParameter parameter : formParameteres) {
|
||||
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)));
|
||||
}
|
||||
|
||||
bodyOrFormParams.add(k6Parameter);
|
||||
}
|
||||
}
|
||||
String accepts = getAccept(openAPI, operation);
|
||||
String responseType = getDoubleQuotedString(accepts);
|
||||
|
||||
try {
|
||||
|
||||
for (io.swagger.v3.oas.models.parameters.Parameter parameter : operation.getParameters()) {
|
||||
switch (parameter.getIn()) {
|
||||
case "header":
|
||||
httpParams.add(new Parameter(parameter.getName(), getTemplateString(parameter.getName())));
|
||||
extraParameters.add(new Parameter(parameter.getName(), parameter.getName().toUpperCase(Locale.ROOT)));
|
||||
break;
|
||||
case "path":
|
||||
case "query":
|
||||
if (parameter.getIn().equals("query"))
|
||||
queryParams.add(new Parameter(parameter.getName(), getVariable(parameter.getName())));
|
||||
variables.add(new Parameter(parameter.getName(), parameter.getName().toUpperCase(Locale.ROOT)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
|
||||
}
|
||||
|
||||
pathVariables.put(path, 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,
|
||||
queryParams.size() > 0 ? queryParams : null,
|
||||
bodyOrFormParams.size() > 0 ? new HTTPBody(bodyOrFormParams) : null,
|
||||
params.headers.size() > 0 ? params : null, k6Checks.size() > 0 ? k6Checks : null));
|
||||
}
|
||||
requestGroups.add(new HTTPRequestGroup(path, pathVariables.get(path), requests));
|
||||
}
|
||||
|
||||
for (HTTPRequestGroup requestGroup : requestGroups) {
|
||||
for (HTTPRequest request : requestGroup.requests) {
|
||||
if (request.path.contains("/{")) {
|
||||
request.path = request.path.replace("/{", "/${");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
additionalProperties.put("requestGroups", requestGroups);
|
||||
additionalProperties.put("extra", extraParameters);
|
||||
|
||||
for (String[] supportingTemplateFile : JAVASCRIPT_SUPPORTING_FILES) {
|
||||
String templateFile = supportingTemplateFile[0];
|
||||
String folder;
|
||||
if (INVOKER_PKG_SUPPORTING_FILES.contains(templateFile))
|
||||
// #1150: script.js must be generated to invokerPackage, otherwise
|
||||
// nothing works!
|
||||
folder = createPath(sourceFolder, invokerPackage);
|
||||
else
|
||||
folder = "";
|
||||
supportingFiles.add(new SupportingFile(templateFile, folder, supportingTemplateFile[1]));
|
||||
}
|
||||
}
|
||||
//
|
||||
private String generateNestedModelTemplate(CodegenModel model) {
|
||||
StringBuilder reference = new StringBuilder();
|
||||
int modelEntrySetSize = model.getAllVars().size();
|
||||
for (CodegenProperty property : model.getAllVars()) {
|
||||
reference.append(getDoubleQuotedString(property.name)).append(": ").append(getDoubleQuotedString(property.dataType.toLowerCase(Locale.ROOT)));
|
||||
if (modelEntrySetSize > 1)
|
||||
reference.append(", ");
|
||||
}
|
||||
reference = new StringBuilder("{" + reference + "}");
|
||||
reference = new StringBuilder(reference.toString().replace(", }", "}"));
|
||||
return reference.toString();
|
||||
}
|
||||
|
||||
private String getVariable(String input) {
|
||||
return "${" + input + "}";
|
||||
}
|
||||
|
||||
private String getTemplateString(String input) {
|
||||
return "`" + getVariable(input) + "`";
|
||||
}
|
||||
|
||||
private String getDoubleQuotedString(String input) {
|
||||
return "\"" + input + "\"";
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates an array of path segments into a path string.
|
||||
*
|
||||
* @param segments The path segments to concatenate. A segment may contain
|
||||
* either of the file separator characters '\' or '/'. A segment
|
||||
* is ignored if it is <code>null</code>, empty or
|
||||
* ".".
|
||||
* @return A path string using the correct platform-specific file separator
|
||||
* character.
|
||||
*/
|
||||
private String createPath(String... segments) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (String segment : segments) {
|
||||
if (!StringUtils.isEmpty(segment) && !segment.equals(".")) {
|
||||
if (buf.length() != 0)
|
||||
buf.append(File.separatorChar);
|
||||
buf.append(segment);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < buf.length(); i++) {
|
||||
char c = buf.charAt(i);
|
||||
if ((c == '/' || c == '\\') && c != File.separatorChar)
|
||||
buf.setCharAt(i, File.separatorChar);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apiFileFolder() {
|
||||
return createPath(outputFolder, sourceFolder, invokerPackage, apiPackage());
|
||||
}
|
||||
|
||||
public String getInvokerPackage() {
|
||||
return invokerPackage;
|
||||
}
|
||||
|
||||
public void setInvokerPackage(String invokerPackage) {
|
||||
this.invokerPackage = invokerPackage;
|
||||
}
|
||||
|
||||
public void setSourceFolder(String sourceFolder) {
|
||||
this.sourceFolder = sourceFolder;
|
||||
}
|
||||
|
||||
public void setProjectName(String projectName) {
|
||||
this.projectName = projectName;
|
||||
}
|
||||
|
||||
public void setModuleName(String moduleName) {
|
||||
this.moduleName = moduleName;
|
||||
}
|
||||
|
||||
public void setProjectDescription(String projectDescription) {
|
||||
this.projectDescription = projectDescription;
|
||||
}
|
||||
|
||||
public void setProjectVersion(String projectVersion) {
|
||||
this.projectVersion = projectVersion;
|
||||
}
|
||||
|
||||
public void setLicenseName(String licenseName) {
|
||||
this.licenseName = licenseName;
|
||||
}
|
||||
|
||||
public void setModelPropertyNaming(String naming) {
|
||||
if ("original".equals(naming) || "camelCase".equals(naming) || "PascalCase".equals(naming)
|
||||
|| "snake_case".equals(naming)) {
|
||||
this.modelPropertyNaming = naming;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid model property naming '" + naming
|
||||
+ "'. Must be 'original', 'camelCase', " + "'PascalCase' or 'snake_case'");
|
||||
}
|
||||
}
|
||||
|
||||
public void setPreserveLeadingParamChar(boolean preserveLeadingParamChar) {
|
||||
this.preserveLeadingParamChar = preserveLeadingParamChar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
// remove ', " to avoid code injection
|
||||
return input.replace("\"", "").replace("'", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input.replace("*/", "*_/").replace("/*", "/_*");
|
||||
}
|
||||
|
||||
private static String getAccept(OpenAPI openAPI, Operation operation) {
|
||||
String accepts = null;
|
||||
String defaultContentType = "application/json";
|
||||
Set<String> producesInfo = getProducesInfo(openAPI, operation);
|
||||
if (producesInfo != null && !producesInfo.isEmpty()) {
|
||||
ArrayList<String> produces = new ArrayList<>(producesInfo);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String produce : produces) {
|
||||
if (defaultContentType.equalsIgnoreCase(produce)) {
|
||||
accepts = defaultContentType;
|
||||
break;
|
||||
} else {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(produce);
|
||||
}
|
||||
}
|
||||
if (accepts == null) {
|
||||
accepts = sb.toString();
|
||||
}
|
||||
} else {
|
||||
accepts = defaultContentType;
|
||||
}
|
||||
|
||||
return accepts;
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,7 @@ org.openapitools.codegen.languages.JavascriptClientCodegen
|
||||
org.openapitools.codegen.languages.JavascriptFlowtypedClientCodegen
|
||||
org.openapitools.codegen.languages.JavascriptClosureAngularClientCodegen
|
||||
org.openapitools.codegen.languages.JMeterClientCodegen
|
||||
org.openapitools.codegen.languages.k6Codegen
|
||||
org.openapitools.codegen.languages.LuaClientCodegen
|
||||
org.openapitools.codegen.languages.MysqlSchemaCodegen
|
||||
org.openapitools.codegen.languages.NimClientCodegen
|
||||
|
||||
13
modules/openapi-generator/src/main/resources/k6/README.mustache
vendored
Normal file
13
modules/openapi-generator/src/main/resources/k6/README.mustache
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Generated k6 script
|
||||
|
||||
The `script.js` file contains most of the Swagger/OpenAPI specification and you can customize it to your needs.
|
||||
|
||||
Global header variables are defined at the top of the file, like `api_key`. Each path in the specification is converted into a [group](https://docs.k6.io/docs/tags-and-groups) in k6 and each group contains all the request methods related to that path. Path and query parameters are extracted from the specification and put at the start of the group. The URL is constructed from the base URL plus path and query.
|
||||
|
||||
k6 specific parameters are in the [`params`](https://docs.k6.io/docs/params-k6http) object, and `body` contains the [request](https://docs.k6.io/docs/http-requests) body which is in the form of `identifier: type`, which the `type` should be substituted by a proper value. Then goes the request and the check.
|
||||
|
||||
[Check](https://docs.k6.io/docs/checks) are like asserts but differ in that they don't halt execution, instead they just store the result of the check, pass or fail, and let the script execution continue.
|
||||
|
||||
Each request is always followed by a 0.1 second [sleep](https://docs.k6.io/docs/sleep-t-1) to prevent the script execution from flooding the system with too many requests simultaneously.
|
||||
|
||||
Note that the default iteration count and VU count is 1. So each request in each group will be executed once. For more information, see the [k6 options](https://docs.k6.io/docs/options).
|
||||
16
modules/openapi-generator/src/main/resources/k6/licenseInfo.mustache
vendored
Normal file
16
modules/openapi-generator/src/main/resources/k6/licenseInfo.mustache
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* {{appName}}
|
||||
* {{appDescription}}
|
||||
*
|
||||
{{#version}}
|
||||
* OpenAPI spec version: {{version}}
|
||||
{{/version}}
|
||||
{{#infoEmail}}
|
||||
* Contact: {{infoEmail}}
|
||||
{{/infoEmail}}
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/OpenAPITools/openapi-generator
|
||||
*
|
||||
* OpenAPI generator version: {{generatorVersion}}
|
||||
*/
|
||||
66
modules/openapi-generator/src/main/resources/k6/script.mustache
vendored
Normal file
66
modules/openapi-generator/src/main/resources/k6/script.mustache
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
{{>licenseInfo}}
|
||||
|
||||
import http from "k6/http";
|
||||
import { group, check, sleep } from "k6";
|
||||
|
||||
const BASE_URL = "{{baseURL}}";
|
||||
// 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.
|
||||
{{#extra}}
|
||||
let {{{key}}} = "TODO_EDIT_THE_{{{value}}}";
|
||||
{{/extra}}
|
||||
|
||||
export default function() {
|
||||
{{#requestGroups}}
|
||||
group("{{{groupName}}}", () => {
|
||||
{{#variables}}
|
||||
let {{{key}}} = "TODO_EDIT_THE_{{{value}}}";
|
||||
{{/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, {
|
||||
"<%& 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}}
|
||||
{{/requests}}
|
||||
});
|
||||
{{/requestGroups}}
|
||||
}
|
||||
23
samples/client/petstore/k6/.openapi-generator-ignore
Normal file
23
samples/client/petstore/k6/.openapi-generator-ignore
Normal file
@@ -0,0 +1,23 @@
|
||||
# OpenAPI Generator Ignore
|
||||
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
||||
|
||||
# Use this file to prevent files from being overwritten by the generator.
|
||||
# The patterns follow closely to .gitignore or .dockerignore.
|
||||
|
||||
# As an example, the C# client generator defines ApiClient.cs.
|
||||
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
||||
#ApiClient.cs
|
||||
|
||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||
#foo/*/qux
|
||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||
|
||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||
#foo/**/qux
|
||||
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||
|
||||
# You can also negate patterns with an exclamation (!).
|
||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||
#docs/*.md
|
||||
# Then explicitly reverse the ignore rule for a single file:
|
||||
#!docs/README.md
|
||||
1
samples/client/petstore/k6/.openapi-generator/VERSION
Normal file
1
samples/client/petstore/k6/.openapi-generator/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
4.3.0-SNAPSHOT
|
||||
13
samples/client/petstore/k6/README.md
Normal file
13
samples/client/petstore/k6/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Generated k6 script
|
||||
|
||||
The `script.js` file contains most of the Swagger/OpenAPI specification and you can customize it to your needs.
|
||||
|
||||
Global header variables are defined at the top of the file, like `api_key`. Each path in the specification is converted into a [group](https://docs.k6.io/docs/tags-and-groups) in k6 and each group contains all the request methods related to that path. Path and query parameters are extracted from the specification and put at the start of the group. The URL is constructed from the base URL plus path and query.
|
||||
|
||||
k6 specific parameters are in the [`params`](https://docs.k6.io/docs/params-k6http) object, and `body` contains the [request](https://docs.k6.io/docs/http-requests) body which is in the form of `identifier: type`, which the `type` should be substituted by a proper value. Then goes the request and the check.
|
||||
|
||||
[Check](https://docs.k6.io/docs/checks) are like asserts but differ in that they don't halt execution, instead they just store the result of the check, pass or fail, and let the script execution continue.
|
||||
|
||||
Each request is always followed by a 0.1 second [sleep](https://docs.k6.io/docs/sleep-t-1) to prevent the script execution from flooding the system with too many requests simultaneously.
|
||||
|
||||
Note that the default iteration count and VU count is 1. So each request in each group will be executed once. For more information, see the [k6 options](https://docs.k6.io/docs/options).
|
||||
204
samples/client/petstore/k6/script.js
Normal file
204
samples/client/petstore/k6/script.js
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* OpenAPI spec version: 1.0.0
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
*
|
||||
* Swagger Codegen version: 4.3.0-SNAPSHOT
|
||||
*/
|
||||
|
||||
|
||||
import http from "k6/http";
|
||||
import { group, check, sleep } from "k6";
|
||||
|
||||
const BASE_URL = "http://petstore.swagger.io/v2";
|
||||
// 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 api_key = "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);
|
||||
|
||||
// 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);
|
||||
});
|
||||
group("/pet/findByStatus", () => {
|
||||
let status = "TODO_EDIT_THE_STATUS";
|
||||
let url = BASE_URL + `/pet/findByStatus?status=${status}`;
|
||||
// Request No. 1
|
||||
let request = http.get(url);
|
||||
check(request, {
|
||||
"successful operation": (r) => r.status === 200
|
||||
});
|
||||
sleep(SLEEP_DURATION);
|
||||
});
|
||||
group("/pet/findByTags", () => {
|
||||
let tags = "TODO_EDIT_THE_TAGS";
|
||||
let url = BASE_URL + `/pet/findByTags?tags=${tags}`;
|
||||
// Request No. 1
|
||||
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";
|
||||
let url = BASE_URL + `/pet/${petId}`;
|
||||
// Request No. 1
|
||||
let request = http.get(url);
|
||||
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": `${api_key}`}};
|
||||
request = http.delete(url, params);
|
||||
sleep(SLEEP_DURATION);
|
||||
});
|
||||
group("/pet/{petId}/uploadImage", () => {
|
||||
let petId = "TODO_EDIT_THE_PETID";
|
||||
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, {
|
||||
"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, {
|
||||
"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";
|
||||
let url = BASE_URL + `/store/order/${orderId}`;
|
||||
// Request No. 1
|
||||
let request = http.get(url);
|
||||
check(request, {
|
||||
"successful operation": (r) => r.status === 200
|
||||
});
|
||||
sleep(SLEEP_DURATION);
|
||||
|
||||
// Request No. 2
|
||||
request = http.delete(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, {
|
||||
"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, {
|
||||
"successful operation": (r) => r.status === 200
|
||||
});
|
||||
sleep(SLEEP_DURATION);
|
||||
});
|
||||
group("/user/createWithList", () => {
|
||||
let url = BASE_URL + `/user/createWithList`;
|
||||
// Request No. 1
|
||||
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/login", () => {
|
||||
let password = "TODO_EDIT_THE_PASSWORD";
|
||||
let username = "TODO_EDIT_THE_USERNAME";
|
||||
let url = BASE_URL + `/user/login?username=${username}&password=${password}`;
|
||||
// Request No. 1
|
||||
let request = http.get(url);
|
||||
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, {
|
||||
"successful operation": (r) => r.status === 200
|
||||
});
|
||||
sleep(SLEEP_DURATION);
|
||||
});
|
||||
group("/user/{username}", () => {
|
||||
let username = "TODO_EDIT_THE_USERNAME";
|
||||
let url = BASE_URL + `/user/${username}`;
|
||||
// Request No. 1
|
||||
let request = http.get(url);
|
||||
check(request, {
|
||||
"successful operation": (r) => r.status === 200
|
||||
});
|
||||
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.delete(url);
|
||||
sleep(SLEEP_DURATION);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user