com.github.searls.jasmine.mojo.AbstractJasmineMojo Maven / Gradle / Ivy
Show all versions of jasmine-maven-plugin Show documentation
/*-
* #%L
* jasmine-maven-plugin
* %%
* Copyright (C) 2010 - 2017 Justin Searls
* %%
* 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.
* #L%
*/
package com.github.searls.jasmine.mojo;
import com.github.searls.jasmine.config.ImmutableJasmineConfiguration;
import com.github.searls.jasmine.config.ImmutableServerConfiguration;
import com.github.searls.jasmine.config.JasmineConfiguration;
import com.github.searls.jasmine.config.ServerConfiguration;
import com.github.searls.jasmine.io.ScansDirectory;
import com.github.searls.jasmine.model.FileSystemReporter;
import com.github.searls.jasmine.model.ImmutableScriptSearch;
import com.github.searls.jasmine.model.Reporter;
import com.github.searls.jasmine.model.ScriptSearch;
import com.github.searls.jasmine.runner.ReporterType;
import com.github.searls.jasmine.runner.SpecRunnerTemplate;
import com.github.searls.jasmine.thirdpartylibs.ProjectClassLoaderFactory;
import com.google.common.annotations.VisibleForTesting;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public abstract class AbstractJasmineMojo extends AbstractMojo {
protected static final String CUSTOM_RUNNER_CONFIGURATION_PARAM = "customRunnerConfiguration";
protected static final String CUSTOM_RUNNER_TEMPLATE_PARAM = "customRunnerTemplate";
// Properties in order of most-to-least interesting for client projects to override
/**
* Directory storing your JavaScript.
*
* @since 1.1.0
*/
@Parameter(
property = "jsSrcDir",
defaultValue = "${project.basedir}${file.separator}src${file.separator}main${file.separator}javascript")
private File jsSrcDir = null;
/**
* Directory storing your Jasmine Specs.
*
* @since 1.1.0
*/
@Parameter(
property = "jsTestSrcDir",
defaultValue = "${project.basedir}${file.separator}src${file.separator}test${file.separator}javascript")
private File jsTestSrcDir = null;
/**
* JavaScript sources (typically vendor/lib dependencies) that need to be loaded
* before other sources (and specs) in a particular order. Each source will first be
* searched for relative to ${jsSrcDir}
, then ${jsTestSrcDir}
,
* then (if it's not found in either) it will be included exactly as it appears in your POM.
*
* Therefore, if jquery.js is in ${jsSrcDir}/vendor
, you would configure:
*
* <preloadSources>
* <source>vendor/jquery.js</source>
* </preloadSources>
*
*
* And jquery.js would load before all the other sources and specs.
*
* @since 1.1.0
*/
@Parameter
private List preloadSources = Collections.emptyList();
/**
* It may be the case that the jasmine-maven-plugin doesn't currently suit all of your needs,
* and as a result the generated SpecRunner HTML files are set up in a way that you can't run
* your specs. Have no fear! Simply specify a custom spec runner template in the plugin configuration
* and make the changes you need.
*
* Potential values are a filesystem path, a URL, or a classpath resource. The default template is
* stored in src/main/resources/jasmine-templates/SpecRunner.htmltemplate
, and the
* required template strings are tokenized in "$*$" patterns.
*
* Example usage:
*
* <customRunnerTemplate>${project.basedir}/src/test/resources/myCustomRunner.template</customRunnerTemplate>
*
*
* @since 1.1.0
*/
@Parameter
private String customRunnerTemplate = null;
/**
* Sometimes you want to have full control over how scriptloaders are configured. In order to
* interpolate custom configuration into the generated runnerTemplate, specify a file containing
* the additional config. Potential values are a filesystem path, a URL, or a classpath resource.
*
* Example usage:
*
* <customRunnerConfiguration>${project.basedir}/src/test/resources/myCustomConfig.txt</customRunnerConfiguration>
*
*
* @since 1.1.0
*/
@Parameter
private String customRunnerConfiguration = null;
/**
* Specify a custom reporter to be used to print the test report.
* Example usage:
*
* <reporters>
* <reporter>
* <reporterName>${project.basedir}/src/test/resources/myCustomReporter.js</reporterName>
* </reporter>
* <reporter>
* <reporterName>STANDARD</reporterName>
* </reporter>
* </reporters>
*
*/
@Parameter
private List reporters = new ArrayList<>();
/**
* Specify a custom file system reporter to be used to store the test report.
* Example usage:
*
* <fileSystemReporters>
* <reporter>
* <fileName>MyFile.log</fileName>
* <reporterName>${project.basedir}/src/test/resources/myCustomReporter.js</reporterName>
* </reporter>
* <reporter>
* <fileName>Test-jasmine.xml</fileName>
* <reporterName>JUNIT_XML</reporterName>
* </reporter>
* </fileSystemReporters>
*
*/
@Parameter
private List fileSystemReporters = new ArrayList<>();
/**
* Target directory for files created by the plugin.
*
* @since 1.1.0
*/
@Parameter(defaultValue = "${project.build.directory}${file.separator}jasmine")
private File jasmineTargetDir = null;
/**
* The name of the Spec Runner file.
*
* @since 1.1.0
*/
@Parameter(defaultValue = "SpecRunner.html")
private String specRunnerHtmlFileName = "SpecRunner.html";
/**
* The name of the directory the specs will be deployed to on the server.
*
* @since 1.1.0
*/
@Parameter(defaultValue = "spec")
private String specDirectoryName = "spec";
/**
* The name of the directory the sources will be deployed to on the server.
*
* @since 1.1.0
*/
@Parameter(defaultValue = "src")
private String srcDirectoryName = "src";
/**
* The source encoding.
*
* @since 1.1.0
*/
@Parameter(defaultValue = "${project.build.sourceEncoding}")
private String sourceEncoding = StandardCharsets.UTF_8.name();
/**
* Allows specifying which source files should be included and in what order.
*
* <sourceIncludes>
* <include>vendor/**/*.js</include>
* <include>myBootstrapFile.js</include>
* <include>**/*.js</include>
* </sourceIncludes>
*
*
* Default sourceIncludes
:
*
* <sourceIncludes>
* <include>**/*.js</include>
* </sourceIncludes>
*
*
* @since 1.1.0
*/
@Parameter
private final List sourceIncludes = ScansDirectory.DEFAULT_INCLUDES;
/**
* Just like sourceIncludes
, but will exclude anything matching the provided patterns.
* There are no sourceExcludes
by default.
*
* @since 1.1.0
*/
@Parameter
private final List sourceExcludes = Collections.emptyList();
/**
* I often find myself needing control of the spec include order
* when I have some global spec helpers or spec-scoped dependencies, like:
*
* <specIncludes>
* <include>jasmine-jquery.js</include>
* <include>spec-helper.js</include>
* <include>**/*.js</include>
* </specIncludes>
*
*
* Default specIncludes
:
*
* <specIncludes>
* <include>**/*.js</include>
* </specIncludes>
*
*
* @since 1.1.0
*/
@Parameter
private final List specIncludes = ScansDirectory.DEFAULT_INCLUDES;
/**
* Just like specIncludes
, but will exclude anything matching the provided patterns.
* There are no specExcludes
by default.
*
* @since 1.1.0
*/
@Parameter
private final List specExcludes = Collections.emptyList();
/**
* Used by the jasmine:bdd
goal to specify port to run the server under.
*
* The jasmine:test
goal always uses a random available port so this property is ignored.
*
* @since 1.1.0
*/
@Parameter(property = "jasmine.serverPort", defaultValue = "8234")
private int serverPort = 8234;
/**
* Specify the URI scheme in which to access the SpecRunner.
*
* @since 1.3.1.4
*/
@Parameter(property = "jasmine.uriScheme", defaultValue = "http")
private String uriScheme = "http";
/**
* Not used by the jasmine:bdd
goal.
*
* The jasmine:test
goal to specify hostname where the server is running. Useful when using
* the RemoteWebDriver.
*
* @since 1.3.1.4
*/
@Parameter(property = "jasmine.serverHostname", defaultValue = "localhost")
private String serverHostname = "localhost";
/**
* Determines the strategy to use when generation the JasmineSpecRunner. This feature allows for custom
* implementation of the runner generator. Typically this is used when using different script runners.
*
* Some valid examples: DEFAULT, REQUIRE_JS
*
* @since 1.1.0
*/
@Parameter(property = "jasmine.specRunnerTemplate", defaultValue = "DEFAULT")
private SpecRunnerTemplate specRunnerTemplate = SpecRunnerTemplate.DEFAULT;
/**
* Automatically refresh the test runner at the given interval (specified in seconds) when using the jasmine:bdd
goal.
* A value of 0
disables the automatic refresh (which is the default).
*
* @since 1.3.1.1
*/
@Parameter(property = "jasmine.autoRefreshInterval", defaultValue = "0")
private int autoRefreshInterval = 0;
/**
* Specify additional contexts to make available.
*
* <additionalContexts>
* <context>
* <contextRoot>lib</contextRoot>
* <directory>${project.basedir}/src/main/lib</directory>
* </context>
* <context>
* <contextRoot>test/lib</contextRoot>
* <directory>${project.basedir}/src/test/lib</directory>
* </context>
* </additionalContexts>
*
*
* @since 1.3.1.5
*/
@Parameter
private List additionalContexts = Collections.emptyList();
private final MavenProject mavenProject;
private final ReporterType reporterType;
private final ResourceRetriever resourceRetriever;
private final ReporterRetriever reporterRetriever;
AbstractJasmineMojo(MavenProject mavenProject,
ReporterType reporterType,
ResourceRetriever resourceRetriever,
ReporterRetriever reporterRetriever) {
this.mavenProject = mavenProject;
this.reporterType = reporterType;
this.resourceRetriever = resourceRetriever;
this.reporterRetriever = reporterRetriever;
}
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
try {
this.run(getServerConfiguration(), getJasmineConfiguration());
} catch (MojoFailureException e) {
throw e;
} catch (Exception e) {
throw new MojoExecutionException("The jasmine-maven-plugin encountered an exception:", e);
}
}
protected final MavenProject getMavenProject() {
return mavenProject;
}
protected abstract void run(ServerConfiguration serverConfiguration,
JasmineConfiguration jasmineConfiguration) throws Exception;
private ServerConfiguration getServerConfiguration() {
return ImmutableServerConfiguration.builder()
.uriScheme(this.uriScheme)
.serverHostname(this.serverHostname)
.serverPort(this.serverPort)
.build();
}
private JasmineConfiguration getJasmineConfiguration() throws MojoExecutionException {
return ImmutableJasmineConfiguration.builder()
.customRunnerConfiguration(getCustomRunnerConfigurationFile())
.customRunnerTemplate(getCustomRunnerTemplateFile())
.contexts(getContexts())
.projectClassLoader(getProjectClassLoader())
.autoRefreshInterval(this.autoRefreshInterval)
.preloadSources(this.preloadSources)
.basedir(this.mavenProject.getBasedir())
.srcDirectoryName(this.srcDirectoryName)
.sources(this.getSources())
.specDirectoryName(this.specDirectoryName)
.specs(this.getSpecs())
.specRunnerHtmlFileName(this.specRunnerHtmlFileName)
.specRunnerTemplate(this.specRunnerTemplate)
.reporters(getReporters())
.fileSystemReporters(getFileSystemReporters())
.reporterType(this.reporterType)
.jasmineTargetDir(this.jasmineTargetDir)
.sourceEncoding(this.sourceEncoding)
.build();
}
private List getFileSystemReporters() throws MojoExecutionException {
return reporterRetriever.retrieveFileSystemReporters(
this.fileSystemReporters,
this.jasmineTargetDir,
this.mavenProject
);
}
private Optional getCustomRunnerTemplateFile() throws MojoExecutionException {
return resourceRetriever.getResourceAsFile(
CUSTOM_RUNNER_TEMPLATE_PARAM,
this.customRunnerTemplate,
this.mavenProject
);
}
private Optional getCustomRunnerConfigurationFile() throws MojoExecutionException {
return resourceRetriever.getResourceAsFile(
CUSTOM_RUNNER_CONFIGURATION_PARAM,
this.customRunnerConfiguration,
this.mavenProject
);
}
private List getReporters() throws MojoExecutionException {
return reporterRetriever.retrieveReporters(this.reporters, this.mavenProject);
}
private ClassLoader getProjectClassLoader() {
return new ProjectClassLoaderFactory(mavenProject.getArtifacts()).create();
}
private List getContexts() {
List contexts = new ArrayList<>();
contexts.add(new Context(this.srcDirectoryName, this.jsSrcDir));
contexts.add(new Context(this.specDirectoryName, this.jsTestSrcDir));
contexts.addAll(additionalContexts);
return contexts;
}
private ScriptSearch getSpecs() {
return ImmutableScriptSearch.builder()
.directory(this.jsTestSrcDir)
.includes(this.specIncludes)
.excludes(this.specExcludes)
.build();
}
private ScriptSearch getSources() {
return ImmutableScriptSearch.builder()
.directory(this.jsSrcDir)
.includes(this.sourceIncludes)
.excludes(this.sourceExcludes)
.build();
}
@VisibleForTesting
void setJsSrcDir(File jsSrcDir) {
this.jsSrcDir = jsSrcDir;
}
@VisibleForTesting
void setJsTestSrcDir(File jsTestSrcDir) {
this.jsTestSrcDir = jsTestSrcDir;
}
@VisibleForTesting
void setJasmineTargetDir(File jasmineTargetDir) {
this.jasmineTargetDir = jasmineTargetDir;
}
@VisibleForTesting
void setSourceEncoding(String sourceEncoding) {
this.sourceEncoding = sourceEncoding;
}
@VisibleForTesting
void setCustomRunnerConfiguration(String customRunnerConfiguration) {
this.customRunnerConfiguration = customRunnerConfiguration;
}
@VisibleForTesting
void setCustomRunnerTemplate(String customRunnerTemplate) {
this.customRunnerTemplate = customRunnerTemplate;
}
@VisibleForTesting
void setReporters(List reporters) {
this.reporters = reporters;
}
@VisibleForTesting
void setFileSystemReporters(List fileSystemReporters) {
this.fileSystemReporters = fileSystemReporters;
}
void setAutoRefreshInterval(int autoRefreshInterval) {
this.autoRefreshInterval = autoRefreshInterval;
}
}