Skip to content

Commit 777a814

Browse files
committed
fix: Fix for #187 - swagger 2.0 parser was adding a trailing / in base path
1 parent abd0319 commit 777a814

File tree

6 files changed

+38
-47
lines changed

6 files changed

+38
-47
lines changed

src/main/java/com/endava/cats/args/ApiArguments.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ public void validateValidServer(CommandLine.Model.CommandSpec spec, OpenAPI open
121121
}
122122
}
123123

124+
this.validateURL(spec);
125+
126+
if (this.server.endsWith("/")) {
127+
this.server = this.server.substring(0, this.server.length() - 1);
128+
}
129+
log.debug("Final server URL: {}", this.server);
130+
}
131+
132+
private void validateURL(CommandLine.Model.CommandSpec spec) {
124133
if (this.server == null) {
125134
throw new CommandLine.ParameterException(spec.commandLine(),
126135
"Missing required option --server=<server>");

src/main/java/com/endava/cats/io/ServiceCaller.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,11 @@ public CatsResponse call(ServiceData data) {
262262
*
263263
* @param data the service data context
264264
* @param processedPayload current payload
265-
* @return an url with path params replaced by urlParams or refData + additional query params
265+
* @return a url with path params replaced by urlParams or refData + additional query params
266266
*/
267267
String constructUrl(ServiceData data, String processedPayload) {
268268
String decodedUrl = CatsUtil.unescapeCurlyBrackets(apiArguments.getServer() + data.getRelativePath());
269+
logger.debug("Decoded URL: {}", decodedUrl);
269270
if (!data.isReplaceUrlParams()) {
270271
String actualUrl = this.replacePathParams(decodedUrl, processedPayload, data);
271272
return this.replaceRemovedParams(actualUrl);
@@ -279,6 +280,7 @@ String constructUrl(ServiceData data, String processedPayload) {
279280
}
280281
url = this.addPathParamsIfNotReplaced(url, data.getPathParamsPayload());
281282
url = this.addAdditionalQueryParams(url, data.getRelativePath());
283+
logger.debug("Replaced URL: {}", url);
282284
return url;
283285
}
284286

src/main/java/com/endava/cats/util/CatsUtil.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,6 @@ public static Faker faker() {
318318
public static boolean isValidURL(String urlString) {
319319
try {
320320
URI.create(urlString).toURL();
321-
322321
return true;
323322
} catch (Exception _) {
324323
return false;

src/test/java/com/endava/cats/args/ApiArgumentsTest.java

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
import io.swagger.v3.oas.models.OpenAPI;
55
import org.assertj.core.api.Assertions;
66
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.params.ParameterizedTest;
8+
import org.junit.jupiter.params.provider.Arguments;
9+
import org.junit.jupiter.params.provider.MethodSource;
710
import org.mockito.Mockito;
811
import org.springframework.test.util.ReflectionTestUtils;
912
import picocli.CommandLine;
1013

1114
import java.util.Collections;
15+
import java.util.stream.Stream;
1216

1317
@QuarkusTest
1418
class ApiArgumentsTest {
@@ -66,54 +70,30 @@ void shouldThrowExceptionWhenServerAndOpenApiNull() {
6670
.hasMessageContaining("server");
6771
}
6872

69-
@Test
70-
void shouldSetServerFromOpenApiWhenServerIsNull() {
73+
@ParameterizedTest(name = "{0}")
74+
@MethodSource("serverResolutionArguments")
75+
void shouldResolveServerAccordingToPriority(String description, String initialServer, String openApiServerUrl, String expectedServer) {
7176
CommandLine.Model.CommandSpec spec = Mockito.mock(CommandLine.Model.CommandSpec.class);
7277
Mockito.when(spec.commandLine()).thenReturn(Mockito.mock(CommandLine.class));
7378
ApiArguments args = new ApiArguments();
74-
args.setServer(null);
79+
args.setServer(initialServer);
7580

7681
OpenAPI openAPI = new OpenAPI();
7782
openAPI.setServers(Collections.singletonList(
78-
new io.swagger.v3.oas.models.servers.Server().url("http://fromopenapi.com")
83+
new io.swagger.v3.oas.models.servers.Server().url(openApiServerUrl)
7984
));
8085

8186
args.validateValidServer(spec, openAPI);
82-
Assertions.assertThat(args.getServer()).isEqualTo("http://fromopenapi.com");
83-
}
84-
85-
@Test
86-
void shouldReplaceServerPlaceholder() {
87-
CommandLine.Model.CommandSpec spec = Mockito.mock(CommandLine.Model.CommandSpec.class);
88-
Mockito.when(spec.commandLine()).thenReturn(Mockito.mock(CommandLine.class));
89-
ApiArguments args = new ApiArguments();
90-
args.setServer("http://api.com");
9187

92-
OpenAPI openAPI = new OpenAPI();
93-
openAPI.setServers(Collections.singletonList(
94-
new io.swagger.v3.oas.models.servers.Server().url("{apiRoot}/v2")
95-
));
96-
args.validateValidServer(spec, openAPI);
97-
// The placeholder should be replaced
98-
Assertions.assertThat(args.getServer()).isEqualTo("http://api.com/v2");
88+
Assertions.assertThat(args.getServer()).isEqualTo(expectedServer);
9989
}
10090

101-
@Test
102-
void shouldPreferCliServerOverOpenApiConcreteServer() {
103-
CommandLine.Model.CommandSpec spec = Mockito.mock(CommandLine.Model.CommandSpec.class);
104-
Mockito.when(spec.commandLine()).thenReturn(Mockito.mock(CommandLine.class));
105-
ApiArguments args = new ApiArguments();
106-
args.setServer("http://localhost:8080");
107-
108-
OpenAPI openAPI = new OpenAPI();
109-
openAPI.setServers(Collections.singletonList(
110-
new io.swagger.v3.oas.models.servers.Server().url("https://api.example.com")
111-
));
112-
113-
args.validateValidServer(spec, openAPI);
114-
115-
// CLI server should take priority over concrete OpenAPI server
116-
Assertions.assertThat(args.getServer()).isEqualTo("http://localhost:8080");
91+
private static Stream<Arguments> serverResolutionArguments() {
92+
return Stream.of(
93+
Arguments.of("should set server from OpenAPI when CLI server is null", null, "http://fromopenapi.com", "http://fromopenapi.com"),
94+
Arguments.of("should replace OpenAPI placeholder with CLI server", "http://api.com", "{apiRoot}/v2", "http://api.com/v2"),
95+
Arguments.of("should prefer CLI server over concrete OpenAPI server", "http://localhost:8080", "https://api.example.com", "http://localhost:8080")
96+
);
11797
}
11898

11999
@Test
@@ -138,4 +118,12 @@ void shouldPassWhenServerIsValidUrl() {
138118
Assertions.assertThatCode(() -> args.validateValidServer(spec, null))
139119
.doesNotThrowAnyException();
140120
}
121+
122+
@Test
123+
void shouldRemoveTrailingSlashFromServer() {
124+
ApiArguments args = new ApiArguments();
125+
args.setServer("http://api.com/");
126+
args.validateValidServer(null, null);
127+
Assertions.assertThat(args.getServer()).isEqualTo("http://api.com");
128+
}
141129
}

src/test/java/com/endava/cats/factory/FuzzingDataFactoryTest.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -875,12 +875,7 @@ void shouldParseOpenApi311WithNullAndStringSchema() throws Exception {
875875
Assertions.assertThat(dataList).hasSize(1);
876876
Assertions.assertThat(dataList.getFirst().getMethod()).isEqualTo(HttpMethod.POST);
877877
String example = dataList.getFirst().getPayload();
878-
Assertions.assertThat(example).contains("title");
879-
Assertions.assertThat(example).contains("departmentId");
880-
Assertions.assertThat(example).contains("deadlineDate");
881-
Assertions.assertThat(example).contains("locationId");
882-
Assertions.assertThat(example).contains("messageTemplateId");
883-
Assertions.assertThat(example).contains("vacancyTemplateId");
878+
Assertions.assertThat(example).contains("title", "deadlineDate", "locationId", "messageTemplateId", "vacancyTemplateId");
884879
}
885880

886881
@Test

src/test/java/com/endava/cats/util/SimpleJsonFormatterTest.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ void shouldHandleMalformedJsonWithExtraClosingSquareBrackets() {
6363
void shouldHandleNestedStructures() {
6464
String input = "{\"outer\":{\"inner\":{\"deep\":\"value\"}}}";
6565
String result = SimpleJsonFormatter.formatJson(input);
66-
assertThat(result).contains("\"outer\":");
67-
assertThat(result).contains("\"inner\":");
68-
assertThat(result).contains("\"deep\": \"value\"");
66+
assertThat(result).contains("\"outer\":", "\"inner\":", "\"deep\": \"value\"");
6967
}
7068
}

0 commit comments

Comments
 (0)