Skip to content

Instantly share code, notes, and snippets.

@kathyrollo
Last active April 17, 2023 00:36
Show Gist options
  • Save kathyrollo/ffcc19a4a1a0b30ac122d39ec8e47c72 to your computer and use it in GitHub Desktop.
Save kathyrollo/ffcc19a4a1a0b30ac122d39ec8e47c72 to your computer and use it in GitHub Desktop.
Polymorphic DriverFactory Pattern with Selenium WebDriver (JDK 17)
<!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
<scope>test</scope>
</dependency>
public sealed interface Driver permits RemoteDriver {
Driver isHeadless(boolean isHeadless);
Driver withGridUrl(URL gridUrl);
Capabilities getOptions();
WebDriver getDriver();
}
public non-sealed abstract class RemoteDriver implements Driver {
protected boolean isHeadless;
protected URL gridUrl;
@Override
public Driver isHeadless(boolean isHeadless) {
this.isHeadless = isHeadless;
return this;
}
@Override
public Driver withGridUrl(URL gridUrl) {
this.gridUrl = gridUrl;
return this;
}
// Returns RemoteWebDriver if URL is supplied, otherwise returns the local WebDriver
protected WebDriver getDriver(Supplier<WebDriver> driver, Capabilities options) {
return Optional.ofNullable(gridUrl)
.<WebDriver>map(gridUrl -> new RemoteWebDriver(gridUrl, options))
.orElseGet(driver);
}
}
// Create a class to represent each browser
public class Chrome extends RemoteDriver {
// ChromeOptions derives from Capabilities, satisfying the Driver interface implemented by RemoteDriver
@Override
public ChromeOptions getOptions() {
var options = new ChromeOptions();
options.setExperimentalOption("prefs", prefs);
if(isHeadless) {
options.addArguments("--headless=new", "--window-size=1920,1080");
} else {
options.addArguments("--start-maximized");
}
// Add other arguments
return options;
}
// Overrides getDriver(), satisfying the Driver interface implemented by RemoteDriver
@Override
public WebDriver getDriver() {
// Internally calls getDriver() from the RemoteDriver parent class
return super.getDriver(() -> new ChromeDriver(getOptions()), getOptions());
}
}
import org.apache.commons.lang3.StringUtils;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;
// Other imports
public class DriverFactory {
private boolean isHeadless;
private URL gridUrl;
public DriverFactory setHeadless(boolean isHeadless) {
this.isHeadless = isHeadless;
return this;
}
public DriverFactory setGridUrl(String gridUrl) throws MalformedURLException {
if(!StringUtils.isBlank(gridUrl)) {
this.gridUrl = new URL(gridUrl);
}
return this;
}
public WebDriver getInstance(String browser) throws ReflectiveOperationException {
// Uses reflection to get a list of classes that implement the Driver interface
return new ArrayList<>(new Reflections(new ConfigurationBuilder()
.forPackage(Driver.class.getPackageName()))
.getSubTypesOf(Driver.class))
.stream()
// Filters the browser by class name
.filter(d -> d.getSimpleName().toLowerCase().contains(browser.toLowerCase()))
.findFirst()
.orElseThrow(() -> new RuntimeException(browser + " browser is not supported"))
.getConstructor()
.newInstance()
.isHeadless(isHeadless)
.withGridUrl(gridUrl)
.getDriver();
}
}
public abstract class BaseTest {
protected WebDriver driver;
@BeforeEach
public void setUp() throws Throwable {
driver = new DriverFactory()
// Set environment variables in the OS
.setHeadless(System.getenv("SELENIUM_HEADLESS"))
.setGridUrl(System.getenv("SELENIUM_GRID_URL"))
.getInstance(System.getenv("SELENIUM_BROWSER"));
driver.get(System.getenv("SELENIUM_BASE_URL"));
// More code
}
@AfterEach
public void tearDown() {
driver.quit();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment