Advanced Selectors Tests
Relevant source files
The following files were used as context for generating this wiki page:
Advanced Selectors Tests refer to the comprehensive suite of test cases designed to validate the extended selector engine in cheerio-select. This engine acts as a wrapper around css-select, providing support for jQuery-style positional pseudo-selectors that are not part of the standard CSS specification. The tests ensure that complex queries—combining standard CSS selectors with positional filters like :first, :last, and :eq()—produce accurate results across various DOM structures.
The testing infrastructure leverages several modules, including htmlparser2 for DOM generation and domutils for content verification. The primary goal is to maintain parity with expectations from libraries like jQuery and Sizzle while ensuring performance and stability when handling advanced combinations, such as nested filters or selectors with custom execution contexts.
Sources: README.md:1-12, test/advanced-selectors.spec.ts:1-7
Core Positional Selectors
The advanced selector engine specifically targets a set of "positional" pseudo-selectors. These allow developers to select elements based on their index within a matched set rather than just their position in the DOM tree.
Supported Positional Pseudos
The following table summarizes the positional selectors validated in the test suites:
| Selector | Description | Example Usage |
|---|---|---|
:first | Selects the first element in the matched set. | div:first |
:last | Selects the last element in the matched set. | div:last |
:eq(index) | Selects the element at the specified zero-based index. | div:eq(1) |
:nth(index) | Equivalent to :eq(index). | div:nth(2) |
:gt(index) | Selects all elements with an index greater than the specified value. | p:gt(0) |
:lt(index) | Selects all elements with an index less than the specified value. | ul li:lt(3) |
:even | Selects even-indexed elements (0, 2, 4...). | tr:even |
:odd | Selects odd-indexed elements (1, 3, 5...). | tr:odd |
Sources: README.md:8-19, src/index.ts:77-110, test/advanced-selectors.spec.ts:10-40
Architecture and Execution Flow
Advanced selectors are processed by splitting the input string into "plain" CSS selectors and "filtered" selectors containing positional pseudos. This allows the engine to use the highly optimized css-select for standard parts while applying custom logic for positional filtering.
Selector Processing Logic
The following diagram illustrates how the select function handles a query containing advanced selectors:
The system distinguishes between standard traversals (like adjacent siblings +) and positional filters to ensure that results maintain correct document order and uniqueness.
Sources: src/index.ts:251-280, src/index.ts:293-340, src/helpers.ts:18-35
Complex Test Scenarios
Advanced tests cover scenarios where positional selectors are used in the middle of a query or in conjunction with complex traversals.
Nested and Middle-Query Positional
Tests verify that a positional selector like :eq() can appear in the middle of a chain, affecting subsequent traversals. For example, div:eq(0) span first finds the first div and then finds all span descendants within that specific div.
[
"Simple selector with :eq() in the middle",
"<div><span>foo</span></div><div><span>bar</span></div>",
"div:eq(0) span",
"foo",
],
[
"Complex selector",
"<div><span><h1>foo</h1></span><span><h1>bar</h1></span></div>",
"div:first span:eq(1) h1",
"bar",
]
Sources: test/advanced-selectors.spec.ts:36-46, src/index.spec.ts:114-122
Context and Root Overrides
The select function accepts an options object that can define a specific context or root. Advanced tests ensure that positional calculations are relative to these provided boundaries.
- Context: Restricts the search to a specific subset of nodes.
- Root: Defines the top-level document structure for absolute traversals or
:rootselectors.
Sources: test/advanced-selectors.spec.ts:55-72, src/index.ts:46-51
Integration with Sizzle Test Suite
cheerio-select includes a port of the Sizzle/jQuery test suite to ensure high compatibility. This involves loading a large HTML fixture (sizzle.html) and executing thousands of assertions against it.
Testing Utilities
| Function | File | Description |
|---|---|---|
q(...ids) | sizzle-testinit.ts | Retrieves an array of elements by their ID attributes for expectation checking. |
t(selector, ids, context) | sizzle-testinit.ts | The primary assertion helper; it runs a selector and compares resulting IDs against expected IDs. |
loadDocument() | sizzle-testinit.ts | Initializes the global Sizzle test document from the filesystem. |
Sources: test/tools/sizzle-testinit.ts:47-81, test/sizzle.spec.ts:20-50
Performance and Edge Case Handling
The test suite includes specific checks for potential engine failures:
- Broken Selectors: Ensuring that invalid syntax like
p:nth-child(-)or unclosed attribute bracketsinput[name=foo[baz]]throws appropriate errors. - Large DOMs: Testing deep recursion depth to prevent stack overflow errors when selecting through hundreds of nested
divelements. - Namespace Handling: Verifying that the engine correctly handles XML-style namespaced elements (e.g.,
soap\:Envelope) whenxmlModeis enabled.
Sources: test/sizzle.spec.ts:145-180, test/sizzle.spec.ts:115-135, test/sizzle.spec.ts:100-110
Advanced Selectors Tests ensure that cheerio-select remains a robust drop-in replacement for jQuery-style selection logic in Node.js environments, providing a bridge between strict CSS standards and developer-friendly positional queries.