diff --git a/pom.xml b/pom.xml index 7fbab0464..782a8eae5 100644 --- a/pom.xml +++ b/pom.xml @@ -137,7 +137,7 @@ - 3.0.4 + 3.1.0 @@ -246,6 +246,11 @@ htmlunit 2.14 + + com.github.klieber + phantomjs-maven-core + 0.6 + diff --git a/src/main/java/com/github/searls/jasmine/driver/WebDriverFactory.java b/src/main/java/com/github/searls/jasmine/driver/WebDriverFactory.java index b9607065d..26bedb54a 100644 --- a/src/main/java/com/github/searls/jasmine/driver/WebDriverFactory.java +++ b/src/main/java/com/github/searls/jasmine/driver/WebDriverFactory.java @@ -1,12 +1,15 @@ package com.github.searls.jasmine.driver; +import com.github.klieber.phantomjs.locate.PhantomJsLocator; +import com.github.klieber.phantomjs.locate.PhantomJsLocatorOptions; +import com.github.klieber.phantomjs.locate.RepositoryDetails; import com.github.searls.jasmine.mojo.Capability; import com.google.common.base.Objects; import org.codehaus.plexus.util.StringUtils; import org.openqa.selenium.Capabilities; import org.openqa.selenium.WebDriver; import org.openqa.selenium.htmlunit.HtmlUnitDriver; -import org.openqa.selenium.remote.BrowserType; +import org.openqa.selenium.phantomjs.PhantomJSDriver; import org.openqa.selenium.remote.DesiredCapabilities; import java.lang.reflect.Constructor; @@ -21,6 +24,8 @@ public class WebDriverFactory { private String browserVersion; private String webDriverClassName; private List webDriverCapabilities; + private PhantomJsLocatorOptions phantomJsLocatorOptions; + private RepositoryDetails repositoryDetails; public WebDriverFactory() { setWebDriverCapabilities(null); @@ -42,9 +47,27 @@ public void setWebDriverCapabilities(List webDriverCapabilities) { this.webDriverCapabilities = Objects.firstNonNull(webDriverCapabilities, Collections.emptyList()); } + public PhantomJsLocatorOptions getPhantomJsLocatorOptions() { + return phantomJsLocatorOptions; + } + + public void setPhantomJsLocatorOptions(PhantomJsLocatorOptions phantomJsLocatorOptions) { + this.phantomJsLocatorOptions = phantomJsLocatorOptions; + } + + public RepositoryDetails getRepositoryDetails() { + return repositoryDetails; + } + + public void setRepositoryDetails(RepositoryDetails repositoryDetails) { + this.repositoryDetails = repositoryDetails; + } + public WebDriver createWebDriver() throws Exception { - if (HtmlUnitDriver.class.getName().equals(webDriverClassName)) { - return createDefaultWebDriver(); + if (PhantomJSDriver.class.getName().equals(webDriverClassName)) { + return createPhantomJsWebDriver(); + } else if (HtmlUnitDriver.class.getName().equals(webDriverClassName)) { + return createHtmlUnitWebDriver(); } else { return createCustomWebDriver(); } @@ -85,6 +108,11 @@ private Object[] getWebDriverConstructorArguments(ConstructorHtmlUnit by default. - * - *

Some valid examples:

- *
    - *
  • org.openqa.selenium.htmlunit.HtmlUnitDriver
  • - *
  • org.openqa.selenium.phantomjs.PhantomJSDriver
  • - *
  • org.openqa.selenium.firefox.FirefoxDriver
  • - *
  • org.openqa.selenium.ie.InternetExplorerDriver
  • - *
- *

- * For org.openqa.selenium.phantomjs.PhantomJSDriver, see the webDriverCapabilities property. - * - * @since 1.1.0 - */ - @Parameter(defaultValue="org.openqa.selenium.htmlunit.HtmlUnitDriver") - protected String webDriverClassName; - - /** - *

Web driver capabilities used to initialize a DesiredCapabilities instance when creating a web driver.

- * - *

Capabilities value can be either a String, a List, or a Map.

- * - *

Example:

- *
-   * <webDriverCapabilities>
-   *   <capability>
-   *     <name>phantomjs.binary.path</name>
-   *     <value>/opt/phantomjs/bin/phantomjs</value>
-   *   </capability>
-   *   <capability>
-   *     <name>phantomjs.cli.args</name>
-   *     <list>
-   *       <value>--disk-cache=true</value>
-   *       <value>--max-disk-cache-size=256</value>
-   *     </list>
-   *   </capability>
-   *   <capability>
-   *     <name>proxy</name>
-   *     <map>
-   *       <httpProxy>myproxyserver.com:8000</httpProxy>
-   *     </map>
-   *   </capability>
-   * </webDriverCapabilities>
-   * 
- * - * @since 1.3.1.1 - */ - @Parameter - protected List webDriverCapabilities = Collections.emptyList(); - - /** - *

Determines the browser and version profile that HtmlUnit will simulate. This setting does nothing if the plugin is configured not to use HtmlUnit. - * This maps 1-to-1 with the public static instances found in {@link com.gargoylesoftware.htmlunit.BrowserVersion}.

- * - *

Some valid examples: CHROME, FIREFOX_17, INTERNET_EXPLORER_9, INTERNET_EXPLORER_10

- * - * @since 1.1.0 - */ - @Parameter(defaultValue="FIREFOX_17") - protected String browserVersion; - - /** - *

Determines the format that jasmine:test will print to console.

- *

Valid options:

- *
    - *
  • "documentation" - (default) - print specs in a nested format
  • - *
  • "progress" - more terse, with a period for a passed specs and an 'F' for failures (e.g. '...F...')
  • - *
- * - * @since 1.1.0 - */ - @Parameter(defaultValue="documentation") - protected String format; - /** *

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 @@ -250,14 +174,6 @@ public abstract class AbstractJasmineMojo extends AbstractMojo implements Jasmin @Parameter(defaultValue="ManualSpecRunner.html") protected String manualSpecRunnerHtmlFileName; - /** - * The name of the generated JUnit XML report. - * - * @since 1.1.0 - */ - @Parameter(defaultValue="TEST-jasmine.xml") - protected String junitXmlReportFileName; - /** * The name of the directory the specs will be deployed to on the server. * @@ -282,15 +198,6 @@ public abstract class AbstractJasmineMojo extends AbstractMojo implements Jasmin @Parameter(defaultValue="${project.build.sourceEncoding}") protected String sourceEncoding; - /** - * Keep the server alive after the jasmine:test goal exists. - * Useful if you need to run further analysis on your tests, like collecting code coverage. - * - * @since 1.3.1.0 - */ - @Parameter(property="keepServerAlive", defaultValue="false") - protected boolean keepServerAlive; - /** *

Allows specifying which source files should be included and in what order.

*
@@ -376,16 +283,16 @@ public abstract class AbstractJasmineMojo extends AbstractMojo implements Jasmin
   @Parameter(property="jasmine.uriScheme", defaultValue="http")
   protected String uriScheme;
 
-    /**
-     * 

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") - protected String serverHostname; + /** + *

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") + protected String serverHostname; /** *

Determines the strategy to use when generation the JasmineSpecRunner. This feature allows for custom diff --git a/src/main/java/com/github/searls/jasmine/mojo/PhantomJsOptions.java b/src/main/java/com/github/searls/jasmine/mojo/PhantomJsOptions.java new file mode 100644 index 000000000..422c2c3e0 --- /dev/null +++ b/src/main/java/com/github/searls/jasmine/mojo/PhantomJsOptions.java @@ -0,0 +1,76 @@ +package com.github.searls.jasmine.mojo; + +import com.github.klieber.phantomjs.locate.PhantomJsLocatorOptions; + +import java.io.File; + +public class PhantomJsOptions implements PhantomJsLocatorOptions { + + private static final String DEFAULT_PHANTOMJS_VERSION = "2.0.0"; + private static final String DEFAULT_OUTPUT_DIRECTORY = "target/phantomjs"; + + private Source source = Source.REPOSITORY; + + private String version; + private boolean checkSystemPath; + private boolean enforceVersion; + + private String baseUrl; + private File outputDirectory; + + public PhantomJsOptions() { + this.source = Source.REPOSITORY; + this.version = DEFAULT_PHANTOMJS_VERSION; + this.checkSystemPath = true; + this.enforceVersion = true; + this.outputDirectory = new File(DEFAULT_OUTPUT_DIRECTORY); + } + + public Source getSource() { + return source; + } + + public void setSource(Source source) { + this.source = source; + } + + public boolean isCheckSystemPath() { + return checkSystemPath; + } + + public void setCheckSystemPath(boolean checkSystemPath) { + this.checkSystemPath = checkSystemPath; + } + + public boolean isEnforceVersion() { + return enforceVersion; + } + + public void setEnforceVersion(boolean enforceVersion) { + this.enforceVersion = enforceVersion; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getBaseUrl() { + return baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public File getOutputDirectory() { + return outputDirectory; + } + + public void setOutputDirectory(File outputDirectory) { + this.outputDirectory = outputDirectory; + } +} diff --git a/src/main/java/com/github/searls/jasmine/mojo/TestMojo.java b/src/main/java/com/github/searls/jasmine/mojo/TestMojo.java index d7d1c3d47..dc26c4aa5 100644 --- a/src/main/java/com/github/searls/jasmine/mojo/TestMojo.java +++ b/src/main/java/com/github/searls/jasmine/mojo/TestMojo.java @@ -1,17 +1,7 @@ package com.github.searls.jasmine.mojo; -import java.io.File; -import java.net.URL; - -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugin.logging.Log; -import org.apache.maven.plugins.annotations.LifecyclePhase; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.ResolutionScope; -import org.eclipse.jetty.server.Server; -import org.openqa.selenium.WebDriver; - +import com.github.klieber.phantomjs.locate.PhantomJsLocatorOptions; +import com.github.klieber.phantomjs.locate.RepositoryDetails; import com.github.searls.jasmine.NullLog; import com.github.searls.jasmine.driver.WebDriverFactory; import com.github.searls.jasmine.format.JasmineResultLogger; @@ -22,16 +12,174 @@ import com.github.searls.jasmine.runner.SpecRunnerExecutor; import com.github.searls.jasmine.server.ResourceHandlerConfigurator; import com.github.searls.jasmine.server.ServerManager; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.jetty.server.Server; +import org.openqa.selenium.WebDriver; + +import javax.inject.Inject; +import java.io.File; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Properties; /** - * Execute specs using Selenium Web Driver. Uses HtmlUnitDriver for head-less execution by default. + * Execute specs using Selenium Web Driver. Uses PhantomJsDriver for head-less execution by default. */ @Mojo(name="test",defaultPhase=LifecyclePhase.TEST,requiresDependencyResolution = ResolutionScope.TEST) public class TestMojo extends AbstractJasmineMojo { + /** + * Determines the Selenium WebDriver class we'll use to execute the tests. See the Selenium documentation for more details. + * The plugin uses HtmlUnit by default. + * + *

Some valid examples:

+ *
    + *
  • org.openqa.selenium.htmlunit.HtmlUnitDriver
  • + *
  • org.openqa.selenium.phantomjs.PhantomJSDriver
  • + *
  • org.openqa.selenium.firefox.FirefoxDriver
  • + *
  • org.openqa.selenium.ie.InternetExplorerDriver
  • + *
+ *

+ * For org.openqa.selenium.phantomjs.PhantomJSDriver, see the webDriverCapabilities property. + * + * @since 1.1.0 + */ + @Parameter(defaultValue="org.openqa.selenium.phantomjs.PhantomJSDriver") + protected String webDriverClassName; + + /** + *

Web driver capabilities used to initialize a DesiredCapabilities instance when creating a web driver.

+ * + *

Capabilities value can be either a String, a List, or a Map.

+ * + *

Example:

+ *
+   * <webDriverCapabilities>
+   *   <capability>
+   *     <name>phantomjs.binary.path</name>
+   *     <value>/opt/phantomjs/bin/phantomjs</value>
+   *   </capability>
+   *   <capability>
+   *     <name>phantomjs.cli.args</name>
+   *     <list>
+   *       <value>--disk-cache=true</value>
+   *       <value>--max-disk-cache-size=256</value>
+   *     </list>
+   *   </capability>
+   *   <capability>
+   *     <name>proxy</name>
+   *     <map>
+   *       <httpProxy>myproxyserver.com:8000</httpProxy>
+   *     </map>
+   *   </capability>
+   * </webDriverCapabilities>
+   * 
+ * + * @since 1.3.1.1 + */ + @Parameter + protected List webDriverCapabilities = Collections.emptyList(); + + /** + *

Determines the browser and version profile that HtmlUnit will simulate. This setting does nothing if the plugin is configured not to use HtmlUnit. + * This maps 1-to-1 with the public static instances found in {@link com.gargoylesoftware.htmlunit.BrowserVersion}.

+ * + *

Some valid examples: CHROME, FIREFOX_17, INTERNET_EXPLORER_9, INTERNET_EXPLORER_10

+ * + * @since 1.1.0 + * @deprecated Use the webDriverCapabilities parameter instead. + */ + @Parameter(defaultValue="FIREFOX_17") + @Deprecated + protected String browserVersion; + + /** + *

Determines the format that jasmine:test will print to console.

+ *

Valid options:

+ *
    + *
  • "documentation" - (default) - print specs in a nested format
  • + *
  • "progress" - more terse, with a period for a passed specs and an 'F' for failures (e.g. '...F...')
  • + *
+ * + * @since 1.1.0 + */ + @Parameter(defaultValue="documentation") + protected String format; + + /** + *

Configure which version of PhantomJS should be used and how it should be found. The core of the + * phantomjs-maven-plugin is used to provide this + * functionality and this parameter should match the configuration of the + * phantomjs-maven-plugin install goal.

+ * + *

Default Options:

+ *
+   * <phantomjs>
+   *   <version>2.0.0</version>
+   *   <checkSystemPath>true</checkSystemPath>
+   *   <enforceVersion>true</enforceVersion>
+   *   <source>REPOSITORY</source>
+   *   <baseUrl></baseUrl>
+   *   <outputDirectory>target/phantomjs</outputDirectory>
+   * </phantomjs>
+   * 
+ * + * @since 2.0 + */ + @Parameter(property = "phantomjs", defaultValue = "${phantomJs}") + protected PhantomJsOptions phantomjs; + + /** + * The name of the generated JUnit XML report. + * + * @since 1.1.0 + */ + @Parameter(defaultValue="TEST-jasmine.xml") + protected String junitXmlReportFileName; + + /** + * Keep the server alive after the jasmine:test goal exists. + * Useful if you need to run further analysis on your tests, like collecting code coverage. + * + * @since 1.3.1.0 + */ + @Parameter(property="keepServerAlive", defaultValue="false") + protected boolean keepServerAlive; + + @Parameter( + defaultValue = "${repositorySystemSession}", + readonly = true + ) + private RepositorySystemSession repositorySystemSession; + + @Parameter( + defaultValue = "${project.remoteProjectRepositories}", + readonly = true + ) + private List remoteRepositories; + + @Component + private MavenSession mavenSession; + + private RepositorySystem repositorySystem; + private final RelativizesFilePaths relativizesFilePaths; - public TestMojo() { + @Inject + public TestMojo(RepositorySystem repositorySystem) { + this.repositorySystem = repositorySystem; this.relativizesFilePaths = new RelativizesFilePaths(); } @@ -92,14 +240,53 @@ private JasmineResult executeSpecs(URL runner) throws Exception { } private WebDriver createDriver() throws Exception { + RepositoryDetails details = new RepositoryDetails(); + details.setRemoteRepositories(remoteRepositories); + details.setRepositorySystem(repositorySystem); + details.setRepositorySystemSession(repositorySystemSession); + + configure(mavenSession.getUserProperties()); + WebDriverFactory factory = new WebDriverFactory(); factory.setWebDriverCapabilities(webDriverCapabilities); factory.setWebDriverClassName(webDriverClassName); factory.setDebug(debug); factory.setBrowserVersion(browserVersion); + factory.setPhantomJsLocatorOptions(phantomjs); + factory.setRepositoryDetails(details); + return factory.createWebDriver(); } + private void configure(Properties properties) { + + phantomjs.setVersion( + properties.getProperty("phantomjs.version", phantomjs.getVersion()) + ); + + phantomjs.setSource( + PhantomJsLocatorOptions.Source.valueOf( + properties.getProperty("phantomjs.source", phantomjs.getSource().toString()) + ) + ); + + phantomjs.setOutputDirectory( + new File(properties.getProperty("phantomjs.outputDirectory", phantomjs.getOutputDirectory().toString())) + ); + + phantomjs.setBaseUrl( + properties.getProperty("phantomjs.baseUrl", phantomjs.getBaseUrl()) + ); + + phantomjs.setCheckSystemPath(configureBoolean(properties, "phantomjs.checkSystemPath", phantomjs.isCheckSystemPath())); + + phantomjs.setEnforceVersion(configureBoolean(properties, "phantomjs.enforceVersion", phantomjs.isEnforceVersion())); + } + + private boolean configureBoolean(Properties properties, String property, boolean defaultValue) { + return Boolean.parseBoolean(properties.getProperty(property, Boolean.toString(defaultValue))); + } + private void logResults(JasmineResult result) { JasmineResultLogger resultLogger = new JasmineResultLogger(); resultLogger.setLog(this.getLog()); diff --git a/src/site/markdown/phantomjs.md.vm b/src/site/markdown/phantomjs.md.vm index 896939176..fbdaf5538 100644 --- a/src/site/markdown/phantomjs.md.vm +++ b/src/site/markdown/phantomjs.md.vm @@ -1,5 +1,11 @@ Using with PhantomJS ==================== +Prior to version `2.0`, [HtmlUnit](http://htmlunit.sourceforge.net/) was used +to execute specs by default. Starting with version `2.0`, [PhantomJS](http://phantomjs.org) is the default. The `jasmine-maven-plugin` uses the core of the [phantomjs-maven-plugin](http://klieber.github.io/phantomjs-maven-plugin) to automatically pull in PhantomJS if it is not currently installed on the system so you do not need to do anything to configure it. If you'd like to use a different version of PhantomJS than what jasmine-maven-plugin uses by default you can configure it with the [phantomjs configuration parameter](/jasmine-maven-plugin/test-mojo.html#phantomjs). + +Configuration prior to 2.0 +-------------------------- + Starting with version `1.3.1.1` it is possible to configure the jasmine-maven-plugin to use [PhantomJS](http://phantomjs.org) instead of [HtmlUnit](http://htmlunit.sourceforge.net/) to execute your specs. Here is an example configuration: @@ -57,8 +63,8 @@ The above configuration assumes that the `phantomjs` binary is on your systems ` For more information on configuration options for PhantomJSDriver see its [documentation](https://github.com/detro/ghostdriver). -Automatically installing phantomjs ----------------------------------- +Automatically installing phantomjs prior to 2.0 +----------------------------------------------- One of the downsides of using phantomjs instead of HtmlUnit is it requires native binaries be present on the system you are running your build on. The [phantomjs-maven-plugin](http://klieber.github.io/phantomjs-maven-plugin) solves that problem by automatically pulling down phantomjs when needed. Here's an example using `phantomjs-maven-plugin` with the `jasmine-maven-plugin`: diff --git a/src/test/java/com/github/searls/jasmine/mojo/TestMojoTest.java b/src/test/java/com/github/searls/jasmine/mojo/TestMojoTest.java index 91ec97bb2..521ff271b 100644 --- a/src/test/java/com/github/searls/jasmine/mojo/TestMojoTest.java +++ b/src/test/java/com/github/searls/jasmine/mojo/TestMojoTest.java @@ -1,16 +1,17 @@ package com.github.searls.jasmine.mojo; -import static org.mockito.Mockito.verify; - -import java.util.Properties; - import org.apache.maven.plugin.logging.Log; +import org.eclipse.aether.RepositorySystem; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.powermock.modules.junit4.PowerMockRunner; +import java.util.Properties; + +import static org.mockito.Mockito.verify; + @RunWith(PowerMockRunner.class) public class TestMojoTest { @@ -22,9 +23,12 @@ public class TestMojoTest { @Mock private Properties properties; + @Mock + private RepositorySystem repositorySystem; + @Before public void before() { - this.mojo = new TestMojo(); + this.mojo = new TestMojo(repositorySystem); this.mojo.setLog(log); } diff --git a/src/test/resources/examples/jasmine-webapp-custom-browser/pom.xml b/src/test/resources/examples/jasmine-webapp-custom-browser/pom.xml index f08988728..1ce62a39c 100644 --- a/src/test/resources/examples/jasmine-webapp-custom-browser/pom.xml +++ b/src/test/resources/examples/jasmine-webapp-custom-browser/pom.xml @@ -24,6 +24,7 @@ + org.openqa.selenium.htmlunit.HtmlUnitDriver INTERNET_EXPLORER_6