Skip to content

Commit 5e386b4

Browse files
committed
✅✨ Added support for using TestContainers for running IT tests (WIP)
Integration tests can now be configured to use AEM running as a Docker container (via TestContainers). This is still work in progress, but it's breathing. The container image I'm using doesn't have the samples files deployed in it. It would need this in order for the tests to work. See the pom.xml for details on what needs to be configured for the IT tests to work.
1 parent ce2a8bf commit 5e386b4

28 files changed

Lines changed: 474 additions & 227 deletions

rest-services/it.tests/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@
9595
<artifactId>awaitility</artifactId>
9696
<scope>test</scope>
9797
</dependency>
98+
<dependency>
99+
<groupId>com.4point.aem</groupId>
100+
<artifactId>aem-package-manager-api</artifactId>
101+
<scope>test</scope>
102+
</dependency>
98103
</dependencies>
99104

100105
</project>

rest-services/it.tests/src/test/java/com/_4point/aem/docservices/rest_services/it_tests/AbstractAemContainerTest.java

Lines changed: 0 additions & 80 deletions
This file was deleted.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package com._4point.aem.docservices.rest_services.it_tests;
2+
3+
import java.io.IOException;
4+
import java.net.URI;
5+
import java.net.http.HttpClient;
6+
import java.net.http.HttpRequest;
7+
import java.net.http.HttpResponse;
8+
import java.net.http.HttpResponse.BodyHandlers;
9+
import java.nio.file.Paths;
10+
import java.util.Base64;
11+
import java.util.concurrent.TimeUnit;
12+
import java.util.concurrent.atomic.AtomicBoolean;
13+
14+
import org.awaitility.Awaitility;
15+
import org.testcontainers.containers.GenericContainer;
16+
import org.testcontainers.utility.DockerImageName;
17+
18+
public enum AemInstance {
19+
AEM_1(TestUtils.USE_TESTCONTAINERS); // Change parameter to false to disable TestContainers and use local AEM instance..
20+
21+
// These tests require an AEM container image with AEM forms installed. Since AEM is proprietary, it is not possible to obtain this
22+
// through public images. By default, this uses a private image hosted in the 4PointSolutions-PS GitHub organization. If you are not
23+
// part of that prg, you will have to supply your own image.
24+
private static final String AEM_IMAGE_NAME = "ghcr.io/4pointsolutions-ps/aem:aem65sp21";
25+
private final GenericContainer<?> aemContainer;
26+
private final AtomicBoolean preparedForTests = new AtomicBoolean(false);
27+
28+
private AemInstance(boolean useTestContainers) {
29+
this(useTestContainers ? new GenericContainer<>(DockerImageName.parse(AEM_IMAGE_NAME))
30+
.withReuse(true)
31+
.withExposedPorts(4502)
32+
: null);
33+
}
34+
35+
private AemInstance(GenericContainer<?> aemContainer) {
36+
this.aemContainer = aemContainer;
37+
if (aemContainer != null) {
38+
aemContainer.start();
39+
40+
}
41+
}
42+
43+
public void prepareForTests() {
44+
if (!preparedForTests.get()) {
45+
Integer mappedPort = aemPort();
46+
47+
startAem(mappedPort);
48+
// deploySampleFiles(mappedPort);
49+
50+
preparedForTests.set(true);
51+
System.out.println("Starting tests...");
52+
}
53+
}
54+
55+
// Make sure AEM is up before running the tests.
56+
private static void startAem(Integer mappedPort) {
57+
System.out.println(String.format("Checking if AEM is available on port %d.", mappedPort));
58+
HttpClient client = HttpClient.newHttpClient();
59+
HttpRequest request = HttpRequest.newBuilder()
60+
.uri(URI.create(String.format("http://localhost:%d/", mappedPort)))
61+
.header("Authorization", encodeBasic(TestUtils.TEST_USER, TestUtils.TEST_USER_PASSWORD))
62+
.GET()
63+
.build();
64+
65+
if (!aemIsUp(client, request)) {
66+
System.out.println(String.format("Waiting for AEM to become available."));
67+
Awaitility.await()
68+
.atMost(5, TimeUnit.MINUTES)
69+
.pollDelay(50, TimeUnit.SECONDS)
70+
.pollInterval(10, TimeUnit.SECONDS)
71+
.until(()->aemIsUp(client, request));
72+
}
73+
System.out.println("AEM is available.");
74+
}
75+
76+
public static void deploySampleFiles(Integer mappedPort) {
77+
System.out.println("Deploying sample files...");
78+
79+
SamplesDeployer deployer = new SamplesDeployer("localhost", mappedPort, TestUtils.TEST_USER, TestUtils.TEST_USER_PASSWORD);
80+
81+
deployer.deployXdp(Paths.get("src", "test", "resources", "SampleForm.xdp"), "sample-forms");
82+
deployer.deployAf(Paths.get("src", "test", "resources", "sample00002test.zip"));
83+
// deployer.deployAf(Paths.get("src", "test", "resources", "SampleForm.xdp"), "sample-forms");
84+
System.out.println("Sample files deployed.");
85+
}
86+
87+
public String aemHost() {
88+
return aemContainer != null ? "localhost" : TestUtils.TEST_MACHINE_NAME;
89+
}
90+
public Integer aemPort() {
91+
return aemContainer != null ? aemContainer.getMappedPort(4502) : Integer.parseInt(TestUtils.TEST_MACHINE_PORT_STR) ;
92+
}
93+
94+
private static boolean aemIsUp(HttpClient restClient, HttpRequest request) {
95+
try {
96+
HttpResponse<Void> result = restClient.send(request, BodyHandlers.discarding());
97+
int statusCode = result.statusCode();
98+
System.out.println(String.format("AEM returned status code %d.", statusCode));
99+
return statusCode >= 200 && statusCode <= 399; // Wait for successful status code.
100+
} catch (InterruptedException e) {
101+
return false;
102+
} catch (IOException e) {
103+
e.printStackTrace();
104+
return false;
105+
}
106+
}
107+
108+
private static String encodeBasic(String username, String password) {
109+
return "Basic "+ Base64
110+
.getEncoder()
111+
.encodeToString((username+":"+password).getBytes());
112+
}
113+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com._4point.aem.docservices.rest_services.it_tests;
2+
3+
import java.nio.file.Path;
4+
import java.nio.file.Paths;
5+
6+
import com._4point.aem.package_manager.FormsAndDocumentsClient;
7+
import com._4point.aem.package_manager.FormsAndDocumentsClientEx;
8+
9+
public class SamplesDeployer {
10+
private final FormsAndDocumentsClientEx client;
11+
12+
public SamplesDeployer(String serverName, Integer port, String user, String password) {
13+
this(FormsAndDocumentsClient.builder()
14+
// By commenting the server name, port, user, and password lines out, the location defaults to locahost:4502 and admin/admin.
15+
.serverName(serverName)
16+
.port(port)
17+
.user(user)
18+
.password(password)
19+
//.password("admin")
20+
.logger(System.out::println)
21+
.buildEx()
22+
);
23+
}
24+
25+
private SamplesDeployer(FormsAndDocumentsClientEx client) {
26+
this.client = client;
27+
}
28+
29+
public void deployXdp(Path localFile, String remoteLocation) {
30+
// client.delete("sample-forms");
31+
client.upload(localFile, remoteLocation);
32+
}
33+
34+
public void deployAf(Path localZipFile) {
35+
// client.delete("sample-forms");
36+
client.upload(localZipFile);
37+
}
38+
39+
}

rest-services/it.tests/src/test/java/com/_4point/aem/docservices/rest_services/it_tests/TestUtils.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,27 @@ public class TestUtils {
3131
public static final String TEST_USER = "admin";
3232
public static final String TEST_USER_PASSWORD = "admin";
3333

34+
// Set this to true to use TestContainers for the integration tests.
35+
// The integration tests will run against an AEM instance running in a Docker container otherwise they will run against a local AEM instance.
36+
public static final boolean USE_TESTCONTAINERS = false;
37+
// Status of TestContainers support.
38+
// AEM Integration test issues:
39+
// * Sample Adaptive Form not deployed - Causes AF Rendering test to fail
40+
// * JSAFE not configured - Causes Assembler test to fail
41+
// * Sample XDP not deployed - Causes HTML5, PDF and Print rendering tests to fail
42+
// * GeneratePrintedOutput test AllArgs seems to want D:\FluentForms\Forms - Need to fix tests
43+
// * Reader Extensions not configured - Causes Reader Extensions test to fail
44+
// * OpenOffice not installed - causes GeneratePdf tests to fail
45+
//
46+
// Tests that pass:
47+
// * DataCacheService Tests
48+
// * GeneratePrintedOutput Form Doc tests
49+
// * GeneratePdfOutput Form Doc tests
50+
// * Import Data tests
51+
// * RenderPdfForm Form Doc tests
52+
// * Export Data tests
53+
// * ConvertPdfToXDP tests
54+
3455
private static final String SAMPLE_FORM_PDF_NAME = "SampleForm.pdf";
3556
private static final String SAMPLE_FORM_XDP_NAME = "SampleForm.xdp";
3657
private static final String SAMPLE_FORM_WITH_DATA_PDF_NAME = "SampleFormWithData.pdf";

rest-services/it.tests/src/test/java/com/_4point/aem/docservices/rest_services/it_tests/client/af/RenderAdaptiveFormTest.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package com._4point.aem.docservices.rest_services.it_tests.client.af;
22

3-
import static org.hamcrest.CoreMatchers.allOf;
4-
import static org.hamcrest.CoreMatchers.anyOf;
5-
import static org.hamcrest.CoreMatchers.containsString;
6-
import static org.hamcrest.CoreMatchers.not;
3+
import static org.hamcrest.CoreMatchers.*;
74
import static org.hamcrest.MatcherAssert.assertThat;
85
import static org.junit.jupiter.api.Assertions.*;
96

@@ -13,16 +10,20 @@
1310
import java.nio.file.Paths;
1411

1512
import org.apache.commons.io.IOUtils;
13+
import org.junit.jupiter.api.BeforeAll;
1614
import org.junit.jupiter.api.BeforeEach;
15+
import org.junit.jupiter.api.Tag;
1716
import org.junit.jupiter.api.Test;
1817

1918
import com._4point.aem.docservices.rest_services.client.af.AdaptiveFormsService;
2019
import com._4point.aem.docservices.rest_services.client.jersey.JerseyRestClient;
20+
import com._4point.aem.docservices.rest_services.it_tests.AemInstance;
2121
import com._4point.aem.docservices.rest_services.it_tests.TestUtils;
2222
import com._4point.aem.fluentforms.api.Document;
2323
import com._4point.aem.fluentforms.api.PathOrUrl;
2424
import com._4point.aem.fluentforms.impl.SimpleDocumentFactoryImpl;
2525

26+
@Tag("client-tests")
2627
class RenderAdaptiveFormTest {
2728

2829
private static final String SAMPLE_AF_NAME = "sample00002test";
@@ -32,11 +33,16 @@ class RenderAdaptiveFormTest {
3233

3334
private static final boolean SAVE_RESULTS = false;
3435

36+
@BeforeAll
37+
static void setUpAll() throws Exception {
38+
AemInstance.AEM_1.prepareForTests();
39+
}
40+
3541
@BeforeEach
3642
void setUp() throws Exception {
3743
underTest = AdaptiveFormsService.builder(JerseyRestClient.factory())
38-
.machineName(TestUtils.TEST_MACHINE_NAME)
39-
.port(TestUtils.TEST_MACHINE_PORT)
44+
.machineName(AemInstance.AEM_1.aemHost())
45+
.port(AemInstance.AEM_1.aemPort())
4046
.basicAuthentication(TestUtils.TEST_USER, TestUtils.TEST_USER_PASSWORD)
4147
.useSsl(false)
4248
.aemServerType(TestUtils.TEST_MACHINE_AEM_TYPE)
@@ -92,7 +98,7 @@ void testRenderAdaptiveFormPath() throws Exception {
9298
@Test
9399
void testRenderAdaptiveFormPathOrUrlDocument() throws Exception {
94100
PathOrUrl template = PathOrUrl.from(SAMPLE_AF_NAME);
95-
Document data = SimpleDocumentFactoryImpl.INSTANCE.create(TestUtils.SAMPLE_FORM_DATA_XML.toFile());
101+
Document data = SimpleDocumentFactoryImpl.INSTANCE.create(TestUtils.SAMPLE_FORM_DATA_XML);
96102
data.setContentTypeIfEmpty("application/xml");
97103

98104
Document result = underTest.renderAdaptiveForm(template, data);
@@ -109,7 +115,7 @@ void testRenderAdaptiveFormPathOrUrlDocument() throws Exception {
109115
@Test
110116
void testRenderAdaptiveFormStringDocument() throws Exception {
111117
String template = SAMPLE_AF_NAME;
112-
Document data = SimpleDocumentFactoryImpl.INSTANCE.create(TestUtils.SAMPLE_FORM_DATA_XML.toFile());
118+
Document data = SimpleDocumentFactoryImpl.INSTANCE.create(TestUtils.SAMPLE_FORM_DATA_XML);
113119
data.setContentTypeIfEmpty("application/xml");
114120

115121
Document result = underTest.renderAdaptiveForm(template, data);
@@ -126,7 +132,7 @@ void testRenderAdaptiveFormStringDocument() throws Exception {
126132
@Test
127133
void testRenderAdaptiveFormPathDocument() throws Exception {
128134
Path template = Paths.get(SAMPLE_AF_NAME);
129-
Document data = SimpleDocumentFactoryImpl.INSTANCE.create(TestUtils.SAMPLE_FORM_DATA_XML.toFile());
135+
Document data = SimpleDocumentFactoryImpl.INSTANCE.create(TestUtils.SAMPLE_FORM_DATA_XML);
130136
data.setContentTypeIfEmpty("application/xml");
131137

132138
Document result = underTest.renderAdaptiveForm(template, data);
@@ -143,7 +149,7 @@ void testRenderAdaptiveFormPathDocument() throws Exception {
143149
@Test
144150
void testRenderAdaptiveFormStringJsonDocument() throws Exception {
145151
String template = SAMPLE_JSON_AF_NAME;
146-
Document data = SimpleDocumentFactoryImpl.INSTANCE.create(TestUtils.SAMPLE_FORM_DATA_JSON.toFile());
152+
Document data = SimpleDocumentFactoryImpl.INSTANCE.create(TestUtils.SAMPLE_FORM_DATA_JSON);
147153
data.setContentTypeIfEmpty("application/json");
148154

149155
Document result = underTest.renderAdaptiveForm(template, data);

0 commit comments

Comments
 (0)