/* * Copyright 2018 the original author or authors. * * Licensed 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 org.sahli.asciidoc.confluence.publisher.cli; import io.restassured.specification.RequestSpecification; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.LoggerFactory; import org.testcontainers.Testcontainers; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.output.Slf4jLogConsumer; import java.util.HashMap; import java.util.Map; import static io.restassured.RestAssured.given; import static java.lang.String.valueOf; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.is; import static org.testcontainers.containers.Network.SHARED; import static org.testcontainers.containers.wait.strategy.Wait.forListeningPort; public class AsciidocConfluencePublisherCommandLineClientIntegrationTest { @BeforeClass public static void exposeConfluenceServerPortOnHost() { Testcontainers.exposeHostPorts(8090); } @Before public void deleteAllPages() throws Exception { String[] args = { "rootConfluenceUrl=http://localhost:8090", "username=confluence-publisher-it", "password=1234", "spaceKey=CPI", "ancestorId=327706", "asciidocRootFolder=src/it/resources/empty" }; AsciidocConfluencePublisherCommandLineClient.main(args); } @Test public void publish_mandatoryArgumentsProvided_publishesDocumentationToConfluence() throws Exception { // arrange String[] args = { "rootConfluenceUrl=http://localhost:8090", "username=confluence-publisher-it", "password=1234", "spaceKey=CPI", "ancestorId=327706", "asciidocRootFolder=src/it/resources/default" }; // act AsciidocConfluencePublisherCommandLineClient.main(args); // assert givenAuthenticatedAsPublisher() .when().get(childPagesFor("327706")) .then().body("results.title", hasItem("Index")); givenAuthenticatedAsPublisher() .when().get(contentFor(pageIdBy("Index"))) .then().body("body.storage.value", is("<p>Content of Index</p>")); } @Test public void publish_customAttributesProvided_replacesAttributesInContent() throws Exception { // arrange String[] args = { "rootConfluenceUrl=http://localhost:8090", "username=confluence-publisher-it", "password=1234", "spaceKey=CPI", "ancestorId=327706", "asciidocRootFolder=src/it/resources/attributes", "attributes={\"attribute-1\": \"value-1\", \"attribute-2\": \"value-2\"}" }; // act AsciidocConfluencePublisherCommandLineClient.main(args); // assert givenAuthenticatedAsPublisher() .when().get(contentFor(pageIdBy("Index"))) .then().body("body.storage.value", is("<p>value-1 value-2</p>")); } @Test public void publish_withSkipSslVerificationTrue_allowsPublishingViaSslAndUntrustedCertificate() throws Exception { // arrange withReverseProxyEnabled("localhost", 8443, "host.testcontainers.internal", 8090, (proxyPort) -> { String[] args = { "rootConfluenceUrl=https://localhost:" + proxyPort, "username=confluence-publisher-it", "password=1234", "spaceKey=CPI", "ancestorId=327706", "asciidocRootFolder=src/it/resources/default", "skipSslVerification=true" }; // act AsciidocConfluencePublisherCommandLineClient.main(args); }); // assert givenAuthenticatedAsPublisher() .when().get(childPagesFor("327706")) .then().body("results.title", hasItem("Index")); } @Test public void publish_proxySchemeHostAndPortProvided_publishesDocumentationViaProxyToConfluence() throws Exception { // arrange withForwardProxyEnabled("localhost", 8443, (proxyPort) -> { String[] args = { "rootConfluenceUrl=http://host.testcontainers.internal:8090", "username=confluence-publisher-it", "password=1234", "spaceKey=CPI", "ancestorId=327706", "asciidocRootFolder=src/it/resources/default", "skipSslVerification=true", "proxyScheme=https", "proxyHost=localhost", "proxyPort=" + proxyPort }; // act AsciidocConfluencePublisherCommandLineClient.main(args); }); // assert givenAuthenticatedAsPublisher() .when().get(childPagesFor("327706")) .then().body("results.title", hasItem("Index")); } @Test public void publish_proxySchemeHostPortAndCredentialsProvided_publishesDocumentationViaProxyToConfluence() throws Exception { // arrange withForwardProxyEnabled("localhost", 8443, "proxy-user", "proxy-password", (proxyPort) -> { String[] args = { "rootConfluenceUrl=http://host.testcontainers.internal:8090", "username=confluence-publisher-it", "password=1234", "spaceKey=CPI", "ancestorId=327706", "asciidocRootFolder=src/it/resources/default", "skipSslVerification=true", "proxyScheme=https", "proxyHost=localhost", "proxyPort=" + proxyPort, "proxyUsername=proxy-user", "proxyPassword=proxy-password" }; // act AsciidocConfluencePublisherCommandLineClient.main(args); }); // assert givenAuthenticatedAsPublisher() .when().get(childPagesFor("327706")) .then().body("results.title", hasItem("Index")); } private static String pageIdBy(String title) { return givenAuthenticatedAsPublisher() .when().get(childPagesFor("327706")) .then().extract().jsonPath().getString("results.find({it.title == '" + title + "'}).id"); } private static String childPagesFor(String pageId) { return "http://localhost:8090/rest/api/content/" + pageId + "/child/page"; } private String contentFor(String pageId) { return "http://localhost:8090/rest/api/content/" + pageId + "?expand=body.storage"; } private static RequestSpecification givenAuthenticatedAsPublisher() { return given().auth().preemptive().basic("confluence-publisher-it", "1234"); } private static void withReverseProxyEnabled(String proxyHost, int proxyPort, String targetHost, int targetPort, PortAwareRunnable runnable) throws Exception { Map<String, String> env = new HashMap<>(); env.put("PROXY_HOST", proxyHost); env.put("PROXY_PORT", valueOf(proxyPort)); env.put("TARGET_HOST", targetHost); env.put("TARGET_PORT", valueOf(targetPort)); startProxy("confluencepublisher/reverse-proxy-it:1.0.0", proxyHost, proxyPort, env, runnable); } private static void withForwardProxyEnabled(String proxyHost, int proxyPort, PortAwareRunnable runnable) throws Exception { Map<String, String> env = new HashMap<>(); env.put("PROXY_HOST", proxyHost); env.put("PROXY_PORT", valueOf(proxyPort)); env.put("BASIC_AUTH", "off"); startProxy("confluencepublisher/forward-proxy-it:1.0.0", proxyHost, proxyPort, env, runnable); } private static void withForwardProxyEnabled(String proxyHost, int proxyPort, String proxyUsername, String proxyPassword, PortAwareRunnable runnable) throws Exception { Map<String, String> env = new HashMap<>(); env.put("PROXY_HOST", proxyHost); env.put("PROXY_PORT", valueOf(proxyPort)); env.put("BASIC_AUTH", "on"); env.put("BASIC_USERNAME", proxyUsername); env.put("BASIC_PASSWORD", proxyPassword); startProxy("confluencepublisher/forward-proxy-it:1.0.0", proxyHost, proxyPort, env, runnable); } private static void startProxy(String dockerImageName, String proxyHost, int proxyPort, Map<String, String> env, PortAwareRunnable runnable) throws Exception { try (GenericContainer<?> proxy = new GenericContainer<>(dockerImageName) .withEnv(env) .withNetwork(SHARED) .withNetworkAliases(proxyHost) .withExposedPorts(proxyPort) .withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger(AsciidocConfluencePublisherCommandLineClientIntegrationTest.class))) .waitingFor(forListeningPort())) { proxy.start(); runnable.run(proxy.getMappedPort(proxyPort)); } } @FunctionalInterface private interface PortAwareRunnable { void run(int port) throws Exception; } }