View Javadoc
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   * Creates a WebDriver for TestMojo using configured properties.
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 }