SELENIUM WEBDRIVER JS Tutorial Course

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})();
Run above code using below command.
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
e.g. to set the Environment to "test", you can use below command
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 here

Sharing Data

You can see how to share data in Mocha tests here

Models

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!
User

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.
Policy

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.
Claim

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.
Document

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.
Coverage

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.
Payment

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.
Provider

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.
Travel

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.
Benefits
  • 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 file
1apiVersion: 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
Create a Service for Selenium Hub - hub-service.yaml file
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
Create a Deployment for Selenium node - node-chrome-deployment.yaml file
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
Create a Service for Selenium Node - node-service.yaml file.
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
Deploy to Kubernetes
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
Verify Deployment
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.