Skip to content

Commit c1f1062

Browse files
committed
✨ Created non-WireMock tests that run against an AEM instance
The AEM instance can be controlled by TestContainers. WIP - The AEM instance tests that require data are not working just yet.
1 parent 6d8212f commit c1f1062

10 files changed

Lines changed: 449 additions & 412 deletions

spring/fluentforms-sample-webmvc-app/pom.xml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515

1616
<properties>
1717
<java.version>17</java.version>
18-
<wiremock.version>4.0.0-beta.15</wiremock.version>
18+
<wiremock.version>3.13.1</wiremock.version>
19+
<wiremock-spring-boot.version>3.10.6</wiremock-spring-boot.version>
1920
<htmlunit.version>4.16.0</htmlunit.version>
20-
<fluentforms.spring.boot.starter.version>0.0.5-SNAPSHOT</fluentforms.spring.boot.starter.version>
21+
<fluentforms.spring.boot.starter.version>0.0.4-SNAPSHOT</fluentforms.spring.boot.starter.version>
2122
<fp.hamcrest.matchers.version>0.0.4-SNAPSHOT</fp.hamcrest.matchers.version>
2223
</properties>
2324

@@ -87,6 +88,12 @@
8788
<version>${wiremock.version}</version>
8889
<scope>test</scope>
8990
</dependency>
91+
<dependency>
92+
<groupId>org.wiremock.integrations</groupId>
93+
<artifactId>wiremock-spring-boot</artifactId>
94+
<version>${wiremock-spring-boot.version}</version>
95+
<scope>test</scope>
96+
</dependency>
9097
<dependency>
9198
<groupId>com.4point.testing</groupId>
9299
<artifactId>4point-hamcrest-matchers</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com._4point.aem.fluentforms.sampleapp.resources;
2+
3+
import static com._4point.aem.fluentforms.sampleapp.resources.ResponseEntityMatchers.hasStringEntityMatching;
4+
import static com._4point.aem.fluentforms.sampleapp.resources.ResponseEntityMatchers.isMediaType;
5+
import static com._4point.aem.fluentforms.sampleapp.resources.ResponseEntityMatchers.isStatus;
6+
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
7+
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
8+
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
9+
import static org.hamcrest.MatcherAssert.assertThat;
10+
import static org.hamcrest.Matchers.allOf;
11+
import static org.hamcrest.Matchers.anyOf;
12+
import static org.hamcrest.Matchers.matchesRegex;
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
15+
import java.net.URI;
16+
import java.nio.file.Path;
17+
import java.util.List;
18+
import java.util.concurrent.TimeUnit;
19+
20+
import org.htmlunit.WebClient;
21+
import org.htmlunit.html.HtmlPage;
22+
import org.junit.jupiter.api.Test;
23+
import org.junit.jupiter.api.Timeout;
24+
import org.springframework.boot.test.web.server.LocalServerPort;
25+
import org.springframework.http.HttpStatus;
26+
import org.springframework.http.MediaType;
27+
import org.springframework.http.ResponseEntity;
28+
import org.springframework.web.client.RestClient;
29+
30+
abstract class AbstractAemProxyEndpointTest {
31+
private static final Path RESOURCES_DIR = Path.of("src", "test", "resources");
32+
private static final Path SAMPLE_FILES_DIR = RESOURCES_DIR.resolve("SampleFiles");
33+
34+
@LocalServerPort
35+
private int port;
36+
37+
@Timeout(value = 30, unit = TimeUnit.SECONDS)
38+
@Test
39+
void testProxyCsrfToken() throws Exception {
40+
String csrf_token_path = "/aem/libs/granite/csrf/token.json";
41+
42+
// RestTestClient requires Spring Boot 4.x, which we can't use yet because Fluent Forms requires Spring Boot 3.x.
43+
// RestTestClient restTestClient = RestTestClient.bindToServer()
44+
// .baseUrl(getBaseUri(port).toASCIIString())
45+
// .build();
46+
// restTestClient.get().uri(csrf_token_path).exchange()
47+
// .expectStatus().isOk()
48+
// .expectHeader().value(HttpHeaders.CONTENT_TYPE,
49+
// org.hamcrest.Matchers.anyOf(org.hamcrest.Matchers.equalTo(MediaType.APPLICATION_JSON_VALUE), org.hamcrest.Matchers.equalTo(MediaType.TEXT_HTML_VALUE)))
50+
// .expectBody(String.class)
51+
// .value(body -> assertThat(body, matchesRegex("\\s*\\{\"token\":\".*\"\\}\\s*")));
52+
53+
RestClient restClient = RestClient.create();
54+
ResponseEntity<String> response = restClient.get()
55+
.uri(getBaseUri(port) + csrf_token_path)
56+
.retrieve()
57+
.toEntity(String.class);
58+
59+
assertThat(response, allOf(isStatus(HttpStatus.OK),
60+
// For some reason that I can't determine, wiremock returns text/html. I would like to fix this, but for now, I accept both.
61+
anyOf(isMediaType(MediaType.APPLICATION_JSON), isMediaType(MediaType.TEXT_HTML)),
62+
hasStringEntityMatching(matchesRegex("\\s*\\{\"token\":\".*\"\\}\\s*"))
63+
));
64+
}
65+
66+
@Test
67+
void proxyTest() throws Exception {
68+
try (final WebClient webClient = new WebClient()) {
69+
String baseUri = getBaseUriString(port) + "/FluentForms/Html5FormsServiceRenderHtml5Form" + "?form=" + SAMPLE_FILES_DIR.resolve("SampleForm.xdp").toAbsolutePath();
70+
final HtmlPage page = webClient.getPage(baseUri);
71+
assertEquals("LC Forms", page.getTitleText());
72+
}
73+
List.of(
74+
/* "/content/xfaforms/profiles/default.html", */ // This fails for some reason however it's not essential to the test because if this were truly not working, none of the other calls would be made.
75+
/* "/libs/granite/csrf/token.json", */ // This is not tested because it doesn't always happen (depending on the timings).
76+
"/etc.clientlibs/fd/xfaforms/clientlibs/I18N/en.js",
77+
"/etc.clientlibs/fd/xfaforms/clientlibs/profile.css",
78+
"/etc.clientlibs/fd/xfaforms/clientlibs/profile.js",
79+
"/etc.clientlibs/clientlibs/granite/jquery/granite/csrf.js",
80+
"/etc.clientlibs/toggles.json"
81+
)
82+
.forEach(url->verify(getRequestedFor(urlPathEqualTo(url))));
83+
}
84+
85+
protected static String getBaseUriString(int port) {
86+
return getBaseUri(port).toString();
87+
}
88+
89+
private static URI getBaseUri(int port) {
90+
return URI.create("http://localhost:" + port);
91+
}
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
package com._4point.aem.fluentforms.sampleapp.resources;
2+
3+
import static com._4point.aem.fluentforms.sampleapp.resources.ResponseEntityMatchers.*;
4+
import static org.hamcrest.MatcherAssert.assertThat;
5+
import static org.hamcrest.Matchers.*;
6+
7+
import java.io.IOException;
8+
import java.net.URI;
9+
import java.nio.file.Files;
10+
import java.nio.file.Path;
11+
12+
import org.junit.jupiter.api.Test;
13+
import org.springframework.boot.test.web.server.LocalServerPort;
14+
import org.springframework.http.HttpStatus;
15+
import org.springframework.http.MediaType;
16+
import org.springframework.http.ResponseEntity;
17+
import org.springframework.web.client.RestClient;
18+
import org.springframework.web.util.UriComponentsBuilder;
19+
20+
public abstract class AbstractFluentFormsResourcesTest {
21+
private static final String APPLICATION_PDF = "application/pdf";
22+
private static final MediaType APPLICATION_PDF_TYPE = MediaType.valueOf(APPLICATION_PDF);
23+
24+
private static final Path RESOURCES_DIR = Path.of("src", "test", "resources");
25+
private static final Path SAMPLE_FILES_DIR = RESOURCES_DIR.resolve("SampleFiles");
26+
27+
private static final RestClient REST_CLIENT = RestClient.create();
28+
29+
@LocalServerPort
30+
private int port;
31+
@Test
32+
void testOutputServiceGeneratePdf_NoData() {
33+
URI uri = UriComponentsBuilder.fromUri(getBaseUri(port))
34+
.path("/FluentForms/OutputServiceGeneratePdf")
35+
.queryParam("form", "sample_template.xdp")
36+
.build()
37+
.toUri();
38+
39+
ResponseEntity<byte[]> response = REST_CLIENT.get()
40+
.uri(uri)
41+
.retrieve()
42+
.toEntity(byte[].class);
43+
44+
assertThat(response, allOf(isStatus(HttpStatus.OK), isMediaType(APPLICATION_PDF_TYPE)));
45+
}
46+
47+
@Test
48+
void testOutputServiceGeneratePdf_WithData() {
49+
String dataKeyValue = "testOutputServiceGeneratePdf_WithData.xml";
50+
URI dataUri = UriComponentsBuilder.fromUri(getBaseUri(port))
51+
.path("/FluentForms/SaveData")
52+
.queryParam("dataKey", dataKeyValue)
53+
.build()
54+
.toUri();
55+
56+
ResponseEntity<Void> dataResponse = REST_CLIENT.post()
57+
.uri(dataUri)
58+
.body(readXmlData())
59+
.retrieve()
60+
.toBodilessEntity();
61+
62+
assertThat(dataResponse, allOf(isStatus(HttpStatus.NO_CONTENT)));
63+
64+
URI uri = UriComponentsBuilder.fromUri(getBaseUri(port))
65+
.path("/FluentForms/OutputServiceGeneratePdf")
66+
.queryParam("form", "sample_template.xdp")
67+
.queryParam("dataKey", dataKeyValue)
68+
.build()
69+
.toUri();
70+
71+
ResponseEntity<byte[]> response = REST_CLIENT.get()
72+
.uri(uri)
73+
.retrieve()
74+
.toEntity(byte[].class);
75+
76+
assertThat(response, allOf(isStatus(HttpStatus.OK), isMediaType(APPLICATION_PDF_TYPE)));
77+
}
78+
79+
@Test
80+
void testOutputServiceGeneratePdf_WithPostedXmlData() {
81+
URI uri = UriComponentsBuilder.fromUri(getBaseUri(port))
82+
.path("/FluentForms/OutputServiceGeneratePdf")
83+
.queryParam("form", "sample_template.xdp")
84+
.build()
85+
.toUri();
86+
87+
ResponseEntity<byte[]> response = REST_CLIENT.post()
88+
.uri(uri)
89+
.body(readXmlData())
90+
.retrieve()
91+
.toEntity(byte[].class);
92+
93+
assertThat(response, allOf(isStatus(HttpStatus.OK), isMediaType(APPLICATION_PDF_TYPE)));
94+
}
95+
96+
@Test
97+
void testOutputServiceGeneratePdf_WithPostedJsonData() {
98+
URI uri = UriComponentsBuilder.fromUri(getBaseUri(port))
99+
.path("/FluentForms/OutputServiceGeneratePdf")
100+
.queryParam("form", "sample_template.xdp")
101+
.build()
102+
.toUri();
103+
104+
ResponseEntity<byte[]> response = REST_CLIENT.post()
105+
.uri(uri)
106+
.body(readJsonData())
107+
.retrieve()
108+
.toEntity(byte[].class);
109+
110+
assertThat(response, allOf(isStatus(HttpStatus.OK), isMediaType(APPLICATION_PDF_TYPE)));
111+
}
112+
113+
@Test
114+
void testAdaptiveFormsServiceRenderAdaptiveForm_NoData() {
115+
URI uri = UriComponentsBuilder.fromUri(getBaseUri(port))
116+
.path("/FluentForms/AdaptiveFormsServiceRenderAdaptiveForm")
117+
.queryParam("form", "sample00002test")
118+
.build()
119+
.toUri();
120+
121+
ResponseEntity<byte[]> response = REST_CLIENT.get()
122+
.uri(uri)
123+
.retrieve()
124+
.toEntity(byte[].class);
125+
126+
assertThat(response, allOf(isStatus(HttpStatus.OK), hasMediaType(isCompatibleWith(MediaType.TEXT_HTML))));
127+
}
128+
129+
@Test
130+
void testAdaptiveFormsServiceRenderAdaptiveForm_WithData() {
131+
String dataKeyValue = "testAdaptiveFormsServiceRenderAdaptiveForm_WithData";
132+
URI dataUri = UriComponentsBuilder.fromUri(getBaseUri(port))
133+
.path("/FluentForms/SaveData")
134+
.queryParam("dataKey", dataKeyValue)
135+
.build()
136+
.toUri();
137+
138+
ResponseEntity<Void> dataResponse = REST_CLIENT.post()
139+
.uri(dataUri)
140+
.body(readXmlData())
141+
.retrieve()
142+
.toBodilessEntity();
143+
144+
assertThat(dataResponse, allOf(isStatus(HttpStatus.NO_CONTENT)));
145+
146+
URI uri = UriComponentsBuilder.fromUri(getBaseUri(port))
147+
.path("/FluentForms/AdaptiveFormsServiceRenderAdaptiveForm")
148+
.queryParam("form", "sample00002test")
149+
.queryParam("dataKey", dataKeyValue)
150+
.build()
151+
.toUri();
152+
153+
ResponseEntity<byte[]> response = REST_CLIENT.get()
154+
.uri(uri)
155+
.retrieve()
156+
.toEntity(byte[].class);
157+
158+
assertThat(response, allOf(isStatus(HttpStatus.OK), hasMediaType(isCompatibleWith(MediaType.TEXT_HTML))));
159+
}
160+
161+
@Test
162+
void testHtml5FormsServiceRenderHtml5Form_NoData() {
163+
URI uri = UriComponentsBuilder.fromUri(getBaseUri(port))
164+
.path("/FluentForms/Html5FormsServiceRenderHtml5Form")
165+
.queryParam("form", SAMPLE_FILES_DIR.resolve("SampleForm.xdp").toAbsolutePath())
166+
.build()
167+
.toUri();
168+
169+
ResponseEntity<byte[]> response = REST_CLIENT.get()
170+
.uri(uri)
171+
.retrieve()
172+
.toEntity(byte[].class);
173+
174+
assertThat(response, allOf(isStatus(HttpStatus.OK), hasMediaType(isCompatibleWith(MediaType.TEXT_HTML))));
175+
}
176+
177+
@Test
178+
void testHtml5FormsServiceRenderHtmlForm_WithData() {
179+
String dataKeyValue = "testHtml5FormsServiceRenderHtmlForm_WithData";
180+
URI dataUri = UriComponentsBuilder.fromUri(getBaseUri(port))
181+
.path("/FluentForms/SaveData")
182+
.queryParam("dataKey", dataKeyValue)
183+
.build()
184+
.toUri();
185+
186+
ResponseEntity<Void> dataResponse = REST_CLIENT.post()
187+
.uri(dataUri)
188+
.body(readXmlData())
189+
.retrieve()
190+
.toBodilessEntity();
191+
192+
assertThat(dataResponse, allOf(isStatus(HttpStatus.NO_CONTENT)));
193+
194+
URI uri = UriComponentsBuilder.fromUri(getBaseUri(port))
195+
.path("/FluentForms/Html5FormsServiceRenderHtml5Form")
196+
.queryParam("form", SAMPLE_FILES_DIR.resolve("SampleForm.xdp").toAbsolutePath())
197+
.queryParam("dataKey", dataKeyValue)
198+
.build()
199+
.toUri();
200+
201+
ResponseEntity<byte[]> response = REST_CLIENT.get()
202+
.uri(uri)
203+
.retrieve()
204+
.toEntity(byte[].class);
205+
206+
assertThat(response, allOf(isStatus(HttpStatus.OK), hasMediaType(isCompatibleWith(MediaType.TEXT_HTML))));
207+
}
208+
209+
private byte[] readXmlData() {
210+
Path sampleData = SAMPLE_FILES_DIR.resolve("SampleForm_data.xml");
211+
try {
212+
return Files.readAllBytes(sampleData);
213+
} catch (IOException e) {
214+
throw new IllegalStateException("Error while reading sample data (%s)".formatted(sampleData.toAbsolutePath()), e);
215+
}
216+
}
217+
218+
private byte[] readJsonData() {
219+
Path sampleData = SAMPLE_FILES_DIR.resolve("SampleForm_data.json");
220+
try {
221+
return Files.readAllBytes(sampleData);
222+
} catch (IOException e) {
223+
throw new IllegalStateException("Error while reading sample data (%s)".formatted(sampleData.toAbsolutePath()), e);
224+
}
225+
}
226+
227+
@Test
228+
void testSaveData() {
229+
URI dataUri = UriComponentsBuilder.fromUri(getBaseUri(port))
230+
.path("/FluentForms/SaveData")
231+
.queryParam("dataKey", "saveDataKey_testSaveData")
232+
.build()
233+
.toUri();
234+
235+
ResponseEntity<Void> dataResponse = REST_CLIENT.post()
236+
.uri(dataUri)
237+
.body("<root/>")
238+
.retrieve()
239+
.toBodilessEntity();
240+
241+
assertThat(dataResponse, allOf(isStatus(HttpStatus.NO_CONTENT)));
242+
}
243+
244+
protected static String getBaseUriString(int port) {
245+
return getBaseUri(port).toString();
246+
}
247+
248+
private static URI getBaseUri(int port) {
249+
return URI.create("http://localhost:" + port);
250+
}
251+
}

0 commit comments

Comments
 (0)