1 package com.github.searls.jasmine.driver;
2
3 import com.github.klieber.phantomjs.locate.PhantomJsLocator;
4 import com.github.klieber.phantomjs.locate.PhantomJsLocatorOptions;
5 import com.github.klieber.phantomjs.locate.RepositoryDetails;
6 import com.github.searls.jasmine.mojo.Capability;
7 import com.google.common.base.MoreObjects;
8 import org.codehaus.plexus.util.StringUtils;
9 import org.openqa.selenium.Capabilities;
10 import org.openqa.selenium.WebDriver;
11 import org.openqa.selenium.htmlunit.HtmlUnitDriver;
12 import org.openqa.selenium.phantomjs.PhantomJSDriver;
13 import org.openqa.selenium.remote.DesiredCapabilities;
14
15 import java.lang.reflect.Constructor;
16 import java.util.Collections;
17 import java.util.List;
18
19
20
21
22 public class WebDriverFactory {
23 private boolean debug;
24 private String browserVersion;
25 private String webDriverClassName;
26 private List<Capability> webDriverCapabilities;
27 private PhantomJsLocatorOptions phantomJsLocatorOptions;
28 private RepositoryDetails repositoryDetails;
29
30 public WebDriverFactory() {
31 setWebDriverCapabilities(null);
32 }
33
34 public void setDebug(boolean debug) {
35 this.debug = debug;
36 }
37
38 public void setBrowserVersion(String browserVersion) {
39 this.browserVersion = browserVersion;
40 }
41
42 public void setWebDriverClassName(String webDriverClassName) {
43 this.webDriverClassName = webDriverClassName;
44 }
45
46 public void setWebDriverCapabilities(List<Capability> webDriverCapabilities) {
47 this.webDriverCapabilities = MoreObjects.firstNonNull(webDriverCapabilities, Collections.<Capability>emptyList());
48 }
49
50 public PhantomJsLocatorOptions getPhantomJsLocatorOptions() {
51 return phantomJsLocatorOptions;
52 }
53
54 public void setPhantomJsLocatorOptions(PhantomJsLocatorOptions phantomJsLocatorOptions) {
55 this.phantomJsLocatorOptions = phantomJsLocatorOptions;
56 }
57
58 public RepositoryDetails getRepositoryDetails() {
59 return repositoryDetails;
60 }
61
62 public void setRepositoryDetails(RepositoryDetails repositoryDetails) {
63 this.repositoryDetails = repositoryDetails;
64 }
65
66 public WebDriver createWebDriver() throws Exception {
67 if (PhantomJSDriver.class.getName().equals(webDriverClassName)) {
68 return createPhantomJsWebDriver();
69 } else if (HtmlUnitDriver.class.getName().equals(webDriverClassName)) {
70 return createHtmlUnitWebDriver();
71 } else {
72 return createCustomWebDriver();
73 }
74 }
75
76 @SuppressWarnings("unchecked")
77 private Class<? extends WebDriver> getWebDriverClass() throws Exception {
78 return (Class<WebDriver>) Class.forName(webDriverClassName);
79 }
80
81 private Constructor<? extends WebDriver> getWebDriverConstructor() throws Exception {
82 Class<? extends WebDriver> webDriverClass = getWebDriverClass();
83 boolean hasCapabilities = !webDriverCapabilities.isEmpty();
84 try {
85 if (hasCapabilities) {
86 return webDriverClass.getConstructor(Capabilities.class);
87 }
88 return webDriverClass.getConstructor();
89 } catch (Exception exception) {
90 if (hasCapabilities) {
91 return webDriverClass.getConstructor();
92 }
93 return webDriverClass.getConstructor(Capabilities.class);
94 }
95 }
96
97 private WebDriver createCustomWebDriver() throws Exception {
98 Constructor<? extends WebDriver> constructor = getWebDriverConstructor();
99 return constructor.newInstance(getWebDriverConstructorArguments(constructor));
100 }
101
102 private Object[] getWebDriverConstructorArguments(Constructor<? extends WebDriver> constructor) {
103 if (constructor.getParameterTypes().length == 0) {
104 return new Object[0];
105 }
106 return new Object[]{getCapabilities()};
107 }
108
109 private DesiredCapabilities getCapabilities() {
110 DesiredCapabilities capabilities = new DesiredCapabilities();
111 customizeCapabilities(capabilities);
112 return capabilities;
113 }
114
115 private void customizeCapabilities(DesiredCapabilities capabilities) {
116 capabilities.setJavascriptEnabled(true);
117
118 for (Capability capability : webDriverCapabilities) {
119 Object value = capability.getValue();
120 if (value != null && (!String.class.isInstance(value) || StringUtils.isNotBlank((String) value))) {
121 capabilities.setCapability(capability.getName(), capability.getValue());
122 } else if (capability.getList() != null && !capability.getList().isEmpty()) {
123 capabilities.setCapability(capability.getName(), capability.getList());
124 } else if (capability.getMap() != null && !capability.getMap().isEmpty()) {
125 capabilities.setCapability(capability.getName(), capability.getMap());
126 }
127 }
128 }
129
130 private WebDriver createHtmlUnitWebDriver() throws Exception {
131 DesiredCapabilities capabilities = DesiredCapabilities.htmlUnitWithJs();
132 if (StringUtils.isNotBlank(capabilities.getVersion())) {
133 capabilities.setVersion(browserVersion.replaceAll("(\\D+)_(\\d.*)?", "$1-$2").replaceAll("_", " ").toLowerCase());
134 }
135 customizeCapabilities(capabilities);
136 return new QuietHtmlUnitDriver(capabilities, debug);
137 }
138
139 private WebDriver createPhantomJsWebDriver() throws Exception {
140 DesiredCapabilities capabilities = DesiredCapabilities.phantomjs();
141 customizeCapabilities(capabilities);
142
143 if (capabilities.getCapability("phantomjs.binary.path") == null) {
144 PhantomJsLocator locator = new PhantomJsLocator(this.phantomJsLocatorOptions, this.repositoryDetails);
145 String phantomJsPath = locator.locate();
146 capabilities.setCapability("phantomjs.binary.path", phantomJsPath);
147 }
148
149 return new PhantomJSDriver(capabilities);
150 }
151 }