Skip to main content

Overview

The content-script.js file serves a vital role in monitoring user interactions with a web page, gathering details about the elements involved, and transmitting this data to the extension’s background script and the Chrome DevTools panel. It tracks various types of events like ‘click’, ‘focus’, ‘blur’, and ‘change’. On detecting an event, it captures the details, including the target element’s XPath, and sends this information for further processing. This data aids in generating Cypress test code corresponding to the user interactions.

Functions

getRelativeXPath(element)

The getRelativeXPath(element) function accepts an HTMLElement and returns its relative XPath. It prioritizes unique attributes like ‘data-cy’, ‘data-test’, ‘data-testid’, and ‘id’ when forming the XPath. If none of these unique attributes are available, it determines the element’s position amongst its siblings sharing the same tag name. For anchor tags with an href attribute, the function modifies global variables accordingly.

inputEventListener(event, callback)

The inputEventListener(event, callback) function serves as an event listener for input events like ‘click’, ‘focus’, ‘blur’, and ‘change’. It takes an event object and a callback function as parameters. The function extracts relevant information from the event object, including the target element’s XPath and the event type, and calls the callback function with the obtained data. This function also handles ‘keydown’, ‘keyup’, and ‘mouseover’ events, enabling the user to trigger custom events using a specific combination of keys.

Event Listeners

The script sets up event listeners for ‘click’, ‘focus’, ‘blur’, ‘change’, ‘keydown’, ‘keyup’, and ‘mouseover’ events. It calls the inputEventListener() function for each event, which subsequently sends messages containing the event details to the background script and the DevTools panel.

Code Snippets


// Flag to indicate if the target element is an anchor tag with an href attribute
let a = false;
// Store the href attribute value of the anchor tag
let href = '';

/**
 * Get the relative XPath of an element
 * @param {HTMLElement} element - The target element
 * @returns {string} - The relative XPath of the element
 */
function getRelativeXPath(element) {
  // If the element is null or undefined, return an empty string
  if (!element) { return ''; }

  // Get the element's tag name and convert it to lowercase to follow xPath conventions
  const tagName = element.tagName.toLowerCase();

  // If the element is an anchor tag, check if it has an href attribute and make assignments to global variables
  if (tagName === 'a') {
    if (element.hasAttribute('href')) {
      a = true;
      href = element.getAttribute('href');
    }
  }
  // Array of unique attributes to use for the XPath
  const uniqueAttributes = ['data-cy', 'data-test', 'data-testid', 'id'];
  let attr = '';

  // Iterate through the uniqueAttributes array and use the first one found on the element
  uniqueAttributes.some((attribute) => {
    if (element.hasAttribute(attribute)) {
      attr = `[@${attribute}="${element.getAttribute(attribute)}"]`;
      return true;
    }
    return false;
  });

  // If a unique attribute is found, return the xPath using that attribute
  if (attr) { return `//${tagName}${attr}`; }

  // Calculate position of the element among siblings with the same tag
  let position = 1;
  let sibling = element.previousElementSibling;
  while (sibling) {
    if (sibling.tagName.toLowerCase() === tagName) { position++; }
    sibling = sibling.previousElementSibling;
  }

  // Generate parent element's xPath and append current element's tag name and position
  const parentXPath = getRelativeXPath(element.parentElement);
  return `${parentXPath}/${tagName}[${position}]`;
}