Skip to content

Commit d46a791

Browse files
authored
Postman Generator: Add folder description (#23249)
* Add folder description * Generate samples * Refactor test to avoid relying on endpoints order * Address cubic-dev comments * Refactor test to avoid relying on endpoints order
1 parent 25fab41 commit d46a791

7 files changed

Lines changed: 379 additions & 215 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PostmanCollectionCodegen.java

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public class PostmanCollectionCodegen extends DefaultCodegen implements CodegenC
8080

8181

8282
// operations grouped by tag
83-
public Map<String, List<CodegenOperation>> codegenOperationsByTag = new HashMap<>();
83+
public Map<PostmanRequestFolder, List<CodegenOperation>> codegenOperationsByTag = new HashMap<>();
8484
// list of operations
8585
public List<CodegenOperation> codegenOperationsList = new ArrayList<>();
8686

@@ -319,22 +319,31 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
319319
* @param codegenOperation Codegen operation instance
320320
*/
321321
public void addToMap(CodegenOperation codegenOperation) {
322-
323-
String key = null;
322+
String tagName;
323+
String tagDescription;
324324
if (codegenOperation.tags == null || codegenOperation.tags.isEmpty()) {
325-
key = "default";
325+
tagName = "Default";
326+
tagDescription = "Default tag";
326327
} else {
327-
key = codegenOperation.tags.get(0).getName();
328+
tagName = codegenOperation.tags.get(0).getName();
329+
tagDescription = codegenOperation.tags.get(0).getDescription();
330+
if (tagDescription == null) {
331+
tagDescription = tagName + " tag";
332+
}
328333
}
329334

330-
List<CodegenOperation> list = codegenOperationsByTag.get(key);
335+
tagName = formatDescription(tagName);
336+
tagDescription = formatDescription(tagDescription);
337+
338+
PostmanRequestFolder folder = new PostmanRequestFolder(tagName, tagDescription);
339+
List<CodegenOperation> list = codegenOperationsByTag.get(folder);
331340

332341
if (list == null) {
333342
list = new ArrayList<>();
334343
}
335344
list.add(codegenOperation);
336345

337-
codegenOperationsByTag.put(key, list);
346+
codegenOperationsByTag.put(folder, list);
338347

339348
// sort requests by path
340349
Collections.sort(list, Comparator.comparing(obj -> obj.path));
@@ -883,6 +892,30 @@ public String getPostmanType(CodegenProperty codegenProperty) {
883892
}
884893
}
885894

895+
@Getter
896+
public static class PostmanRequestFolder {
897+
private final String name;
898+
private final String description;
899+
900+
public PostmanRequestFolder(String name, String description) {
901+
this.name = name;
902+
this.description = description;
903+
}
904+
905+
@Override
906+
public boolean equals(Object o) {
907+
if (this == o) return true;
908+
if (o == null || getClass() != o.getClass()) return false;
909+
PostmanRequestFolder that = (PostmanRequestFolder) o;
910+
return Objects.equals(name, that.name) && Objects.equals(description, that.description);
911+
}
912+
913+
@Override
914+
public int hashCode() {
915+
return Objects.hash(name, description);
916+
}
917+
}
918+
886919
// Supporting models
887920
@Getter
888921
@Setter

modules/openapi-generator/src/main/resources/postman-collection/postman.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
{{#codegenOperationsByTag}}
1313
{{#entrySet}}
1414
{
15-
"name": "{{key}}",
15+
"name": "{{{key.name}}}",
16+
"description": "{{{key.description}}}",
1617
"item": [{{#value}}
1718
{{>item}}{{^-last}},{{/-last}}{{/value}}
1819
]

modules/openapi-generator/src/test/java/org/openapitools/codegen/postman/PostmanCollectionCodegenTest.java

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
import java.nio.file.Paths;
1818
import java.util.ArrayList;
1919
import java.util.Arrays;
20+
import java.util.HashMap;
2021
import java.util.LinkedHashMap;
2122
import java.util.List;
23+
import java.util.Map;
2224

2325
import static org.junit.jupiter.api.Assertions.*;
2426
import static org.openapitools.codegen.TestUtils.*;
@@ -76,6 +78,21 @@ public void testBasicGeneration() throws IOException {
7678
// verify request endpoint
7779
TestUtils.assertFileContains(path, "\"name\": \"/users/:userId\"");
7880

81+
ObjectMapper objectMapper = new ObjectMapper();
82+
JsonNode root = objectMapper.readTree(new File(output + "/postman.json"));
83+
JsonNode folders = root.get("item");
84+
85+
JsonNode basicFolder = null;
86+
for (JsonNode folder : folders) {
87+
if ("basic".equals(folder.get("name").asText())) {
88+
basicFolder = folder;
89+
break;
90+
}
91+
}
92+
93+
assertNotNull(basicFolder);
94+
assertEquals("Basic tag", basicFolder.get("description").asText());
95+
7996
}
8097

8198
@Test
@@ -101,6 +118,38 @@ public void testBasicGenerationJson() throws IOException {
101118
assertFileContains(path, "\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"");
102119
}
103120

121+
@Test
122+
public void testTagDescriptionIsJsonEscaped() throws IOException {
123+
File output = Files.createTempDirectory("postmantest_").toFile();
124+
output.deleteOnExit();
125+
126+
final CodegenConfigurator configurator = new CodegenConfigurator()
127+
.setGeneratorName("postman-collection")
128+
.setInputSpec("src/test/resources/3_0/postman-collection/TagDescriptionEscaping.yaml")
129+
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
130+
131+
final ClientOptInput clientOptInput = configurator.toClientOptInput();
132+
DefaultGenerator generator = new DefaultGenerator();
133+
List<File> files = generator.opts(clientOptInput).generate();
134+
135+
files.forEach(File::deleteOnExit);
136+
137+
ObjectMapper objectMapper = new ObjectMapper();
138+
JsonNode root = objectMapper.readTree(new File(output + "/postman.json"));
139+
JsonNode folders = root.get("item");
140+
141+
JsonNode basicFolder = null;
142+
for (JsonNode folder : folders) {
143+
if ("basic".equals(folder.get("name").asText())) {
144+
basicFolder = folder;
145+
break;
146+
}
147+
}
148+
149+
assertNotNull(basicFolder);
150+
assertEquals("Basic \"quoted\" tag\nsecond line", basicFolder.get("description").asText());
151+
}
152+
104153
@Test
105154
public void testValidatePostmanJson() throws IOException {
106155

@@ -702,24 +751,26 @@ public void testAddToMap() {
702751

703752
CodegenOperation operationUsers = new CodegenOperation();
704753
operationUsers.path = "/users";
705-
operationUsers.tags = new ArrayList<>(Arrays.asList(new Tag().name("basic")));
754+
operationUsers.tags = new ArrayList<>(Arrays.asList(new Tag().name("basic").description("Basic tag")));
706755
postmanV2Generator.addToMap(operationUsers);
707756

708757
CodegenOperation operationGroups = new CodegenOperation();
709758
operationGroups.path = "/groups";
710-
operationGroups.tags = new ArrayList<>(Arrays.asList(new Tag().name("basic")));
759+
operationGroups.tags = new ArrayList<>(Arrays.asList(new Tag().name("basic").description("Basic tag")));
711760
postmanV2Generator.addToMap(operationGroups);
712761

713762
CodegenOperation operationUserId = new CodegenOperation();
714763
operationUserId.path = "/users/{id}";
715-
operationUserId.tags = new ArrayList<>(Arrays.asList(new Tag().name("basic")));
764+
operationUserId.tags = new ArrayList<>(Arrays.asList(new Tag().name("basic").description("Basic tag")));
716765
postmanV2Generator.addToMap(operationUserId);
717766

767+
PostmanCollectionCodegen.PostmanRequestFolder folder = new PostmanCollectionCodegen.PostmanRequestFolder("basic", "Basic tag");
768+
718769
// verify tag 'basic'
719770
assertEquals(1, postmanV2Generator.codegenOperationsByTag.size());
720-
assertEquals(true, postmanV2Generator.codegenOperationsByTag.containsKey("basic"));
771+
assertEquals(true, postmanV2Generator.codegenOperationsByTag.containsKey(folder));
721772

722-
List<CodegenOperation> operations = postmanV2Generator.codegenOperationsByTag.get("basic");
773+
List<CodegenOperation> operations = postmanV2Generator.codegenOperationsByTag.get(folder);
723774
// verify order
724775
assertEquals("/groups", operations.get(0).path);
725776
assertEquals("/users", operations.get(1).path);
@@ -737,7 +788,18 @@ public void testAddToMapUsingDefaultTag() {
737788

738789
// verify tag 'default' is used
739790
assertEquals(1, postmanV2Generator.codegenOperationsByTag.size());
740-
assertEquals(true, postmanV2Generator.codegenOperationsByTag.containsKey("default"));
791+
assertEquals(true, postmanV2Generator.codegenOperationsByTag.containsKey(new PostmanCollectionCodegen.PostmanRequestFolder("Default", "Default tag")));
792+
}
793+
794+
@Test
795+
public void testPostmanRequestFolderInMap() {
796+
PostmanCollectionCodegen.PostmanRequestFolder folder1 = new PostmanCollectionCodegen.PostmanRequestFolder("test", "descr");
797+
Map<PostmanCollectionCodegen.PostmanRequestFolder, String> map = new HashMap<>();
798+
map.put(folder1, "folder1");
799+
PostmanCollectionCodegen.PostmanRequestFolder folder2 = new PostmanCollectionCodegen.PostmanRequestFolder("test", "descr");
800+
801+
assertTrue(map.containsKey(folder2));
802+
assertEquals("folder1", map.get(folder2));
741803
}
742804

743805
@Test
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
openapi: 3.0.0
2+
info:
3+
title: Tag Description Escaping
4+
version: '1.0'
5+
servers:
6+
- url: 'http://localhost:5001'
7+
paths:
8+
'/users/{userId}':
9+
get:
10+
summary: Get User
11+
operationId: get-users-userId
12+
tags:
13+
- basic
14+
parameters:
15+
- description: Unique identifier of the user
16+
name: userId
17+
in: path
18+
required: true
19+
schema:
20+
type: string
21+
responses:
22+
'200':
23+
description: User Found
24+
content:
25+
application/json:
26+
schema:
27+
type: object
28+
properties:
29+
id:
30+
type: integer
31+
tags:
32+
- name: basic
33+
description: |-
34+
Basic "quoted" tag
35+
second line

0 commit comments

Comments
 (0)