selenium server | Cell 2 | Cell 4 | Search

The findElements function uses the Chrome debugger API to find elements on a webpage based on an input selector, and is called by two express routes to handle POST requests. The function and express router are exported as part of the module, allowing it to be used in other applications.

Cell 3

var express = require('express');
var router = express.Router();

function findElements(selector) {
    return promisifyChrome('debugger.sendCommand', {
        tabId: getTab()
    }, 'Runtime.evaluate', {
        expression: `new window.BackupPromise(resolve => setTimeout(() => {
resolve([].slice.call(window.document.querySelectorAll(${JSON.stringify(selector)}), 0)[0])
}, 500))`,
        awaitPromise: true
    })
        .then(r => {
            return promisifyChrome('debugger.sendCommand', {
                tabId: getTab()
            }, 'DOM.requestNode', {
                objectId: r.result.objectId
            })
        })
        .then(r => ({value: {ELEMENT: r.nodeId}}))
        .catch(e => console.log(e))
}

router.post('/session/:sessionId/element', (req, res) =>
    response(res, findElements(req.body.value)));
router.post('/session/:sessionId/elements', (req, res) =>
    response(res, findElements(req.body.value)));

module.exports = {
    findElements,
    router
}

What the code could have been:

const express = require('express');
const router = express.Router();
const { promisifyChrome } = require('./promisifyChrome'); // Assuming promisifyChrome is in a separate file

// Helper function to get the current tab ID
const getTab = () => {
  // Assuming getTab is implemented elsewhere
};

// Helper function to send a response
const response = (res, data) => {
  res.json(data);
};

// Helper function to handle Chrome DevTools commands
const handleChromeCommand = (method, params) => {
  try {
    return promisifyChrome(method, params);
  } catch (error) {
    console.error('Error handling Chrome DevTools command:', error);
    return Promise.reject(error);
  }
};

// Helper function to get elements using the given selector
const findElements = async (selector) => {
  /**
   * Finds elements on the current page using the given selector.
   * 
   * @param {string} selector - A CSS selector to find elements.
   * @returns {object[]} An array of element objects.
   */
  const tabId = getTab();
  const chromeMethod = 'Runtime.evaluate';
  const evaluateParams = {
    expression: `new window.BackupPromise(resolve => setTimeout(() => {
    resolve([].slice.call(window.document.querySelectorAll(${JSON.stringify(selector)}), 0)[0])
  }, 500))`,
    awaitPromise: true,
  };

  try {
    const evaluateResult = await handleChromeCommand('debugger.sendCommand', {
      tabId,
    }, chromeMethod, evaluateParams);
    const nodeId = evaluateResult.result.objectId;
    const domMethod = 'DOM.requestNode';
    const requestParams = { objectId: nodeId };
    const nodeResult = await handleChromeCommand('debugger.sendCommand', {
      tabId,
    }, domMethod, requestParams);
    return { value: { ELEMENT: nodeResult.nodeId } };
  } catch (error) {
    console.error('Error finding elements:', error);
    return Promise.reject(error);
  }
};

// Routes for finding a single element or multiple elements
router.post('/session/:sessionId/element', (req, res) =>
  response(res, findElements(req.body.value))
);
router.post('/session/:sessionId/elements', (req, res) =>
  response(res, findElements(req.body.value))
);

module.exports = { findElements, router };

Code Breakdown

Requires and Dependencies

Function: findElements(selector)

Express Router

Module Exports