Skip to content

Commit

Permalink
Run a webserver to serve test content rather than loading from file://
Browse files Browse the repository at this point in the history
  • Loading branch information
niloc132 committed Jul 11, 2020
1 parent ff36284 commit 97c5409
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 23 deletions.
21 changes: 20 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@

<!-- Test goal -->
<selenium.version>3.141.59</selenium.version>
<selenium.htmlunit.version>2.36.0</selenium.htmlunit.version>
<selenium.htmlunit.version>2.41.0</selenium.htmlunit.version>
<jsoup.version>1.12.1</jsoup.version>
<jetty.version>9.4.26.v20200117</jetty.version>

<!-- Required core j2cl dependencies -->
<vertispan.jsinterop.base.version>1.0.0-SNAPSHOT</vertispan.jsinterop.base.version>
Expand Down Expand Up @@ -204,6 +205,20 @@
</exclusions>
</dependency>

<!-- allow test goal to start a simple server -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>

<!-- specified to help htmlunit-driver and selenium-server have consistent dependencies -->
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-client</artifactId>
<version>${jetty.version}</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down Expand Up @@ -342,6 +357,10 @@
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</dependency>

<!-- Test -->
<dependency>
Expand Down
80 changes: 58 additions & 22 deletions src/main/java/net/cardosi/mojo/TestMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Level;

import com.google.gson.GsonBuilder;
Expand All @@ -22,6 +23,12 @@
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.resource.Resource;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
Expand Down Expand Up @@ -224,7 +231,6 @@ public void execute() throws MojoExecutionException, MojoFailureException {
String testClass = testFilePathWithoutSuffix.replaceAll("/", ".");

// Synthesize a new project which only depends on the last one, and only contains the named test's .testsuite content, remade into a one-off JS file

ArrayList<CachedProject> finalChildren = new ArrayList<>(e.getChildren());
finalChildren.add(e);
CachedProject t = new CachedProject(diskCache, project.getArtifact(), project, finalChildren, Collections.singletonList(tmp.toString()), Collections.emptyList());
Expand All @@ -241,56 +247,86 @@ public void execute() throws MojoExecutionException, MojoFailureException {
// write a simple html file to that output dir
//TODO parallelize this - run once each is done, possibly concurrently
//TODO don't fail on the first test that doesn't work
String startupHtmlFile;
Path startupHtmlFile;
try {
Path webappDirPath = Paths.get(webappDirectory);
Path outputJsPath = webappDirPath.resolve(config.getInitialScriptFilename());
File outputJs = new File(new File(webappDirectory), config.getInitialScriptFilename());
Path junitStartupFile = Paths.get(outputJs.getParent(), outputJs.getName().substring(0, outputJs.getName().length() - 2) + "html");
Files.createDirectories(junitStartupFile.getParent());
Path junitStartupPath = outputJsPath.resolveSibling(outputJsPath.getFileName().toString().substring(0, outputJs.getName().length() - 2) + "html");
Files.createDirectories(junitStartupPath.getParent());
String fileContents = CharStreams.toString(new InputStreamReader(TestMojo.class.getResourceAsStream("/junit.html")));
fileContents = fileContents.replace("<TEST_SCRIPT>", outputJs.getName());

Files.write(junitStartupFile, fileContents.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
startupHtmlFile = junitStartupFile.toAbsolutePath().toString();
Files.write(junitStartupPath, fileContents.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
startupHtmlFile = webappDirPath.relativize(junitStartupPath);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
// assuming that was successful, start htmlunit to run the test

// Start a webserver TODO start just once for all tests
Server server = new Server(0);

// Tell jetty how to serve our compiled content
ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setDirectoriesListed(true);//enabled for easier debugging, if we introduce a "manual" mode
resourceHandler.setBaseResource(Resource.newResource(webappDirectory));

server.setHandler(resourceHandler);
server.start();

// With the server started, start a browser too so they work in parallel
WebDriver driver = createBrowser();

// Wait until server is ready
if (!server.isStarted()) {
CountDownLatch started = new CountDownLatch(1);
server.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() {
@Override
public void lifeCycleStarted(LifeCycle event) {
started.countDown();
}
});
started.await();
}
int port = ((ServerConnector) server.getConnectors()[0]).getLocalPort();

try {
driver.get("file://" + startupHtmlFile);
// loop and poll if tests are done
String url = "http://localhost:" + port + "/" + startupHtmlFile.toString();
System.out.println("fetching " + url);
driver.get(url);

// Loop and poll if tests are done
new FluentWait<>(driver)
.withTimeout(Duration.ofMinutes(1))
.withMessage("Tests failed to finish in timeout")
.withMessage("Tests failed to finish before timeout")
.pollingEvery(Duration.ofMillis(100))
.until(d -> isFinished(d));
// check for success
// Check for success
if (!isSuccess(driver)) {
// print the content of the browser console to the log
// Print the content of the browser console to the log
this.analyzeLog(driver);
failedTests.put(config.getTest(), startupHtmlFile);
failedTests.put(config.getTest(), generatedTest);
getLog().error("Test failed!");
} else {
getLog().info("Test passed!");
}
} catch (Exception ex) {
failedTests.put(config.getTest(), startupHtmlFile);
if (!Objects.isNull(driver)) {
this.analyzeLog(driver);
}
failedTests.put(config.getTest(), generatedTest);
this.analyzeLog(driver);
getLog().error("Test failed!");
getLog().error(cleanForMavenLog(String.format(ex.getMessage())));
getLog().error(cleanForMavenLog(ex.getMessage()));
} finally {
if (driver != null) {
driver.quit();
}
driver.quit();
}
}
} catch (ProjectBuildingException | IOException e) {
throw new MojoExecutionException("Failed to build project structure", e);
} catch (Exception e) {
//TODO refine this, possibly remove
throw new MojoExecutionException("Failed on test server start", e);
}

if(failedTests.isEmpty()) {
if (failedTests.isEmpty()) {
getLog().info("All tests were passed successfully!");
} else {
failedTests.forEach((name, startupHtmlFile) -> getLog().error(String.format("Test %s failed, please try manually %s", name, startupHtmlFile)));
Expand Down

0 comments on commit 97c5409

Please sign in to comment.