# Selenium REPL Cheatsheet

- General example
- Installing browser drivers
- Browser manipulation
- Locating elements
- Waits
- JS alerts, prompts, and confirmations
- HTTP proxies
- Page loading strategy
- Web Element
- Keyboard
- Remote Webdriver
- BiDi APIs
- Driver specific capabilities
- On test automation
- Mouse and keyboard actions in detail
- Working with cookies
- Chrome devtools

## General example

Source Table of Contents

    copyconst {Builder, By, Key, until} = require('selenium-webdriver');
    let driver = await new Builder().forBrowser('firefox').build();
    try {
        // Navigate to Url
        await driver.get('https://www.google.com');

        // Enter text "cheese" and perform keyboard action "Enter"
        await driver.findElement(By.name('q')).sendKeys('cheese', Key.ENTER);

        let firstResult = await driver.wait(until.elementLocated(By.css('h3')), 10000);

        console.log(await firstResult.getAttribute('textContent'));
    }
    finally {
        await driver.quit();
    }

## Installing browser drivers

Source Table of Contents

    copyconst {Builder} = require('selenium-webdriver');
    let driver = await new Builder().forBrowser('chrome').build();

    copyconst {Builder} = require('selenium-webdriver');
    let driver = await new Builder().forBrowser('firefox').build();

    copyconst {Builder} = require('selenium-webdriver');
    let driver = await new Builder().forBrowser('MicrosoftEdge').build();

    copyconst {Builder} = require('selenium-webdriver');
    let driver = await new Builder().forBrowser('internet explorer').build();

    copyconst {Builder} = require('selenium-webdriver');
    let driver = await new Builder().forBrowser('opera').build();

    copyconst {Builder} = require('selenium-webdriver');
    let driver = await new Builder().forBrowser('safari').build();

## Browser manipulation

Source Table of Contents

    copyawait driver.get('https://selenium.dev');

    copyawait driver.getCurrentUrl();

    copyawait driver.navigate().back();

    copyawait driver.navigate().forward();

    copyawait driver.navigate().refresh();

    copyawait driver.getTitle();

    copyawait driver.getWindowHandle();

    copy// Wait for the new window or tab
    await driver.wait(
        async () => (await driver.getAllWindowHandles()).length === 2,
        10000
    );

    copy// Loop through until we find a new window handle
    const windows = await driver.getAllWindowHandles();
    windows.forEach(async handle => {
      if (handle !== originalWindow) {
        await driver.switchTo().window(handle);
      }
    });

    copy// Wait for the new tab to finish loading content
    await driver.wait(until.titleIs('Selenium documentation'), 10000);

    copy// Opens a new tab and switches to new tab
    await driver.switchTo().newWindow('tab');

    copy// Opens a new window and switches to new window
    await driver.switchTo().newWindow('window');

    copy// Close the tab or window
    await driver.close();

    copy// Switch back to the old tab or window
    await driver.switchTo().window(originalWindow);

    copy// Store the web element
    const iframe = driver.findElement(By.css('#modal > iframe'));
    // Switch to the frame
    await driver.switchTo().frame(iframe);

    copy// Using the ID
    await driver.switchTo().frame('buttonframe');

    copy// Or using the name instead
    await driver.switchTo().frame('myframe');

    copy// Switches to the second frame
    await driver.switchTo().frame(1);

    copy// Return to the top level
    await driver.switchTo().defaultContent();

    copyconst { width, height } = await driver.manage().window().getRect();

    copyawait driver.manage().window().setRect({ width: 1024, height: 768 });

    copyconst { x, y } = await driver.manage().window().getRect();

    copy// Move the window to the top left of the primary monitor
    await driver.manage().window().setRect({ x: 0, y: 0 });

    copyawait driver.manage().window().maximize();

    copyawait driver.manage().window().minimize();

    copyawait driver.manage().window().fullscreen();

    copy// Returns base64 encoded string
    let encodedString = await driver.takeScreenshot();
    await fs.writeFileSync('./image.png', encodedString, 'base64');

    copy// Captures the element screenshot
    let encodedString = await element.takeScreenshot(true);
    await fs.writeFileSync('./image.png', encodedString, 'base64');

    copy// Executing JavaScript to capture innerText of header element
    let text = await driver.executeScript('return arguments[0].innerText', header);

    copy// Print page as PDF
    let base64 = await driver.printPage({pageRanges:["1-2"]});
    await fs.writeFileSync('./test.pdf', base64, 'base64');

## Locating elements

Source Table of Contents
The By object has the functions: className(name), css(selector), id(id), js(script, ...var_args), linkText(text), name(name), partialLinkText(text), tagName(name), and xpath(xpath).
"In general, if HTML IDs are available, unique, and consistently predictable, they are the preferred method for locating an element on a page. They tend to work very quickly, and forego much processing that comes with complicated DOM traversals.
If unique IDs are unavailable, a well-written CSS selector is the preferred method of locating an element. XPath works as well as CSS selectors, but the syntax is complicated and frequently difficult to debug. Though XPath selectors are very flexible, they are typically not performance tested by browser vendors and tend to be quite slow.
Selection strategies based on linkText and partialLinkText have drawbacks in that they only work on link elements. Additionally, they call down to XPath selectors internally in WebDriver.
Tag name can be a dangerous way to locate elements. There are frequently multiple elements of the same tag present on the page. This is mostly useful when calling the findElements(By) method which returns a collection of elements.
The recommendation is to keep your locators as compact and readable as possible. Asking WebDriver to traverse the DOM structure is an expensive operation, and the more you can narrow the scope of your search, the better."

    copyconst cheese = driver.findElement(By.id('cheese'));

    copyconst cheddar = driver.findElement(By.css('#cheese #cheddar'));

    copylet passwordField = driver.findElement(By.id('password'));
    let emailAddressField = await driver.findElement(locateWith(By.css('input')).above(passwordField));

    copylet emailAddressField = driver.findElement(By.id('email'));
    let passwordField = await driver.findElement(locateWith(By.css('input')).below(emailAddressField));

    copylet submitButton = driver.findElement(By.id('submit'));
    let cancelButton = await driver.findElement(locateWith(By.css('button')).toLeftOf(submitButton));

    copylet cancelButton = driver.findElement(By.id('cancel'));
    let submitButton = await driver.findElement(locateWith(By.css('button')).toRightOf(cancelButton));

    copylet emailAddressLabel = driver.findElement(By.id("lbl-email"));
    let emailAddressField = await driver.findElement(locateWith(By.css("input")).near(emailAddressLabel));

## Waits

Source Table of Contents

    copyconst documentInitialised = () =>
        driver.executeScript('return initialised');

    await driver.get('file:///race_condition.html');
    await driver.wait(() => documentInitialised(), 10000);
    const element = driver.findElement(By.css('p'));
    assert.strictEqual(await element.getText(), 'Hello from JavaScript!');

    copylet ele = await driver.wait(until.elementLocated(By.css('p')),10000);

    copy// Apply timeout for 10 seconds
    await driver.manage().setTimeouts( { implicit: 10000 } );

    copy// Waiting 30 seconds for an element to be present on the page, checking
    // for its presence once every 5 seconds.
    let foo = await driver.wait(until.elementLocated(By.id('foo')), 30000, 'Timed out after 30 seconds', 5000);

## JS alerts, prompts, and confirmations

Source Table of Contents

    copy// Wait for the alert to be displayed
    await driver.wait(until.alertIsPresent());

    // Store the alert in a variable
    let alert = await driver.switchTo().alert();

    //Store the alert text in a variable
    let alertText = await alert.getText();

    //Press the OK button
    await alert.accept();

    copyawait alert.dismiss();

## HTTP proxies

Source Table of Contents

    copylet webdriver = require('selenium-webdriver');
    let chrome = require('selenium-webdriver/chrome');
    let proxy = require('selenium-webdriver/proxy');
    let opts = new chrome.Options();

    opts.setProxy(proxy.manual({http: ''}));
    let driver = new webdriver.Builder()
        .forBrowser('chrome')
        .setChromeOptions(opts)
        .build();

## Page loading strategy

Source Table of Contents

    copyconst {Builder, Capabilities} = require('selenium-webdriver');
    const caps = new Capabilities();
    caps.setPageLoadStrategy("normal");
    let driver = await new Builder().
                withCapabilities(caps).
                forBrowser('chrome').
                build();

    copycaps.setPageLoadStrategy("eager");

    copycaps.setPageLoadStrategy("none");

## Web Element

Source Table of Contents

    copy// Click an element
    element.click();

    copy// Type in an element
    element.sendKeys('Input Text');

    copy// Get all the elements available with tag 'p'
    await driver.findElements(By.css('p'));

    copy// Get search box element from webElement 'form'
    let searchBar = searchForm.findElement(By.name('q'));

    copyawait element.findElements(By.css("p"));

    copy// Get attribute of current active element
    let attr = await driver.switchTo().activeElement().getAttribute("title");

    copyawait driver.findElement(By.name("btnK")).isEnabled();

    copy// Returns TagName of the element
    let value = await driver.findElement(By.css('h1')).getTagName();

    copy// Returns height, width, x and y coordinates referenced element
    let element = await driver.findElement(By.css("h1")).getRect();

    copy// Retrieves the computed style property 'color' of linktext
    let cssValue = await driver.findElement(By.linkText("More information...")).getCssValue('color');

    copy// retrieves the text of the element
    let text = await driver.findElement(By.css('h1')).getText();

## Keyboard

Source Table of Contents

    copy// Enter text "webdriver" and perform keyboard action "Enter"
    await driver.findElement(By.name('q')).sendKeys('webdriver', Key.ENTER);

    copy// Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page
    await driver.actions().keyDown(Key.CONTROL).sendKeys('a').perform();

    copy// Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty)
    await driver.actions().click(search).keyDown(Key.SHIFT).sendKeys("qwerty").keyUp(Key.SHIFT).sendKeys("qwerty").perform();

    copy// Clear the input field text
    await searchInput.clear();

## Remote Webdriver

Source Table of Contents

    copyconst { Builder, Capabilities } = require("selenium-webdriver");
    var capabilities = Capabilities.firefox();
    let driver = new Builder()
        .usingServer("http://example.com")
        .withCapabilities(capabilities)
        .build();

    copy
    const { Builder } = require("selenium-webdriver");
    const chrome = require("selenium-webdriver/chrome");
    let opts = new chrome.Options();
    opts.setAcceptInsecureCerts(true);
    opts.setBrowserVersion('67');
    opts.setPlatform('Windows XP');
    let driver = new Builder()
        .usingServer("http://example.com")
        .forBrowser('chrome')
        .setChromeOptions(opts)
        .build();

    copyvar remote = require('selenium-webdriver/remote');
    driver.setFileDetector(new remote.FileDetector);

## BiDi APIs

Source Table of Contents

    copyconst pageCdpConnection = await driver.createCDPConnection('page');
    await driver.register('username', 'password', pageCdpConnection);

    copyconst cdpConnection = await driver.createCDPConnection('page');
    await driver.logMutationEvents(cdpConnection, event => {
        assert.deepStrictEqual(event['attribute_name'], 'style');
        assert.deepStrictEqual(event['current_value'], "");
        assert.deepStrictEqual(event['old_value'], "display:none;");
    });

    copyconst cdpConnection = await driver.createCDPConnection('page');
    await driver.onLogEvent(cdpConnection, function (event) {
        console.log(event['args'][0]['value']);
    });
    await driver.executeScript('console.log("here")');

    copyconst cdpConnection = await driver.createCDPConnection('page')
    await driver.onLogException(cdpConnection, function (event) {
        console.log(event['exceptionDetails']);
    })

    copyawait driver.sendAndGetDevToolsCommand('Performance.enable')

    let result = await driver.sendAndGetDevToolsCommand('Performance.getMetrics')
    console.log(result)

    copyconst connection = await driver.createCDPConnection()
    let url = fileServer.whereIs("/cheese")
    let httpResponse = new HttpResponse(url)
    httpResponse.addHeaders("Content-Type", "UTF-8")
    httpResponse.body = "sausages"
    await driver.onIntercept(connection, httpResponse, async function () {
        let body = await driver.getPageSource()
        assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`)
    })
    driver.get(url)

## Driver specific capabilities

Source Table of Contents

    copyconst { Builder } = require("selenium-webdriver");
    const firefox = require('selenium-webdriver/firefox');

    const options = new firefox.Options();
    options.headless();
    const driver = new Builder()
        .forBrowser('firefox')
        .setFirefoxOptions(options)
        .build();

    copyconst { Builder } = require("selenium-webdriver");
    const firefox = require('selenium-webdriver/firefox');

    const options = new firefox.Options();
    let profile = '/path to custom profile';
    options.setProfile(profile);
    const driver = new Builder()
        .forBrowser('firefox')
        .setFirefoxOptions(options)
        .build();

## On test automation

Source Table of Contents

    copy// Create a user who has read-only permissions--they can configure a unicorn,
    // but they do not have payment information set up, nor do they have
    // administrative privileges. At the time the user is created, its email
    // address and password are randomly generated--you don't even need to
    // know them.
    var user = userFactory.createCommonUser(); //This method is defined elsewhere.

    // Log in as this user.
    // Logging in on this site takes you to your personal "My Account" page, so the
    // AccountPage object is returned by the loginAs method, allowing you to then
    // perform actions from the AccountPage.
    var accountPage = loginAs(user.email, user.password);

    copy// The Unicorn is a top-level Object--it has attributes, which are set here.
    // This only stores the values; it does not fill out any web forms or interact
    // with the browser in any way.
    var sparkles = new Unicorn("Sparkles", UnicornColors.PURPLE, UnicornAccessories.SUNGLASSES, UnicornAdornments.STAR_TATTOOS);

    // Since we are already "on" the account page, we have to use it to get to the
    // actual place where you configure unicorns. Calling the "Add Unicorn" method
    // takes us there.

    var addUnicornPage = accountPage.addUnicorn();

    // Now that we're on the AddUnicornPage, we will pass the "sparkles" object to
    // its createUnicorn() method. This method will take Sparkles' attributes,
    // fill out the form, and click submit.
    var unicornConfirmationPage = addUnicornPage.createUnicorn(sparkles);

    copy// The exists() method from UnicornConfirmationPage will take the Sparkles
    // object--a specification of the attributes you want to see, and compare
    // them with the fields on the page.
    assert(unicornConfirmationPage.exists(sparkles), "Sparkles should have been created, with all attributes intact");

## Mouse and keyboard actions in detail

Source Table of Contents

    copy// Press and hold
    const actions = driver.actions({async: true});
    // Perform mouseMove to element and mouseDown (press) action on the element
    await actions.move({origin:searchBtn}).press().perform();

    copyconst actions = driver.actions({async: true});
    // Perform context-click action on the element
    await actions.contextClick(searchBtn).perform();

    copyconst actions = driver.actions({async: true});
    // Perform double-click action on the element
    await actions.doubleClick(searchBtn).perform();

    copy// Move to element
    const actions = driver.actions({async: true});
    // Performs mouse move action onto the element
    await actions.move({origin:gmailLink}).perform();

    copy// Move by offset
    // Capture offset positions of element
    let offset = await gmailLink.getRect();
    let x = await offset.x;
    let y = await offset.y;
    const actions = driver.actions({async: true});
    // Performs mouse move action onto the element
    await actions.move({x:parseInt(x),y:parseInt(y)}).pause(3000).perform();

    copy// Drag and drop
    // Store 'box A' as source element
    let sourceEle = driver.findElement(By.id("draggable"));
    // Store 'box B' as source element
    let targetEle = driver.findElement(By.id("droppable"));
    const actions = driver.actions({async: true});
    // Performs drag and drop action of sourceEle onto the targetEle
    await actions.dragAndDrop(sourceEle, targetEle).perform();

    copy// Drag and drop by offset
    // Store 'box A' as source element
    let sourceEle = driver.findElement(By.id("draggable"));
    // Store 'box B' as source element
    let targetEle = driver.findElement(By.id("droppable"));
    let offset = await targetEle.getRect();
    let x = await offset.x;
    let y = await offset.y;
    const actions = driver.actions({async: true});
    // Performs dragAndDropBy onto the  target element offset position
    await actions.dragAndDrop(sourceEle, {x:parseInt(x), y:parseInt(y)}).perform();

    copy// Store 'box A' as source element
    let sourceEle = driver.findElement(By.id("draggable"));
    // Store 'box B' as source element
    let targetEle = driver.findElement(By.id("droppable"));
    const actions = driver.actions({async: true});
    await actions.move({origin:sourceEle}).press().perform();
    // Performs release event on target element
    await actions.move({origin:targetEle}).release().perform();

## Working with cookies

Source Table of Contents

    copy// set a cookie on the current domain
    await driver.manage().addCookie({name:'key', value: 'value'});

    copy// Get cookie details with named cookie 'foo'
    driver.manage().getCookie('foo').then(function (cookie) {
        console.log('cookie details => ', cookie);
    });

    copy// Get all Available cookies
    driver.manage().getCookies().then(function (cookies) {
        console.log('cookie details => ', cookies);
    });

    copy// Delete a cookie with name 'test1'
    await driver.manage().deleteCookie('test1');

    copy// Delete all cookies
    await driver.manage().deleteAllCookies();

    copy// set a cookie on the current domain with sameSite 'Strict' (or) 'Lax'
    await driver.manage().addCookie({name:'key', value: 'value', sameSite:'Strict'});
    await driver.manage().addCookie({name:'key', value: 'value', sameSite:'Lax'});
    console.log(await driver.manage().getCookie('key'));

## Chrome devtools

Source Table of Contents

    copyconst pageCdpConnection = await driver.createCDPConnection('page');
    //Latitude and longitude of Tokyo, Japan
    const coordinates = {
        latitude: 35.689487,
        longitude: 139.691706,
        accuracy: 100,
    };
    await pageCdpConnection.execute(
        "Emulation.setGeolocationOverride",
        1,
        coordinates
    );

    copyconst {Builder} = require('selenium-webdriver');
    const firefox = require('selenium-webdriver/firefox');
    const options = new firefox.Options();
    // enable debugger for CDP
    options.enableDebugger();

    let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(options).build();
    const pageCdpConnection = await driver.createCDPConnection('page');
    const metrics = {
        width: 300,
        height: 200,
        deviceScaleFactor: 50,
        mobile: true,
    };
    await pageCdpConnection.execute(
        "Emulation.setDeviceMetricsOverride",
        1,
        metrics
    );