Easily generate unique and optimized CSS or XPath selectors for any DOM element.
This library provides tools to generate unique CSS and XPath selectors for DOM elements. It's perfect for automated testing, web scraping, or any situation where you need a reliable way to reference specific elements in the DOM.
- Unique Selectors: Generates selectors that uniquely identify elements.
- CSS and XPath Support: Choose between CSS and XPath selector generation.
- Customizable Strategies: Tailor the generation process with various strategies.
- Optimized Selectors: Produces the shortest possible selector without sacrificing uniqueness.
- Debug Logging: Optional debug logs to trace the generation process.
- Module Compatibility: Works seamlessly with both CommonJS (
require
) and ES6 modules (import
).
Install via npm:
npm install selektra
The library is compatible with both CommonJS and ES6 module systems.
import { CSSSelectorGenerator, XPathSelectorGenerator } from 'selektra';
const { CSSSelectorGenerator, XPathSelectorGenerator } = require('selektra');
import { CSSSelectorGenerator } from 'selektra';
// Initialize the generator with optional configurations
const generator = new CSSSelectorGenerator({
debug: true, // Enable debug logs
idName: (id) => !id.startsWith('skip-'), // Custom ID filtering
});
// Select your target element
const element = document.querySelector('.my-element');
// Generate a unique CSS selector
const selector = generator.generate(element);
console.log('Generated CSS selector:', selector);
import { XPathSelectorGenerator } from 'selektra';
// Initialize the generator with optional configurations
const generator = new XPathSelectorGenerator({
debug: true, // Enable debug logs
tagName: (tag) => tag !== 'div', // Custom tag filtering
});
// Select your target element
const element = document.querySelector('.my-element');
// Generate a unique XPath selector
const xpath = generator.generate(element);
console.log('Generated XPath selector:', xpath);
You can also use this library with Puppeteer to generate selectors for elements on a webpage. Here's an example:
const puppeteer = require('puppeteer');
const { CSSSelectorGenerator } = require('selektra');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
// Use Puppeteer's page.evaluate to interact with the DOM
const selector = await page.evaluate(() => {
const generator = new CSSSelectorGenerator({
debug: true, // Enable debug logs
});
// Select your target element
const element = document.querySelector('h1');
// Generate a unique CSS selector
return generator.generate(element);
});
console.log('Generated CSS selector:', selector);
await browser.close();
})();
Both CSSSelectorGenerator
and XPathSelectorGenerator
accept an options object to customize their behavior:
const options = {
root: document.body,
idName: (id) => true,
className: (className) => true,
tagName: (tagName) => true,
attr: (name, value) => false,
seedMinLength: 1,
optimizedMinLength: 2,
maxCandidates: 1000,
maxCombinations: 10000,
timeoutMs: undefined,
maxDepth: undefined,
debug: false,
};
root
: The root element or document for generating selectors (default isdocument.body
).idName
: Function to determine if an element's ID should be used.className
: Function to determine if an element's class should be used.tagName
: Function to determine if an element's tag name should be used.attr
: Function to determine if an attribute should be used.seedMinLength
: Minimum length of the initial selector path (default is1
).optimizedMinLength
: Minimum length after optimization (default is2
).maxCandidates
: Maximum candidates to consider (default is1000
).maxCombinations
: Maximum combinations to test during optimization (default is10000
).timeoutMs
: Timeout in milliseconds to prevent long executions.maxDepth
: Maximum depth for DOM traversal.debug
: Enable debug logging (default isfalse
).
const generator = new CSSSelectorGenerator({
idName: (id) => !id.startsWith('temp-'),
className: (className) => !['ignore', 'skip'].includes(className),
});
const generator = new XPathSelectorGenerator({
attr: (name, value) => name === 'data-test-id',
});
const generator = new CSSSelectorGenerator({
maxDepth: 3, // Limit traversal to 3 levels up the DOM
});
const generator = new XPathSelectorGenerator({
timeoutMs: 2000, // Timeout after 2 seconds
});
Enable debug mode to see detailed logs of the selector generation process:
const generator = new CSSSelectorGenerator({
debug: true,
});
This will output logs like:
[CSSSelectorGenerator] Starting selector generation for element: span
[CSSSelectorGenerator] Applying strategies at depth 0 for element: span
[CSSSelectorGenerator] Strategy found part: .active
[CSSSelectorGenerator] Unique path found: .active
[CSSSelectorGenerator] Initial path: [".active"]
[CSSSelectorGenerator] Path length is less than or equal to optimizedMinLength; skipping optimization.
[CSSSelectorGenerator] Generated selector: .active
The generator traverses the DOM from the target element up to the root, applying various strategies to build a unique selector:
-
Strategies Applied:
- ID Strategy: Uses element IDs.
- Class Strategy: Uses element classes.
- Attribute Strategy: Uses element attributes.
- Tag Strategy: Uses tag names.
- Nth-Child Strategy: Uses the element's position among siblings.
-
Path Building:
- Builds an initial path by collecting selector parts from each strategy.
-
Optimization:
- Attempts to shorten the selector while maintaining uniqueness.
-
Uniqueness Check:
- Ensures the selector uniquely identifies the target element.
The library is designed to work seamlessly with different module systems:
- ES6 Modules: Use
import
statements as shown in the examples. - CommonJS: Use
require
statements if your environment does not support ES6 modules.
const { CSSSelectorGenerator } = require('selektra');
const generator = new CSSSelectorGenerator();
const element = document.querySelector('.my-element');
const selector = generator.generate(element);
console.log('Generated CSS selector:', selector);
Contributions are welcome! Here's how you can help:
- Report Bugs: If you find a bug, please open an issue.
- Feature Requests: Have an idea? Let's discuss it.
- Pull Requests: Feel free to submit PRs with improvements.
This project is licensed under the MIT License.
If you have any questions or need assistance, feel free to open an issue on the GitHub repository.