io.github.microcks.util.postman.PostmanTestStepsRunner.java Source code

Java tutorial

Introduction

Here is the source code for io.github.microcks.util.postman.PostmanTestStepsRunner.java

Source

/*
 * Licensed to Laurent Broudoux (the "Author") under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. Author licenses this
 * file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package io.github.microcks.util.postman;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.github.microcks.domain.*;
import io.github.microcks.util.URIBuilder;
import io.github.microcks.util.test.AbstractTestRunner;
import io.github.microcks.util.test.TestReturn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * @author laurent
 */
public class PostmanTestStepsRunner extends AbstractTestRunner<HttpMethod> {

    /** A simple logger for diagnostic messages. */
    private static Logger log = LoggerFactory.getLogger(PostmanTestStepsRunner.class);

    private ObjectMapper mapper = new ObjectMapper();

    private JsonNode collection;

    private ClientHttpRequestFactory clientHttpRequestFactory;

    private String testsCallbackUrl = null;

    private String postmanRunnerUrl = null;

    /**
     * Build a new PostmanTestStepsRunner for a collection.
     * @param collectionFilePath The path to SoapUI project file
     * @throws java.io.IOException if file cannot be found or accessed.
     */
    public PostmanTestStepsRunner(String collectionFilePath) throws IOException {
        try {
            // Read Json bytes.
            byte[] jsonBytes = Files.readAllBytes(Paths.get(collectionFilePath));
            // Convert them to Node using Jackson object mapper.
            ObjectMapper mapper = new ObjectMapper();
            collection = mapper.readTree(jsonBytes);
        } catch (Exception e) {
            throw new IOException("Postman collection file");
        }
    }

    /**
     * Set the ClientHttpRequestFactory used for reaching endpoint.
     * @param clientHttpRequestFactory The ClientHttpRequestFactory used for reaching endpoint
     */
    public void setClientHttpRequestFactory(ClientHttpRequestFactory clientHttpRequestFactory) {
        this.clientHttpRequestFactory = clientHttpRequestFactory;
    }

    public void setTestsCallbackUrl(String testsCallbackUrl) {
        this.testsCallbackUrl = testsCallbackUrl;
    }

    public void setPostmanRunnerUrl(String postmanRunnerUrl) {
        this.postmanRunnerUrl = postmanRunnerUrl;
    }

    @Override
    public List<TestReturn> runTest(Service service, Operation operation, TestResult testResult,
            List<Request> requests, String endpointUrl, HttpMethod method) throws URISyntaxException, IOException {
        if (log.isDebugEnabled()) {
            log.debug("Launching test run on " + endpointUrl + " for " + requests.size() + " request(s)");
        }

        if (endpointUrl.endsWith("/")) {
            endpointUrl = endpointUrl.substring(0, endpointUrl.length() - 1);
        }

        // Microcks-postman-runner interface object building.
        JsonNode jsonArg = mapper.createObjectNode();
        ((ObjectNode) jsonArg).put("operation", operation.getName());
        ((ObjectNode) jsonArg).put("callbackUrl",
                testsCallbackUrl + "/api/tests/" + testResult.getId() + "/testCaseResult");

        // First we have to retrieved and add the test script for this operation from within Postman collection.
        JsonNode testScript = extractOperationTestScript(operation);
        if (testScript != null) {
            log.debug("Found a testScript for this operation !");
            ((ObjectNode) jsonArg).set("testScript", testScript);
        }

        // Then we have to add the corresponding 'requests' objects.
        ArrayNode jsonRequests = mapper.createArrayNode();
        for (Request request : requests) {
            JsonNode jsonRequest = mapper.createObjectNode();

            String operationName = operation.getName().substring(operation.getName().indexOf(" ") + 1);
            String customizedEndpointUrl = endpointUrl
                    + URIBuilder.buildURIFromPattern(operationName, request.getQueryParameters());
            log.debug("Using customized endpoint url: " + customizedEndpointUrl);

            ((ObjectNode) jsonRequest).put("endpointUrl", customizedEndpointUrl);
            ((ObjectNode) jsonRequest).put("method", operation.getMethod());
            ((ObjectNode) jsonRequest).put("name", request.getName());

            if (request.getContent() != null && request.getContent().length() > 0) {
                ((ObjectNode) jsonRequest).put("body", request.getContent());
            }
            if (request.getQueryParameters() != null && request.getQueryParameters().size() > 0) {
                ArrayNode jsonParams = buildQueryParams(request.getQueryParameters());
                ((ObjectNode) jsonRequest).set("queryParams", jsonParams);
            }
            if (request.getHeaders() != null && request.getHeaders().size() > 0) {
                ArrayNode jsonHeaders = buildHeaders(request.getHeaders());
                ((ObjectNode) jsonRequest).set("headers", jsonHeaders);
            }

            jsonRequests.add(jsonRequest);
        }
        ((ObjectNode) jsonArg).set("requests", jsonRequests);

        URI postmanRunnerURI = new URI(postmanRunnerUrl + "/tests/" + testResult.getId());
        ClientHttpRequest httpRequest = clientHttpRequestFactory.createRequest(postmanRunnerURI, HttpMethod.POST);
        httpRequest.getBody().write(mapper.writeValueAsBytes(jsonArg));
        httpRequest.getHeaders().add("Content-Type", "application/json");

        // Actually execute request.
        ClientHttpResponse httpResponse = null;
        try {
            httpResponse = httpRequest.execute();
        } catch (IOException ioe) {
            log.error("IOException while executing request ", ioe);
        }

        return new ArrayList<TestReturn>();
    }

    @Override
    public HttpMethod buildMethod(String method) {
        return null;
    }

    private JsonNode extractOperationTestScript(Operation operation) {
        List<JsonNode> collectedScripts = new ArrayList<>();

        Iterator<JsonNode> items = collection.path("item").elements();
        while (items.hasNext()) {
            JsonNode item = items.next();
            extractTestScript("", item, operation, collectedScripts);
        }
        if (collectedScripts.size() > 0) {
            return collectedScripts.get(0);
        }
        return null;
    }

    private void extractTestScript(String operationNameRadix, JsonNode itemNode, Operation operation,
            List<JsonNode> collectedScripts) {
        String itemNodeName = itemNode.path("name").asText();

        // Item may be a folder or an operation description.
        if (!itemNode.has("request")) {
            // Item is simply a folder that may contain some other folders recursively.
            Iterator<JsonNode> items = itemNode.path("item").elements();
            while (items.hasNext()) {
                JsonNode item = items.next();
                extractTestScript(operationNameRadix + "/" + itemNodeName, item, operation, collectedScripts);
            }
        } else {
            // Item is here an operation description.
            String operationName = PostmanCollectionImporter.buildOperationName(itemNode, operationNameRadix);
            log.debug("Found operation '{}', comparing with '{}'", operationName, operation.getName());
            if (operationName.equals(operation.getName())) {
                // We've got the correct operation.
                JsonNode events = itemNode.path("event");
                for (JsonNode event : events) {
                    if ("test".equals(event.path("listen").asText())) {
                        log.debug("Found a matching event where listen=test");
                        collectedScripts.add(event);
                    }
                }
            }
        }
    }

    private ArrayNode buildQueryParams(List<Parameter> queryParameters) {
        ArrayNode jsonQPS = mapper.createArrayNode();
        for (Parameter parameter : queryParameters) {
            JsonNode jsonQP = mapper.createObjectNode();
            ((ObjectNode) jsonQP).put("key", parameter.getName());
            ((ObjectNode) jsonQP).put("value", parameter.getValue());
            jsonQPS.add(jsonQP);
        }
        return jsonQPS;
    }

    private ArrayNode buildHeaders(Set<Header> headers) {
        ArrayNode jsonHS = mapper.createArrayNode();
        for (Header header : headers) {
            JsonNode jsonH = mapper.createObjectNode();
            ((ObjectNode) jsonH).put("key", header.getName());
            ((ObjectNode) jsonH).put("value", buildValue(header.getValues()));
            jsonHS.add(jsonH);
        }
        return jsonHS;
    }
}