PlumaDriver is a Node.js implementation of the W3C WebDriver Recommendation for the jsdom library. The goal of this project is to provide an automation tool for jsdom in order to test web applications without the overhead of modern web browsers.
PlumaDriver can be used with the Java language binding for Selenium WebDriver (additional language bindings will be developed in the future). Alternatively, as a RESTful API, PlumaDriver can be used with any HTTP request client (see Using PlumaDriver Without Selenium).
- Download or build the PlumaDriver executable.
- Add the pluma.jar file to your project libraries in addition to the Selenium Java bindings.
// Set PlumaDriver executable path
System.setProperty("webdriver.pluma.driver","<path_to_executable>");
// Create a driver Instance
Webdriver driver = new PlumaDriver();
driver.get("https://www.example.com"); // navigate to
WebElement e = driver.findElement(By.tagName("p"));
String text = e.getText();
System.out.println(text);
driver.quit();
PlumaOptions options = new PlumaOptions();
options.setAcceptInsecureCerts(false);
options.setRunScripts(true);
options.rejectPublicSuffixes(false);
PlumaDriver plumaDriver = new PlumaDriver(options);
The following options are available when creating a PlumaDriver instance:
AcceptInsecureCerts
: Determines whether or not invalid SSL certificates are accepted.RunScripts
: Enables executing scripts inside the page. In most cases, you'll likely want to set this totrue
.RejectPublicSuffixes
: Determines whether or not cookies with domains likecom
andco.uk
are rejected. See https://publicsuffix.org/ for more information.
The PlumaDriver class will create a server instance at creation and destroy it when the quit()
method is called. This means that for every instance of this class a separate server will be created resulting in a significant amount of resource usage. To reduce the resource consumption, the following options are available:
PlumaDriverService:
PlumaDriverService service = new PlumaDriverService() {
.usingDriverExecuteable(new File("path/to/plumadriver/"))
.usingAnyFreePort()
.build();
service.start();
WebDriver pluma = new RemoteWebDriver(service.getUrl(), new PlumaOptions());
Starting the PlumaDriver server directly from the terminal and connecting it to the Remote WebDriver:
Terminal:
./plumadriver --port=4040
Java:
WebDriver pluma = new RemoteWebDriver("https://127.0.0.1:4040", new PlumaOptions());
pluma.get("https://www.example.com");
You may also use PlumaDriver with any HTTP request software (e.g. Postman
, fetch
, cURL
, etc.):
- Download or build PlumaDriver executable appropriate for your operating system.
- Run the executable. This will start the server by default on port 3000 (alternatively, set the port instead with
--port <number>
). - Use your preferred HTTP Client to make requests to the endpoints.
POST
the following example JSON to https://localhost:3000/session
to create a new session:
{
"capabilities": {
"alwaysMatch": {
"plm:plumaOptions": {
"runScripts": true
}
}
}
}
PlumaDriver should respond with a unique sessionId
along with the session information:
{
"value": {
"sessionId": "<unique-id>",
"capabilities": {...}
}
}
You may use the above sessionId
value provided by the web driver to make further requests. For instance, to navigate to a page, POST
the following to https://localhost:3000/session/<sessionId>/url
:
{
"url": "https://example.com"
}
See the W3C endpoint specification or this simplified guide to learn more about how to work with WebDriver endpoints.
- Ensure Node.js v12.19.0 is installed, or run
nvm use
.
From the command line:
- Clone this repository
cd plumadriver
npm install
- For Linux:
npm run build:linux
For Windows:
npm run build:win
For Mac:
npm run build:macos
These scripts will transpile all the typescript code found within src directory and output the result to the build directory. From here pkg will create an executable which should appear in the project's root directory.
It is important to keep in mind that jsdom is not intended to be a full rendering browser but rather emulate enough of a browser to be useful for testing and web scraping applications. As a result, W3C WebDriver endpoints which require browser rendering capabilities will not be implemented at this time.
- New Session: POST /session
- Delete Session: DELETE /session/{session id}
- Get Status: GET /status
- Get Timeouts: GET /session/{session id}/timeouts
- Set Timeouts: POST /session/{session id}/timeouts
- Navigate To: POST /session/{session id}/url
- Get Current URL: GET /session/{session id}/url
- Get Title: GET /session/{session id}/title
- Find Elements: POST /session/{session id}/elements
- Find Element: POST /session/{session id}/element
- Find Element from Element: POST /session/{session id}/element/{element id}/element
- Find Elements from Element: POST /session/{session id}/element/{element id}/elements
- Get Element Text: GET /session/{session id}/element/{element id}/text
- Get Element Tag Name: POST /session/{session id}/element/{element id}/{name}
- Get All Cookies: GET /session/{session id}/cookie
- Add Cookie: POST /session/{session id}/cookie
- Get Named Cookie: GET /session/{session id}/cookie/{name}
- Delete Cookie: DELETE /session/{session id}/cookie/{name}
- Delete All Cookies: DELETE /session/{session id)/cookie
- Execute Script: POST /session/{session id}/execute/sync
- Get Element Attribute: POST /session/{session id}/element/{element id}/attribute/{name}
- Get Element Property: GET /session/{session id}/element/{element id}/property/{name}
- Get Element CSS Value GET /session/{session id}/element/{element id}/css/{property name}
- Element Click: POST /session/{session id}/element/{element id}/click
- Element Clear: POST /session/{session id}/element/{element id}/clear
- Is Element Enabled: GET /session/{session id}/element/{element id}/enabled
- Is Displayed: GET /session/{session id}/element/{element id}/displayed
- Get Page Source: GET /session/{session id}/source
- Shutdown: GET /shutdown (Non-W3C)
- Get Active Element: GET /session/{session id}/element/active
- Switch To Frame: POST /session/{session id}/frame
- Switch To Parent Frame: POST /session/{session id}/frame/parent
- Is Element Selected: GET /session/{session id}/element/{element id}/selected
- Get Computed Label: GET /session/{session id}/element/{element id}/computedlabel
- Get Computed Role: GET /session/{session id}/element/{element id}/computedrole