package com.googlecode.jmeter.plugins.webdriver.config;
import com.googlecode.jmeter.plugins.webdriver.proxy.ProxyFactory;
import com.googlecode.jmeter.plugins.webdriver.proxy.ProxyHostPort;
import com.googlecode.jmeter.plugins.webdriver.proxy.ProxyType;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.jmeter.engine.event.LoopIterationListener;
import org.apache.jmeter.testelement.ThreadListener;
import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jmeter.threads.JMeterVariables;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.SessionNotFoundException;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.Is.is;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class WebDriverConfigTest {
private ProxyFactory proxyFactory;
private WebDriver browser;
private WebDriverConfig config;
private JMeterVariables variables;
@Before
public void createConfig() {
proxyFactory = mock(ProxyFactory.class);
browser = getBrowserMock();
config = new WebDriverConfigImpl(proxyFactory, browser);
variables = new JMeterVariables();
JMeterContextService.getContext().setVariables(variables);
}
@After
public void resetConfig() {
config.clearThreadBrowsers();
JMeterContextService.getContext().setVariables(null);
}
@Test
public void shouldAssignProxyPacUrl() {
String pacUrl = "http://proxy/pac.url";
config.setProxyPacUrl(pacUrl);
assertThat(config.getProxyPacUrl(), is(pacUrl));
}
@Test
public void shouldAssignHttpHost() {
String host = "host";
config.setHttpHost(host);
assertThat(config.getHttpHost(), is(host));
}
@Test
public void shouldAssignHttpPort() {
int port = 1;
config.setHttpPort(port);
assertThat(config.getHttpPort(), is(port));
}
@Test
public void byDefaultShouldReturnTrueForUseHttpSettingsForAllProtocols() {
assertThat(config.isUseHttpSettingsForAllProtocols(), is(true));
}
@Test
public void shouldBeAbleToDisableUseHttpSettingsForAllProtocols() {
config.setUseHttpSettingsForAllProtocols(false);
assertThat(config.isUseHttpSettingsForAllProtocols(), is(false));
}
@Test
public void shouldBeAbleToEnableUseHttpSettingsForAllProtocols() {
config.setUseHttpSettingsForAllProtocols(true);
assertThat(config.isUseHttpSettingsForAllProtocols(), is(true));
}
@Test
public void shouldAssignHttpsHost() {
String host = "host";
config.setHttpsHost(host);
assertThat(config.getHttpsHost(), is(host));
}
@Test
public void shouldAssignHttpsPort() {
int port = 1;
config.setHttpsPort(port);
assertThat(config.getHttpsPort(), is(port));
}
@Test
public void shouldAssignFtpHost() {
String host = "host";
config.setFtpHost(host);
assertThat(config.getFtpHost(), is(host));
}
@Test
public void shouldAssignFtpPort() {
int port = 1;
config.setFtpPort(port);
assertThat(config.getFtpPort(), is(port));
}
@Test
public void shouldAssignSocksHost() {
String host = "host";
config.setSocksHost(host);
assertThat(config.getSocksHost(), is(host));
}
@Test
public void shouldAssignSocksPort() {
int port = 1;
config.setSocksPort(port);
assertThat(config.getSocksPort(), is(port));
}
@Test
public void shouldAssignNoProxyHost() {
String list = "host1, host2";
config.setNoProxyHost(list);
assertThat(config.getNoProxyHost(), is(list));
}
@Test
public void byDefaultShouldReturnSystemProxyType() {
assertThat(config.getProxyType(), is(ProxyType.SYSTEM));
}
@Test
public void shouldAssignProxyType() {
ProxyType type = ProxyType.MANUAL;
config.setProxyType(type);
assertThat(config.getProxyType(), is(type));
}
@Test
public void shouldDelegateToProxyFactoryWhenCreatingSystemProxy() {
when(proxyFactory.getSystemProxy()).thenReturn(new Proxy());
config.setProxyType(ProxyType.SYSTEM);
Proxy proxy = config.createProxy();
assertThat(proxy, is(notNullValue()));
verify(proxyFactory, times(1)).getSystemProxy();
}
@Test
public void shouldDelegateToProxyFactoryWhenCreatingDirectProxy() {
when(proxyFactory.getDirectProxy()).thenReturn(new Proxy());
config.setProxyType(ProxyType.DIRECT);
Proxy proxy = config.createProxy();
assertThat(proxy, is(notNullValue()));
verify(proxyFactory, times(1)).getDirectProxy();
}
@Test
public void shouldDelegateToProxyFactoryWhenCreatingAutoDetectProxy() {
when(proxyFactory.getAutodetectProxy()).thenReturn(new Proxy());
config.setProxyType(ProxyType.AUTO_DETECT);
Proxy proxy = config.createProxy();
assertThat(proxy, is(notNullValue()));
verify(proxyFactory, times(1)).getAutodetectProxy();
}
@Test
public void shouldDelegateToProxyFactoryWhenCreatingManualProxyWithAllValuesSpecified() {
final ProxyHostPort http = new ProxyHostPort("http", 1);
final ProxyHostPort https = new ProxyHostPort("https", 2);
final ProxyHostPort ftp = new ProxyHostPort("ftp", 3);
final ProxyHostPort socks = new ProxyHostPort("socks", 4);
final String noProxy = "host1, host2";
config.setHttpHost(http.getHost());
config.setHttpPort(http.getPort());
config.setUseHttpSettingsForAllProtocols(false);
config.setHttpsHost(https.getHost());
config.setHttpsPort(https.getPort());
config.setFtpHost(ftp.getHost());
config.setFtpPort(ftp.getPort());
config.setSocksHost(socks.getHost());
config.setSocksPort(socks.getPort());
config.setNoProxyHost(noProxy);
when(proxyFactory.getManualProxy(http, https, ftp, socks, noProxy)).thenReturn(new Proxy());
config.setProxyType(ProxyType.MANUAL);
Proxy proxy = config.createProxy();
assertThat(proxy, is(notNullValue()));
verify(proxyFactory, times(1)).getManualProxy(http, https, ftp, socks, noProxy);
}
@Test
public void shouldDelegateToProxyFactoryWhenCreatingManualProxyWithHttpAsDefault() {
final ProxyHostPort http = new ProxyHostPort("http", 1);
final String noProxy = "host1, host2";
config.setHttpHost(http.getHost());
config.setHttpPort(http.getPort());
config.setUseHttpSettingsForAllProtocols(true);
config.setNoProxyHost(noProxy);
when(proxyFactory.getManualProxy(http, http, http, http, noProxy)).thenReturn(new Proxy());
config.setProxyType(ProxyType.MANUAL);
Proxy proxy = config.createProxy();
assertThat(proxy, is(notNullValue()));
verify(proxyFactory, times(1)).getManualProxy(http, http, http, http, noProxy);
}
@Test
public void shouldDelegateToProxyFactoryWhenCreatingProxyPacProxy() throws MalformedURLException {
String url = "http://proxy/pac.url";
when(proxyFactory.getConfigUrlProxy(url)).thenReturn(new Proxy());
config.setProxyPacUrl(url);
config.setProxyType(ProxyType.PROXY_PAC);
Proxy proxy = config.createProxy();
assertThat(proxy, is(notNullValue()));
verify(proxyFactory, times(1)).getConfigUrlProxy(Mockito.isA(String.class));
}
@Test
public void shouldSetBrowserForCurrentThread() {
WebDriver browser = getBrowserMock();
config.setThreadBrowser(browser);
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasSize(1));
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasItem(browser));
}
@Test
public void shouldNotSetNullBrowserForCurrentThread() {
WebDriver browser = getBrowserMock();
config.setThreadBrowser(browser);
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasSize(1));
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasItem(browser));
config.setThreadBrowser(null);
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasSize(1));
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasItem(browser));
}
@Test
public void shouldOnlyHaveOneBrowserForCurrentThread() {
WebDriver firstBrowser = getBrowserMock();
WebDriver secondBrowser = getBrowserMock();
config.setThreadBrowser(firstBrowser);
config.setThreadBrowser(secondBrowser);
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasSize(1));
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasItem(secondBrowser));
}
@Test
public void shouldBeAbleToAddMultipleBrowsersForEachThread() throws InterruptedException {
// mock the browsers that will be created per thread
final WebDriver firstBrowser = getBrowserMock();
final WebDriver secondBrowser = getBrowserMock();
Thread firstThread = new Thread() {
public void run() {
config.setThreadBrowser(firstBrowser);
}
};
Thread secondThread = new Thread() {
public void run() {
config.setThreadBrowser(secondBrowser);
}
};
// start and wait for threads to finish
firstThread.start();
secondThread.start();
firstThread.join();
secondThread.join();
// assertions
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasSize(2));
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasItem(firstBrowser));
assertThat((Collection<WebDriver>) config.getThreadBrowsers().values(), hasItem(secondBrowser));
}
@Test
public void shouldHaveBrowserForCurrentThread() {
WebDriver browser = getBrowserMock();
config.setThreadBrowser(browser);
assertThat(config.hasThreadBrowser(), is(true));
}
@Test
public void shouldNotHaveBrowserForCurrentThread() {
assertThat(config.hasThreadBrowser(), is(false));
}
@Test
public void shouldRemoveBrowserFromCurrentThread() {
WebDriver browser = getBrowserMock();
config.setThreadBrowser(browser);
final WebDriver removed = config.removeThreadBrowser();
assertThat((Map<String, WebDriver>) config.getThreadBrowsers(), is(Collections.<String, WebDriver>emptyMap()));
assertThat(browser, is(removed));
}
@Test
public void shouldRemoveBrowserFromCurrentThreadEvenIfNoBrowserPresent() {
final WebDriver removed = config.removeThreadBrowser();
assertThat((Map<String, WebDriver>) config.getThreadBrowsers(), is(Collections.<String, WebDriver>emptyMap()));
assertThat(removed, is(nullValue()));
}
@Test
public void shouldImplementThreadListener() {
assertThat(config, is(instanceOf(ThreadListener.class)));
}
@Test
public void shouldCreateWebDriverWhenThreadStartedIsInvoked() throws Exception {
config.threadStarted();
assertThat(config.getThreadBrowser(), is(browser));
}
@Test
public void shouldOnlyCreateSingleWebDriverEvenWhenThreadStartedIsCalledMultipleTimes() throws Exception {
config.threadStarted();
config.threadStarted();
assertThat(config.getThreadBrowser(), is(browser));
}
@Test
public void shouldQuitWebDriverWhenThreadFinishedIsInvoked() throws Exception {
config.setThreadBrowser(browser);
config.threadFinished();
assertThat(config.getThreadBrowser(), is(nullValue()));
verify(browser, times(1)).quit();
}
@Test
public void shouldBeAbleToCallThreadFinishedMultipleTimes() throws Exception {
config.setThreadBrowser(browser);
config.threadFinished();
config.threadFinished();
assertThat(config.getThreadBrowser(), is(nullValue()));
verify(browser, times(1)).quit();
}
@Test
public void shouldNotClearNorQuitBrowserWhenDevModeIsEnabled() {
config.setThreadBrowser(browser);
config.setDevMode(true);
config.threadFinished();
assertThat(config.getThreadBrowser(), is(browser));
verify(browser, times(0)).quit();
}
@Test
public void shouldQuitBrowser() {
config.quitBrowser(browser);
verify(browser, times(1)).quit();
}
@Test
public void shouldNotQuitBrowserWhenArgumentIsNull() {
config.quitBrowser(null);
verify(browser, times(0)).quit();
}
@Test
public void shouldHandleScenarioWhenBrowserHasAlreadyQuit() {
doThrow(new SessionNotFoundException()).when(browser).quit();
config.quitBrowser(browser);
verify(browser, times(1)).quit();
}
@Test
public void shouldImplementLoopIterationListener() {
assertThat(config, is(instanceOf(LoopIterationListener.class)));
}
@Test
public void shouldAddBrowserToJMeterVariablesWhenIterationStarts() throws Exception {
config.setThreadBrowser(browser);
config.iterationStart(null);
assertThat(variables.getObject(WebDriverConfig.BROWSER), is(notNullValue()));
assertThat((WebDriver) variables.getObject(WebDriverConfig.BROWSER), is(browser));
}
@Test
public void shouldAssignRecreateBrowserOnIterationStart() {
config.setRecreateBrowserOnIterationStart(true);
assertThat(config.isRecreateBrowserOnIterationStart(), is(true));
}
@Test
public void byDefaultShouldNotRecreateBrowserOnIterationStart() {
assertThat(config.isRecreateBrowserOnIterationStart(), is(false));
}
@Test
public void shouldRecreateBrowserOnEachIterationStart() {
final WebDriver firstBrowser = getBrowserMock();
final WebDriver secondBrowser = getBrowserMock();
this.config = new WebDriverConfigImpl(proxyFactory, firstBrowser, secondBrowser);
this.config.setRecreateBrowserOnIterationStart(true);
config.iterationStart(null);
assertThat((WebDriver) variables.getObject(WebDriverConfig.BROWSER), is(firstBrowser));
config.iterationStart(null);
assertThat((WebDriver) variables.getObject(WebDriverConfig.BROWSER), is(secondBrowser));
verify(firstBrowser, times(1)).quit();
}
private WebDriver getBrowserMock() {
WebDriver.Options manage = mock(WebDriver.Options.class);
when(manage.window()).thenReturn(mock(WebDriver.Window.class));
WebDriver browser = mock(WebDriver.class);
when(browser.manage()).thenReturn(manage);
return browser;
}
@Test
public void shouldNotRecreateBrowserOnEachIterationStartWhenDevModeIsEnabled() {
final WebDriver browser = getBrowserMock();
this.config = new WebDriverConfigImpl(proxyFactory, browser);
this.config.setRecreateBrowserOnIterationStart(true);
this.config.setDevMode(true);
config.threadStarted();
config.iterationStart(null);
assertThat((WebDriver) variables.getObject(WebDriverConfig.BROWSER), is(browser));
verify(browser, times(0)).quit();
}
@Test
public void shouldAssignDevMode() {
config.setDevMode(true);
assertThat(config.isDevMode(), is(true));
}
@Test
public void byDefaultDevModeShouldNotBeSet() {
assertThat(config.isDevMode(), is(false));
}
private static class WebDriverConfigImpl extends WebDriverConfig {
final List<WebDriver> browsers = new CopyOnWriteArrayList<WebDriver>();
/**
* @param proxyFactory mock ProxyFactory to use
* @param browsers the list of browsers (in order) to return when createBrowser() method is invoked.
*/
public WebDriverConfigImpl(ProxyFactory proxyFactory, WebDriver... browsers) {
super(proxyFactory);
this.browsers.addAll(Arrays.asList(browsers));
}
@Override
protected WebDriver createBrowser() {
if (browsers.isEmpty()) {
throw new IllegalStateException("Unexpected call to createBrowser(). No more instances to return");
}
return browsers.remove(0);
}
}
}