diff --git a/karate-core/src/main/java/com/intuit/karate/convert/ConvertUtils.java b/karate-core/src/main/java/com/intuit/karate/convert/ConvertUtils.java index 441ad403d..a90888c77 100644 --- a/karate-core/src/main/java/com/intuit/karate/convert/ConvertUtils.java +++ b/karate-core/src/main/java/com/intuit/karate/convert/ConvertUtils.java @@ -28,63 +28,91 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Created by rkumar32 on 7/5/17. */ public class ConvertUtils { - + private static final Logger logger = LoggerFactory.getLogger(ConvertUtils.class); private ConvertUtils() { // only static methods } - public static String toKarateFeature(List requests) { - String scenarios = ""; - for (PostmanRequest request : requests) { - scenarios += request.convert(); + public static String toKarateFeature(List items) { + return toKarateFeature(UUID.randomUUID().toString(), items); + } + + public static String toKarateFeature(String collectionName, List items) { + StringBuilder sb = new StringBuilder("Feature: ").append(collectionName); + sb.append(System.lineSeparator()).append(System.lineSeparator()); + for (PostmanItem item : items) { + sb.append(item.convert()); } - String feature = "Feature: \n\n" + scenarios; - return feature; + return sb.toString(); } - - public static List readPostmanJson(String json) { + + public static List readPostmanJson(String json) { DocumentContext doc = JsonPath.parse(json); List> list = (List) doc.read("$.item"); - List requests = new ArrayList<>(list.size()); + return readPostmanItems(null, list); + } + + private static List readPostmanItems(PostmanItem parent, List> list) { + PostmanItem item; + List requests = new ArrayList<>(list.size()); for (Map map : list) { logger.debug("map: {}", map); - String name = (String) map.get("name"); - Map requestInfo = (Map) map.get("request"); - String url = (String) requestInfo.get("url"); - String method = (String) requestInfo.get("method"); - List> headersList = (List) requestInfo.get("header"); - Map headers = new HashMap<>(); + item = readPosmanItem(parent, map); + requests.add(item); + } + return requests; + } + + private static PostmanItem readPosmanItem(PostmanItem parent, Map itemMap) { + PostmanItem item = new PostmanItem(); + String name = (String) itemMap.get("name"); + item.setName(name); + item.setParent(Optional.ofNullable(parent)); + Map requestInfo = (Map) itemMap.get("request"); + if (requestInfo != null) { + item.setRequest(readPostmanRequest(requestInfo)); + } else { // this may have list of sub-items + List subItems = readPostmanItems(item, (List>) itemMap.get("item")); + item.setItems(Optional.of(subItems)); + } + return item; + } + + private static PostmanRequest readPostmanRequest(Map requestInfo) { + String url = getUrl(requestInfo.get("url")); + String method = (String) requestInfo.get("method"); + List> headersList = (List) requestInfo.get("header"); + Map headers = new HashMap<>(); + if (headersList != null) { for (Map header : headersList) { headers.put((String) header.get("key"), (String) header.get("value")); } - Map bodyInfo = (Map) requestInfo.get("body"); - String body = null; - if (bodyInfo.containsKey("raw")) { - body = ((String) bodyInfo.get("raw")).replace(System.lineSeparator(), ""); - } - else if (bodyInfo.containsKey("formdata")) { - body = ((List) bodyInfo.get("formdata")).toString().replace(System.lineSeparator(), ""); - } - PostmanRequest request = new PostmanRequest(); - request.setName(name); - request.setUrl(url); - request.setMethod(method); - request.setHeaders(headers); - request.setBody(body); - requests.add(request); } - return requests; - } - + Map bodyInfo = (Map) requestInfo.get("body"); + String body = null; + if (bodyInfo.containsKey("raw")) { + body = ((String) bodyInfo.get("raw")).replace(System.lineSeparator(), ""); + } else if (bodyInfo.containsKey("formdata")) { + body = ((List) bodyInfo.get("formdata")).toString().replace(System.lineSeparator(), ""); + } + PostmanRequest request = new PostmanRequest(); + request.setUrl(url); + request.setMethod(method); + request.setHeaders(headers); + request.setBody(body); + return request; + } + + private static String getUrl(Object url) { + return (url instanceof String) ? (String) url : (String) ((Map) url).get("raw"); + } + } diff --git a/karate-core/src/main/java/com/intuit/karate/convert/PostmanItem.java b/karate-core/src/main/java/com/intuit/karate/convert/PostmanItem.java new file mode 100644 index 000000000..44ac3f126 --- /dev/null +++ b/karate-core/src/main/java/com/intuit/karate/convert/PostmanItem.java @@ -0,0 +1,111 @@ +/* + * The MIT License + * + * Copyright 2017 Intuit Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.intuit.karate.convert; + +import java.util.List; +import java.util.Optional; + +/** + * @author vmchukky + */ + +//http://schema.getpostman.com/json/collection/v2.1.0/docs/index.html +public class PostmanItem { + + private String name; + private PostmanRequest request; // schema says request is mandatory but have seen example collections without it + private Optional parent; // top level item (without a parent becomes a scenario) + private Optional> items; // items within an item become part of the same scenario associated with parent + + public PostmanItem() { + this.items = Optional.empty(); + this.parent = Optional.empty(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = (name == null) ? "" : name; + } + + public PostmanRequest getRequest() { + return request; + } + + public void setRequest(PostmanRequest request) { + this.request = request; + } + + public Optional getParent() { + return parent; + } + + public void setParent(Optional parent) { + this.parent = parent; + } + + public Optional> getItems() { + return items; + } + + public void setItems(Optional> items) { + this.items = items; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[name: ").append(name); + if (items.isPresent()) { + sb.append(items.toString()); + } else { + sb.append(", request: ").append(request.toString()); + } + sb.append("]"); + return sb.toString(); + } + + public String convert() { + StringBuilder sb = new StringBuilder(); + + sb.append(parent.isPresent() ? "# " : "Scenario: "); + sb.append(name).append(System.lineSeparator()); + if (items.isPresent()) { + for (PostmanItem item : items.get()) { + sb.append(item.convert()); + } + } else { + RequestBuilder builder = new RequestBuilder(); + sb.append(builder.addUrl(request.getUrl()) + .addHeaders(request.getHeaders()) + .addBody(request.getBody()) + .addMethod(request.getMethod()) + .build()); + } + return sb.toString(); + } + +} diff --git a/karate-core/src/main/java/com/intuit/karate/convert/PostmanRequest.java b/karate-core/src/main/java/com/intuit/karate/convert/PostmanRequest.java index 9399acfaa..c74e2c043 100644 --- a/karate-core/src/main/java/com/intuit/karate/convert/PostmanRequest.java +++ b/karate-core/src/main/java/com/intuit/karate/convert/PostmanRequest.java @@ -30,8 +30,7 @@ * @author pthomas3 */ public class PostmanRequest { - - private String name; + private String url; private String method; private Map headers; @@ -68,20 +67,11 @@ public String getUrl() { public void setUrl(String url) { this.url = url; } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("[name: ").append(name); - sb.append(", url: ").append(url); + sb.append("[url: ").append(url); sb.append(", method: ").append(method); sb.append(", headers: ").append(headers); sb.append(", body: ").append(body); @@ -89,10 +79,8 @@ public String toString() { return sb.toString(); } - public String convert() { - return new FeatureBuilder() - .addName(name) + return new RequestBuilder() .addUrl(url) .addHeaders(headers) .addBody(body) diff --git a/karate-core/src/main/java/com/intuit/karate/convert/FeatureBuilder.java b/karate-core/src/main/java/com/intuit/karate/convert/RequestBuilder.java similarity index 69% rename from karate-core/src/main/java/com/intuit/karate/convert/FeatureBuilder.java rename to karate-core/src/main/java/com/intuit/karate/convert/RequestBuilder.java index 8dcf4e547..f4b0cfc87 100644 --- a/karate-core/src/main/java/com/intuit/karate/convert/FeatureBuilder.java +++ b/karate-core/src/main/java/com/intuit/karate/convert/RequestBuilder.java @@ -24,78 +24,60 @@ package com.intuit.karate.convert; import com.intuit.karate.StringUtils; + import java.util.Map; /** * Created by rkumar32 on 5/24/17. */ -public class FeatureBuilder { +public class RequestBuilder { - private String name; private String url; private String method; private String headers; private String body; - private final String SCENARIO_TEMPLATE = "Scenario: %s" + // Scenario Description - "Given url " + "%s" + // url - "%s" + // Headers - "%s" + // Body - "When method %s" + System.lineSeparator(); // Method + private final String REQUEST_TEMPLATE = "Given url " + "%s" + // url + "%s" + // Headers + "%s" + // Body + "When method %s" + System.lineSeparator(); // Method - public FeatureBuilder addName(String name) { - if (name != null) { - this.name = name + System.lineSeparator(); - } - else { - this.name = ""; - } - return this; - } - - public FeatureBuilder addUrl(String url) { + public RequestBuilder addUrl(String url) { if (url != null) { this.url = "'" + url + "'" + System.lineSeparator(); - } - else { + } else { throw new IllegalArgumentException("Url is null"); } return this; } - public FeatureBuilder addMethod(String method) { + public RequestBuilder addMethod(String method) { if (url != null) { this.method = method + System.lineSeparator(); - } - else { + } else { throw new IllegalArgumentException("Method is null"); } return this; } - public FeatureBuilder addHeaders(Map headers) { + public RequestBuilder addHeaders(Map headers) { this.headers = ""; - for (Map.Entry entry: headers.entrySet()) { + for (Map.Entry entry : headers.entrySet()) { this.headers += "And header " + entry.getKey() + " = " + "'" + entry.getValue() + "'" + System.lineSeparator(); } return this; } - public FeatureBuilder addBody(String body) { + public RequestBuilder addBody(String body) { if (body != null) { this.body = "And request " + body + System.lineSeparator(); - } - else { + } else { this.body = ""; } return this; } - public String getName() { - return name; - } - public String getUrl() { return url; } @@ -116,12 +98,10 @@ public String build() { if ("POST".equals(method) && StringUtils.isBlank(body)) { throw new IllegalArgumentException("Body can't be null if method is POST"); } - return String.format(SCENARIO_TEMPLATE, name, - url, + return String.format(REQUEST_TEMPLATE, url, headers, body, method); } - -} +} diff --git a/karate-core/src/main/java/com/intuit/karate/ui/App.java b/karate-core/src/main/java/com/intuit/karate/ui/App.java index 7d370d8f5..6ce0e7f48 100644 --- a/karate-core/src/main/java/com/intuit/karate/ui/App.java +++ b/karate-core/src/main/java/com/intuit/karate/ui/App.java @@ -26,7 +26,7 @@ import com.intuit.karate.FileUtils; import com.intuit.karate.ScriptBindings; import com.intuit.karate.convert.ConvertUtils; -import com.intuit.karate.convert.PostmanRequest; +import com.intuit.karate.convert.PostmanItem; import javafx.application.Application; import javafx.geometry.Insets; import javafx.scene.Scene; @@ -113,8 +113,8 @@ private void initImportOpenAction(HeaderPanel header, String envString, Stage st header.setImportOpenAction(e -> { File file = chooseFile(stage, "*.postman_collection files", "*.postman_collection"); String json = FileUtils.toString(file); - List requests = ConvertUtils.readPostmanJson(json); - String featureText = ConvertUtils.toKarateFeature(requests); + List items = ConvertUtils.readPostmanJson(json); + String featureText = ConvertUtils.toKarateFeature(file.getName(), items); String featurePath = FileUtils.replaceFileExtension(file.getPath(), "feature"); File featureFile = new File(featurePath); FileUtils.writeToFile(featureFile, featureText); diff --git a/karate-core/src/test/java/com/intuit/karate/convert/ConvertUtilsTest.java b/karate-core/src/test/java/com/intuit/karate/convert/ConvertUtilsTest.java index 9a61b4545..d6c577829 100644 --- a/karate-core/src/test/java/com/intuit/karate/convert/ConvertUtilsTest.java +++ b/karate-core/src/test/java/com/intuit/karate/convert/ConvertUtilsTest.java @@ -1,35 +1,55 @@ package com.intuit.karate.convert; import com.intuit.karate.FileUtils; -import java.io.InputStream; -import java.util.List; import org.junit.Test; -import static org.junit.Assert.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.InputStream; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + /** - * * @author pthomas3 */ public class ConvertUtilsTest { - - private static final Logger logger = LoggerFactory.getLogger(ConvertUtilsTest.class); - + + private static final Logger logger = LoggerFactory.getLogger(ConvertUtilsTest.class); + @Test - public void testReading() { + public void testReadingSinglePostmanItemWithOneRequest() { InputStream is = getClass().getResourceAsStream("postman-echo-single.postman_collection"); String json = FileUtils.toString(is); - List requests = ConvertUtils.readPostmanJson(json); - logger.debug("list: {}", requests); - assertEquals(1, requests.size()); - PostmanRequest request = requests.get(0); - assertEquals("OAuth1.0 Verify Signature", request.getName()); + List items = ConvertUtils.readPostmanJson(json); + logger.debug("list: {}", items); + assertEquals(1, items.size()); + PostmanItem item = items.get(0); + PostmanRequest request = item.getRequest(); + assertEquals("OAuth1.0 Verify Signature", item.getName()); assertEquals("https://echo.getpostman.com/oauth1", request.getUrl()); assertEquals("GET", request.getMethod()); assertEquals(1, request.getHeaders().size()); assertEquals("OAuth oauth_consumer_key=\"RKCGzna7bv9YD57c\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1442394747\",oauth_nonce=\"UIGipk\",oauth_version=\"1.0\",oauth_signature=\"CaeyGPr2mns1WCq4Cpm5aLvz6Gs=\"", request.getHeaders().get("Authorization")); logger.debug(request.getBody()); } - + + @Test + public void testReadingItemListWithSubItems() { + String collectionFileName = "postman-multiple-items-and-sub-items.postman_collection"; + InputStream is = getClass().getResourceAsStream(collectionFileName); + String json = FileUtils.toString(is); + List items = ConvertUtils.readPostmanJson(json); + logger.debug("list: {}", items); + String featureJson = ConvertUtils.toKarateFeature(collectionFileName, items).trim(); + assertTrue(featureJson.startsWith("Feature: " + collectionFileName)); // assert feature name + assertTrue(featureJson.contains("Scenario: rootItem-1")); // assert scenario names + assertTrue(featureJson.contains("Scenario: rootItem-2")); + assertTrue(featureJson.contains("Scenario: rootItem-3")); + assertTrue(featureJson.contains("# subitem-1-1")); // assert comment for each sub request + assertTrue(featureJson.contains("# subitem-1-2")); + assertTrue(featureJson.contains("# subitem-2-1")); + } + } diff --git a/karate-core/src/test/java/com/intuit/karate/convert/FeatureBuilderTest.java b/karate-core/src/test/java/com/intuit/karate/convert/RequestBuilderTest.java similarity index 74% rename from karate-core/src/test/java/com/intuit/karate/convert/FeatureBuilderTest.java rename to karate-core/src/test/java/com/intuit/karate/convert/RequestBuilderTest.java index d78c66dfa..ace8e5a73 100644 --- a/karate-core/src/test/java/com/intuit/karate/convert/FeatureBuilderTest.java +++ b/karate-core/src/test/java/com/intuit/karate/convert/RequestBuilderTest.java @@ -13,21 +13,21 @@ /** * Created by rkumar32 on 7/5/17. */ -public class FeatureBuilderTest { +public class RequestBuilderTest { - private static final Logger logger = LoggerFactory.getLogger(FeatureBuilderTest.class); + private static final Logger logger = LoggerFactory.getLogger(RequestBuilderTest.class); @Test public void testConverting() { InputStream is = getClass().getResourceAsStream("postman-echo-single.postman_collection"); String json = FileUtils.toString(is); - List requests = ConvertUtils.readPostmanJson(json); - logger.debug("list: {}", requests); - assertEquals(1, requests.size()); - PostmanRequest request = requests.get(0); - FeatureBuilder builder = new FeatureBuilder(); - builder.addName(request.getName()); - assertEquals("OAuth1.0 Verify Signature", builder.getName().trim()); + List items = ConvertUtils.readPostmanJson(json); + logger.debug("list: {}", items); + assertEquals(1, items.size()); + PostmanItem item = items.get(0); + PostmanRequest request = item.getRequest(); + RequestBuilder builder = new RequestBuilder(); + assertEquals("OAuth1.0 Verify Signature", item.getName().trim()); builder.addUrl(request.getUrl()); assertEquals("'https://echo.getpostman.com/oauth1'", builder.getUrl().trim()); builder.addHeaders(request.getHeaders()); diff --git a/karate-core/src/test/java/com/intuit/karate/convert/postman-multiple-items-and-sub-items.postman_collection b/karate-core/src/test/java/com/intuit/karate/convert/postman-multiple-items-and-sub-items.postman_collection new file mode 100644 index 000000000..920f8cb69 --- /dev/null +++ b/karate-core/src/test/java/com/intuit/karate/convert/postman-multiple-items-and-sub-items.postman_collection @@ -0,0 +1,101 @@ +{ + "info":{ + "_postman_id":"test-collection", + "name":"test collection", + "schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item":[ + { + "name":"rootItem-1", + "item":[ + { + "name":"subitem-1-1", + "request":{ + "method":"GET", + "body":{}, + "url":"https://duckduckgo.com/?q=karate+web+service+testing" + }, + "response":[] + }, + { + "name":"subitem-1-2", + "request":{ + "method":"GET", + "header":[ + { + "key":"Content-Type", + "value":"application/json" + } + ], + "body":{}, + "url":"http://schema.getpostman.com/json/collection/v2.1.0/docs/index.html" + }, + "response":[] + } + ] + }, + { + "name":"rootItem-2", + "item":[ + { + "name":"subitem-2-1", + "request":{ + "auth":{ + "type":"basic", + "basic":{ + "username":"testUser", + "password":"testPa$$w0rd", + "showPassword":false + } + }, + "method":"GET", + "header":[ + { + "key":"Content-Type", + "value":"application/x-www-form-urlencoded" + }, + { + "key":"Authorization", + "value":"Basic dGVzdFVzZXI6dGVzdFBhJCR3MHJk" + } + ], + "body":{ + "mode":"urlencoded", + "urlencoded":[ + { + "description":{ + "content":"", + "type":"text/plain" + }, + "key":"si211", + "value":"test", + "type":"text" + }, + { + "description":{ + "content":"", + "type":"text/plain" + }, + "key":"si212", + "value":"06/26/2018", + "type":"text" + } + ] + }, + "url":"https://httpbin.org/basic-auth/testUser/testPa%24%24w0rd" + }, + "response":[] + } + ] + }, + { + "name":"rootItem-3", + "request":{ + "method":"GET", + "body":{}, + "url":"https://github.com/intuit/karate" + }, + "response":[] + } + ] +} \ No newline at end of file diff --git a/karate-web/src/main/java/com/intuit/karate/web/wicket/PostmanConvertPanel.java b/karate-web/src/main/java/com/intuit/karate/web/wicket/PostmanConvertPanel.java index 07cf71232..2f993e20d 100644 --- a/karate-web/src/main/java/com/intuit/karate/web/wicket/PostmanConvertPanel.java +++ b/karate-web/src/main/java/com/intuit/karate/web/wicket/PostmanConvertPanel.java @@ -24,7 +24,7 @@ package com.intuit.karate.web.wicket; import com.intuit.karate.convert.ConvertUtils; -import com.intuit.karate.convert.PostmanRequest; +import com.intuit.karate.convert.PostmanItem; import com.intuit.karate.web.service.KarateService; import com.intuit.karate.web.service.KarateSession; import org.apache.wicket.markup.html.form.Form; @@ -54,8 +54,8 @@ public PostmanConvertPanel(String id) { @Override protected void onSubmit() { logger.debug("text is: {}", text); - List requests = ConvertUtils.readPostmanJson(text); - String feature = ConvertUtils.toKarateFeature(requests); + List items = ConvertUtils.readPostmanJson(text); + String feature = ConvertUtils.toKarateFeature(items); KarateSession session = service.createSession("dev", feature); setResponsePage(new FeaturePage(session.getId())); }