001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 */ 019package org.nuxeo.runtime.test.runner.web; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.util.function.UnaryOperator; 024 025import org.openqa.selenium.WebDriver; 026import org.openqa.selenium.WebDriverException; 027import org.openqa.selenium.chrome.ChromeDriver; 028import org.openqa.selenium.firefox.FirefoxDriver; 029import org.openqa.selenium.firefox.FirefoxProfile; 030import org.openqa.selenium.htmlunit.HtmlUnitDriver; 031import org.openqa.selenium.ie.InternetExplorerDriver; 032import org.openqa.selenium.remote.DesiredCapabilities; 033 034import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController; 035import com.gargoylesoftware.htmlunit.Page; 036import com.gargoylesoftware.htmlunit.WebClient; 037import com.gargoylesoftware.htmlunit.WebResponse; 038import com.gargoylesoftware.htmlunit.attachment.AttachmentHandler; 039 040/** 041 * @author <a href="mailto:[email protected]">Bogdan Stefanescu</a> 042 */ 043public enum BrowserFamily { 044 045 FIREFOX, IE, CHROME, HTML_UNIT, HTML_UNIT_JS; 046 047 public DriverFactory getDriverFactory() { 048 switch (this) { 049 case FIREFOX: 050 return new FirefoxDriverFactory(); 051 case IE: 052 return new IEDriverFactory(); 053 case CHROME: 054 return new ChromeDriverFactory(); 055 case HTML_UNIT: 056 return new HtmlUnitDriverFactory(); 057 case HTML_UNIT_JS: 058 default: 059 return new HtmlUnitJsDriverFactory(); 060 } 061 } 062 063 class FirefoxDriverFactory implements DriverFactory { 064 @Override 065 public WebDriver createDriver() { 066 FirefoxProfile profile = new FirefoxProfile(); 067 String dir = "target/downloads"; 068 profile.setPreference("browser.download.defaultFolder", dir); 069 profile.setPreference("browser.download.downloadDir", dir); 070 profile.setPreference("browser.download.lastDir", dir); 071 profile.setPreference("browser.download.dir", dir); 072 profile.setPreference("browser.download.useDownloadDir", "true"); 073 profile.setPreference("browser.helperApps.neverAsk.saveToDisk", "text/json"); 074 profile.setPreference("browser.download.folderList", 2); 075 profile.setPreference("browser.download manager.useWindow", "false"); 076 DesiredCapabilities dc = DesiredCapabilities.firefox(); 077 dc.setCapability(FirefoxDriver.PROFILE, profile); 078 return new FirefoxDriver(dc); 079 } 080 081 @Override 082 public void disposeDriver(WebDriver driver) { 083 } 084 085 @Override 086 public BrowserFamily getBrowserFamily() { 087 return BrowserFamily.this; 088 } 089 090 } 091 092 class ChromeDriverFactory implements DriverFactory { 093 @Override 094 public WebDriver createDriver() { 095 ChromeDriver ff = new ChromeDriver(); 096 // ff.manage().setSpeed(Speed.FAST); 097 return ff; 098 } 099 100 @Override 101 public void disposeDriver(WebDriver driver) { 102 } 103 104 @Override 105 public BrowserFamily getBrowserFamily() { 106 return BrowserFamily.this; 107 } 108 109 } 110 111 class IEDriverFactory implements DriverFactory { 112 @Override 113 public WebDriver createDriver() { 114 InternetExplorerDriver driver = new InternetExplorerDriver(); 115 // driver.manage().setSpeed(Speed.FAST); 116 return driver; 117 } 118 119 @Override 120 public void disposeDriver(WebDriver driver) { 121 } 122 123 @Override 124 public BrowserFamily getBrowserFamily() { 125 return BrowserFamily.this; 126 } 127 128 } 129 130 class HtmlUnitDriverFactory implements DriverFactory { 131 132 Attachment attachment; 133 134 final AttachmentHandler attachmentHandler = new AttachmentHandler() { 135 136 @Override 137 public void handleAttachment(Page page) { 138 attachment = new Attachment() { 139 @Override 140 public String getFilename() { 141 String filename = getSuggestedFilename(); 142 if (filename != null) { 143 return filename; 144 } 145 String path = page.getUrl().getPath(); 146 return path.substring(path.lastIndexOf('/') + 1); 147 } 148 149 @Override 150 public InputStream getContent() throws IOException { 151 return page.getWebResponse().getContentAsStream(); 152 } 153 154 public String getSuggestedFilename() { 155 final WebResponse response = page.getWebResponse(); 156 final String disp = response.getResponseHeaderValue("Content-Disposition"); 157 int start = disp.indexOf("filename="); 158 if (start == -1) { 159 return null; 160 } 161 start += "filename=".length(); 162 int end = disp.indexOf(';', start); 163 if (end == -1) { 164 end = disp.length(); 165 } 166 if (disp.charAt(start) == '"' && disp.charAt(end - 1) == '"') { 167 start++; 168 end--; 169 } 170 return disp.substring(start, end); 171 } 172 }; 173 } 174 }; 175 176 UnaryOperator<WebClient> customizer() { 177 return client -> { 178 client.setAttachmentHandler(attachmentHandler); 179 return client; 180 }; 181 } 182 183 boolean jsEnabled() { 184 return false; 185 } 186 187 class CustomizableHtmlUnitDriver extends HtmlUnitDriver implements TakesAttachment { 188 189 @Override 190 public WebClient getWebClient() { 191 return super.getWebClient(); 192 } 193 194 protected CustomizableHtmlUnitDriver() { 195 super(jsEnabled()); 196 } 197 198 @Override 199 protected WebClient modifyWebClient(WebClient client) { 200 return customizer().apply(client); 201 } 202 203 @Override 204 public Attachment getAttachment() throws WebDriverException { 205 return attachment; 206 } 207 208 } 209 210 @Override 211 public WebDriver createDriver() { 212 return new CustomizableHtmlUnitDriver(); 213 } 214 215 @Override 216 public void disposeDriver(WebDriver driver) { 217 } 218 219 @Override 220 public BrowserFamily getBrowserFamily() { 221 return BrowserFamily.this; 222 } 223 224 @Override 225 public void waitForAjax(WebDriver driver) { 226 return; 227 } 228 229 } 230 231 class HtmlUnitJsDriverFactory extends HtmlUnitDriverFactory { 232 @Override 233 boolean jsEnabled() { 234 return true; 235 } 236 237 @Override 238 UnaryOperator<WebClient> customizer() { 239 UnaryOperator<WebClient> setJavascript = client -> { 240 client.getOptions().setThrowExceptionOnScriptError(false); 241 client.setAjaxController(new NicelyResynchronizingAjaxController()); 242 return client; 243 }; 244 return client -> setJavascript.apply(super.customizer().apply(client)); 245 } 246 247 @Override 248 public void waitForAjax(WebDriver driver) { 249 ((CustomizableHtmlUnitDriver) driver).getWebClient().waitForBackgroundJavaScript(30000); 250 } 251 252 } 253 254}