Introduction to Selenium WebDriver JS
What is Selenium WebDriver?
Selenium WebDriver is a tool used for automating web browsers. It provides a programming interface for controlling a browser, allowing you to write scripts in various programming languages to perform tasks such as navigating web pages, interacting with web elements, and testing web applications. Selenium WebDriver is part of the Selenium suite, which also includes Selenium IDE and Selenium Grid.Key Features of Selenium WebDriver
- Cross-Browser Testing - WebDriver supports multiple browsers including Chrome, Firefox, Safari, Edge, and Internet Explorer. This allows you to run your tests across different browsers to ensure compatibility.
- Programming Language Support - WebDriver can be used with several programming languages such as Java, Python, C#, Ruby, JavaScript, and Kotlin. This flexibility allows you to integrate it into your existing development workflow.
- API for Browser Interaction - WebDriver provides a rich set of APIs for interacting with web elements. You can perform actions like clicking buttons, filling out forms, selecting options, and verifying content.
- Element Locators - You can locate elements using various strategies such as ID, name, class name, tag name, link text, partial link text, CSS selectors, and XPath.
- Synchronization - WebDriver offers mechanisms for waiting until certain conditions are met, such as waiting for elements to be present or visible, ensuring that your tests are more reliable.
- Headless Mode - WebDriver supports running browsers in headless mode (i.e., without a GUI), which can speed up test execution and is useful for running tests on CI/CD pipelines.
- Integration with Testing Frameworks - WebDriver integrates well with various testing frameworks and tools such as JUnit, TestNG, NUnit, Mocha, and others, allowing for comprehensive test management and reporting.
- WebDriver Grid - Selenium Grid allows you to distribute your tests across multiple machines and browsers, enabling parallel execution and reducing test execution time.
Setting Up Selenium WebDriver
Installing Selenium WebDriver
1npm init
2npm install selenium-webdriver
Configuring mocha
You can use Mocha testing framework to run Selenium tests !UI automation with Selenium
Opening a Browser
1const { Builder, By } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3
4(async function example() {
5 let driver = await new Builder().forBrowser('chrome').setChromeOptions(new chrome.Options()).build();
6 try {
7 await driver.get('https://www.example.com');
8 console.log(await driver.getTitle());
9 } finally {
10 await driver.quit();
11 }
12})();
node your_fileName.js
Locating Elements
1const { Builder, By, Key, until } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3
4(async function demoLocators() {
5 // Initialize the WebDriver instance
6 let driver = await new Builder()
7 .forBrowser('chrome')
8 .setChromeOptions(new chrome.Options())
9 .build();
10
11 try {
12 // Navigate to a test page
13 await driver.get('https://www.example.com');
14
15 // Locate an element by ID
16 let elementById = await driver.findElement(By.id('some-id'));
17 console.log('Located by ID:', await elementById.getText());
18
19 // Locate an element by name
20 let elementByName = await driver.findElement(By.name('some-name'));
21 console.log('Located by Name:', await elementByName.getAttribute('value'));
22
23 // Locate an element by class name
24 let elementByClassName = await driver.findElement(By.className('some-class'));
25 console.log('Located by Class Name:', await elementByClassName.getText());
26
27 // Locate an element by tag name
28 let elementByTagName = await driver.findElement(By.tagName('h1'));
29 console.log('Located by Tag Name:', await elementByTagName.getText());
30
31 // Locate an element by link text
32 let elementByLinkText = await driver.findElement(By.linkText('More information...'));
33 console.log('Located by Link Text:', await elementByLinkText.getText());
34
35 // Locate an element by partial link text
36 let elementByPartialLinkText = await driver.findElement(By.partialLinkText('More info'));
37 console.log('Located by Partial Link Text:', await elementByPartialLinkText.getText());
38
39 // Locate an element by CSS selector
40 let elementByCss = await driver.findElement(By.css('div.some-class > p'));
41 console.log('Located by CSS Selector:', await elementByCss.getText());
42
43 // Locate an element by XPath
44 let elementByXPath = await driver.findElement(By.xpath('//h1'));
45 console.log('Located by XPath:', await elementByXPath.getText());
46
47 // Interact with an element
48 let inputElement = await driver.findElement(By.name('input-name'));
49 await inputElement.sendKeys('Test input', Key.RETURN);
50
51 // Wait for an element to be visible
52 let visibleElement = await driver.wait(until.elementLocated(By.id('some-id')), 10000);
53 console.log('Located and visible element:', await visibleElement.getText());
54
55 } finally {
56 // Quit the driver instance
57 await driver.quit();
58 }
59})();
Handling Popups and Alerts
1const { Builder, By, Key, until } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3
4(async function handlePopupsAndAlerts() {
5 // Initialize the WebDriver instance
6 let driver = await new Builder()
7 .forBrowser('chrome')
8 .setChromeOptions(new chrome.Options())
9 .build();
10
11 try {
12 // Navigate to a test page with popups and alerts
13 await driver.get('https://the-internet.herokuapp.com/javascript_alerts');
14
15 // Handling Alert
16 await driver.findElement(By.xpath("//button[text()='Click for JS Alert']")).click();
17 let alert = await driver.switchTo().alert();
18 console.log('Alert Text:', await alert.getText());
19 await alert.accept(); // Clicks "OK" on the alert
20
21 // Handling Confirmation Dialog
22 await driver.findElement(By.xpath("//button[text()='Click for JS Confirm']")).click();
23 let confirm = await driver.switchTo().alert();
24 console.log('Confirm Text:', await confirm.getText());
25 await confirm.accept(); // Clicks "OK" on the confirmation dialog
26
27 // Handling Prompt Dialog
28 await driver.findElement(By.xpath("//button[text()='Click for JS Prompt']")).click();
29 let prompt = await driver.switchTo().alert();
30 console.log('Prompt Text:', await prompt.getText());
31 await prompt.sendKeys('Selenium'); // Types 'Selenium' into the prompt dialog
32 await prompt.accept(); // Clicks "OK" on the prompt dialog
33
34 // Optionally, you can also dismiss alerts and confirmations
35 // await confirm.dismiss(); // Clicks "Cancel" on the confirmation dialog
36
37 } catch (error) {
38 console.error('An error occurred:', error);
39 } finally {
40 // Quit the driver instance
41 await driver.quit();
42 }
43})();
Interacting with Web Elements
1const { Builder, By, Key, until } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3
4(async function seleniumInteractions() {
5 // Initialize the WebDriver instance
6 let driver = await new Builder()
7 .forBrowser('chrome')
8 .setChromeOptions(new chrome.Options())
9 .build();
10
11 try {
12 // Navigate to a test page
13 await driver.get('https://www.example.com');
14
15 // Example 1: Clicking an element
16 let button = await driver.findElement(By.id('example-button-id'));
17 await button.click();
18 console.log('Button clicked.');
19
20 // Example 2: Typing into an input field
21 let inputField = await driver.findElement(By.id('example-input-id'));
22 await inputField.sendKeys('Sample text', Key.RETURN);
23 console.log('Text entered into input field.');
24
25 // Example 3: Selecting an option from a dropdown menu
26 let dropdown = await driver.findElement(By.id('example-dropdown-id'));
27 await dropdown.click(); // Open the dropdown
28
29 // Select an option by visible text
30 let option = await driver.findElement(By.xpath('//option[text()="Option Text"]'));
31 await option.click();
32 console.log('Option selected from dropdown.');
33
34 // Example 4: Waiting for an element to be present before interacting
35 let dynamicElement = await driver.wait(until.elementLocated(By.id('dynamic-element-id')), 10000);
36 await dynamicElement.click();
37 console.log('Dynamic element clicked.');
38
39 } finally {
40 // Quit the driver instance
41 await driver.quit();
42 }
43})();
Waiting for Elements
Implicit Wait
Implicit waits in Selenium WebDriver are used to specify a default wait time for the driver to wait when searching for elements that may not be immediately available. This can be useful when dealing with dynamic content on a web page. Here's how you can use implicit waits in Selenium WebDriver with JavaScript (Node.js).1const { Builder, By, until } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3
4(async function implicitWaitExample() {
5 // Initialize the WebDriver instance
6 let driver = await new Builder()
7 .forBrowser('chrome')
8 .setChromeOptions(new chrome.Options())
9 .build();
10
11 try {
12 // Set implicit wait time to 10 seconds
13 driver.manage().setTimeouts({ implicit: 10000 });
14
15 // Navigate to a test page
16 await driver.get('https://www.example.com');
17
18 // Example: Trying to find an element that might take some time to appear
19 let dynamicElement = await driver.findElement(By.id('dynamic-element-id'));
20
21 // Perform some action with the element
22 await dynamicElement.click();
23 console.log('Dynamic element clicked.');
24
25 } catch (error) {
26 console.error('An error occurred:', error);
27 } finally {
28 // Quit the driver instance
29 await driver.quit();
30 }
31})();
Explicit Wait
Explicit waits in Selenium WebDriver are used to wait for a specific condition to occur before proceeding. This is more flexible compared to implicit waits, as it allows you to wait for certain conditions like the visibility of an element, text to be present, or an element to be clickable. Explicit waits are implemented using the WebDriverWait class in Selenium.1const { Builder, By, until } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3
4(async function explicitWaitExample() {
5 // Initialize the WebDriver instance
6 let driver = await new Builder()
7 .forBrowser('chrome')
8 .setChromeOptions(new chrome.Options())
9 .build();
10
11 try {
12 // Navigate to a test page
13 await driver.get('https://www.example.com');
14
15 // Explicit wait for an element to be visible
16 let wait = new until.WebDriverWait(driver, 10000);
17 let dynamicElement = await wait.until(until.elementLocated(By.id('dynamic-element-id')));
18 await driver.wait(until.elementIsVisible(dynamicElement), 10000);
19
20 // Perform an action with the element
21 await dynamicElement.click();
22 console.log('Dynamic element clicked.');
23
24 // Example: Waiting for a condition, e.g., an element's text to be present
25 let elementWithText = await wait.until(until.elementLocated(By.id('text-element-id')));
26 await driver.wait(until.elementTextIs(elementWithText, 'Expected Text'), 10000);
27 console.log('Text found and verified.');
28
29 } catch (error) {
30 console.error('An error occurred:', error);
31 } finally {
32 // Quit the driver instance
33 await driver.quit();
34 }
35})();
Fluent Wait
Fluent Wait in Selenium WebDriver is a type of explicit wait that allows you to define a custom polling interval and ignore specific exceptions while waiting for a condition to be met. Fluent Wait is useful for waiting until a condition becomes true, with the flexibility to adjust polling frequency and handle specific exceptions.1const { Builder, By, until, WebDriver } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3
4// Fluent Wait function
5async function fluentWait(driver, locator, timeout, pollingInterval, ignoredExceptions) {
6 let endTime = Date.now() + timeout;
7 let exception;
8
9 while (Date.now() < endTime) {
10 try {
11 let element = await driver.findElement(locator);
12 if (await element.isDisplayed()) {
13 return element;
14 }
15 } catch (e) {
16 if (!ignoredExceptions.includes(e.constructor)) {
17 throw e;
18 }
19 exception = e;
20 }
21 await driver.sleep(pollingInterval);
22 }
23 throw exception;
24}
25
26(async function fluentWaitExample() {
27 // Initialize the WebDriver instance
28 let driver = await new Builder()
29 .forBrowser('chrome')
30 .setChromeOptions(new chrome.Options())
31 .build();
32
33 try {
34 // Navigate to a test page
35 await driver.get('https://www.example.com');
36
37 // Fluent Wait parameters
38 let timeout = 10000; // Maximum wait time in milliseconds
39 let pollingInterval = 500; // Polling interval in milliseconds
40 let ignoredExceptions = [WebDriver.error.NoSuchElementError];
41
42 // Use Fluent Wait to wait for an element to be visible
43 let locator = By.id('dynamic-element-id');
44 let element = await fluentWait(driver, locator, timeout, pollingInterval, ignoredExceptions);
45
46 // Perform an action with the element
47 await element.click();
48 console.log('Dynamic element clicked.');
49
50 } catch (error) {
51 console.error('An error occurred:', error);
52 } finally {
53 // Quit the driver instance
54 await driver.quit();
55 }
56})();
Miscellaneous
Full Page Screenshot
1const { Builder, By, until } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3const fs = require('fs');
4
5(async function fullPageScreenshotExample() {
6 // Initialize the WebDriver instance
7 let driver = await new Builder()
8 .forBrowser('chrome')
9 .setChromeOptions(new chrome.Options())
10 .build();
11
12 try {
13 // Navigate to a test page
14 await driver.get('https://www.example.com');
15
16 // Take a full-page screenshot
17 let screenshot = await driver.takeScreenshot();
18
19 // Save the screenshot to a file
20 fs.writeFileSync('full-page-screenshot.png', screenshot, 'base64');
21
22 console.log('Full-page screenshot saved as full-page-screenshot.png');
23
24 } catch (error) {
25 console.error('An error occurred:', error);
26 } finally {
27 // Quit the driver instance
28 await driver.quit();
29 }
30})();
Screenshot of Specific Elements
1const { Builder, By } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3const fs = require('fs');
4
5(async function specificElementScreenshot() {
6 // Initialize the WebDriver instance
7 let driver = await new Builder()
8 .forBrowser('chrome')
9 .setChromeOptions(new chrome.Options())
10 .build();
11
12 try {
13 // Navigate to a test page
14 await driver.get('https://www.example.com');
15
16 // Locate the specific element
17 let element = await driver.findElement(By.css('h1')); // Adjust the selector as needed
18
19 // Capture a screenshot of the specific element
20 let screenshot = await element.takeScreenshot();
21
22 // Save the screenshot to a file
23 fs.writeFileSync('element-screenshot.png', screenshot, 'base64');
24
25 console.log('Screenshot of the specific element saved as element-screenshot.png');
26
27 } catch (error) {
28 console.error('An error occurred:', error);
29 } finally {
30 // Quit the driver instance
31 await driver.quit();
32 }
33})();
Executing JavaScript in Browser
1const { Builder, By, until } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3
4(async function executeJavaScriptExample() {
5 // Initialize the WebDriver instance
6 let driver = await new Builder()
7 .forBrowser('chrome')
8 .setChromeOptions(new chrome.Options())
9 .build();
10
11 try {
12 // Navigate to a test page
13 await driver.get('https://www.example.com');
14
15 // Example 1: Execute JavaScript to get the title of the page
16 let pageTitle = await driver.executeScript('return document.title;');
17 console.log('Page Title:', pageTitle);
18
19 // Example 2: Execute JavaScript to manipulate the DOM
20 await driver.executeScript('document.body.style.backgroundColor = "lightblue";');
21
22 // Example 3: Execute JavaScript to retrieve a value from a JavaScript variable on the page
23 let jsVariableValue = await driver.executeScript('return window.someJavaScriptVariable;');
24 console.log('JavaScript Variable Value:', jsVariableValue);
25
26 // Example 4: Execute JavaScript to trigger a custom JavaScript function
27 await driver.executeScript('myCustomFunction();');
28
29 } catch (error) {
30 console.error('An error occurred:', error);
31 } finally {
32 // Quit the driver instance
33 await driver.quit();
34 }
35})();
Selenium BiDi
What is BiDi
Selenium BiDi (Bidirectional) is a protocol designed to enhance communication between the browser and automation tools. It represents a significant evolution in how Selenium interacts with web browsers, aiming to provide a more efficient and versatile means of automating and controlling web interactions.- Bidirectional Communication - Unlike traditional WebDriver, which follows a request-response model where commands are sent from the client to the browser and responses are received, BiDi introduces bidirectional communication. This allows the browser to send messages back to the client in real-time.
- Real-time Event Handling - Selenium BiDi enables handling and reacting to browser events (e.g., network requests, console messages) in real-time. This is particularly useful for scenarios like monitoring network activity, debugging, and interacting with JavaScript events as they happen.
- Enhanced Performance: By providing a more efficient way of handling browser events and interactions, BiDi can lead to performance improvements in automated testing and browser interaction tasks.
- Integration with DevTools Protocol: BiDi is designed to work with the DevTools Protocol (CDP), which is used by browsers to provide detailed access to their internal workings. This integration enables advanced interactions and monitoring capabilities.
- Improved Test Automation: With bidirectional communication, it becomes easier to handle asynchronous events and dynamic content changes in web applications. This enhances the ability to write more robust and responsive test scripts.
BiDi Use Cases
Here's an example showing how to use Selenium BiDi to capture network requests and console logs in Node.js:1const { Builder, By, Key, until } = require('selenium-webdriver');
2const chrome = require('selenium-webdriver/chrome');
3const { Console } = require('console');
4const fs = require('fs');
5
6(async function bidiExample() {
7 // Set up the Chrome options
8 let options = new chrome.Options();
9 options.addArguments('--remote-debugging-port=9222'); // Enable remote debugging
10
11 // Initialize the WebDriver instance with BiDi
12 let driver = await new Builder()
13 .forBrowser('chrome')
14 .setChromeOptions(options)
15 .build();
16
17 try {
18 // Navigate to a test page
19 await driver.get('https://www.example.com');
20
21 // Set up BiDi connection
22 let client = await driver.getDevTools();
23
24 // Enable network domain to capture network requests
25 await client.send('Network.enable');
26
27 // Set up a handler to capture network requests
28 client.on('Network.requestWillBeSent', (params) => {
29 console.log('Network request:', params);
30 });
31
32 // Enable console domain to capture console messages
33 await client.send('Console.enable');
34
35 // Set up a handler to capture console messages
36 client.on('Console.messageAdded', (params) => {
37 console.log('Console message:', params);
38 });
39
40 // Interact with the page
41 await driver.findElement(By.css('h1')).click();
42
43 // Wait to capture some network activity
44 await driver.sleep(5000);
45
46 } catch (error) {
47 console.error('An error occurred:', error);
48 } finally {
49 // Quit the driver instance
50 await driver.quit();
51 }
52})();
Selenium Framework
Environment Variables
process.env.NODE_ENV is an environment variable used in Node.js and various JavaScript environments to indicate the current execution environment of the application. It is commonly used to differentiate between various stages of the development lifecycle, such as development, testing, and production.
Common values of NODE_ENV are- development
- production
- test
NODE_ENV=test node app.js
Then you can use below code to read values from specific environment file (.env.development, .env.test etc). Please note that you will need to install dotenv package!
1require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` });
2let apiUrl = process.env.API_URL
Reports
You can see how to generate reports for Mocha tests hereSharing Data
You can see how to share data in Mocha tests hereModels
Before writing any tests, it is important to find the models in app. Models represent the core data structures of an application, typically corresponding to the entities in the application's domain. They often interact with databases and define the data schema and business logic. You can find model information in design documents, database schemas, or API documentation.
e.g. In travel insurance app, you will find models like user, policy, claim, payment etc!Description: Represents the individuals or entities purchasing insurance policies.
Attributes:
- id: Unique identifier
- name: Full name of the user
- email: Email address
- phoneNumber: Contact number
- address: Physical address
- dateOfBirth: Date of birth
- passportNumber: Passport or ID number (for international travelers)
Relationships:
- Policies: A user can have multiple insurance policies.
Description: Represents an insurance policy purchased by a user.
Attributes:
- id: Unique identifier
- policyNumber: Unique policy number
- coverageType: Type of coverage (e.g., medical, trip cancellation, baggage loss)
- startDate: Policy start date
- endDate: Policy end date
- premiumAmount: Amount paid for the policy
- coverageDetails: Description of what is covered
Relationships:
- User: Each policy is associated with a single user.
- Claims: A policy can have multiple claims.
Description: Represents a claim made by the user under a specific policy.
Attributes:
- id: Unique identifier
- claimNumber: Unique claim number
- claimDate: Date when the claim was made
- amountRequested: Amount requested for the claim
- amountApproved: Amount approved for the claim
- status: Status of the claim (e.g., pending, approved, denied)
- description: Description of the claim
Relationships:
- Policy: Each claim is associated with a single policy.
- Documents: A claim may have multiple supporting documents.
Description: Represents supporting documents for a claim, such as medical reports or receipts.
Attributes:
- id: Unique identifier
- documentType: Type of document (e.g., receipt, medical report)
- documentUrl: URL or path to the document
- uploadedDate: Date when the document was uploaded
Relationships:
- Claim: Each document is associated with a specific claim.
Description: Represents different types of coverage offered by insurance policies.
Attributes:
- id: Unique identifier
- coverageType: Type of coverage (e.g., medical, trip cancellation)
- description: Detailed description of the coverage
- limit: Coverage limit (maximum amount payable)
Relationships:
- Policies: Policies are associated with specific types of coverage.
Description: Represents payment transactions related to insurance policies.
Attributes:
- id: Unique identifier
- paymentDate: Date when the payment was made
- amount: Amount paid
- paymentMethod: Method of payment (e.g., credit card, bank transfer)
- transactionId: Unique transaction identifier
Relationships:
- Policy: Each payment is associated with a specific policy.
Description: Represents insurance providers or companies offering the policies.
Attributes:
- id: Unique identifier
- name: Name of the provider
- contactInfo: Contact information of the provider
- address: Address of the provider
Relationships:
- Policies: Policies are associated with a specific provider.
Description: Represents details about the travel, which may be relevant for certain types of coverage.
Attributes:
- id: Unique identifier
- destination: Destination of travel
- startDate: Travel start date
- endDate: Travel end date
- purpose: Purpose of travel (e.g., business, leisure)
Relationships:
- Policies: Policies may be linked to specific travel details.
Selenium Grid
What is Selenium Grid
Selenium Grid is a component of the Selenium suite that allows for the parallel execution of Selenium tests across multiple machines and environments. It is designed to distribute tests across various configurations and platforms, enhancing the efficiency and speed of testing.
Selenium Grid is used to run Selenium tests on multiple machines simultaneously, which is particularly useful for cross-browser and cross-platform testing.
Grid Architecture
Selenium Grid consists of two main components: Hub and node.- Hub - Central server that receives all the test requests and routes them to the appropriate nodes. It manages the distribution of test cases across different nodes.
- The Node - A machine where the tests are executed. Each node registers itself with the hub and provides information about its capabilities (e.g., browser versions, operating systems). Nodes execute tests as directed by the hub. Nodes can be configured to support different browser types, versions, and operating systems. This allows for testing on a variety of environments and configurations.
- Parallel Execution: Tests can be run concurrently on different nodes, significantly reducing the overall test execution time.
- Scalability: New nodes can be added to the grid to increase capacity and handle more tests.
- Cross-Browser Testing: Tests can be run on different browsers and browser versions to ensure compatibility.
- Cross-Platform Testing: Tests can be executed on various operating systems and devices.
Grid Setup
- Start the hub server, which listens for test requests and manages the grid.
java -jar selenium-server-standalone.jar -role hub
- Then Configure and start nodes, specifying their capabilities and registering them with the hub.
java -jar selenium-server-standalone.jar -role node -hub http://localhost:4444/grid/register -browser "browserName=chrome,maxInstances=5"
- When a test is initiated, it sends a request to the hub. The hub identifies the appropriate node based on the requested capabilities and forwards the test request to that node.
- The node executes the test and returns the results to the hub.
- The hub consolidates results from all nodes and provides feedback on the test execution.
1const { Builder, By, until } = require('selenium-webdriver');
2
3async function runTest() {
4 // Define capabilities for the browser you want to test
5 let capabilities = {
6 browserName: 'chrome'
7 };
8
9 // Connect to the Selenium Grid Hub
10 let driver = await new Builder()
11 .usingServer('http://localhost:4444/wd/hub') // URL of the Selenium Grid Hub
12 .withCapabilities(capabilities)
13 .build();
14
15 try {
16 // Open a website
17 await driver.get('https://www.example.com');
18
19 // Find an element and perform an action
20 let element = await driver.findElement(By.tagName('h1'));
21 console.log("Page title is: " + await element.getText());
22
23 // Example of waiting until a condition is met (not necessary for this example)
24 await driver.wait(until.titleIs('Example Domain'), 1000);
25
26 } finally {
27 // Close the browser
28 await driver.quit();
29 }
30}
31
32runTest().catch(console.error);
Grid using K8s
Setting up Selenium Grid with Kubernetes (K8s) involves deploying Selenium components—Hub and Nodes—using Kubernetes resources such as Deployments, Services, and ConfigMaps. This setup allows you to leverage Kubernetes for scaling, managing, and orchestrating your Selenium Grid environment.
Prerequisites- A running Kubernetes cluster
- kubectl CLI tool installed and configured
- Docker images for Selenium Hub and Nodes
Selenium provides official Docker images for Hub and Nodes. You can use these images or create custom ones based on your requirements. Official Docker images are - selenium/hub and selenium/node-chrome
Create a Deployment for Selenium Hub - hub-deployment.yaml file1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: selenium-hub
5 labels:
6 app: selenium
7spec:
8 replicas: 1
9 selector:
10 matchLabels:
11 app: selenium
12 component: hub
13 template:
14 metadata:
15 labels:
16 app: selenium
17 component: hub
18 spec:
19 containers:
20 - name: selenium-hub
21 image: selenium/hub:latest
22 ports:
23 - containerPort: 4444
1apiVersion: v1
2kind: Service
3metadata:
4 name: selenium-hub
5 labels:
6 app: selenium
7spec:
8 ports:
9 - port: 4444
10 targetPort: 4444
11 selector:
12 app: selenium
13 component: hub
14 type: LoadBalancer
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: selenium-node-chrome
5 labels:
6 app: selenium
7 component: node
8spec:
9 replicas: 2 # Adjust based on your needs
10 selector:
11 matchLabels:
12 app: selenium
13 component: node
14 template:
15 metadata:
16 labels:
17 app: selenium
18 component: node
19 spec:
20 containers:
21 - name: selenium-node-chrome
22 image: selenium/node-chrome:latest
23 env:
24 - name: HUB_HOST
25 value: selenium-hub
26 - name: HUB_PORT
27 value: "4444"
28 ports:
29 - containerPort: 5555
1apiVersion: v1
2kind: Service
3metadata:
4 name: selenium-node-chrome
5 labels:
6 app: selenium
7spec:
8 ports:
9 - port: 5555
10 targetPort: 5555
11 selector:
12 app: selenium
13 component: node
1kubectl apply -f hub-deployment.yaml
2kubectl apply -f hub-service.yaml
3kubectl apply -f node-chrome-deployment.yaml
4kubectl apply -f node-service.yaml
1kubectl get deployments
2kubectl get services
3kubectl get pods
The Selenium Hub can be accessed via the service URL. If you are using a LoadBalancer type service, it will provide an external IP or DNS name. You can access the Grid console at http://external-ip:4444/grid/console.
Additional Configuration- Scaling: You can scale the number of Selenium Nodes by adjusting the replicas field in the node deployment file and reapplying the configuration.
- Multiple Browsers: If you need different types of nodes (e.g., Firefox), create separate deployments for each type and configure them similarly.
- Persistent Storage: For more advanced setups, consider adding persistent storage for logs and other data.