Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/org/labkey/test/ExtraSiteWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ public WebDriver getWrappedDriver()
return extraDriver.getLeft();
}

@Override
protected boolean allowTimeZoneShifting()
{
return false;
}

@Override
public void pauseJsErrorChecker(){}
@Override
Expand Down
12 changes: 6 additions & 6 deletions src/org/labkey/test/TestProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public abstract class TestProperties
}
}

private static ZoneId browserTimeZone = null;
private static ZoneId browserZoneId = null;

public static void load()
{
Expand Down Expand Up @@ -166,24 +166,24 @@ public static boolean isDumpBrowserConsole()
return getBooleanProperty("webtest.dump.browser.console", false);
}

public static ZoneId getBrowserTimeZone()
public static ZoneId getBrowserZoneId()
{
if (browserTimeZone == null)
if (browserZoneId == null)
{
String tz = StringUtils.trimToNull(System.getProperty("webtest.browser.tz"));
if (tz != null)
{
String[] split = tz.split("[,\\s]+");
tz = split[LocalDateTime.now().getDayOfMonth() % split.length];
// Verify that time zone is valid
browserTimeZone = ZoneId.of(tz);
browserZoneId = ZoneId.of(tz);
}
else
{
browserTimeZone = ZoneId.systemDefault();
browserZoneId = ZoneId.systemDefault();
}
}
return browserTimeZone;
return browserZoneId;
}

public static double getTimeoutMultiplier()
Expand Down
191 changes: 110 additions & 81 deletions src/org/labkey/test/WebDriverWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxBinary;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxDriverLogLevel;
import org.openqa.selenium.firefox.FirefoxDriverService;
Expand Down Expand Up @@ -120,6 +119,7 @@
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -206,64 +206,93 @@ protected Pair<WebDriver, DriverService> createNewWebDriver(BrowserType browserT
return createNewWebDriver(new ImmutablePair<>(null, null), browserType, downloadDir);
}

/**
* Number of minutes to add to convert browser Date to UTC.<br>
* <em> Note: The sign of this is the opposite of Java's concept of time zone offset </em>
* @return Actual browser time zone offset in minutes
*/
public int getWebDriverTimeZoneOffset()
{
return Math.toIntExact(executeScript("return new Date().getTimezoneOffset();", Long.class));
}

/**
* Test process might be running in a different time zone from the browser. This allows shifting test date to
* browser dates.
* <pre>{@code
* TestDateUtils.diffFromTodaysDate(Calendar.MINUTE, getRelativeTimeZoneOffset())
* }</pre>
* @return The number of minutes to add to a system date to convert to the equivalent browser date
*/
public int getRelativeTimeZoneOffset()
{
return ZoneId.systemDefault().getRules().getOffset(Instant.now()).getTotalSeconds() / 60 - getWebDriverTimeZoneOffset();
}

/**
* Allow tests to disable time zone shifting. Warning: {@link TestProperties#getBrowserZoneId()} might not match actual
* browser time zone if this is false.
*/
protected boolean allowTimeZoneShifting()
{
return true;
}

protected Pair<WebDriver, DriverService> createNewWebDriver(@NotNull Pair<WebDriver, DriverService> oldDriverAndService, BrowserType browserType, File downloadDir)
{
WebDriver oldWebDriver = oldDriverAndService.getLeft();
WebDriver newWebDriver = null;
WebDriver newWebDriver;
DriverService oldDriverService = oldDriverAndService.getRight();
DriverService newDriverService = null;
DriverService newDriverService;

Map<String, String> browserEnv = new HashMap<>();
ZoneId browserTimeZone = TestProperties.getBrowserTimeZone();
if (browserTimeZone != ZoneId.systemDefault())
ZoneId targetBrowserTimeZone = allowTimeZoneShifting() ? TestProperties.getBrowserZoneId() : ZoneId.systemDefault();
int targetOffsetInSeconds = targetBrowserTimeZone.getRules().getOffset(Instant.now()).getTotalSeconds();

if (targetBrowserTimeZone != ZoneId.systemDefault())
{
TestLogger.info("Starting browser with TZ = " + browserTimeZone);
browserEnv.put("TZ", browserTimeZone.toString());
browserEnv.put("TZ", targetBrowserTimeZone.toString());
}
else

if (oldWebDriver != null &&
(!browserType.matchesDriver(oldWebDriver) ||
new WebDriverWrapperImpl(oldWebDriver).getWebDriverTimeZoneOffset() * -60 != targetOffsetInSeconds))
{
TestLogger.info("Starting browser with TZ = " + browserTimeZone + " (system default)");
TestLogger.info("Quitting existing driver and service");
oldWebDriver.quit();
oldWebDriver = null;
if (oldDriverService != null && oldDriverService.isRunning())
oldDriverService.stop();
}

switch (browserType)
final Pair<WebDriver, DriverService> result;

if (oldWebDriver == null)
{
case REMOTE: //experimental
{
try
{
newWebDriver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), new ChromeOptions());
}
catch (MalformedURLException e)
{
throw new RuntimeException(e);
}
break;
}
case IE: //experimental
log("Starting new browser: " + browserType);

switch (browserType)
{
if (oldWebDriver != null && !(oldWebDriver instanceof InternetExplorerDriver))
case REMOTE: //experimental
{
oldWebDriver.quit();
oldWebDriver = null;
if (oldDriverService != null && oldDriverService.isRunning())
oldDriverService.stop();
try
{
newDriverService = null; // Remote service runs independently of tests
newWebDriver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), new ChromeOptions());
}
catch (MalformedURLException e)
{
throw new RuntimeException(e);
}
break;
}
if (oldWebDriver == null)
case IE: //experimental
{
newDriverService = new InternetExplorerDriverService.Builder().withEnvironment(browserEnv).build();
newWebDriver = new InternetExplorerDriver((InternetExplorerDriverService) newDriverService);
break;
}
break;
}
case CHROME:
{
if (oldWebDriver != null && !(oldWebDriver instanceof ChromeDriver))
{
oldWebDriver.quit();
oldWebDriver = null;
if (oldDriverService != null && oldDriverService.isRunning())
oldDriverService.stop();
}
if (oldWebDriver == null)
case CHROME:
{
configureChromeDriverLogging(downloadDir);
ChromeOptions options = new ChromeOptions();
Expand Down Expand Up @@ -292,19 +321,9 @@ protected Pair<WebDriver, DriverService> createNewWebDriver(@NotNull Pair<WebDri

newDriverService = new ChromeDriverService.Builder().withEnvironment(browserEnv).build();
newWebDriver = new ChromeDriver((ChromeDriverService) newDriverService, options);
break;
}
break;
}
case FIREFOX:
{
if (oldWebDriver != null && !(oldWebDriver instanceof FirefoxDriver))
{
oldWebDriver.quit();
oldWebDriver = null;
if (oldDriverService != null && oldDriverService.isRunning())
oldDriverService.stop();
}
if (oldWebDriver == null)
case FIREFOX:
{
configureGeckoDriverLogging(downloadDir);
final FirefoxProfile profile = new FirefoxProfile();
Expand Down Expand Up @@ -367,22 +386,17 @@ protected Pair<WebDriver, DriverService> createNewWebDriver(@NotNull Pair<WebDri
capabilities.addPreference("--log", "WARN");

String browserPath = System.getProperty("selenium.firefox.binary", "");
FirefoxBinary binary;
if (browserPath.length() > 0)
if (!browserPath.isEmpty())
{
binary = new FirefoxBinary(new File(browserPath));
}
else
{
binary = new FirefoxBinary();
capabilities.setBinary(browserPath);
}

if (TestProperties.isRunWebDriverHeadless())
{
TestLogger.warn("Launching Firefox in headless mode. This is still experimental");
binary.addCommandLineOptions("--headless");
capabilities.addArguments("--headless");
}
capabilities.setBinary(binary);

// Firefox 128: UnhandledAlertException doesn't include alert text. Need to leave alerts to get text manually.
capabilities.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE);
FirefoxOptions firefoxOptions = new FirefoxOptions(capabilities);
Expand Down Expand Up @@ -413,15 +427,13 @@ protected Pair<WebDriver, DriverService> createNewWebDriver(@NotNull Pair<WebDri
"https://firefox-source-docs.mozilla.org/testing/geckodriver/Support.html", rethrow);
}
}
break;
}
default:
{
throw new IllegalArgumentException("Browser not yet implemented: " + browserType);
}
break;
}
default:
throw new IllegalArgumentException("Browser not yet implemented: " + browserType);
}

if (newWebDriver != null)
{

Optional<Dimension> windowSize = TestProperties.getWindowSize();
if (windowSize.isPresent())
Expand All @@ -430,16 +442,21 @@ protected Pair<WebDriver, DriverService> createNewWebDriver(@NotNull Pair<WebDri
newWebDriver.manage().window().setSize(windowSize.get());
}

Capabilities caps = ((HasCapabilities) newWebDriver).getCapabilities();
String browserName = caps.getBrowserName();
String browserVersion = caps.getBrowserVersion();
log("Browser: " + browserName + " " + browserVersion);
return new ImmutablePair<>(newWebDriver, newDriverService);
result = Pair.of(newWebDriver, newDriverService);
}
else
{
return oldDriverAndService;
log("Reusing existing browser");
result = oldDriverAndService;
}

Capabilities caps = ((HasCapabilities) result.getLeft()).getCapabilities();
String browserName = caps.getBrowserName();
String browserVersion = caps.getBrowserVersion();
log("Browser: " + browserName + " " + browserVersion);
log("Started browser with TZ = " + targetBrowserTimeZone + (targetBrowserTimeZone != ZoneId.systemDefault() ? "" : " (system default)"));

return result;
}

private void configureChromeDriverLogging(File downloadDir)
Expand Down Expand Up @@ -483,7 +500,7 @@ private void configureGeckoDriverLogging(File downloadDir)

public boolean isFirefox()
{
return getDriver().getClass().isAssignableFrom(FirefoxDriver.class);
return BrowserType.FIREFOX.matchesDriver(getDriver());
}

public Object executeScript(@Language("JavaScript") String script, Object... arguments)
Expand Down Expand Up @@ -553,11 +570,23 @@ private void setJsErrorLogging(boolean b)

public enum BrowserType
{
REMOTE,
FIREFOX,
IE,
CHROME,
HTML
REMOTE(null),
FIREFOX(FirefoxDriver.class),
IE(InternetExplorerDriver.class),
CHROME(ChromeDriver.class),
;

private final Class<?> _driverClass;

BrowserType(Class<?> driverClass)
{
_driverClass = driverClass;
}

boolean matchesDriver(@NotNull WebDriver oldDriver)
{
return _driverClass != null && oldDriver.getClass().isAssignableFrom(_driverClass);
}
}

public static void sleep(long ms)
Expand Down
9 changes: 9 additions & 0 deletions src/org/labkey/test/tests/DataViewsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ public class DataViewsTest extends ParticipantListTest

private final PortalHelper _portalHelper = new PortalHelper(this);

/**
* 52268: Data Views Webpart behaves badly when the server is in a different time zone
*/
@Override
protected boolean allowTimeZoneShifting()
{
return false;
}

@Override @LogMethod
protected void doCreateSteps()
{
Expand Down