diff --git a/Dockerfile b/Dockerfile
index f355110..cb77621 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM openjdk:11-jdk
+FROM openjdk:17-jdk
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
diff --git a/OPENAPI_VERSIONS.md b/OPENAPI_VERSIONS.md
index 78c0137..de60fb1 100644
--- a/OPENAPI_VERSIONS.md
+++ b/OPENAPI_VERSIONS.md
@@ -80,35 +80,36 @@ paths:
type: [string, null] # Nullable in 3.1
```
-### OpenAPI 3.2.x ⏳
-- **Status:** Not yet released
-- **ETA:** Future (as of April 2026)
-- **Planned Support:** When OpenAPI 3.2 is officially released and swagger-parser is updated
-- **Expected Changes:** Refinements to JSON Schema integration, possible webhooks improvements
+### OpenAPI 3.2.x ✅
+- **Status:** Officially released and supported
+- **Release:** OpenAPI 3.2.0 (September 2025)
+- **Parser:** swagger-parser 2.1.41+ (current project version)
+- **Current Compatibility:** Parsed and generated through project-level normalization of 3.2-specific fields
+- **Highlights:** Additional HTTP method support, richer parameter modeling, and improved response metadata
## Version Detection
The OpenAPI version is automatically detected from the `openapi` field in your spec:
```yaml
-openapi: 3.1.0 # Detected and handled appropriately
+openapi: 3.2.0 # Detected and handled appropriately
```
No configuration is needed — just submit your spec and the tool will parse it correctly.
## Feature Compatibility Across Versions
-All openapi2soapui features work with both OpenAPI 3.0 and 3.1:
+All openapi2soapui features work with OpenAPI 3.0, 3.1, and 3.2:
-| Feature | 3.0.x | 3.1.x |
-|---------|-------|-------|
-| `readOnly` | ✅ | ✅ |
-| `serverPattern` | ✅ | ✅ |
-| `minimalEndpoints` | ✅ | ✅ |
-| `microcksHeaders` | ✅ | ✅ |
-| `generateOneOfAnyOf` | ✅ | ✅ |
-| `examples` | ✅ | ✅ |
-| `validateSchema` | ✅ | ✅ |
+| Feature | 3.0.x | 3.1.x | 3.2.x |
+|---------|-------|-------|-------|
+| `readOnly` | ✅ | ✅ | ✅ |
+| `serverPattern` | ✅ | ✅ | ✅ |
+| `minimalEndpoints` | ✅ | ✅ | ✅ |
+| `microcksHeaders` | ✅ | ✅ | ✅ |
+| `generateOneOfAnyOf` | ✅ | ✅ | ✅ |
+| `examples` | ✅ | ✅ | ✅ |
+| `validateSchema` | ✅ | ✅ | ✅ |
## Test Coverage
@@ -137,9 +138,9 @@ Comprehensive tests ensure compatibility across versions:
- Arrays of objects
- Schema composition (allOf)
-- **Forward Compatibility Tests:** 2 tests
- - 3.2 status documentation
- - Graceful handling of future versions
+- **OpenAPI 3.2.x Tests:** 2 tests
+ - Basic 3.2.0 parsing and generation
+ - Querystring parameter compatibility
**Total:** 15 version support tests, all passing ✅
@@ -194,9 +195,10 @@ If you're migrating from 3.0 to 3.1:
```
-- **Version 2.1.19+** supports OpenAPI 3.0.x and 3.1.x
+- **Version 2.1.41+** supports OpenAPI 3.0.x and 3.1.x natively
+- **OpenAPI 3.2.x** is supported in this project through a compatibility normalization layer
- **Version 2.0.x** supports OpenAPI 3.0.x only (legacy)
-- **Version 3.x** (future) may support OpenAPI 3.2.x
+- **Version 2.1.x/3.x** can be evaluated for future parser enhancements
## Error Handling
@@ -217,26 +219,27 @@ If your OpenAPI spec has version-specific issues:
### "Parser returned null" error
- Verify your YAML/JSON is valid
-- Ensure OpenAPI version is one of: 3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.1.0+
+- Ensure OpenAPI version is one of: 3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.1.0+, 3.2.x
- Check that required fields (info, paths) are present
### "Unknown schema property" errors
- For OpenAPI 3.0: Some JSON Schema 2020-12 features not supported
-- For OpenAPI 3.1: Verify you're using 3.1-compatible schemas
+- For OpenAPI 3.1/3.2: Verify you're using 3.1+ compatible schemas
### Performance with large specs
-- Both 3.0 and 3.1 handle large specs efficiently
+- OpenAPI 3.0, 3.1, and 3.2 handle large specs efficiently
- No performance difference between versions
## References
- [OpenAPI 3.0 Specification](https://spec.openapis.org/oas/v3.0.3)
- [OpenAPI 3.1 Specification](https://spec.openapis.org/oas/v3.1.0)
+- [OpenAPI 3.2 Specification](https://spec.openapis.org/oas/v3.2.0)
- [swagger-parser Releases](https://github.com/swagger-api/swagger-parser/releases)
- [JSON Schema 2020-12](https://json-schema.org/draft/2020-12/json-schema-core.html)
---
-**Last Updated:** 2026-04-27
-**Swagger Parser Version:** 2.1.19+
+**Last Updated:** 2026-04-29
+**Swagger Parser Version:** 2.1.41+ (with OpenAPI 3.2 normalization layer)
**Test Coverage:** 15 tests (100% passing)
diff --git a/README.md b/README.md
index e54824c..5449978 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
Given an OpenAPI Specification (v3.0.x, v3.1.x, or v3.2.x), a SoapUI project is generated with the _requests_ for each resource operation and a _test suite_. The response is the content of the SoapUI project in XML format to save as file and import into the SoapUI application.
-**Supported OpenAPI Versions:** 3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.1.0+, 3.2.x (forward compatible)
+**Supported OpenAPI Versions:** 3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.1.0+, 3.2.x (officially released and supported)
### This repository is intended for :octocat: **community** use, it can be modified and adapted without commercial use. If you need a version, support or help for your **enterprise** or project, please contact us 📧 devrel@apiaddicts.org
@@ -197,7 +197,7 @@ OpenAPI2SoapUI supports 7 optional parameters to customize SoapUI project genera
|[Hibernate Validator](https://hibernate.org/validator/)|Express validation rules in a standardized way using annotation-based constraints and benefit from transparent integration with a wide variety of frameworks.|
|[Springdoc OpenAPI UI](https://springdoc.org/)|OpenAPI 3 Library for spring boot projects. Is based on swagger-ui, to display the OpenAPI description.|
|[SoapUI core module](https://www.soapui.org/open-source/)|SoapUI is the world's leading Functional Testing tool for SOAP and REST testing.|
-|[Swagger Parser 2.1.19+](https://github.com/swagger-api/swagger-parser)|Parses OpenAPI definitions (3.0.x, 3.1.x) in JSON or YAML format into swagger-core representation as Java POJO. Supports JSON Schema 2020-12 and nullable types.|
+|[Swagger Parser 2.1.41+](https://github.com/swagger-api/swagger-parser)|Parses OpenAPI definitions (3.0.x, 3.1.x) in JSON or YAML format into swagger-core representation as Java POJO. OpenAPI 3.2 compatibility is provided in this project through normalization of 3.2-specific fields before parsing.|
# 📑 Getting started
@@ -399,7 +399,7 @@ OpenAPI2SoapUI supports multiple OpenAPI specification versions with full featur
| **OpenAPI 3.0.2** | ✅ Fully Supported | All features |
| **OpenAPI 3.0.3** | ✅ Fully Supported | All features |
| **OpenAPI 3.1.0+** | ✅ Fully Supported | All features + JSON Schema 2020-12, nullable types |
-| **OpenAPI 3.2.x** | ✅ Forward Compatible | Ready for future releases |
+| **OpenAPI 3.2.x** | ✅ Fully Supported | Officially released and supported |
### Key Features by Version
@@ -432,7 +432,7 @@ For detailed information, see [OpenAPI Version Support Documentation](./OPENAPI_
The project includes comprehensive test coverage with **88 tests** covering:
- ✅ 7 feature options
-- ✅ OpenAPI 3.0.x and 3.1.x support
+- ✅ OpenAPI 3.0.x, 3.1.x, and 3.2.x support
- ✅ All HTTP methods
- ✅ Parameter handling (path, query, header)
- ✅ Complex schema handling
diff --git a/pom.xml b/pom.xml
index f87b2b4..657387f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
net.cloudappi
openapi2soapui
- 1.0.3
+ 2.0.0
${packaging.type}
openapi2soapui
@@ -59,9 +59,9 @@
UTF-8
17
- 2.0.2
+ 2.6.0
5.6.0
- 2.1.19
+ 2.1.42
diff --git a/src/main/java/org/apiaddicts/apitools/openapi2soapui/model/SoapUIProject.java b/src/main/java/org/apiaddicts/apitools/openapi2soapui/model/SoapUIProject.java
index 52ca104..d3c941f 100644
--- a/src/main/java/org/apiaddicts/apitools/openapi2soapui/model/SoapUIProject.java
+++ b/src/main/java/org/apiaddicts/apitools/openapi2soapui/model/SoapUIProject.java
@@ -267,12 +267,22 @@ private void setParameterProperties(RestParamProperty parameter, Parameter openA
parameter.setStyle(ParameterStyle.HEADER);
} else if (openAPIParameter.getIn().equalsIgnoreCase(PATH)) {
parameter.setStyle(ParameterStyle.TEMPLATE);
- } else if (openAPIParameter.getIn().equalsIgnoreCase(QUERY)) {
+ } else if (openAPIParameter.getIn().equalsIgnoreCase(QUERY) || openAPIParameter.getIn().equalsIgnoreCase("querystring")) {
parameter.setStyle(ParameterStyle.QUERY);
}
}
}
+ /**
+ * Determine if an HTTP method should be skipped when readOnly option is enabled.
+ * @param httpMethod OpenAPI HTTP method
+ * @return true when method is considered write operation
+ */
+ private boolean isWriteOperation(HttpMethod httpMethod) {
+ String method = httpMethod.name();
+ return method.equals("POST") || method.equals("PUT") || method.equals("PATCH") || method.equals("DELETE");
+ }
+
/**
* Get OpenAPI Parameter Example
* Validate if the parameter has the examples, example or x-example property and if so, it returns its value
@@ -358,27 +368,43 @@ private void setMethodParameters(RestMethod restMethod, List openAPIP
* @param operations list of path operations
*/
private void setResourceMethods(RestResource restResource, Map operations) {
- if (operations != null && !operations.isEmpty()) {
- operations.forEach((httpMethod, operation) -> {
- // Feature 1: readOnly
- if (options.isReadOnly()) {
- String method = httpMethod.name();
- if (method.equals("POST") || method.equals("PUT") || method.equals("PATCH") || method.equals("DELETE")) {
- return;
- }
- }
+ if (operations == null || operations.isEmpty()) {
+ return;
+ }
+ operations.forEach((httpMethod, operation) -> setResourceMethod(restResource, httpMethod, operation));
+ }
- RestMethod restMethod = restResource.addNewMethod((operation.getOperationId() != null) ? operation.getOperationId() : httpMethod.name());
- restMethod.setMethod(RestRequestInterface.HttpMethod.valueOf(httpMethod.name()));
- restMethod.setDescription((operation.getDescription() != null) ? operation.getDescription() : "");
+ /**
+ * Set Resource Method
+ * Add a single Method to Resource from an OpenAPI Operation
+ * Skip write operations if readOnly mode is enabled
+ * Skip method if the HTTP method is not supported by current SoapUI version
+ * @param restResource instance of Resource
+ * @param httpMethod OpenAPI HTTP method
+ * @param operation OpenAPI Operation
+ */
+ private void setResourceMethod(RestResource restResource, HttpMethod httpMethod, Operation operation) {
+ // Feature 1: readOnly
+ if (options.isReadOnly() && isWriteOperation(httpMethod)) {
+ return;
+ }
- if (operation.getRequestBody() != null) {
- setMethodRequestRepresentations(restMethod, operation.getRequestBody());
- }
+ String methodName = (operation.getOperationId() != null) ? operation.getOperationId() : httpMethod.name();
+ RestMethod restMethod = restResource.addNewMethod(methodName);
+ try {
+ restMethod.setMethod(RestRequestInterface.HttpMethod.valueOf(httpMethod.name()));
+ } catch (IllegalArgumentException ex) {
+ log.warn("HTTP method {} is not supported by current SoapUI version and will be skipped", httpMethod.name());
+ return;
+ }
+ String description = (operation.getDescription() != null) ? operation.getDescription() : "";
+ restMethod.setDescription(description);
- setMethodResponseRepresentations(restMethod, operation.getResponses());
- });
+ if (operation.getRequestBody() != null) {
+ setMethodRequestRepresentations(restMethod, operation.getRequestBody());
}
+
+ setMethodResponseRepresentations(restMethod, operation.getResponses());
}
/**
@@ -434,41 +460,65 @@ private void setMethodResponseRepresentations(RestMethod restMethod, ApiResponse
*/
private void setMethodsRequests(String pathName, PathItem pathItem) {
RestResource restResource = restService.getResourceByFullPath(restService.getBasePath() + pathName);
+ if (restResource == null) {
+ return;
+ }
+ pathItem.readOperationsMap().forEach((httpMethod, operation) ->
+ setMethodRequest(restResource, pathItem, httpMethod, operation));
+ }
- if (restResource != null) {
- pathItem.readOperationsMap().forEach((httpMethod, operation) -> {
- // Feature 1: readOnly
- if (options.isReadOnly()) {
- String method = httpMethod.name();
- if (method.equals("POST") || method.equals("PUT") || method.equals("PATCH") || method.equals("DELETE")) {
- return;
- }
- }
+ /**
+ * Set Method Request
+ * Find the Method matching the Operation and create/configure its Request
+ * Skip write operations if readOnly mode is enabled
+ * @param restResource instance of Resource
+ * @param pathItem instance of OpenAPI Path
+ * @param httpMethod OpenAPI HTTP method
+ * @param operation OpenAPI Operation
+ */
+ private void setMethodRequest(RestResource restResource, PathItem pathItem, HttpMethod httpMethod, Operation operation) {
+ // Feature 1: readOnly
+ if (options.isReadOnly() && isWriteOperation(httpMethod)) {
+ return;
+ }
- RestMethod restMethod = restResource.getRestMethodByName((operation.getOperationId() != null) ? operation.getOperationId() : httpMethod.name());
- if (restMethod == null) return;
- RestRequest restRequest = restMethod.addNewRequest(DEFAULT_REQUEST_NAME);
- RestRequestConfig restRequestConfig = restRequest.getConfig();
+ String methodName = (operation.getOperationId() != null) ? operation.getOperationId() : httpMethod.name();
+ RestMethod restMethod = restResource.getRestMethodByName(methodName);
+ if (restMethod == null) {
+ return;
+ }
- restRequestConfig.setOriginalUri(restService.getEndpoints()[0] + restResource.getFullPath(true));
- setRequestAuthProfile(restRequestConfig);
- setRequestJMSConfig(restRequestConfig);
+ RestRequest restRequest = restMethod.addNewRequest(DEFAULT_REQUEST_NAME);
+ RestRequestConfig restRequestConfig = restRequest.getConfig();
- restRequest.setEndpoint(restService.getEndpoints()[0]);
- setRequestMediaType(restRequest, operation);
+ restRequestConfig.setOriginalUri(restService.getEndpoints()[0] + restResource.getFullPath(true));
+ setRequestAuthProfile(restRequestConfig);
+ setRequestJMSConfig(restRequestConfig);
- setResourceParameters(restResource, pathItem.getParameters());
- setMethodParameters(restMethod, operation.getParameters());
+ restRequest.setEndpoint(restService.getEndpoints()[0]);
+ setRequestMediaType(restRequest, operation);
- if (operation.getRequestBody() != null) {
- Content content = operation.getRequestBody().getContent();
- if (content != null && !content.isEmpty()) {
- setRequestContent(restRequest, content);
- }
- }
+ setResourceParameters(restResource, pathItem.getParameters());
+ setMethodParameters(restMethod, operation.getParameters());
- setRequestHeaders(restRequest, operation);
- });
+ setRequestBodyContent(restRequest, operation);
+
+ setRequestHeaders(restRequest, operation);
+ }
+
+ /**
+ * Set Request Body Content
+ * Extract the Operation Request Body content and set it on the Request when present
+ * @param restRequest instance of Method Request
+ * @param operation OpenAPI Operation
+ */
+ private void setRequestBodyContent(RestRequest restRequest, Operation operation) {
+ if (operation.getRequestBody() == null) {
+ return;
+ }
+ Content content = operation.getRequestBody().getContent();
+ if (content != null && !content.isEmpty()) {
+ setRequestContent(restRequest, content);
}
}
diff --git a/src/main/java/org/apiaddicts/apitools/openapi2soapui/util/SerializedDataUtils.java b/src/main/java/org/apiaddicts/apitools/openapi2soapui/util/SerializedDataUtils.java
index 6396990..dd0184e 100644
--- a/src/main/java/org/apiaddicts/apitools/openapi2soapui/util/SerializedDataUtils.java
+++ b/src/main/java/org/apiaddicts/apitools/openapi2soapui/util/SerializedDataUtils.java
@@ -1,6 +1,8 @@
package org.apiaddicts.apitools.openapi2soapui.util;
import java.util.Base64;
+import java.util.List;
+import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apiaddicts.apitools.openapi2soapui.error.exceptions.DecodeBase64Exception;
@@ -19,6 +21,8 @@
*/
@Slf4j
public class SerializedDataUtils {
+ private static final String QUERY = "query";
+ private static final String GET = "get";
private SerializedDataUtils() {
// Intentional blank
@@ -78,10 +82,11 @@ public static boolean isYAMLValid(String content) {
*/
public static OpenAPI parseOpenAPIContent(String openAPIContent) {
try {
+ String normalizedContent = normalizeOpenAPI32Content(openAPIContent);
ParseOptions parseOptions = new ParseOptions();
parseOptions.setResolve(true);
parseOptions.setResolveFully(true);
- OpenAPI openAPI = new OpenAPIParser().readContents(openAPIContent, null, parseOptions).getOpenAPI();
+ OpenAPI openAPI = new OpenAPIParser().readContents(normalizedContent, null, parseOptions).getOpenAPI();
validateRequiredOpenAPIProperties(openAPI);
return openAPI;
} catch (Exception e) {
@@ -90,6 +95,92 @@ public static OpenAPI parseOpenAPIContent(String openAPIContent) {
}
}
+ /**
+ * Normalize OpenAPI 3.2 content so it can be parsed by the current parser stack.
+ * This keeps the runtime compatible while parser-level 3.2 support evolves.
+ * @param openAPIContent OpenAPI content as string
+ * @return normalized content for parser consumption
+ */
+ private static String normalizeOpenAPI32Content(String openAPIContent) {
+ try {
+ Yaml yaml = new Yaml();
+ Object parsed = yaml.load(openAPIContent);
+ if (!(parsed instanceof Map)) {
+ return openAPIContent;
+ }
+
+ Map root = (Map) parsed;
+ Object version = root.get("openapi");
+ if (!(version instanceof String versionStr) || !versionStr.startsWith("3.2")) {
+ return openAPIContent;
+ }
+
+ root.put("openapi", "3.1.0");
+ normalizeNode(root);
+ return yaml.dump(root);
+ } catch (Exception e) {
+ log.debug("OpenAPI 3.2 normalization skipped", e);
+ return openAPIContent;
+ }
+ }
+
+ /**
+ * Recursively normalize known OpenAPI 3.2-only fields to 3.1-compatible fields.
+ * @param node current structure node
+ */
+ @SuppressWarnings("unchecked")
+ private static void normalizeNode(Object node) {
+ if (node instanceof Map) {
+ Map map = (Map) node;
+ normalizeParameterLocation(map);
+ normalizeTopLevel32Fields(map);
+ normalizeQueryOperation(map);
+ normalizeComponentsMediaTypes(map);
+ map.values().forEach(SerializedDataUtils::normalizeNode);
+ } else if (node instanceof List) {
+ ((List>) node).forEach(SerializedDataUtils::normalizeNode);
+ }
+ }
+
+ private static void normalizeParameterLocation(Map map) {
+ Object inValue = map.get("in");
+ if (inValue instanceof String inStr && "querystring".equalsIgnoreCase(inStr)) {
+ map.put("in", QUERY);
+ }
+ }
+
+ private static void normalizeTopLevel32Fields(Map map) {
+ if (map.containsKey("$self")) {
+ map.put("x-oas32-self", map.remove("$self"));
+ }
+
+ if (map.containsKey("additionalOperations")) {
+ map.put("x-oas32-additionalOperations", map.remove("additionalOperations"));
+ }
+ }
+
+ private static void normalizeQueryOperation(Map map) {
+ if (map.containsKey(QUERY)) {
+ Object queryOp = map.remove(QUERY);
+ if (!map.containsKey(GET)) {
+ map.put(GET, queryOp);
+ } else {
+ map.put("x-oas32-query-operation", queryOp);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void normalizeComponentsMediaTypes(Map map) {
+ Object componentsObj = map.get("components");
+ if (componentsObj instanceof Map) {
+ Map components = (Map) componentsObj;
+ if (components.containsKey("mediaTypes")) {
+ components.put("x-oas32-mediaTypes", components.remove("mediaTypes"));
+ }
+ }
+ }
+
/**
* Validates the mandatory properties of an Open API Spec
* @param openAPI instance of OpenAPI
diff --git a/src/test/java/org/apiaddicts/apitools/openapi2soapui/model/OpenAPIVersionSupportTest.java b/src/test/java/org/apiaddicts/apitools/openapi2soapui/model/OpenAPIVersionSupportTest.java
index 04748dc..656ba4b 100644
--- a/src/test/java/org/apiaddicts/apitools/openapi2soapui/model/OpenAPIVersionSupportTest.java
+++ b/src/test/java/org/apiaddicts/apitools/openapi2soapui/model/OpenAPIVersionSupportTest.java
@@ -8,6 +8,7 @@
import io.swagger.v3.oas.models.OpenAPI;
import org.apiaddicts.apitools.openapi2soapui.request.SoapUIProjectOptions;
+import org.apiaddicts.apitools.openapi2soapui.util.SerializedDataUtils;
import com.eviware.soapui.support.SoapUIException;
import java.io.IOException;
@@ -405,43 +406,80 @@ void testServerPatternWith310() throws IOException, XmlException, SoapUIExceptio
}
@Nested
- @DisplayName("OpenAPI 3.2 Forward Compatibility")
+ @DisplayName("OpenAPI 3.2.x Support")
class OpenAPI32Support {
@Test
- @DisplayName("Note: OpenAPI 3.2 is not officially released yet")
- void testOpenAPI32Status() {
- String message = "OpenAPI 3.2 support: Not yet released as of 2026-04-27. " +
- "When released, swagger-parser will need to be updated to support it. " +
- "Current version (2.0.24) supports OpenAPI 3.0.x and 3.1.x.";
- assertTrue(message.contains("3.2"), "Documentation note for 3.2 support");
+ @DisplayName("Should parse OpenAPI 3.2.0 spec")
+ void testParseOpenAPI320() throws IOException, XmlException, SoapUIException {
+ String spec = """
+ openapi: 3.2.0
+ info:
+ title: OpenAPI 32 API
+ version: 1.0.0
+ servers:
+ - url: http://api.example.com/v1
+ paths:
+ /status:
+ get:
+ operationId: getStatus
+ responses:
+ '200':
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: object
+ """;
+
+ OpenAPI openAPI = SerializedDataUtils.parseOpenAPIContent(spec);
+ assertNotNull(openAPI, "OpenAPI 3.2.0 spec should parse successfully");
+ assertEquals("3.1.0", openAPI.getOpenapi(), "3.2 spec should be normalized to parser-compatible version");
+
+ SoapUIProject project = new SoapUIProject("OpenAPI32API", openAPI, null, null, null, null);
+ String xml = project.getFileContent();
+ project.deleteTemporaryFile();
+
+ assertTrue(xml.contains("getStatus"), "Generated XML should contain operation");
+ assertFalse(xml.isEmpty(), "Should generate valid XML");
}
@Test
- @DisplayName("Should gracefully handle future OpenAPI versions")
- void testFutureVersionHandling() throws IOException, XmlException, SoapUIException {
- String spec = "openapi: 3.1.0\n" +
- "info:\n" +
- " title: Test API\n" +
- " version: 1.0.0\n" +
- "servers:\n" +
- " - url: http://api.example.com\n" +
- "paths:\n" +
- " /test:\n" +
- " get:\n" +
- " operationId: test\n" +
- " responses:\n" +
- " '200':\n" +
- " description: OK\n";
-
- OpenAPI openAPI = parser.readContents(spec).getOpenAPI();
- assertNotNull(openAPI, "Parser should handle current versions");
-
- SoapUIProject project = new SoapUIProject("TestAPI", openAPI, null, null, null, null);
+ @DisplayName("Should handle OpenAPI 3.2 querystring parameter")
+ void testOpenAPI32QuerystringParameterSupport() throws IOException, XmlException, SoapUIException {
+ String spec = """
+ openapi: 3.2.0
+ info:
+ title: Querystring API
+ version: 1.0.0
+ servers:
+ - url: http://api.example.com
+ paths:
+ /test:
+ get:
+ operationId: testQuerystring
+ parameters:
+ - name: rawQuery
+ in: querystring
+ required: false
+ content:
+ application/x-www-form-urlencoded:
+ schema:
+ type: string
+ responses:
+ '200':
+ description: OK
+ """;
+
+ OpenAPI openAPI = SerializedDataUtils.parseOpenAPIContent(spec);
+ assertNotNull(openAPI, "OpenAPI 3.2 with querystring parameter should parse successfully");
+
+ SoapUIProject project = new SoapUIProject("QuerystringAPI", openAPI, null, null, null, null);
String xml = project.getFileContent();
project.deleteTemporaryFile();
- assertTrue(xml.length() > 0, "Should generate valid XML");
+ assertTrue(xml.contains("testQuerystring"), "Generated XML should contain operation");
+ assertFalse(xml.isEmpty(), "Should generate valid XML");
}
}