Skip to content

Commit a451edf

Browse files
committed
fix: Fix for #5 - parameters example leaking between ops on the same path
1 parent 12bd938 commit a451edf

3 files changed

Lines changed: 91 additions & 6 deletions

File tree

src/main/java/dev/dochia/cli/core/factory/PlaybookDataFactory.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import dev.dochia.cli.core.util.OpenApiUtils;
2121
import io.github.ludovicianul.prettylogger.PrettyLogger;
2222
import io.github.ludovicianul.prettylogger.PrettyLoggerFactory;
23+
import io.swagger.v3.core.util.Json;
2324
import io.swagger.v3.oas.models.OpenAPI;
2425
import io.swagger.v3.oas.models.Operation;
2526
import io.swagger.v3.oas.models.PathItem;
@@ -159,13 +160,14 @@ private Schema<?> createSyntheticSchemaForGet(List<Parameter> operationParameter
159160

160161
if ((isPathParam || isQueryParam) && filesArguments.isNotUrlParam(parameter.getName()) && StringUtils.isNotBlank(parameter.getName())) {
161162
String newParameterName = parameter.getName() + "|" + parameter.getIn();
162-
parameter.setSchema(Optional.ofNullable(parameter.getSchema()).orElse(new Schema<>()));
163-
parameter.getSchema().setName(newParameterName);
163+
Schema<?> originalSchema = Optional.ofNullable(parameter.getSchema()).orElse(new Schema<>());
164+
Schema<?> schemaCopy = Json.mapper().convertValue(originalSchema, Schema.class);
165+
schemaCopy.setName(newParameterName);
164166

165-
syntheticSchema.addProperty(parameter.getName(), parameter.getSchema());
166-
if (parameter.getSchema().getExample() == null) {
167-
parameter.getSchema().setExample(parameter.getExample());
168-
}
167+
Object effectiveExample = schemaCopy.getExample() != null ? schemaCopy.getExample() : parameter.getExample();
168+
schemaCopy.setExample(effectiveExample);
169+
170+
syntheticSchema.addProperty(parameter.getName(), schemaCopy);
169171
if (parameter.getRequired() != null && parameter.getRequired()) {
170172
required.add(parameter.getName());
171173
}

src/test/java/dev/dochia/cli/core/factory/PlaybookDataFactoryTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,4 +1330,23 @@ void shouldMergeParametersSameNameDifferentIn() {
13301330
List<Parameter> merged = playbookDataFactory.mergeParameters(pathItem, operation);
13311331
Assertions.assertThat(merged).hasSize(2);
13321332
}
1333+
1334+
@Test
1335+
void shouldNotLeakPostExampleIntoGetQueryParams() throws Exception {
1336+
Mockito.when(processingArguments.examplesFlags()).thenReturn(new ProcessingArguments.ExamplesFlags(false, false, false, true));
1337+
List<PlaybookData> dataList = setupPlaybookData("/api/products", "src/test/resources/cross-operation-example-leak.yml");
1338+
1339+
List<PlaybookData> getDataList = dataList.stream().filter(d -> d.getMethod() == HttpMethod.GET).toList();
1340+
Assertions.assertThat(getDataList).isNotEmpty();
1341+
1342+
PlaybookData getData = getDataList.getFirst();
1343+
String payload = getData.getPayload();
1344+
1345+
String postLongExample = "images,variantParameters,allCategories,flags";
1346+
1347+
Assertions.assertThat(JsonUtils.getVariableFromJson(payload, "$.include")).asString().isEqualTo("images");
1348+
Assertions.assertThat(JsonUtils.getVariableFromJson(payload, "$.supplierGuid")).asString().isNotEqualTo(postLongExample);
1349+
Assertions.assertThat(JsonUtils.getVariableFromJson(payload, "$.brandName")).asString().isNotEqualTo(postLongExample);
1350+
Assertions.assertThat(JsonUtils.getVariableFromJson(payload, "$.changeTimeFrom")).asString().isNotEqualTo(postLongExample);
1351+
}
13331352
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
openapi: 3.0.3
2+
info:
3+
title: Cross-operation example leak regression test
4+
version: 1.0.0
5+
paths:
6+
/api/products:
7+
post:
8+
operationId: createProducts
9+
summary: POST products
10+
parameters:
11+
- name: include
12+
in: query
13+
example: images,variantParameters,allCategories,flags
14+
schema:
15+
type: string
16+
requestBody:
17+
required: true
18+
content:
19+
application/json:
20+
schema:
21+
$ref: '#/components/schemas/ProductRequest'
22+
responses:
23+
'201':
24+
description: Created
25+
get:
26+
operationId: listProducts
27+
summary: GET products
28+
parameters:
29+
- name: include
30+
in: query
31+
example: images
32+
schema:
33+
type: string
34+
- name: supplierGuid
35+
in: query
36+
example: 16a67ec6-d957-11e0-b04f-57a43310b768
37+
schema:
38+
type: string
39+
- name: brandName
40+
in: query
41+
example: AcmeBrand
42+
schema:
43+
type: string
44+
- name: changeTimeFrom
45+
in: query
46+
example: 2017-02-28T17:04:47+0100
47+
schema:
48+
type: string
49+
- name: page
50+
in: query
51+
example: 3
52+
schema:
53+
type: integer
54+
responses:
55+
'200':
56+
description: OK
57+
components:
58+
schemas:
59+
ProductRequest:
60+
type: object
61+
properties:
62+
name:
63+
type: string
64+
example: MyProduct

0 commit comments

Comments
 (0)