-
Notifications
You must be signed in to change notification settings - Fork 7
/
CypressTest.java
80 lines (70 loc) · 3.56 KB
/
CypressTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package com.integralblue.demo.jumpstart;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.time.Duration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import org.testcontainers.Testcontainers;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.SelinuxContext;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy;
import lombok.extern.slf4j.Slf4j;
//if the Cypress tests end up writing to the database, a separate database instance must be used to ensure this test doesn't pollute the expected database state of other tests that run after it. &TC_REUSABLE=true ensures that.
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"spring.datasource.url=${internal.datasource.url}&TC_REUSABLE=true"})
@Slf4j
/* default */ class CypressTest {
//see: https://candrews.integralblue.com/2021/08/cypress-testing-integrated-with-gradle-and-spring-boot/
@LocalServerPort
private int port;
private static String cypressVersion;
@BeforeAll
/* default */ static void beforeAll() throws Exception {
cypressVersion = getCypressVersion();
log.info("Tests will run using Cypress version {}", cypressVersion);
}
@Test
/* default */ void testCypress() throws Exception {
Testcontainers.exposeHostPorts(port); // allow the container to access the running web application
try (GenericContainer<?> container = new GenericContainer<>("cypress/included:" + cypressVersion)) {
container.addFileSystemBind(Path.of(".").toAbsolutePath().toString(), "/src", BindMode.READ_WRITE, SelinuxContext.SHARED);
container
.withLogConsumer(new Slf4jLogConsumer(log))
.withEnv("CYPRESS_baseUrl", String.format("https://%s:%d", GenericContainer.INTERNAL_HOST_HOSTNAME, port))
.withWorkingDirectory("/src/frontend")
.withStartupCheckStrategy(
new OneShotStartupCheckStrategy().withTimeout(Duration.ofHours(1))
).start();
assertThat(container.getLogs()).contains("All specs passed!");
}
}
/** Get the installed version of Cypress.
*
* This approach ensures that as the version of Cypress specified in package management changes,
* this tests will always use the same version.
* @return installed version of Cypress.
* @throws Exception if something goes wrong
*/
private static String getCypressVersion() throws Exception {
String cmd = "./gradlew";
if (System.getProperty("os.name").startsWith("Win")) {
cmd = "./gradlew.bat";
}
final Process process = Runtime.getRuntime().exec(new String[]{cmd, "npmCypressVersion"}, null, new File("."));
Assert.state(process.waitFor() == 0,"Cypress version command did not complete successfully");
final String output = StreamUtils.copyToString(process.getInputStream(), StandardCharsets.UTF_8);
final Matcher matcher = Pattern.compile("Cypress package version: (?<version>\\d++(?:\\.\\d++)++)").matcher(output);
Assert.state(matcher.find(), "Could not determine Cypress version from command output. Output: " + output);
return matcher.group("version");
}
}