@cerios/playwright-table 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/polling.ts","../src/cell-content-type.ts","../src/table-utils.ts","../src/table-body.ts","../src/table-header.ts","../src/playwright-table.ts"],"sourcesContent":["export * from \"./playwright-table\";\nexport * from \"./row\";\nexport { HeaderRowOptions } from \"./table-header\";\nexport { CellContentType } from \"./cell-content-type\";\nexport { PollingOptions } from \"./polling\";\n","export type PollingOptions = {\n\ttimeout?: number;\n\tinterval?: number;\n};\n\nexport async function pollTable(fn: () => Promise<void>, options?: PollingOptions): Promise<void> {\n\tif (!options) {\n\t\toptions = {};\n\t}\n\n\tconst timeout = options.timeout ?? 30_000;\n\tconst interval = options.interval ?? 100;\n\tconst startTime = Date.now();\n\tlet lastError: Error | undefined;\n\n\twhile (Date.now() - startTime < timeout) {\n\t\ttry {\n\t\t\tawait fn();\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tlastError = err as Error;\n\n\t\t\tawait new Promise(resolve => setTimeout(resolve, interval));\n\t\t}\n\t}\n\n\tthrow lastError || new Error(\"Playwright Tables: Polling timeout reached\");\n}\n","/**\n * Enum representing the possible types of content that can be extracted from a table cell.\n *\n * - `TextContent`: The raw text content of the cell, including hidden elements and extra whitespace.\n * - `InnerText`: The rendered text content of the cell, as seen by the user, with whitespace collapsed and hidden elements excluded.\n */\nexport enum CellContentType {\n\tTextContent = \"textContent\",\n\tInnerText = \"innerText\",\n}\n","import { Locator } from \"@playwright/test\";\n\nimport { CellContentType } from \"./cell-content-type\";\n\n/**\n * Utility class for extracting table cell content and attributes.\n * Contains only static methods - cannot be instantiated.\n */\nexport class TableUtils {\n\tprivate constructor() {\n\t\t// Prevent instantiation - this class only has static methods\n\t}\n\t/**\n\t * Extracts text content from a table cell.\n\t * @param cell - The Playwright locator for the cell.\n\t * @param cellContentType - The type of content to extract (InnerText or TextContent).\n\t * @returns The trimmed text content of the cell, or empty string if no content.\n\t * @throws Error if the cell locator doesn't exist in the DOM.\n\t */\n\tstatic async getCellContent(cell: Locator, cellContentType: CellContentType): Promise<string> {\n\t\ttry {\n\t\t\tconst count = await cell.count();\n\t\t\tif (count === 0) {\n\t\t\t\tthrow new Error(\"Cell locator does not exist in the DOM\");\n\t\t\t}\n\n\t\t\tconst content = cellContentType === CellContentType.InnerText ? await cell.innerText() : await cell.textContent();\n\t\t\treturn content?.trim() || \"\";\n\t\t} catch (error) {\n\t\t\tconst locatorDescription = this.getLocatorDescription(cell);\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to get cell content.\\n` +\n\t\t\t\t\t`Locator: ${locatorDescription}\\n` +\n\t\t\t\t\t`Content type: ${cellContentType}\\n` +\n\t\t\t\t\t`Error: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Parses rowspan and colspan attributes from a table cell.\n\t * Fetches both attributes in parallel for optimal performance.\n\t * @param cell - The Playwright locator for the cell.\n\t * @returns Object containing rowspan and colspan values (defaults to 1 if not present).\n\t * @throws Error if attributes contain invalid values (non-numeric or less than 1).\n\t */\n\tstatic async parseSpanAttributes(cell: Locator): Promise<{ rowspan: number; colspan: number }> {\n\t\ttry {\n\t\t\tconst [rowspanAttr, colspanAttr] = await Promise.all([\n\t\t\t\tcell.getAttribute(\"rowspan\"),\n\t\t\t\tcell.getAttribute(\"colspan\"),\n\t\t\t]);\n\n\t\t\tconst rowspan = parseInt(rowspanAttr || \"1\", 10);\n\t\t\tconst colspan = parseInt(colspanAttr || \"1\", 10);\n\n\t\t\tif (isNaN(rowspan) || rowspan < 1) {\n\t\t\t\tthrow new Error(`Invalid rowspan attribute: \"${rowspanAttr}\". Expected positive integer.`);\n\t\t\t}\n\t\t\tif (isNaN(colspan) || colspan < 1) {\n\t\t\t\tthrow new Error(`Invalid colspan attribute: \"${colspanAttr}\". Expected positive integer.`);\n\t\t\t}\n\n\t\t\treturn { rowspan, colspan };\n\t\t} catch (error) {\n\t\t\tconst locatorDescription = this.getLocatorDescription(cell);\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to parse span attributes.\\n` +\n\t\t\t\t\t`Locator: ${locatorDescription}\\n` +\n\t\t\t\t\t`Error: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Extracts a human-readable locator description from a Playwright Locator.\n\t * This captures Playwright's internal selector chain for better error messages.\n\t * @param locator - The Playwright locator to describe.\n\t * @returns A string representation of the locator's selector chain.\n\t */\n\tprivate static getLocatorDescription(locator: Locator): string {\n\t\tconst locatorString = locator.toString();\n\t\t// Example: \"Locator@#root >> table >> tbody >> tr >> td\"\n\t\treturn locatorString;\n\t}\n}\n","import { Locator } from \"@playwright/test\";\n\nimport { CellContentType } from \"./cell-content-type\";\nimport { BodyRow, Cell } from \"./row\";\nimport { TableUtils } from \"./table-utils\";\n\n/**\n * Utility class for extracting and processing table body rows.\n * Handles rowspan and colspan attributes to properly structure table data.\n * Contains only static methods - cannot be instantiated.\n */\nexport class TableBody {\n\tprivate constructor() {\n\t\t// Prevent instantiation - this class only has static methods\n\t}\n\t/**\n\t * Extracts body rows from a table with proper handling of rowspan and colspan.\n\t *\n\t * @param rowLocator - The Playwright locator for body rows.\n\t * @param columnsSelector - CSS selector for locating columns within rows (e.g., \"td\").\n\t * @param bodyRowsOptions - Optional configuration for cell content extraction.\n\t * @param bodyRowsOptions.cellContentType - The type of content to extract (InnerText or TextContent).\n\t * @returns Promise resolving to an array of processed body rows.\n\t * @throws Error if columnsSelector is empty or if row processing fails.\n\t *\n\t * @example\n\t * const rows = await TableBody.getRows(\n\t * page.locator('tbody tr'),\n\t * 'td',\n\t * { cellContentType: CellContentType.TextContent }\n\t * );\n\t */\n\tstatic async getRows(\n\t\trowLocator: Locator,\n\t\tcolumnsSelector: string,\n\t\tbodyRowsOptions?: {\n\t\t\tcellContentType?: CellContentType;\n\t\t}\n\t): Promise<BodyRow[]> {\n\t\tif (!columnsSelector || columnsSelector.trim() === \"\") {\n\t\t\tthrow new Error(\"columnsSelector cannot be empty\");\n\t\t}\n\n\t\tconst locatorDescription = rowLocator.toString();\n\t\tconst rows: BodyRow[] = [];\n\t\tconst rowsCount = await rowLocator.count();\n\n\t\tif (rowsCount === 0) {\n\t\t\treturn rows;\n\t\t}\n\n\t\tconst spannedCells: Record<number, Cell[]> = {};\n\n\t\tfor (let rowIndex = 0; rowIndex < rowsCount; rowIndex++) {\n\t\t\ttry {\n\t\t\t\tconst row = rowLocator.nth(rowIndex);\n\t\t\t\tconst columns = await this.extractColumns(\n\t\t\t\t\trow,\n\t\t\t\t\tcolumnsSelector,\n\t\t\t\t\trowIndex,\n\t\t\t\t\tspannedCells,\n\t\t\t\t\tbodyRowsOptions?.cellContentType\n\t\t\t\t);\n\t\t\t\trows.push(columns as BodyRow);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to process body row at index ${rowIndex}.\\n` +\n\t\t\t\t\t\t`Body row locator: ${locatorDescription}\\n` +\n\t\t\t\t\t\t`Columns selector: \"${columnsSelector}\"\\n` +\n\t\t\t\t\t\t`Error: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn rows;\n\t}\n\n\tprivate static async extractColumns(\n\t\trow: Locator,\n\t\tcolumnsSelector: string,\n\t\trowIndex: number,\n\t\tspannedCells: Record<number, Cell[]>,\n\t\tcellContentType?: CellContentType\n\t): Promise<Cell[]> {\n\t\tconst columns: Cell[] = [];\n\t\tconst columnLocators = row.locator(columnsSelector);\n\t\tconst columnCount = await columnLocators.count();\n\n\t\tif (columnCount === 0) {\n\t\t\t// Still apply any spanned cells even if this row has no DOM cells\n\t\t\tthis.applySpannedCells(spannedCells, rowIndex, columns);\n\t\t\treturn columns;\n\t\t}\n\n\t\tconst cellDataPromises = [];\n\t\tfor (let colIndex = 0; colIndex < columnCount; colIndex++) {\n\t\t\tcellDataPromises.push(this.fetchCellData(columnLocators.nth(colIndex), cellContentType));\n\t\t}\n\t\tconst cellDataArray = await Promise.all(cellDataPromises);\n\n\t\t// First, determine which column positions are occupied by rowspans from above\n\t\tconst spannedPositions = new Set<number>();\n\t\tif (spannedCells[rowIndex]) {\n\t\t\tspannedCells[rowIndex].forEach((_, colIndex) => {\n\t\t\t\tif (spannedCells[rowIndex][colIndex] !== undefined) {\n\t\t\t\t\tspannedPositions.add(colIndex);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// Process cells, accounting for spanned positions\n\t\tlet actualColIndex = 0;\n\t\tfor (let domCellIndex = 0; domCellIndex < columnCount; domCellIndex++) {\n\t\t\t// Skip columns that are occupied by rowspans from above\n\t\t\twhile (spannedPositions.has(actualColIndex)) {\n\t\t\t\tactualColIndex++;\n\t\t\t}\n\n\t\t\tconst cellData = cellDataArray[domCellIndex];\n\t\t\tthis.processCellData(cellData, actualColIndex, columns, rowIndex, spannedCells);\n\n\t\t\t// Move past this cell and any colspan it creates\n\t\t\tactualColIndex += cellData.colspan;\n\t\t}\n\n\t\tthis.applySpannedCells(spannedCells, rowIndex, columns);\n\n\t\treturn columns;\n\t}\n\n\t/**\n\t * Fetches cell content and span attributes in parallel.\n\t * This method performs DOM operations that can be parallelized across multiple cells.\n\t */\n\tprivate static async fetchCellData(\n\t\tcolumn: Locator,\n\t\tcellContentType: CellContentType = CellContentType.InnerText\n\t): Promise<{ content: string; rowspan: number; colspan: number }> {\n\t\tconst [content, spanAttributes] = await Promise.all([\n\t\t\tTableUtils.getCellContent(column, cellContentType),\n\t\t\tTableUtils.parseSpanAttributes(column),\n\t\t]);\n\n\t\treturn {\n\t\t\tcontent,\n\t\t\trowspan: spanAttributes.rowspan,\n\t\t\tcolspan: spanAttributes.colspan,\n\t\t};\n\t}\n\n\t/**\n\t * Processes pre-fetched cell data and applies it to the columns array.\n\t * This method is purely computational and doesn't perform any DOM operations.\n\t */\n\tprivate static processCellData(\n\t\tcellData: { content: string; rowspan: number; colspan: number },\n\t\tcolIndex: number,\n\t\tcolumns: Cell[],\n\t\trowIndex: number,\n\t\tspannedCells: Record<number, Cell[]>\n\t): void {\n\t\tconst { content, rowspan, colspan } = cellData;\n\n\t\tif (colIndex < 0) {\n\t\t\tthrow new Error(`Invalid column index: ${colIndex}. Must be non-negative.`);\n\t\t}\n\t\tif (rowIndex < 0) {\n\t\t\tthrow new Error(`Invalid row index: ${rowIndex}. Must be non-negative.`);\n\t\t}\n\n\t\tfor (let span = 0; span < colspan; span++) {\n\t\t\tcolumns[colIndex + span] = content;\n\t\t}\n\n\t\tif (rowspan > 1) {\n\t\t\tthis.storeSpannedCells(rowIndex, colIndex, rowspan, colspan, content, spannedCells);\n\t\t}\n\t}\n\n\tprivate static storeSpannedCells(\n\t\trowIndex: number,\n\t\tcolIndex: number,\n\t\trowspan: number,\n\t\tcolspan: number,\n\t\tcontent: Cell,\n\t\tspannedCells: Record<number, Cell[]>\n\t): void {\n\t\tfor (let rowSpan = 1; rowSpan < rowspan; rowSpan++) {\n\t\t\tif (!spannedCells[rowIndex + rowSpan]) {\n\t\t\t\tspannedCells[rowIndex + rowSpan] = [];\n\t\t\t}\n\t\t\t// Store the content for each column covered by colspan\n\t\t\tfor (let colSpan = 0; colSpan < colspan; colSpan++) {\n\t\t\t\tspannedCells[rowIndex + rowSpan][colIndex + colSpan] = content;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static applySpannedCells(spannedCells: Record<number, Cell[]>, rowIndex: number, columns: Cell[]): void {\n\t\tif (spannedCells[rowIndex]) {\n\t\t\tspannedCells[rowIndex].forEach((spannedContent, colIndex) => {\n\t\t\t\tif (spannedContent !== undefined) {\n\t\t\t\t\tcolumns[colIndex] = spannedContent;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n}\n","import { Locator } from \"@playwright/test\";\n\nimport { CellContentType } from \"./cell-content-type\";\nimport { HeaderRow } from \"./row\";\nimport { TableUtils } from \"./table-utils\";\n\n/**\n * Options for configuring a table header row.\n *\n * @property cellContentType - The type of content allowed in the header cell.\n * @property emptyCellReplacement - If true, replaces empty header cells with a default value.\n * @property duplicateSuffix - If true, appends a suffix to duplicate header values.\n * @property colspan - Configuration for column spanning in the header row.\n * @property colspan.enabled - If true, enables column spanning.\n * @property colspan.suffix - If true, appends a suffix to spanned columns.\n */\nexport type HeaderRowOptions = {\n\tcellContentType?: CellContentType;\n\temptyCellReplacement?: boolean;\n\tduplicateSuffix?: boolean;\n\tcolspan?: { enabled?: boolean; suffix?: boolean };\n\tnormalizeWhitespace?: boolean;\n\tstripIconGlyphs?: boolean;\n};\n\n/**\n * Utility class for extracting and processing table header rows.\n * Handles complex scenarios including colspan, rowspan, empty cells, and duplicate header names.\n * Contains only static methods - cannot be instantiated.\n */\nexport class TableHeader {\n\tprivate constructor() {\n\t\t// Prevent instantiation - this class only has static methods\n\t}\n\tprivate static readonly EMPTY_CELL_PLACEHOLDER = \"{{Empty}}\";\n\tprivate static readonly COLSPAN_SUFFIX_PREFIX = \"__C\";\n\tprivate static readonly DUPLICATE_SUFFIX_PREFIX = \"__D\";\n\tprivate static readonly COLSPAN_PATTERN = /__C\\d+/;\n\tprivate static readonly ICON_GLYPH_PATTERN = /[\\uE000-\\uF8FF\\u{F0000}-\\u{FFFFD}\\u{100000}-\\u{10FFFD}]/gu;\n\n\t/**\n\t * Extracts header rows from a table with optional processing for colspan, rowspan, and duplicates.\n\t *\n\t * @param headerRowLocator - The Playwright locator for header rows.\n\t * @param columnsSelector - CSS selector for locating header columns (e.g., \"th\").\n\t * @param headerRowOptions - Optional configuration for header processing.\n\t * @returns Promise resolving to an array of processed header rows.\n\t * @throws Error if columnsSelector is empty or if no header rows are found.\n\t *\n\t * @example\n\t * const headers = await TableHeader.getRows(\n\t * page.locator('thead tr'),\n\t * 'th',\n\t * { duplicateSuffix: true, colspan: { enabled: true } }\n\t * );\n\t */\n\tstatic async getRows(\n\t\theaderRowLocator: Locator,\n\t\tcolumnsSelector: string,\n\t\theaderRowOptions?: HeaderRowOptions\n\t): Promise<HeaderRow[]> {\n\t\tif (!columnsSelector || columnsSelector.trim() === \"\") {\n\t\t\tthrow new Error(\"columnsSelector cannot be empty\");\n\t\t}\n\n\t\tconst locatorDescription = headerRowLocator.toString();\n\t\tconst options = this.getDefaultOptions(headerRowOptions);\n\t\tconst rows = await headerRowLocator.all();\n\n\t\tconst headerRows: HeaderRow[] = [];\n\n\t\tif (rows.length === 0) {\n\t\t\treturn headerRows;\n\t\t}\n\n\t\tconst rowSpans: Map<number, string> = new Map();\n\n\t\tfor (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {\n\t\t\ttry {\n\t\t\t\tconst headerRow = await this.processRow(rows[rowIndex], columnsSelector, rowSpans, options);\n\t\t\t\theaderRows.push(headerRow);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to process header row at index ${rowIndex}.\\n` +\n\t\t\t\t\t\t`Header row locator: ${locatorDescription}\\n` +\n\t\t\t\t\t\t`Columns selector: \"${columnsSelector}\"\\n` +\n\t\t\t\t\t\t`Error: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis.applyColspanOptions(headerRows, options);\n\t\tthis.applyDuplicateSuffix(headerRows, options);\n\n\t\treturn headerRows;\n\t}\n\n\tprivate static getDefaultOptions(options?: HeaderRowOptions): Required<HeaderRowOptions> {\n\t\treturn {\n\t\t\tcellContentType: options?.cellContentType ?? CellContentType.InnerText,\n\t\t\temptyCellReplacement: options?.emptyCellReplacement ?? false,\n\t\t\tduplicateSuffix: options?.duplicateSuffix ?? false,\n\t\t\tnormalizeWhitespace: options?.normalizeWhitespace ?? false,\n\t\t\tstripIconGlyphs: options?.stripIconGlyphs ?? false,\n\t\t\tcolspan: {\n\t\t\t\tenabled: options?.colspan?.enabled ?? false,\n\t\t\t\tsuffix: options?.colspan?.suffix ?? false,\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate static async processRow(\n\t\trow: Locator,\n\t\tcolumnsSelector: string,\n\t\trowSpans: Map<number, string>,\n\t\toptions: Required<HeaderRowOptions>\n\t): Promise<HeaderRow> {\n\t\tconst headerRow: HeaderRow = [];\n\t\tconst cells = await row.locator(columnsSelector).all();\n\n\t\tif (cells.length === 0) {\n\t\t\treturn headerRow;\n\t\t}\n\n\t\tconst cellDataArray = await Promise.all(\n\t\t\tcells.map(cell =>\n\t\t\t\tthis.fetchHeaderCellData(cell, options.cellContentType, options.normalizeWhitespace, options.stripIconGlyphs)\n\t\t\t)\n\t\t);\n\n\t\tlet columnIndex = 0;\n\t\tfor (let i = 0; i < cellDataArray.length; i++) {\n\t\t\tcolumnIndex = this.processHeaderCellData(\n\t\t\t\tcellDataArray[i],\n\t\t\t\theaderRow,\n\t\t\t\trowSpans,\n\t\t\t\tcolumnIndex,\n\t\t\t\toptions.emptyCellReplacement\n\t\t\t);\n\t\t}\n\n\t\tthis.addRemainingRowSpans(headerRow, rowSpans, columnIndex);\n\t\treturn headerRow;\n\t}\n\n\t/**\n\t * Fetches header cell content and span attributes in parallel.\n\t * This method performs DOM operations that can be parallelized across multiple cells.\n\t */\n\tprivate static async fetchHeaderCellData(\n\t\tcell: Locator,\n\t\tcellContentType: CellContentType,\n\t\tnormalizeWhitespace: boolean,\n\t\tstripIconGlyphs: boolean\n\t): Promise<{ text: string; rowspan: number; colspan: number }> {\n\t\tconst [text, spanAttributes] = await Promise.all([\n\t\t\tTableUtils.getCellContent(cell, cellContentType),\n\t\t\tTableUtils.parseSpanAttributes(cell),\n\t\t]);\n\n\t\treturn {\n\t\t\ttext: this.sanitizeHeaderText(text, normalizeWhitespace, stripIconGlyphs),\n\t\t\trowspan: spanAttributes.rowspan,\n\t\t\tcolspan: spanAttributes.colspan,\n\t\t};\n\t}\n\n\tprivate static sanitizeHeaderText(text: string, normalizeWhitespace: boolean, stripIconGlyphs: boolean): string {\n\t\tlet result = text;\n\n\t\tif (stripIconGlyphs) {\n\t\t\tresult = result.replace(this.ICON_GLYPH_PATTERN, \"\");\n\t\t}\n\n\t\tif (normalizeWhitespace) {\n\t\t\tresult = result.replace(/\\s+/g, \" \");\n\t\t}\n\n\t\treturn result.trim();\n\t}\n\n\t/**\n\t * Processes pre-fetched header cell data and applies it to the header row.\n\t * This method is purely computational and doesn't perform any DOM operations.\n\t */\n\tprivate static processHeaderCellData(\n\t\tcellData: { text: string; rowspan: number; colspan: number },\n\t\theaderRow: HeaderRow,\n\t\trowSpans: Map<number, string>,\n\t\tcolumnIndex: number,\n\t\temptyCellReplacement: boolean\n\t): number {\n\t\twhile (rowSpans.has(columnIndex)) {\n\t\t\theaderRow.push(rowSpans.get(columnIndex)!);\n\t\t\trowSpans.delete(columnIndex);\n\t\t\tcolumnIndex++;\n\t\t}\n\n\t\tlet text = cellData.text;\n\t\tif (!text && emptyCellReplacement) {\n\t\t\ttext = this.EMPTY_CELL_PLACEHOLDER;\n\t\t}\n\n\t\tconst { colspan, rowspan } = cellData;\n\n\t\theaderRow.push(text);\n\t\tthis.handleColspan(headerRow, text, colspan);\n\t\tthis.handleRowspan(rowSpans, text, columnIndex, colspan, rowspan);\n\n\t\treturn columnIndex + colspan;\n\t}\n\n\tprivate static handleColspan(headerRow: HeaderRow, text: string, colspan: number): void {\n\t\tfor (let i = 1; i < colspan; i++) {\n\t\t\theaderRow.push(`${text}${this.COLSPAN_SUFFIX_PREFIX}${i}`);\n\t\t}\n\t}\n\n\tprivate static handleRowspan(\n\t\trowSpans: Map<number, string>,\n\t\ttext: string,\n\t\tcolumnIndex: number,\n\t\tcolspan: number,\n\t\trowspan: number\n\t): void {\n\t\tif (rowspan > 1) {\n\t\t\tfor (let i = 0; i < colspan; i++) {\n\t\t\t\trowSpans.set(columnIndex + i, text);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static addRemainingRowSpans(headerRow: HeaderRow, rowSpans: Map<number, string>, columnIndex: number): void {\n\t\twhile (rowSpans.has(columnIndex)) {\n\t\t\theaderRow.push(rowSpans.get(columnIndex)!);\n\t\t\trowSpans.delete(columnIndex);\n\t\t\tcolumnIndex++;\n\t\t}\n\t}\n\n\tprivate static applyColspanOptions(headerRows: HeaderRow[], options: Required<HeaderRowOptions>): void {\n\t\tif (!options.colspan.enabled) {\n\t\t\tthis.removeColspanCells(headerRows);\n\t\t}\n\n\t\tif (!options.colspan.suffix) {\n\t\t\tthis.removeColspanSuffix(headerRows);\n\t\t}\n\t}\n\n\tprivate static removeColspanCells(headerRows: HeaderRow[]): void {\n\t\tfor (let i = 0; i < headerRows.length; i++) {\n\t\t\theaderRows[i] = headerRows[i].filter(cell => !this.COLSPAN_PATTERN.test(cell));\n\t\t}\n\t}\n\n\tprivate static removeColspanSuffix(headerRows: HeaderRow[]): void {\n\t\tfor (const headerRow of headerRows) {\n\t\t\tfor (let i = 0; i < headerRow.length; i++) {\n\t\t\t\tif (this.COLSPAN_PATTERN.test(headerRow[i])) {\n\t\t\t\t\theaderRow[i] = headerRow[i].replace(this.COLSPAN_PATTERN, \"\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static applyDuplicateSuffix(headerRows: HeaderRow[], options: Required<HeaderRowOptions>): void {\n\t\tif (!options.duplicateSuffix) return;\n\n\t\tfor (const headerRow of headerRows) {\n\t\t\tconst headerCountMap: Map<string, number> = new Map();\n\t\t\tfor (let i = 0; i < headerRow.length; i++) {\n\t\t\t\tconst header = headerRow[i];\n\t\t\t\tconst currentCount = headerCountMap.get(header);\n\t\t\t\tif (currentCount !== undefined) {\n\t\t\t\t\theaderRow[i] = `${header}${this.DUPLICATE_SUFFIX_PREFIX}${currentCount}`;\n\t\t\t\t\theaderCountMap.set(header, currentCount + 1);\n\t\t\t\t} else {\n\t\t\t\t\theaderCountMap.set(header, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","import { Locator } from \"@playwright/test\";\n\nimport { CellContentType } from \"./cell-content-type\";\nimport { pollTable, PollingOptions } from \"./polling\";\nimport { BodyRow, Cell, HeaderRow } from \"./row\";\nimport { TableBody } from \"./table-body\";\nimport { HeaderRowOptions, TableHeader } from \"./table-header\";\n\n/**\n * Options for loading table data, headers, and rows.\n *\n * @example\n * // Use custom cell content type for body rows and header options\n * const options: TableOptions = {\n * bodyRowOptions: { cellContentType: CellContentType.TextContent },\n * headerRowOptions: {\n * colspan: { enabled: true, suffix: true },\n * duplicateSuffix: true,\n * emptyCellReplacement: false,\n * },\n * };\n * await table.getBodyRows(options);\n */\nexport type TableOptions = {\n\t/** See {@link HeaderRowOptions} for available options. */\n\theaderRowOptions?: HeaderRowOptions;\n\t/** Options for parsing body rows. */\n\tbodyRowOptions?: { cellContentType?: CellContentType };\n\t/** @deprecated Use `bodyRowOptions.cellContentType` instead. */\n\tcellContentType?: CellContentType;\n};\n\n/**\n * Represents a table in Playwright, providing methods to interact with its headers, rows, and cells.\n */\nexport class PlaywrightTable {\n\tprivate _bodyRowLocator: Locator;\n\tprivate _bodyRowColumnSelector: string;\n\tprivate _headerRowLocator: Locator;\n\tprivate _headerColumnSelector: string;\n\n\t/**\n\t * Creates an instance of the table handler with customizable selectors for headers and rows.\n\t *\n\t * @param _tableLocator - The Playwright `Locator` pointing to the root table element.\n\t * @param _options - Optional configuration for customizing header and row selectors.\n\t * @param _options.header - Options for header row and columns.\n\t * @param _options.header.setMainHeaderRow - (Optional) Index of the main header row if multiple header rows exist.\n\t * @param _options.header.rowSelector - (Optional) CSS selector for locating header rows. Defaults to `\"thead>tr\"`.\n\t * @param _options.header.columnSelector - (Optional) CSS selector for locating header columns. Defaults to `\"th\"`.\n\t * @param _options.row - Options for body rows and columns.\n\t * @param _options.row.rowSelector - (Optional) CSS selector for locating body rows. Defaults to `\"tbody>tr\"`.\n\t * @param _options.row.columnSelector - (Optional) CSS selector for locating body columns. Defaults to `\"td\"`.\n\t *\n\t * @example\n\t * const table = new PlaywrightTable(\n\t * page.locator('table.my-table'),\n\t * {\n\t * header: {\n\t * rowSelector: 'thead tr.header',\n\t * columnSelector: 'th.header-cell'\n\t * },\n\t * row: {\n\t * rowSelector: 'tbody tr.data-row',\n\t * columnSelector: 'td.data-cell'\n\t * }\n\t * }\n\t * );\n\t */\n\tconstructor(\n\t\tprivate readonly _tableLocator: Locator,\n\t\tprivate readonly _options?: {\n\t\t\theader?: {\n\t\t\t\tsetMainHeaderRow?: number;\n\t\t\t\trowSelector?: string;\n\t\t\t\tcolumnSelector?: string;\n\t\t\t};\n\t\t\trow?: {\n\t\t\t\trowSelector?: string;\n\t\t\t\tcolumnSelector?: string;\n\t\t\t};\n\t\t}\n\t) {\n\t\tconst headerRowSelector = this._options?.header?.rowSelector;\n\t\tconst bodyRowSelector = this._options?.row?.rowSelector;\n\t\tif (headerRowSelector && bodyRowSelector && headerRowSelector === bodyRowSelector) {\n\t\t\tconsole.warn(\n\t\t\t\t`PlaywrightTable: header.rowSelector and row.rowSelector are identical (\"${headerRowSelector}\"). ` +\n\t\t\t\t\t`This can cause header rows to be included in body rows. Consider scoping selectors to separate row groups.`\n\t\t\t);\n\t\t}\n\n\t\tthis._headerRowLocator = this._tableLocator.locator(this._options?.header?.rowSelector ?? \"thead>tr\");\n\t\tthis._headerColumnSelector = this._options?.header?.columnSelector ?? \"th\";\n\t\tthis._bodyRowLocator = this._tableLocator.locator(this._options?.row?.rowSelector ?? \"tbody>tr\");\n\t\tthis._bodyRowColumnSelector = this._options?.row?.columnSelector ?? \"td\";\n\t}\n\n\t/**\n\t * Retrieves all header rows of the table.\n\t * @param options - Optional parameters for header row parsing configuration.\n\t * @returns A promise that resolves to an array of header rows.\n\t * @throws Error if no header rows found after table loads.\n\t *\n\t * @example\n\t * // Get headers with colspan enabled\n\t * const headers = await table.getHeaderRows({\n\t * colspan: { enabled: true, suffix: true },\n\t * duplicateSuffix: true\n\t * });\n\t *\n\t * @see {@link getMainHeaderRow} for getting only the main header row\n\t * @see {@link HeaderRowOptions} for all available configuration options\n\t */\n\tasync getHeaderRows(options?: HeaderRowOptions): Promise<HeaderRow[]> {\n\t\tconst table = await this.getTable({\n\t\t\theaderRowOptions: options,\n\t\t});\n\t\treturn table.headerRows;\n\t}\n\n\t/**\n\t * Retrieves the main header row of the table.\n\t * By default, uses the last header row if multiple exist. Can be customized via constructor.\n\t * @param options - Optional parameters for header row parsing configuration.\n\t * @returns A promise that resolves to the main header row.\n\t * @throws Error if no header rows available.\n\t * @throws Error if setMainHeaderRow index is out of bounds (negative or >= header row count).\n\t *\n\t * @example\n\t * // Get main header with custom index set in constructor\n\t * const table = new PlaywrightTable(page.locator('table'), {\n\t * header: { setMainHeaderRow: 0 } // Use first row as main header\n\t * });\n\t * const mainHeader = await table.getMainHeaderRow();\n\t *\n\t * @see {@link getHeaderRows} for getting all header rows\n\t */\n\tasync getMainHeaderRow(options?: HeaderRowOptions): Promise<HeaderRow> {\n\t\tconst table = await this.getTable({\n\t\t\theaderRowOptions: options,\n\t\t});\n\t\treturn this.mainHeaderRow(table.headerRows);\n\t}\n\n\t/**\n\t * Retrieves all body rows of the table.\n\t * @param options - Optional table or body-row configuration.\n\t * @param options.cellContentType - Legacy shortcut for body row content extraction. See {@link CellContentType}.\n\t * @param options.bodyRowOptions - Body row parsing options.\n\t * @param options.headerRowOptions - Header parsing options used when resolving row/colspan layouts.\n\t * @returns A promise that resolves to an array of body rows.\n\t * @throws Error if no body rows found after table loads.\n\t *\n\t * @example\n\t * // Get body rows with TextContent (includes hidden elements)\n\t * const rows = await table.getBodyRows({\n\t * cellContentType: CellContentType.TextContent\n\t * });\n\t *\n\t * @example\n\t * // Get body rows with default InnerText\n\t * const rows = await table.getBodyRows();\n\t *\n\t * @example\n\t * // Use full table options (for example to sanitize noisy treegrid headers)\n\t * const rows = await table.getBodyRows({\n\t * bodyRowOptions: { cellContentType: CellContentType.InnerText },\n\t * headerRowOptions: { normalizeWhitespace: true, stripIconGlyphs: true }\n\t * });\n\t */\n\tasync getBodyRows(options?: TableOptions): Promise<BodyRow[]> {\n\t\tconst tableOptions = this.normalizeGetBodyRowsOptions(options);\n\n\t\tconst table = await this.getTable({\n\t\t\tbodyRowOptions: tableOptions.bodyRowOptions,\n\t\t\theaderRowOptions: this.resolveHeaderRowOptions(tableOptions.headerRowOptions, {\n\t\t\t\tforceColspanEnabled: true,\n\t\t\t}),\n\t\t});\n\t\treturn table.bodyRows;\n\t}\n\n\t/**\n\t * Retrieves a specific cell locator in the body of the table by row and column index.\n\t * @param rowNumber - The row number (0-based index).\n\t * @param headerPosition - The column/header position (0-based index).\n\t * @returns A Playwright Locator for the specified cell.\n\t *\n\t * @example\n\t * // Get cell at row 1, column 2\n\t * const cellLocator = table.getBodyCellLocator(1, 2);\n\t * await expect(cellLocator).toHaveText('Expected Text');\n\t *\n\t * @example\n\t * // Get first cell in first row\n\t * const firstCell = table.getBodyCellLocator(0, 0);\n\t * await firstCell.click();\n\t *\n\t * @see {@link getBodyCellLocatorByRowConditions} for finding cells by content matching\n\t * @see {@link getAllBodyCellLocatorsByHeaderIndex} for getting all cells in a column\n\t * @see {@link getAllBodyCellLocatorsByHeaderName} for getting all cells under a header\n\t */\n\tgetBodyCellLocator(rowNumber: number, headerPosition: number): Locator {\n\t\treturn this._bodyRowLocator.nth(rowNumber).locator(this._bodyRowColumnSelector).nth(headerPosition);\n\t}\n\n\t/**\n\t * Retrieves a cell locator in the body of the table based on row conditions and a target header.\n\t * Finds the first row where all conditions match, then returns the cell in the target column.\n\t * @param conditions - An object where keys are header names and values are expected cell contents, or a single [header, value] tuple.\n\t * @param targetHeader - The header name of the column containing the cell to retrieve.\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to a Playwright Locator for the matching cell.\n\t * @throws Error if no row matches all specified conditions.\n\t * @throws Error if any condition header or target header is not found in the table.\n\t *\n\t * @example\n\t * // Find cell with multiple conditions\n\t * const emailLocator = await table.getBodyCellLocatorByRowConditions(\n\t * { \"First name\": \"John\", \"Status\": \"Active\" },\n\t * \"Email\"\n\t * );\n\t * await expect(emailLocator).toContainText('@example.com');\n\t *\n\t * @example\n\t * // Find cell with single condition using tuple syntax\n\t * const actionCell = await table.getBodyCellLocatorByRowConditions(\n\t * [\"Username\", \"john.doe\"],\n\t * \"Actions\"\n\t * );\n\t * await actionCell.locator('button').click();\n\t *\n\t * @example\n\t * // Find cell with single condition using object syntax\n\t * const statusCell = await table.getBodyCellLocatorByRowConditions(\n\t * { \"Username\": \"john.doe\" },\n\t * \"Status\"\n\t * );\n\t *\n\t * @see {@link getBodyCellLocator} for getting cells by direct index\n\t * @see {@link getAllBodyCellLocatorsByHeaderName} for getting all cells in a column\n\t */\n\tasync getBodyCellLocatorByRowConditions(\n\t\tconditions: Record<string, string> | [string, string],\n\t\ttargetHeader: string,\n\t\toptions?: TableOptions\n\t): Promise<Locator> {\n\t\tconst table = await this.getTable(options);\n\t\tconst mainHeader = this.mainHeaderRow(table.headerRows);\n\n\t\tconst targetHeaderIndex = this.getHeaderIndex(targetHeader, mainHeader);\n\n\t\t// Normalize conditions to object format\n\t\tconst conditionsObj = Array.isArray(conditions) ? { [conditions[0]]: conditions[1] } : conditions;\n\n\t\tfor (let rowIndex = 0; rowIndex < table.bodyRows.length; rowIndex++) {\n\t\t\tconst row = table.bodyRows[rowIndex];\n\t\t\tlet matches = true;\n\n\t\t\tfor (const [header, value] of Object.entries(conditionsObj)) {\n\t\t\t\tconst headerIndex = this.getHeaderIndex(header, mainHeader);\n\t\t\t\tconst cellValue = row[headerIndex] ?? \"\";\n\t\t\t\tif (cellValue !== value) {\n\t\t\t\t\tmatches = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matches) {\n\t\t\t\treturn this.getBodyCellLocator(rowIndex, targetHeaderIndex);\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`No row found matching conditions: ${JSON.stringify(conditionsObj)}\\n` +\n\t\t\t\t`Target header: \"${targetHeader}\"\\n` +\n\t\t\t\t`Searched ${table.bodyRows.length} rows\\n` +\n\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}`\n\t\t);\n\t}\n\n\t/**\n\t * Retrieves all cell locators in the body of the table for a specific header name.\n\t * Returns locators for every cell in the column identified by the header.\n\t * @param header - The header name identifying the column.\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to an array of Playwright Locators for all cells in the column.\n\t * @throws Error if the header is not found in the table.\n\t *\n\t * @example\n\t * // Get all cells in the \"Status\" column\n\t * const statusCells = await table.getAllBodyCellLocatorsByHeaderName(\"Status\");\n\t * for (const cell of statusCells) {\n\t * await expect(cell).toHaveText(/Active|Inactive/);\n\t * }\n\t *\n\t * @example\n\t * // Get text from all cells in \"Name\" column\n\t * const nameCells = await table.getAllBodyCellLocatorsByHeaderName(\"Name\");\n\t * const names = await Promise.all(nameCells.map(cell => cell.textContent()));\n\t *\n\t * @see {@link getAllBodyCellLocatorsByHeaderIndex} for getting cells by column index\n\t * @see {@link getBodyCellLocatorByRowConditions} for finding specific cells by content\n\t */\n\tasync getAllBodyCellLocatorsByHeaderName(header: string, options?: TableOptions): Promise<Locator[]> {\n\t\tconst table = await this.getTable(options);\n\t\tconst headers = this.mainHeaderRow(table.headerRows);\n\t\tconst headerIndex = this.getHeaderIndex(header, headers);\n\t\tconst locators: Locator[] = [];\n\t\tfor (let rowIndex = 0; rowIndex < table.bodyRows.length; rowIndex++) {\n\t\t\tconst cellLocator = this.getBodyCellLocator(rowIndex, headerIndex);\n\t\t\tlocators.push(cellLocator);\n\t\t}\n\t\treturn locators;\n\t}\n\n\t/**\n\t * Retrieves all cell locators in the body of the table for a specific header index.\n\t * Returns locators for every cell in the column at the specified position.\n\t * @param headerIndex - The header/column index (0-based).\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to an array of Playwright Locators for all cells in the column.\n\t * @throws Error if the header index is out of bounds (negative or >= column count).\n\t *\n\t * @example\n\t * // Get all cells in the third column (index 2)\n\t * const thirdColumnCells = await table.getAllBodyCellLocatorsByHeaderIndex(2);\n\t * for (const cell of thirdColumnCells) {\n\t * await expect(cell).toBeVisible();\n\t * }\n\t *\n\t * @example\n\t * // Get all cells in first column\n\t * const firstColumnCells = await table.getAllBodyCellLocatorsByHeaderIndex(0);\n\t * const values = await Promise.all(firstColumnCells.map(c => c.textContent()));\n\t *\n\t * @see {@link getAllBodyCellLocatorsByHeaderName} for getting cells by header name\n\t * @see {@link getBodyCellLocator} for getting a specific cell by row and column index\n\t */\n\tasync getAllBodyCellLocatorsByHeaderIndex(headerIndex: number, options?: TableOptions): Promise<Locator[]> {\n\t\tconst table = await this.getTable(options);\n\t\tconst columnCount = this.mainHeaderRow(table.headerRows).length;\n\t\tif (headerIndex < 0 || headerIndex >= columnCount) {\n\t\t\tthrow new Error(\n\t\t\t\t`Header index ${headerIndex} out of bounds. Table has ${columnCount} columns.\\n` +\n\t\t\t\t\t`Header row locator: ${this._headerRowLocator.toString()}`\n\t\t\t);\n\t\t}\n\t\tconst locators: Locator[] = [];\n\t\tfor (let rowIndex = 0; rowIndex < table.bodyRows.length; rowIndex++) {\n\t\t\tconst cellLocator = this.getBodyCellLocator(rowIndex, headerIndex);\n\t\t\tlocators.push(cellLocator);\n\t\t}\n\t\treturn locators;\n\t}\n\n\t/**\n\t * Converts the table data into a JSON array where each object represents a row.\n\t * Keys are header names, values are cell contents.\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to an array of objects representing table rows.\n\t * @throws Error if no header rows or body rows found.\n\t *\n\t * @example\n\t * // Convert table to JSON with default options\n\t * const data = await table.getJson();\n\t * // Result: [{\"Name\": \"John\", \"Age\": \"30\"}, {\"Name\": \"Jane\", \"Age\": \"25\"}]\n\t *\n\t * @example\n\t * // Convert with colspan enabled and duplicate suffix\n\t * const data = await table.getJson({\n\t * headerRowOptions: {\n\t * colspan: { enabled: true, suffix: true },\n\t * duplicateSuffix: true,\n\t * emptyCellReplacement: true\n\t * }\n\t * });\n\t */\n\tasync getJson(options?: TableOptions): Promise<Record<string, string>[]> {\n\t\tconst table = await this.getTable({\n\t\t\tbodyRowOptions: options?.bodyRowOptions,\n\t\t\theaderRowOptions: this.resolveHeaderRowOptions(options?.headerRowOptions, {\n\t\t\t\tdefaultColspanEnabled: true,\n\t\t\t\tdefaultColspanSuffix: true,\n\t\t\t\tdefaultDuplicateSuffix: true,\n\t\t\t\tdefaultEmptyCellReplacement: true,\n\t\t\t\tdefaultNormalizeWhitespace: false,\n\t\t\t\tdefaultStripIconGlyphs: false,\n\t\t\t}),\n\t\t});\n\n\t\tconst headers = this.mainHeaderRow(table.headerRows);\n\t\treturn table.bodyRows.map(row => {\n\t\t\tconst rowObj: Record<string, Cell> = {};\n\t\t\theaders.forEach((header, index) => {\n\t\t\t\trowObj[header] = row[index] || \"\";\n\t\t\t});\n\t\t\treturn rowObj;\n\t\t});\n\t}\n\n\t/**\n\t * Waits for the table body to be empty (no body rows).\n\t * @param options - Polling options (timeout, interval, retries).\n\t * @returns A promise that resolves when table body is empty.\n\t * @throws Error if table is not empty within timeout period.\n\t *\n\t * @example\n\t * // Wait for table to clear after delete operation\n\t * await table.waitForEmpty({ timeout: 5000 });\n\t *\n\t * @see {@link waitForNonEmpty} for waiting until table has data\n\t *\n\t * @remarks\n\t * **Alternative:** Consider using Playwright's `expect.poll` for more flexibility:\n\t * ```ts\n\t * await expect.poll(async () => (await table.getBodyRows()).length).toBe(0);\n\t * ```\n\t */\n\tasync waitForEmpty(options?: PollingOptions): Promise<void> {\n\t\tawait pollTable(async () => {\n\t\t\tconst rows = await this._bodyRowLocator.all();\n\t\t\tif (rows.length > 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Expected table to be empty, but found ${rows.length} body rows.\\n` +\n\t\t\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}`\n\t\t\t\t);\n\t\t\t}\n\t\t}, options);\n\t}\n\n\t/**\n\t * Waits for the table body to be non-empty (at least one body row with content).\n\t * A row is considered valid if it has at least one cell containing text.\n\t * @param options - Polling options (timeout, interval, retries).\n\t * @returns A promise that resolves when table has at least one body row with content.\n\t * @throws Error if table remains empty or has no rows with content within timeout period.\n\t *\n\t * @example\n\t * // Wait for table to populate after search\n\t * await table.waitForNonEmpty({ timeout: 5000 });\n\t *\n\t * @see {@link waitForEmpty} for waiting until table is cleared\n\t *\n\t * @remarks\n\t * **Alternative:** Consider using Playwright's `expect.poll` for more flexibility:\n\t * ```ts\n\t * await expect.poll(async () => (await table.getBodyRows()).length).toBeGreaterThan(0);\n\t * ```\n\t */\n\tasync waitForNonEmpty(options?: PollingOptions): Promise<void> {\n\t\tawait pollTable(async () => {\n\t\t\tconst rows = await this._bodyRowLocator.all();\n\t\t\tif (rows.length === 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Expected table to be non-empty, but found 0 body rows.\\n` +\n\t\t\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check if at least one row has content in at least one cell\n\t\t\tlet hasRowWithContent = false;\n\t\t\tfor (const row of rows) {\n\t\t\t\tconst cells = await row.locator(this._bodyRowColumnSelector).all();\n\t\t\t\tfor (const cell of cells) {\n\t\t\t\t\tconst content = await cell.innerText();\n\t\t\t\t\tif (content.trim().length > 0) {\n\t\t\t\t\t\thasRowWithContent = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (hasRowWithContent) break;\n\t\t\t}\n\n\t\t\tif (!hasRowWithContent) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Expected table to have at least one row with content, but all ${rows.length} rows are empty.\\n` +\n\t\t\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}`\n\t\t\t\t);\n\t\t\t}\n\t\t}, options);\n\t}\n\n\t/**\n\t * Waits for the table body to have exactly N rows.\n\t * @param count - The exact number of body rows expected.\n\t * @param options - Polling options (timeout, interval, retries).\n\t * @returns A promise that resolves when the table has exactly the specified number of rows.\n\t * @throws Error if row count doesn't match within timeout period.\n\t *\n\t * @example\n\t * // Wait for exactly 10 rows after pagination\n\t * await table.waitForExactRowCount(10, { timeout: 5000 });\n\t *\n\t * @example\n\t * // Verify table has exactly 0 rows (alternative to waitForEmpty)\n\t * await table.waitForExactRowCount(0);\n\t *\n\t * @see {@link getRowCount} for getting current row counts\n\t *\n\t * @remarks\n\t * **Alternative:** Consider using Playwright's `expect.poll` for more flexibility:\n\t * ```ts\n\t * await expect.poll(async () => (await table.getBodyRows()).length).toBe(10);\n\t * ```\n\t */\n\tasync waitForExactRowCount(count: number, options?: PollingOptions): Promise<void> {\n\t\tif (count < 0 || !Number.isInteger(count)) {\n\t\t\tthrow new Error(`Row count must be a non-negative integer, got: ${count}`);\n\t\t}\n\n\t\tawait pollTable(async () => {\n\t\t\tconst rows = await this._bodyRowLocator.all();\n\t\t\tif (rows.length !== count) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Expected exactly ${count} rows, but found ${rows.length}.\\n` +\n\t\t\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}`\n\t\t\t\t);\n\t\t\t}\n\t\t}, options);\n\t}\n\n\t/**\n\t * Gets the count of header and body rows in the table.\n\t * Lightweight method that doesn't fetch cell data, only counts rows.\n\t * @returns A promise that resolves to an object with header and body row counts.\n\t *\n\t * @example\n\t * // Get current row counts\n\t * const counts = await table.getRowCount();\n\t * console.log(`Headers: ${counts.header}, Body: ${counts.body}`);\n\t *\n\t * @example\n\t * // Assert specific row count\n\t * const { body } = await table.getRowCount();\n\t * expect(body).toBe(10);\n\t */\n\tasync getRowCount(): Promise<{ header: number; body: number }> {\n\t\tconst [headerRows, bodyRows] = await Promise.all([this._headerRowLocator.all(), this._bodyRowLocator.all()]);\n\t\treturn {\n\t\t\theader: headerRows.length,\n\t\t\tbody: bodyRows.length,\n\t\t};\n\t}\n\n\t/**\n\t * Gets all distinct (unique) values from a specific column.\n\t * Returns a sorted array of unique string values, excluding empty values.\n\t * @param headerName - The header name of the column to extract distinct values from.\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to a sorted array of distinct values.\n\t * @throws Error if the specified header is not found in the table.\n\t *\n\t * @example\n\t * // Get all unique status values\n\t * const statuses = await table.getDistinctColumnValues(\"Status\");\n\t * // Result: [\"Active\", \"Inactive\", \"Pending\"]\n\t *\n\t * @example\n\t * // Get distinct countries for filtering\n\t * const countries = await table.getDistinctColumnValues(\"Country\");\n\t * console.log(`Available countries: ${countries.join(\", \")}`);\n\t *\n\t * @example\n\t * // Verify expected values exist\n\t * const roles = await table.getDistinctColumnValues(\"Role\");\n\t * expect(roles).toContain(\"Admin\");\n\t * expect(roles).toHaveLength(3);\n\t *\n\t * @see {@link getAllBodyCellLocatorsByHeaderName} for getting all cell locators in a column\n\t * @see {@link getJson} for getting full table data\n\t */\n\tasync getDistinctColumnValues(headerName: string, options?: TableOptions): Promise<string[]> {\n\t\tconst table = await this.getTable(options);\n\t\tconst mainHeader = this.mainHeaderRow(table.headerRows);\n\t\tconst headerIndex = this.getHeaderIndex(headerName, mainHeader);\n\n\t\tconst values = new Set<string>();\n\t\tfor (const row of table.bodyRows) {\n\t\t\tconst value = String(row[headerIndex] ?? \"\").trim();\n\t\t\tif (value) values.add(value);\n\t\t}\n\n\t\treturn Array.from(values).sort();\n\t}\n\n\t/**\n\t * Finds the index of the first body row matching the specified conditions.\n\t * Returns -1 if no matching row is found.\n\t * @param conditions - Record of header names and expected cell values to match.\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to the 0-based index of the first matching row, or -1 if not found.\n\t * @throws Error if specified headers don't exist in the table.\n\t *\n\t * @example\n\t * // Find index of row where Status is \"Active\"\n\t * const index = await table.findRowIndex({ Status: \"Active\" });\n\t * if (index >= 0) {\n\t * console.log(`Found at row ${index}`);\n\t * }\n\t *\n\t * @example\n\t * // Find row and interact with it\n\t * const rowIndex = await table.findRowIndex({ Username: \"john.doe\" });\n\t * if (rowIndex >= 0) {\n\t * const cell = table.getBodyCellLocator(rowIndex, 0);\n\t * await cell.click();\n\t * }\n\t *\n\t * @see {@link getBodyCellLocatorByRowConditions} for getting cell locators from matching rows\n\t * @see {@link waitForRowByConditions} for waiting until matching row appears\n\t */\n\tasync findRowIndex(conditions: Record<string, string>, options?: TableOptions): Promise<number> {\n\t\tconst table = await this.getTable({\n\t\t\theaderRowOptions: this.resolveHeaderRowOptions(options?.headerRowOptions, {\n\t\t\t\tforceColspanEnabled: true,\n\t\t\t}),\n\t\t\tbodyRowOptions: options?.bodyRowOptions,\n\t\t});\n\t\tconst mainHeader = this.mainHeaderRow(table.headerRows);\n\n\t\t// Validate all condition headers exist and get their indices\n\t\tconst headerIndices = new Map<string, number>();\n\t\tfor (const header of Object.keys(conditions)) {\n\t\t\theaderIndices.set(header, this.getHeaderIndex(header, mainHeader));\n\t\t}\n\n\t\t// Find first matching row\n\t\tfor (let rowIndex = 0; rowIndex < table.bodyRows.length; rowIndex++) {\n\t\t\tconst row = table.bodyRows[rowIndex];\n\t\t\tlet rowMatches = true;\n\n\t\t\tfor (const [header, expectedValue] of Object.entries(conditions)) {\n\t\t\t\tconst headerIndex = headerIndices.get(header)!;\n\t\t\t\tconst cellValue = String(row[headerIndex] ?? \"\");\n\t\t\t\tif (cellValue !== expectedValue) {\n\t\t\t\t\trowMatches = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (rowMatches) {\n\t\t\t\treturn rowIndex;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\tprivate async getTable(options?: TableOptions): Promise<{ headerRows: HeaderRow[]; bodyRows: BodyRow[] }> {\n\t\tconst [headerRows, bodyRows] = await Promise.all([\n\t\t\tTableHeader.getRows(this._headerRowLocator, this._headerColumnSelector, options?.headerRowOptions),\n\t\t\tTableBody.getRows(this._bodyRowLocator, this._bodyRowColumnSelector, options?.bodyRowOptions),\n\t\t]);\n\n\t\tif (headerRows.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`No header rows found, is table loaded completely?\\n` +\n\t\t\t\t\t`Header row locator: ${this._headerRowLocator.toString()}\\n` +\n\t\t\t\t\t`Table locator: ${this._tableLocator.toString()}`\n\t\t\t);\n\t\t}\n\t\tif (bodyRows.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`No body rows found, is table loaded completely?\\n` +\n\t\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}\\n` +\n\t\t\t\t\t`Table locator: ${this._tableLocator.toString()}`\n\t\t\t);\n\t\t}\n\n\t\treturn { headerRows, bodyRows };\n\t}\n\n\tprivate normalizeGetBodyRowsOptions(options?: TableOptions): TableOptions {\n\t\tif (!options) {\n\t\t\treturn {};\n\t\t}\n\n\t\tif (options.bodyRowOptions || options.headerRowOptions) {\n\t\t\treturn options;\n\t\t}\n\n\t\tif (options.cellContentType !== undefined) {\n\t\t\treturn {\n\t\t\t\tbodyRowOptions: {\n\t\t\t\t\tcellContentType: options.cellContentType,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn options;\n\t}\n\n\tprivate resolveHeaderRowOptions(\n\t\theaderOptions: HeaderRowOptions | undefined,\n\t\tdefaults?: {\n\t\t\tdefaultColspanEnabled?: boolean;\n\t\t\tdefaultColspanSuffix?: boolean;\n\t\t\tdefaultDuplicateSuffix?: boolean;\n\t\t\tdefaultEmptyCellReplacement?: boolean;\n\t\t\tdefaultNormalizeWhitespace?: boolean;\n\t\t\tdefaultStripIconGlyphs?: boolean;\n\t\t\tforceColspanEnabled?: boolean;\n\t\t}\n\t): HeaderRowOptions {\n\t\tconst resolvedColspanEnabled = defaults?.forceColspanEnabled\n\t\t\t? true\n\t\t\t: (headerOptions?.colspan?.enabled ?? defaults?.defaultColspanEnabled);\n\n\t\treturn {\n\t\t\tcellContentType: headerOptions?.cellContentType,\n\t\t\temptyCellReplacement: headerOptions?.emptyCellReplacement ?? defaults?.defaultEmptyCellReplacement,\n\t\t\tduplicateSuffix: headerOptions?.duplicateSuffix ?? defaults?.defaultDuplicateSuffix,\n\t\t\tnormalizeWhitespace: headerOptions?.normalizeWhitespace ?? defaults?.defaultNormalizeWhitespace,\n\t\t\tstripIconGlyphs: headerOptions?.stripIconGlyphs ?? defaults?.defaultStripIconGlyphs,\n\t\t\tcolspan: {\n\t\t\t\tenabled: resolvedColspanEnabled,\n\t\t\t\tsuffix: headerOptions?.colspan?.suffix ?? defaults?.defaultColspanSuffix,\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate mainHeaderRow(headers: HeaderRow[]): HeaderRow {\n\t\tif (headers.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`No header rows available. Ensure table has been loaded.\\n` +\n\t\t\t\t\t`Header row locator: ${this._headerRowLocator.toString()}`\n\t\t\t);\n\t\t}\n\n\t\tconst headerIndex = this._options?.header?.setMainHeaderRow ?? headers.length - 1;\n\t\tif (headerIndex < 0 || headerIndex >= headers.length) {\n\t\t\tthrow new Error(\n\t\t\t\t`Header row index ${headerIndex} out of bounds. Table has ${headers.length} header rows.\\n` +\n\t\t\t\t\t`Header row locator: ${this._headerRowLocator.toString()}`\n\t\t\t);\n\t\t}\n\n\t\treturn headers[headerIndex];\n\t}\n\n\t/**\n\t * Gets the index of a header in the main header row, throwing an error if not found.\n\t * @param header - The header name to find.\n\t * @param mainHeader - The main header row to search in.\n\t * @returns The 0-based index of the header.\n\t * @throws Error if the header is not found.\n\t */\n\tprivate getHeaderIndex(header: string, mainHeader: HeaderRow): number {\n\t\tconst index = mainHeader.indexOf(header);\n\t\tif (index === -1) {\n\t\t\tthrow new Error(\n\t\t\t\t`Header \"${header}\" not found.\\n` +\n\t\t\t\t\t`Available headers: [${mainHeader.join(\", \")}]\\n` +\n\t\t\t\t\t`Header row locator: ${this._headerRowLocator.toString()}`\n\t\t\t);\n\t\t}\n\t\treturn index;\n\t}\n}\n"],"mappings":"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","names":["CellContentType"]}
1
+ {"version":3,"file":"index.js","names":["defaultSelectors","base","baseExpect","test"],"sources":["../src/polling.ts","../src/cell-content-type.ts","../src/table-utils.ts","../src/table-body.ts","../src/table-header.ts","../src/playwright-table.ts","../src/table-selector-engine.ts","../src/cell-matcher-serializer.ts","../src/table-diagnostics.ts","../src/table-format.ts","../src/table-navigation.ts","../src/table-locator.ts","../src/table-presets.ts","../src/table-selectors.ts","../src/table-matchers.ts"],"sourcesContent":["export type PollingOptions = {\n\ttimeout?: number;\n\tinterval?: number;\n};\n\nexport async function pollTable(fn: () => Promise<void>, options: PollingOptions = {}): Promise<void> {\n\tconst timeout = checkTimeout(options.timeout ?? 30_000);\n\tconst interval = options.interval ?? 100;\n\tconst deadline = Date.now() + timeout;\n\tlet lastError = new Error(\"Playwright Tables: Polling timeout reached\");\n\n\t// Always tries at least once, and once more at the deadline, so a timeout of 0 still checks the table.\n\tfor (;;) {\n\t\ttry {\n\t\t\tawait fn();\n\t\t\treturn;\n\t\t} catch (err) {\n\t\t\tlastError = err as Error;\n\t\t}\n\t\tconst left = deadline - Date.now();\n\t\tif (left <= 0) break;\n\t\tawait new Promise(resolve => setTimeout(resolve, Math.min(interval, left)));\n\t}\n\n\tthrow lastError;\n}\n\n/** Minimum time a single read may take, so the last read before the deadline can still succeed. */\nexport const MIN_READ_TIMEOUT = 100;\n\n/** Waits between reads, like Playwright's `expect.poll`. The last one repeats. */\nconst POLL_INTERVALS = [100, 250, 500, 1_000];\n\n/**\n * `timeout`, checked: a non-negative number (`Infinity` allowed).\n * @throws Error for a negative timeout or `NaN`, which would otherwise poll forever.\n * @internal\n */\nexport function checkTimeout(timeout: number, name = \"timeout\"): number {\n\tif (typeof timeout !== \"number\" || !(timeout >= 0)) {\n\t\tthrow new Error(`${name} must be a non-negative number of milliseconds, got: ${timeout}`);\n\t}\n\treturn timeout;\n}\n\n/** The outcome of {@link pollUntil}. */\nexport type PollOutcome<T> = {\n\t/** The value of the last read that succeeded, or the initial value if none did. */\n\tvalue: T;\n\t/** Whether any read succeeded. */\n\tread: boolean;\n\t/** The error of the last read, or `undefined` if it succeeded. */\n\terror: unknown;\n};\n\n/**\n * Reads until `done` accepts a value, or until `deadline`. A read gets the time left until the deadline\n * (at least {@link MIN_READ_TIMEOUT}) as its timeout. A read that throws keeps the last value, so a\n * table that is not attached yet is retried. An error thrown by `done` is not a read error: it is thrown.\n *\n * @internal\n */\nexport async function pollUntil<T>(\n\tread: (timeout: number) => Promise<T>,\n\tdone: (value: T) => boolean,\n\tinitial: T,\n\tdeadline: number\n): Promise<PollOutcome<T>> {\n\tif (Number.isNaN(deadline)) throw new Error(\"pollUntil: the deadline is not a number\");\n\tconst outcome: PollOutcome<T> = { value: initial, read: false, error: undefined };\n\tfor (let attempt = 0; ; attempt++) {\n\t\tlet value: T | undefined;\n\t\tlet succeeded = false;\n\t\ttry {\n\t\t\tvalue = await read(Math.max(MIN_READ_TIMEOUT, deadline - Date.now()));\n\t\t\tsucceeded = true;\n\t\t} catch (error) {\n\t\t\t// The last read gets little time and can time out; keep the error that says what is wrong.\n\t\t\tif (!isTimeout(error) || outcome.error === undefined || isTimeout(outcome.error)) outcome.error = error;\n\t\t}\n\t\tif (succeeded) {\n\t\t\toutcome.value = value as T;\n\t\t\toutcome.read = true;\n\t\t\toutcome.error = undefined;\n\t\t\tif (done(outcome.value)) return outcome;\n\t\t}\n\t\tconst left = deadline - Date.now();\n\t\tif (left <= 0) return outcome;\n\t\tconst interval = POLL_INTERVALS[Math.min(attempt, POLL_INTERVALS.length - 1)] ?? MIN_READ_TIMEOUT;\n\t\tawait new Promise(resolve => setTimeout(resolve, Math.min(interval, left)));\n\t}\n}\n\nfunction isTimeout(error: unknown): boolean {\n\treturn error instanceof Error && error.name === \"TimeoutError\";\n}\n\n/** A `Last error:` line for a failure message, or `\"\"` if there is no error. */\nexport function describeLastError(error: unknown): string {\n\tif (error === undefined) return \"\";\n\tconst message = error instanceof Error ? error.message : typeof error === \"string\" ? error : JSON.stringify(error);\n\treturn `Last error: ${message.split(\"\\n\")[0]}\\n`;\n}\n","/**\n * Enum representing the possible types of content that can be extracted from a table cell.\n *\n * - `TextContent`: all text in the DOM of the cell, also the text of hidden elements.\n * - `InnerText`: the text as it is shown, without hidden text and with CSS `text-transform`.\n *\n * `TableLocator` normalizes the text either way (whitespace collapsed, icon glyphs and `ignore`d elements\n * left out), unless you ask for raw text. `PlaywrightTable` trims it.\n */\nexport enum CellContentType {\n\tTextContent = \"textContent\",\n\tInnerText = \"innerText\",\n}\n","import { Locator } from \"@playwright/test\";\n\nimport { CellContentType } from \"./cell-content-type\";\nimport type { SerializedSelector } from \"./table-locator.types\";\n\n/**\n * Utility class for extracting table cell content and attributes.\n * Contains only static methods - cannot be instantiated.\n */\nexport class TableUtils {\n\tprivate constructor() {\n\t\t// Prevent instantiation - this class only has static methods\n\t}\n\t/**\n\t * Extracts text content from a table cell.\n\t * @param cell - The Playwright locator for the cell.\n\t * @param cellContentType - The type of content to extract (InnerText or TextContent).\n\t * @returns The trimmed text content of the cell, or empty string if no content.\n\t * @throws Error if the cell locator doesn't exist in the DOM.\n\t */\n\tstatic async getCellContent(cell: Locator, cellContentType: CellContentType): Promise<string> {\n\t\ttry {\n\t\t\tconst count = await cell.count();\n\t\t\tif (count === 0) {\n\t\t\t\tthrow new Error(\"Cell locator does not exist in the DOM\");\n\t\t\t}\n\n\t\t\tconst content = cellContentType === CellContentType.InnerText ? await cell.innerText() : await cell.textContent();\n\t\t\treturn content?.trim() ?? \"\";\n\t\t} catch (error) {\n\t\t\tconst locatorDescription = this.getLocatorDescription(cell);\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to get cell content.\\n` +\n\t\t\t\t\t`Locator: ${locatorDescription}\\n` +\n\t\t\t\t\t`Content type: ${cellContentType}\\n` +\n\t\t\t\t\t`Error: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Parses rowspan and colspan attributes from a table cell.\n\t * Fetches both attributes in parallel for optimal performance.\n\t * @param cell - The Playwright locator for the cell.\n\t * @returns Object containing rowspan and colspan values (defaults to 1 if not present).\n\t * @throws Error if attributes contain invalid values (non-numeric or less than 1).\n\t */\n\tstatic async parseSpanAttributes(cell: Locator): Promise<{ rowspan: number; colspan: number }> {\n\t\ttry {\n\t\t\tconst [rowspanAttr, colspanAttr] = await Promise.all([\n\t\t\t\tcell.getAttribute(\"rowspan\"),\n\t\t\t\tcell.getAttribute(\"colspan\"),\n\t\t\t]);\n\t\t\treturn this.parseSpans(rowspanAttr, colspanAttr);\n\t\t} catch (error) {\n\t\t\tconst locatorDescription = this.getLocatorDescription(cell);\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to parse span attributes.\\n` +\n\t\t\t\t\t`Locator: ${locatorDescription}\\n` +\n\t\t\t\t\t`Error: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Warns when the header and body row selectors are identical, because header rows would then also\n\t * be read as body rows.\n\t * @param owner - The class name used in the warning.\n\t * @param headerRowSelector - The configured header row selector, if any.\n\t * @param bodyRowSelector - The configured body row selector, if any.\n\t */\n\tstatic warnOnIdenticalRowSelectors(\n\t\towner: string,\n\t\theaderRowSelector: SerializedSelector | undefined,\n\t\tbodyRowSelector: SerializedSelector | undefined\n\t): void {\n\t\tif (headerRowSelector === undefined || headerRowSelector === \"\") return;\n\t\tconst header = JSON.stringify(headerRowSelector);\n\t\tif (header === JSON.stringify(bodyRowSelector)) {\n\t\t\tconsole.warn(\n\t\t\t\t`${owner}: header.rowSelector and row.rowSelector are identical (${header}). ` +\n\t\t\t\t\t`This can cause header rows to be included in body rows. Consider scoping selectors to separate row groups.`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Reads the content and span attributes of every cell in `row` in a single round trip.\n\t * @param row - The Playwright locator for one row.\n\t * @param columnsSelector - Selector for the cells within the row, with the same meaning as in `row.locator()`.\n\t * @param cellContentType - The type of content to extract (InnerText or TextContent).\n\t * @returns One entry per cell, in DOM order, with the trimmed content.\n\t * @throws Error if a span attribute is invalid (non-numeric or less than 1).\n\t */\n\tstatic async readRowCells(\n\t\trow: Locator,\n\t\tcolumnsSelector: string,\n\t\tcellContentType: CellContentType\n\t): Promise<{ content: string; rowspan: number; colspan: number }[]> {\n\t\tconst cells = await row.locator(columnsSelector).evaluateAll(\n\t\t\t(elements, innerText) =>\n\t\t\t\telements.map(el => ({\n\t\t\t\t\ttext: innerText && \"innerText\" in el ? el.innerText : el.textContent,\n\t\t\t\t\trowspan: el.getAttribute(\"rowspan\"),\n\t\t\t\t\tcolspan: el.getAttribute(\"colspan\"),\n\t\t\t\t})),\n\t\t\tcellContentType === CellContentType.InnerText\n\t\t);\n\t\treturn cells.map(cell => ({\n\t\t\tcontent: cell.text.trim(),\n\t\t\t...this.parseSpans(cell.rowspan, cell.colspan),\n\t\t}));\n\t}\n\n\t/** Parses and validates the `rowspan` and `colspan` attributes of a cell. */\n\tprivate static parseSpans(\n\t\trowspanAttr: string | null,\n\t\tcolspanAttr: string | null\n\t): { rowspan: number; colspan: number } {\n\t\tconst parsed = this.parseSpan(rowspanAttr);\n\t\t// `rowspan=\"0\"` spans to the end of the row group; HTML caps a rowspan at 65534.\n\t\tconst rowspan = parsed === 0 ? 65_534 : parsed;\n\t\tconst colspan = this.parseSpan(colspanAttr);\n\n\t\tif (isNaN(rowspan) || rowspan < 1) {\n\t\t\tthrow new Error(`Invalid rowspan attribute: \"${rowspanAttr}\". Expected a non-negative integer.`);\n\t\t}\n\t\tif (isNaN(colspan) || colspan < 1) {\n\t\t\tthrow new Error(`Invalid colspan attribute: \"${colspanAttr}\". Expected positive integer.`);\n\t\t}\n\n\t\treturn { rowspan, colspan };\n\t}\n\n\t/** Parses a `rowspan`/`colspan` attribute value. A missing or empty attribute means 1. */\n\tprivate static parseSpan(attr: string | null): number {\n\t\treturn attr === null || attr === \"\" ? 1 : parseInt(attr, 10);\n\t}\n\n\t/**\n\t * Extracts a human-readable locator description from a Playwright Locator.\n\t * This captures Playwright's internal selector chain for better error messages.\n\t * @param locator - The Playwright locator to describe.\n\t * @returns A string representation of the locator's selector chain.\n\t */\n\tprivate static getLocatorDescription(locator: Locator): string {\n\t\tconst locatorString = locator.toString();\n\t\t// Example: \"Locator@#root >> table >> tbody >> tr >> td\"\n\t\treturn locatorString;\n\t}\n}\n","import { Locator } from \"@playwright/test\";\n\nimport { CellContentType } from \"./cell-content-type\";\nimport { BodyRow, Cell } from \"./row\";\nimport { TableUtils } from \"./table-utils\";\n\n/**\n * The DOM cell behind a grid position: the cell at index `cell` among the cells of body row `row`.\n * A rowspan cell is the source of positions in later rows too.\n */\nexport type CellSource = { row: number; cell: number };\n\n/** Cell contents carried down by rowspans, by row index. Columns without a carried cell are holes. */\ntype SpannedCells = Record<number, ({ content: Cell; source: CellSource } | undefined)[]>;\n\ntype CellData = { content: string; rowspan: number; colspan: number };\n\n/**\n * Utility class for extracting and processing table body rows.\n * Handles rowspan and colspan attributes to properly structure table data.\n * Contains only static methods - cannot be instantiated.\n */\nexport class TableBody {\n\tprivate constructor() {\n\t\t// Prevent instantiation - this class only has static methods\n\t}\n\t/**\n\t * Extracts body rows from a table with proper handling of rowspan and colspan.\n\t *\n\t * @param rowLocator - The Playwright locator for body rows.\n\t * @param columnsSelector - CSS selector for locating columns within rows (e.g., \"td\").\n\t * @param bodyRowsOptions - Optional configuration for cell content extraction.\n\t * @param bodyRowsOptions.cellContentType - The type of content to extract (InnerText or TextContent).\n\t * @returns Promise resolving to an array of processed body rows.\n\t * @throws Error if columnsSelector is empty or if row processing fails.\n\t *\n\t * @example\n\t * const rows = await TableBody.getRows(\n\t * page.locator('tbody tr'),\n\t * 'td',\n\t * { cellContentType: CellContentType.TextContent }\n\t * );\n\t */\n\tstatic async getRows(\n\t\trowLocator: Locator,\n\t\tcolumnsSelector: string,\n\t\tbodyRowsOptions?: {\n\t\t\tcellContentType?: CellContentType;\n\t\t}\n\t): Promise<BodyRow[]> {\n\t\treturn (await this.getRowsWithSources(rowLocator, columnsSelector, bodyRowsOptions)).rows;\n\t}\n\n\t/**\n\t * Like {@link getRows}, and also returns, for every grid position, the DOM cell it comes from.\n\t * `sources[r][c]` is `undefined` for a position without a cell.\n\t *\n\t * @internal\n\t */\n\tstatic async getRowsWithSources(\n\t\trowLocator: Locator,\n\t\tcolumnsSelector: string,\n\t\tbodyRowsOptions?: {\n\t\t\tcellContentType?: CellContentType;\n\t\t}\n\t): Promise<{ rows: BodyRow[]; sources: (CellSource | undefined)[][] }> {\n\t\tif (!columnsSelector || columnsSelector.trim() === \"\") {\n\t\t\tthrow new Error(\"columnsSelector cannot be empty\");\n\t\t}\n\n\t\tconst locatorDescription = rowLocator.toString();\n\t\tconst rowsCount = await rowLocator.count();\n\t\tconst cellContentType = bodyRowsOptions?.cellContentType ?? CellContentType.InnerText;\n\n\t\t// Read every row in parallel, one round trip each; the spans are resolved afterwards, in order.\n\t\tconst cellData = await Promise.all(\n\t\t\tArray.from({ length: rowsCount }, async (_, rowIndex) => {\n\t\t\t\ttry {\n\t\t\t\t\treturn await TableUtils.readRowCells(rowLocator.nth(rowIndex), columnsSelector, cellContentType);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow this.rowError(rowIndex, locatorDescription, columnsSelector, error);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tconst rows: BodyRow[] = [];\n\t\tconst sources: (CellSource | undefined)[][] = [];\n\t\tconst spannedCells: SpannedCells = {};\n\t\tfor (const [rowIndex, cells] of cellData.entries()) {\n\t\t\ttry {\n\t\t\t\tconst row = this.placeCells(cells, rowIndex, spannedCells, rowsCount);\n\t\t\t\trows.push(row.columns);\n\t\t\t\tsources.push(row.sources);\n\t\t\t} catch (error) {\n\t\t\t\tthrow this.rowError(rowIndex, locatorDescription, columnsSelector, error);\n\t\t\t}\n\t\t}\n\n\t\treturn { rows, sources };\n\t}\n\n\tprivate static rowError(\n\t\trowIndex: number,\n\t\tlocatorDescription: string,\n\t\tcolumnsSelector: string,\n\t\terror: unknown\n\t): Error {\n\t\treturn new Error(\n\t\t\t`Failed to process body row at index ${rowIndex}.\\n` +\n\t\t\t\t`Body row locator: ${locatorDescription}\\n` +\n\t\t\t\t`Columns selector: \"${columnsSelector}\"\\n` +\n\t\t\t\t`Error: ${error instanceof Error ? error.message : String(error)}`\n\t\t);\n\t}\n\n\t/** Places the cells of one row on the grid, skipping the positions taken by rowspans from above. */\n\tprivate static placeCells(\n\t\tcells: CellData[],\n\t\trowIndex: number,\n\t\tspannedCells: SpannedCells,\n\t\trowsCount: number\n\t): { columns: Cell[]; sources: (CellSource | undefined)[] } {\n\t\tconst columns: Cell[] = [];\n\t\tconst sources: (CellSource | undefined)[] = [];\n\n\t\t// First, determine which column positions are occupied by rowspans from above\n\t\tconst spannedPositions = new Set<number>();\n\t\tspannedCells[rowIndex]?.forEach((spanned, colIndex) => {\n\t\t\tif (spanned !== undefined) {\n\t\t\t\tspannedPositions.add(colIndex);\n\t\t\t}\n\t\t});\n\n\t\t// Process cells, accounting for spanned positions\n\t\tlet actualColIndex = 0;\n\t\tfor (const [cellIndex, cellData] of cells.entries()) {\n\t\t\t// Skip columns that are occupied by rowspans from above\n\t\t\twhile (spannedPositions.has(actualColIndex)) {\n\t\t\t\tactualColIndex++;\n\t\t\t}\n\n\t\t\tconst source = { row: rowIndex, cell: cellIndex };\n\t\t\tfor (let span = 0; span < cellData.colspan; span++) {\n\t\t\t\tcolumns[actualColIndex + span] = cellData.content;\n\t\t\t\tsources[actualColIndex + span] = source;\n\t\t\t}\n\t\t\tif (cellData.rowspan > 1) {\n\t\t\t\tthis.storeSpannedCells(rowIndex, actualColIndex, cellData, source, spannedCells, rowsCount);\n\t\t\t}\n\n\t\t\t// Move past this cell and any colspan it creates\n\t\t\tactualColIndex += cellData.colspan;\n\t\t}\n\n\t\t// Apply any spanned cells, also when this row has no DOM cells\n\t\tspannedCells[rowIndex]?.forEach((spanned, colIndex) => {\n\t\t\tif (spanned !== undefined) {\n\t\t\t\tcolumns[colIndex] = spanned.content;\n\t\t\t\tsources[colIndex] = spanned.source;\n\t\t\t}\n\t\t});\n\n\t\treturn { columns, sources };\n\t}\n\n\tprivate static storeSpannedCells(\n\t\trowIndex: number,\n\t\tcolIndex: number,\n\t\tcellData: CellData,\n\t\tsource: CellSource,\n\t\tspannedCells: SpannedCells,\n\t\trowsCount: number\n\t): void {\n\t\t// A rowspan never reaches past the last row (`rowspan=\"0\"` spans to it)\n\t\tfor (let rowSpan = 1; rowSpan < cellData.rowspan && rowIndex + rowSpan < rowsCount; rowSpan++) {\n\t\t\tconst spannedRow = spannedCells[rowIndex + rowSpan] ?? [];\n\t\t\tspannedCells[rowIndex + rowSpan] = spannedRow;\n\t\t\t// Store the content for each column covered by colspan\n\t\t\tfor (let colSpan = 0; colSpan < cellData.colspan; colSpan++) {\n\t\t\t\tspannedRow[colIndex + colSpan] = { content: cellData.content, source };\n\t\t\t}\n\t\t}\n\t}\n}\n","import { Locator } from \"@playwright/test\";\n\nimport { CellContentType } from \"./cell-content-type\";\nimport { HeaderRow } from \"./row\";\nimport { TableUtils } from \"./table-utils\";\n\n/**\n * Options for configuring a table header row.\n *\n * @property cellContentType - The type of content allowed in the header cell.\n * @property emptyCellReplacement - If true, replaces empty header cells with a default value.\n * @property duplicateSuffix - If true, appends a suffix to duplicate header values.\n * @property colspan - Configuration for column spanning in the header row.\n * @property colspan.enabled - If true, enables column spanning.\n * @property colspan.suffix - If true, appends a suffix to spanned columns.\n * @property normalizeWhitespace - If true, collapses line breaks, tabs and runs of whitespace to one space.\n * @property stripIconGlyphs - If true, removes icon-font glyphs (Unicode private use characters).\n */\nexport type HeaderRowOptions = {\n\tcellContentType?: CellContentType;\n\temptyCellReplacement?: boolean;\n\tduplicateSuffix?: boolean;\n\tcolspan?: { enabled?: boolean; suffix?: boolean };\n\tnormalizeWhitespace?: boolean;\n\tstripIconGlyphs?: boolean;\n};\n\n/** The cells of earlier header rows that span into the next rows, by column, with the rows they still cover. */\ntype RowSpans = Map<number, { text: string; rows: number }>;\n\n/**\n * Utility class for extracting and processing table header rows.\n * Handles complex scenarios including colspan, rowspan, empty cells, and duplicate header names.\n * Contains only static methods - cannot be instantiated.\n */\nexport class TableHeader {\n\tprivate constructor() {\n\t\t// Prevent instantiation - this class only has static methods\n\t}\n\tprivate static readonly EMPTY_CELL_PLACEHOLDER = \"{{Empty}}\";\n\tprivate static readonly COLSPAN_SUFFIX_PREFIX = \"__C\";\n\tprivate static readonly DUPLICATE_SUFFIX_PREFIX = \"__D\";\n\tprivate static readonly COLSPAN_PATTERN = /__C\\d+/;\n\tprivate static readonly ICON_GLYPH_PATTERN = /[\\uE000-\\uF8FF\\u{F0000}-\\u{FFFFD}\\u{100000}-\\u{10FFFD}]/gu;\n\tprivate static readonly CONTROL_WHITESPACE_PATTERN = /[\\p{Cc}\\p{Zl}\\p{Zp}]+/gu;\n\tprivate static readonly WHITESPACE_PATTERN = /\\s+/g;\n\n\t/**\n\t * Extracts header rows from a table with optional processing for colspan, rowspan, and duplicates.\n\t *\n\t * @param headerRowLocator - The Playwright locator for header rows.\n\t * @param columnsSelector - CSS selector for locating header columns (e.g., \"th\").\n\t * @param headerRowOptions - Optional configuration for header processing.\n\t * @returns Promise resolving to an array of processed header rows.\n\t * @throws Error if columnsSelector is empty, or if a header row cannot be read.\n\t *\n\t * @example\n\t * const headers = await TableHeader.getRows(\n\t * page.locator('thead tr'),\n\t * 'th',\n\t * { duplicateSuffix: true, colspan: { enabled: true } }\n\t * );\n\t */\n\tstatic async getRows(\n\t\theaderRowLocator: Locator,\n\t\tcolumnsSelector: string,\n\t\theaderRowOptions?: HeaderRowOptions\n\t): Promise<HeaderRow[]> {\n\t\tif (!columnsSelector || columnsSelector.trim() === \"\") {\n\t\t\tthrow new Error(\"columnsSelector cannot be empty\");\n\t\t}\n\n\t\tconst locatorDescription = headerRowLocator.toString();\n\t\tconst options = this.getDefaultOptions(headerRowOptions);\n\t\tconst rowsCount = await headerRowLocator.count();\n\t\tconst rowError = (rowIndex: number, error: unknown): Error =>\n\t\t\tnew Error(\n\t\t\t\t`Failed to process header row at index ${rowIndex}.\\n` +\n\t\t\t\t\t`Header row locator: ${locatorDescription}\\n` +\n\t\t\t\t\t`Columns selector: \"${columnsSelector}\"\\n` +\n\t\t\t\t\t`Error: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t);\n\n\t\t// Read every row in parallel, one round trip each; the spans are resolved afterwards, in order.\n\t\tconst cellData = await Promise.all(\n\t\t\tArray.from({ length: rowsCount }, async (_, rowIndex) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst cells = await TableUtils.readRowCells(\n\t\t\t\t\t\theaderRowLocator.nth(rowIndex),\n\t\t\t\t\t\tcolumnsSelector,\n\t\t\t\t\t\toptions.cellContentType\n\t\t\t\t\t);\n\t\t\t\t\treturn cells.map(cell => ({\n\t\t\t\t\t\ttext: this.sanitizeHeaderText(cell.content, options.normalizeWhitespace, options.stripIconGlyphs),\n\t\t\t\t\t\trowspan: cell.rowspan,\n\t\t\t\t\t\tcolspan: cell.colspan,\n\t\t\t\t\t}));\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow rowError(rowIndex, error);\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\tconst headerRows: HeaderRow[] = [];\n\t\tconst rowSpans: RowSpans = new Map();\n\t\tfor (const cells of cellData) {\n\t\t\theaderRows.push(this.processRow(cells, rowSpans, options));\n\t\t}\n\n\t\tthis.applyColspanOptions(headerRows, options);\n\t\tthis.applyDuplicateSuffix(headerRows, options);\n\n\t\treturn headerRows;\n\t}\n\n\tprivate static getDefaultOptions(options: HeaderRowOptions = {}): Required<HeaderRowOptions> {\n\t\tconst colspan = options.colspan ?? {};\n\t\treturn {\n\t\t\tcellContentType: options.cellContentType ?? CellContentType.InnerText,\n\t\t\temptyCellReplacement: options.emptyCellReplacement ?? false,\n\t\t\tduplicateSuffix: options.duplicateSuffix ?? false,\n\t\t\tnormalizeWhitespace: options.normalizeWhitespace ?? false,\n\t\t\tstripIconGlyphs: options.stripIconGlyphs ?? false,\n\t\t\tcolspan: {\n\t\t\t\tenabled: colspan.enabled ?? false,\n\t\t\t\tsuffix: colspan.suffix ?? false,\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate static processRow(\n\t\tcellDataArray: { text: string; rowspan: number; colspan: number }[],\n\t\trowSpans: RowSpans,\n\t\toptions: Required<HeaderRowOptions>\n\t): HeaderRow {\n\t\tconst headerRow: HeaderRow = [];\n\n\t\tif (cellDataArray.length === 0) {\n\t\t\t// An empty row is still a row: the cells spanning into it end one row sooner.\n\t\t\tfor (const column of [...rowSpans.keys()]) this.takeRowSpan(rowSpans, column);\n\t\t\treturn headerRow;\n\t\t}\n\n\t\tlet columnIndex = 0;\n\t\tfor (const cellData of cellDataArray) {\n\t\t\tcolumnIndex = this.processHeaderCellData(\n\t\t\t\tcellData,\n\t\t\t\theaderRow,\n\t\t\t\trowSpans,\n\t\t\t\tcolumnIndex,\n\t\t\t\toptions.emptyCellReplacement\n\t\t\t);\n\t\t}\n\n\t\tthis.addRemainingRowSpans(headerRow, rowSpans, columnIndex);\n\t\treturn headerRow;\n\t}\n\n\tprivate static sanitizeHeaderText(text: string, normalizeWhitespace: boolean, stripIconGlyphs: boolean): string {\n\t\tlet result = text;\n\n\t\tif (stripIconGlyphs) {\n\t\t\tresult = result.replace(this.ICON_GLYPH_PATTERN, \"\");\n\t\t}\n\n\t\tif (normalizeWhitespace) {\n\t\t\tresult = result.replace(this.CONTROL_WHITESPACE_PATTERN, \" \").replace(this.WHITESPACE_PATTERN, \" \");\n\t\t}\n\n\t\treturn result.trim();\n\t}\n\n\t/**\n\t * Processes pre-fetched header cell data and applies it to the header row.\n\t * This method is purely computational and doesn't perform any DOM operations.\n\t */\n\tprivate static processHeaderCellData(\n\t\tcellData: { text: string; rowspan: number; colspan: number },\n\t\theaderRow: HeaderRow,\n\t\trowSpans: RowSpans,\n\t\tcolumnIndex: number,\n\t\temptyCellReplacement: boolean\n\t): number {\n\t\twhile (rowSpans.has(columnIndex)) {\n\t\t\theaderRow.push(this.takeRowSpan(rowSpans, columnIndex));\n\t\t\tcolumnIndex++;\n\t\t}\n\n\t\tlet text = cellData.text;\n\t\tif (!text && emptyCellReplacement) {\n\t\t\ttext = this.EMPTY_CELL_PLACEHOLDER;\n\t\t}\n\n\t\tconst { colspan, rowspan } = cellData;\n\n\t\theaderRow.push(text);\n\t\tthis.handleColspan(headerRow, text, colspan);\n\t\tthis.handleRowspan(rowSpans, text, columnIndex, colspan, rowspan);\n\n\t\treturn columnIndex + colspan;\n\t}\n\n\tprivate static handleColspan(headerRow: HeaderRow, text: string, colspan: number): void {\n\t\tfor (let i = 1; i < colspan; i++) {\n\t\t\theaderRow.push(`${text}${this.COLSPAN_SUFFIX_PREFIX}${i}`);\n\t\t}\n\t}\n\n\tprivate static handleRowspan(\n\t\trowSpans: RowSpans,\n\t\ttext: string,\n\t\tcolumnIndex: number,\n\t\tcolspan: number,\n\t\trowspan: number\n\t): void {\n\t\tif (rowspan > 1) {\n\t\t\tfor (let i = 0; i < colspan; i++) {\n\t\t\t\trowSpans.set(columnIndex + i, { text, rows: rowspan - 1 });\n\t\t\t}\n\t\t}\n\t}\n\n\t/** The text of the cell spanning into `column` of this row; the span ends after its last row. */\n\tprivate static takeRowSpan(rowSpans: RowSpans, column: number): string {\n\t\tconst span = rowSpans.get(column);\n\t\tif (span === undefined) return \"\";\n\t\tspan.rows--;\n\t\tif (span.rows <= 0) rowSpans.delete(column);\n\t\treturn span.text;\n\t}\n\n\tprivate static addRemainingRowSpans(headerRow: HeaderRow, rowSpans: RowSpans, columnIndex: number): void {\n\t\twhile (rowSpans.has(columnIndex)) {\n\t\t\theaderRow.push(this.takeRowSpan(rowSpans, columnIndex));\n\t\t\tcolumnIndex++;\n\t\t}\n\t}\n\n\tprivate static applyColspanOptions(headerRows: HeaderRow[], options: Required<HeaderRowOptions>): void {\n\t\tif (!options.colspan.enabled) {\n\t\t\tthis.removeColspanCells(headerRows);\n\t\t}\n\n\t\tif (!options.colspan.suffix) {\n\t\t\tthis.removeColspanSuffix(headerRows);\n\t\t}\n\t}\n\n\tprivate static removeColspanCells(headerRows: HeaderRow[]): void {\n\t\tfor (const [i, headerRow] of headerRows.entries()) {\n\t\t\theaderRows[i] = headerRow.filter(cell => !this.COLSPAN_PATTERN.test(cell));\n\t\t}\n\t}\n\n\tprivate static removeColspanSuffix(headerRows: HeaderRow[]): void {\n\t\tfor (const headerRow of headerRows) {\n\t\t\tfor (const [i, header] of headerRow.entries()) {\n\t\t\t\tif (this.COLSPAN_PATTERN.test(header)) {\n\t\t\t\t\theaderRow[i] = header.replace(this.COLSPAN_PATTERN, \"\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static applyDuplicateSuffix(headerRows: HeaderRow[], options: Required<HeaderRowOptions>): void {\n\t\tif (!options.duplicateSuffix) return;\n\n\t\tfor (const headerRow of headerRows) {\n\t\t\tconst headerCountMap: Map<string, number> = new Map();\n\t\t\tfor (const [i, header] of headerRow.entries()) {\n\t\t\t\tconst currentCount = headerCountMap.get(header);\n\t\t\t\tif (currentCount !== undefined) {\n\t\t\t\t\theaderRow[i] = `${header}${this.DUPLICATE_SUFFIX_PREFIX}${currentCount}`;\n\t\t\t\t\theaderCountMap.set(header, currentCount + 1);\n\t\t\t\t} else {\n\t\t\t\t\theaderCountMap.set(header, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","import { Locator } from \"@playwright/test\";\n\nimport { CellContentType } from \"./cell-content-type\";\nimport { pollTable, PollingOptions } from \"./polling\";\nimport { BodyRow, Cell, HeaderRow } from \"./row\";\nimport { CellSource, TableBody } from \"./table-body\";\nimport { HeaderRowOptions, TableHeader } from \"./table-header\";\nimport { TableUtils } from \"./table-utils\";\n\n/**\n * Options for loading table data, headers, and rows.\n *\n * @example\n * // Use custom cell content type for body rows and header options\n * const options: TableOptions = {\n * bodyRowOptions: { cellContentType: CellContentType.TextContent },\n * headerRowOptions: {\n * colspan: { enabled: true, suffix: true },\n * duplicateSuffix: true,\n * emptyCellReplacement: false,\n * },\n * };\n * await table.getBodyRows(options);\n */\nexport type TableOptions = {\n\t/** See {@link HeaderRowOptions} for available options. */\n\theaderRowOptions?: HeaderRowOptions;\n\t/** Options for parsing body rows. */\n\tbodyRowOptions?: { cellContentType?: CellContentType };\n\t/** @deprecated Use `bodyRowOptions.cellContentType` instead. */\n\tcellContentType?: CellContentType;\n};\n\n/** Fallbacks for header row options the caller did not set. */\ntype HeaderRowOptionDefaults = {\n\tdefaultColspanEnabled?: boolean;\n\tdefaultColspanSuffix?: boolean;\n\tdefaultDuplicateSuffix?: boolean;\n\tdefaultEmptyCellReplacement?: boolean;\n\tdefaultNormalizeWhitespace?: boolean;\n\tdefaultStripIconGlyphs?: boolean;\n\tforceColspanEnabled?: boolean;\n};\n\n/**\n * Represents a table in Playwright, providing methods to interact with its headers, rows, and cells.\n */\nexport class PlaywrightTable {\n\tprivate _bodyRowLocator: Locator;\n\tprivate _bodyRowColumnSelector: string;\n\tprivate _headerRowLocator: Locator;\n\tprivate _headerColumnSelector: string;\n\n\t/**\n\t * Creates an instance of the table handler with customizable selectors for headers and rows.\n\t *\n\t * @param _tableLocator - The Playwright `Locator` pointing to the root table element.\n\t * @param _options - Optional configuration for customizing header and row selectors.\n\t * @param _options.header - Options for header row and columns.\n\t * @param _options.header.setMainHeaderRow - (Optional) Index of the main header row if multiple header rows exist.\n\t * @param _options.header.rowSelector - (Optional) CSS selector for locating header rows. Defaults to `\"thead>tr\"`.\n\t * @param _options.header.columnSelector - (Optional) CSS selector for locating header columns. Defaults to `\"th\"`.\n\t * @param _options.row - Options for body rows and columns.\n\t * @param _options.row.rowSelector - (Optional) CSS selector for locating body rows. Defaults to `\"tbody>tr\"`.\n\t * @param _options.row.columnSelector - (Optional) CSS selector for locating body columns. Defaults to `\"td\"`.\n\t *\n\t * @example\n\t * const table = new PlaywrightTable(\n\t * page.locator('table.my-table'),\n\t * {\n\t * header: {\n\t * rowSelector: 'thead tr.header',\n\t * columnSelector: 'th.header-cell'\n\t * },\n\t * row: {\n\t * rowSelector: 'tbody tr.data-row',\n\t * columnSelector: 'td.data-cell'\n\t * }\n\t * }\n\t * );\n\t */\n\tconstructor(\n\t\tprivate readonly _tableLocator: Locator,\n\t\tprivate readonly _options?: {\n\t\t\theader?: {\n\t\t\t\tsetMainHeaderRow?: number;\n\t\t\t\trowSelector?: string;\n\t\t\t\tcolumnSelector?: string;\n\t\t\t};\n\t\t\trow?: {\n\t\t\t\trowSelector?: string;\n\t\t\t\tcolumnSelector?: string;\n\t\t\t};\n\t\t}\n\t) {\n\t\tconst { header = {}, row = {} } = this._options ?? {};\n\t\tTableUtils.warnOnIdenticalRowSelectors(\"PlaywrightTable\", header.rowSelector, row.rowSelector);\n\n\t\tthis._headerRowLocator = this._tableLocator.locator(header.rowSelector ?? \"thead>tr\");\n\t\tthis._headerColumnSelector = header.columnSelector ?? \"th\";\n\t\tthis._bodyRowLocator = this._tableLocator.locator(row.rowSelector ?? \"tbody>tr\");\n\t\tthis._bodyRowColumnSelector = row.columnSelector ?? \"td\";\n\t}\n\n\t/**\n\t * Retrieves all header rows of the table.\n\t * @param options - Optional parameters for header row parsing configuration.\n\t * @returns A promise that resolves to an array of header rows.\n\t * @throws Error if the table has no header rows or no body rows.\n\t *\n\t * @example\n\t * // Get headers with colspan enabled\n\t * const headers = await table.getHeaderRows({\n\t * colspan: { enabled: true, suffix: true },\n\t * duplicateSuffix: true\n\t * });\n\t *\n\t * @see {@link getMainHeaderRow} for getting only the main header row\n\t * @see {@link HeaderRowOptions} for all available configuration options\n\t */\n\tasync getHeaderRows(options?: HeaderRowOptions): Promise<HeaderRow[]> {\n\t\tconst table = await this.getTable({\n\t\t\theaderRowOptions: options,\n\t\t});\n\t\treturn table.headerRows;\n\t}\n\n\t/**\n\t * Retrieves the main header row of the table.\n\t * By default, uses the last header row if multiple exist. Can be customized via constructor.\n\t * @param options - Optional parameters for header row parsing configuration.\n\t * @returns A promise that resolves to the main header row.\n\t * @throws Error if the table has no header rows or no body rows.\n\t * @throws Error if setMainHeaderRow index is out of bounds (negative or >= header row count).\n\t *\n\t * @example\n\t * // Get main header with custom index set in constructor\n\t * const table = new PlaywrightTable(page.locator('table'), {\n\t * header: { setMainHeaderRow: 0 } // Use first row as main header\n\t * });\n\t * const mainHeader = await table.getMainHeaderRow();\n\t *\n\t * @see {@link getHeaderRows} for getting all header rows\n\t */\n\tasync getMainHeaderRow(options?: HeaderRowOptions): Promise<HeaderRow> {\n\t\tconst table = await this.getTable({\n\t\t\theaderRowOptions: options,\n\t\t});\n\t\treturn this.mainHeaderRow(table.headerRows);\n\t}\n\n\t/**\n\t * Retrieves all body rows of the table.\n\t * @param options - Optional table or body-row configuration.\n\t * @param options.cellContentType - Legacy shortcut for body row content extraction. See {@link CellContentType}.\n\t * @param options.bodyRowOptions - Body row parsing options.\n\t * @param options.headerRowOptions - Header parsing options used when resolving row/colspan layouts.\n\t * @returns A promise that resolves to an array of body rows.\n\t * @throws Error if the table has no header rows or no body rows.\n\t *\n\t * @example\n\t * // Get body rows with TextContent (includes hidden elements)\n\t * const rows = await table.getBodyRows({\n\t * cellContentType: CellContentType.TextContent\n\t * });\n\t *\n\t * @example\n\t * // Get body rows with default InnerText\n\t * const rows = await table.getBodyRows();\n\t *\n\t * @example\n\t * // Use full table options (for example to sanitize noisy treegrid headers)\n\t * const rows = await table.getBodyRows({\n\t * bodyRowOptions: { cellContentType: CellContentType.InnerText },\n\t * headerRowOptions: { normalizeWhitespace: true, stripIconGlyphs: true }\n\t * });\n\t */\n\tasync getBodyRows(options?: TableOptions): Promise<BodyRow[]> {\n\t\tconst tableOptions = this.normalizeGetBodyRowsOptions(options);\n\n\t\tconst table = await this.getTable({\n\t\t\tbodyRowOptions: tableOptions.bodyRowOptions,\n\t\t\theaderRowOptions: this.resolveHeaderRowOptions(tableOptions.headerRowOptions, {\n\t\t\t\tforceColspanEnabled: true,\n\t\t\t}),\n\t\t});\n\t\treturn table.bodyRows;\n\t}\n\n\t/**\n\t * Retrieves a specific cell locator in the body of the table by row and column index.\n\t * Both are positions in the DOM: `headerPosition` is the index among the cells of the row, so with\n\t * colspan or rowspan it can differ from the column. The methods that find cells by header name\n\t * account for spans.\n\t * @param rowNumber - The row number (0-based index).\n\t * @param headerPosition - The cell position within the row (0-based index).\n\t * @returns A Playwright Locator for the specified cell.\n\t *\n\t * @example\n\t * // Get cell at row 1, column 2\n\t * const cellLocator = table.getBodyCellLocator(1, 2);\n\t * await expect(cellLocator).toHaveText('Expected Text');\n\t *\n\t * @example\n\t * // Get first cell in first row\n\t * const firstCell = table.getBodyCellLocator(0, 0);\n\t * await firstCell.click();\n\t *\n\t * @see {@link getBodyCellLocatorByRowConditions} for finding cells by content matching\n\t * @see {@link getAllBodyCellLocatorsByHeaderIndex} for getting all cells in a column\n\t * @see {@link getAllBodyCellLocatorsByHeaderName} for getting all cells under a header\n\t */\n\tgetBodyCellLocator(rowNumber: number, headerPosition: number): Locator {\n\t\treturn this._bodyRowLocator.nth(rowNumber).locator(this._bodyRowColumnSelector).nth(headerPosition);\n\t}\n\n\t/**\n\t * Retrieves a cell locator in the body of the table based on row conditions and a target header.\n\t * Finds the first row where all conditions match, then returns the cell in the target column.\n\t * @param conditions - An object where keys are header names and values are expected cell contents, or a single [header, value] tuple.\n\t * @param targetHeader - The header name of the column containing the cell to retrieve.\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to a Playwright Locator for the matching cell.\n\t * @throws Error if no row matches all specified conditions.\n\t * @throws Error if any condition header or target header is not found in the table.\n\t *\n\t * @example\n\t * // Find cell with multiple conditions\n\t * const emailLocator = await table.getBodyCellLocatorByRowConditions(\n\t * { \"First name\": \"John\", \"Status\": \"Active\" },\n\t * \"Email\"\n\t * );\n\t * await expect(emailLocator).toContainText('@example.com');\n\t *\n\t * @example\n\t * // Find cell with single condition using tuple syntax\n\t * const actionCell = await table.getBodyCellLocatorByRowConditions(\n\t * [\"Username\", \"john.doe\"],\n\t * \"Actions\"\n\t * );\n\t * await actionCell.locator('button').click();\n\t *\n\t * @example\n\t * // Find cell with single condition using object syntax\n\t * const statusCell = await table.getBodyCellLocatorByRowConditions(\n\t * { \"Username\": \"john.doe\" },\n\t * \"Status\"\n\t * );\n\t *\n\t * @see {@link getBodyCellLocator} for getting cells by direct index\n\t * @see {@link getAllBodyCellLocatorsByHeaderName} for getting all cells in a column\n\t */\n\tasync getBodyCellLocatorByRowConditions(\n\t\tconditions: Record<string, string> | [string, string],\n\t\ttargetHeader: string,\n\t\toptions?: TableOptions\n\t): Promise<Locator> {\n\t\tconst table = await this.getTable(this.resolveTableOptionsForHeaderKeyMethods(options));\n\t\tconst mainHeader = this.mainHeaderRow(table.headerRows);\n\n\t\tconst targetHeaderIndex = this.getHeaderIndex(targetHeader, mainHeader);\n\n\t\t// Normalize conditions to object format\n\t\tconst conditionsObj = Array.isArray(conditions) ? { [conditions[0]]: conditions[1] } : conditions;\n\n\t\tfor (const [rowIndex, row] of table.bodyRows.entries()) {\n\t\t\tlet matches = true;\n\n\t\t\tfor (const [header, value] of Object.entries(conditionsObj)) {\n\t\t\t\tconst headerIndex = this.getHeaderIndex(header, mainHeader);\n\t\t\t\tconst cellValue = row[headerIndex] ?? \"\";\n\t\t\t\tif (cellValue !== value) {\n\t\t\t\t\tmatches = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (matches) {\n\t\t\t\treturn this.gridCellLocator(table.sources, rowIndex, targetHeaderIndex);\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`No row found matching conditions: ${JSON.stringify(conditionsObj)}\\n` +\n\t\t\t\t`Target header: \"${targetHeader}\"\\n` +\n\t\t\t\t`Searched ${table.bodyRows.length} rows\\n` +\n\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}`\n\t\t);\n\t}\n\n\t/**\n\t * Retrieves all cell locators in the body of the table for a specific header name.\n\t * Returns locators for every cell in the column identified by the header.\n\t * @param header - The header name identifying the column.\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to an array of Playwright Locators for all cells in the column.\n\t * @throws Error if the header is not found, or if the table has no header rows or no body rows.\n\t *\n\t * @example\n\t * // Get all cells in the \"Status\" column\n\t * const statusCells = await table.getAllBodyCellLocatorsByHeaderName(\"Status\");\n\t * for (const cell of statusCells) {\n\t * await expect(cell).toHaveText(/Active|Inactive/);\n\t * }\n\t *\n\t * @example\n\t * // Get text from all cells in \"Name\" column\n\t * const nameCells = await table.getAllBodyCellLocatorsByHeaderName(\"Name\");\n\t * const names = await Promise.all(nameCells.map(cell => cell.textContent()));\n\t *\n\t * @see {@link getAllBodyCellLocatorsByHeaderIndex} for getting cells by column index\n\t * @see {@link getBodyCellLocatorByRowConditions} for finding specific cells by content\n\t */\n\tasync getAllBodyCellLocatorsByHeaderName(header: string, options?: TableOptions): Promise<Locator[]> {\n\t\tconst table = await this.getTable(this.resolveTableOptionsForHeaderKeyMethods(options));\n\t\tconst headers = this.mainHeaderRow(table.headerRows);\n\t\tconst headerIndex = this.getHeaderIndex(header, headers);\n\t\tconst locators: Locator[] = [];\n\t\tfor (let rowIndex = 0; rowIndex < table.bodyRows.length; rowIndex++) {\n\t\t\tconst cellLocator = this.gridCellLocator(table.sources, rowIndex, headerIndex);\n\t\t\tlocators.push(cellLocator);\n\t\t}\n\t\treturn locators;\n\t}\n\n\t/**\n\t * Retrieves all cell locators in the body of the table for a specific header index.\n\t * Returns locators for every cell in the column at the specified position.\n\t * @param headerIndex - The header/column index (0-based).\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to an array of Playwright Locators for all cells in the column.\n\t * @throws Error if the header index is out of bounds (negative or >= the number of columns, counting colspans).\n\t *\n\t * @example\n\t * // Get all cells in the third column (index 2)\n\t * const thirdColumnCells = await table.getAllBodyCellLocatorsByHeaderIndex(2);\n\t * for (const cell of thirdColumnCells) {\n\t * await expect(cell).toBeVisible();\n\t * }\n\t *\n\t * @example\n\t * // Get all cells in first column\n\t * const firstColumnCells = await table.getAllBodyCellLocatorsByHeaderIndex(0);\n\t * const values = await Promise.all(firstColumnCells.map(c => c.textContent()));\n\t *\n\t * @see {@link getAllBodyCellLocatorsByHeaderName} for getting cells by header name\n\t * @see {@link getBodyCellLocator} for getting a specific cell by row and column index\n\t */\n\tasync getAllBodyCellLocatorsByHeaderIndex(headerIndex: number, options?: TableOptions): Promise<Locator[]> {\n\t\t// Count the columns that colspans cover, as the grid positions of the body cells do\n\t\tconst tableOptions = this.normalizeGetBodyRowsOptions(options);\n\t\tconst table = await this.getTable({\n\t\t\tbodyRowOptions: tableOptions.bodyRowOptions,\n\t\t\theaderRowOptions: this.resolveHeaderRowOptions(tableOptions.headerRowOptions, { forceColspanEnabled: true }),\n\t\t});\n\t\tconst columnCount = this.mainHeaderRow(table.headerRows).length;\n\t\tif (headerIndex < 0 || headerIndex >= columnCount) {\n\t\t\tthrow new Error(\n\t\t\t\t`Header index ${headerIndex} out of bounds. Table has ${columnCount} columns.\\n` +\n\t\t\t\t\t`Header row locator: ${this._headerRowLocator.toString()}`\n\t\t\t);\n\t\t}\n\t\tconst locators: Locator[] = [];\n\t\tfor (let rowIndex = 0; rowIndex < table.bodyRows.length; rowIndex++) {\n\t\t\tconst cellLocator = this.gridCellLocator(table.sources, rowIndex, headerIndex);\n\t\t\tlocators.push(cellLocator);\n\t\t}\n\t\treturn locators;\n\t}\n\n\t/**\n\t * Converts the table data into a JSON array where each object represents a row.\n\t * Keys are header names, values are cell contents.\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to an array of objects representing table rows.\n\t * @throws Error if no header rows or body rows found.\n\t *\n\t * @example\n\t * // Convert table to JSON with default options\n\t * const data = await table.getJson();\n\t * // Result: [{\"Name\": \"John\", \"Age\": \"30\"}, {\"Name\": \"Jane\", \"Age\": \"25\"}]\n\t *\n\t * @example\n\t * // Convert with colspan enabled and duplicate suffix\n\t * const data = await table.getJson({\n\t * headerRowOptions: {\n\t * colspan: { enabled: true, suffix: true },\n\t * duplicateSuffix: true,\n\t * emptyCellReplacement: true\n\t * }\n\t * });\n\t */\n\tasync getJson(options?: TableOptions): Promise<Record<string, string>[]> {\n\t\tconst tableOptions = this.normalizeGetBodyRowsOptions(options);\n\t\tconst table = await this.getTable({\n\t\t\tbodyRowOptions: tableOptions.bodyRowOptions,\n\t\t\theaderRowOptions: this.resolveHeaderRowOptionsForJsonKeys(tableOptions.headerRowOptions),\n\t\t});\n\n\t\tconst headers = this.mainHeaderRow(table.headerRows);\n\t\treturn table.bodyRows.map(row => {\n\t\t\tconst rowObj: Record<string, Cell> = {};\n\t\t\theaders.forEach((header, index) => {\n\t\t\t\trowObj[header] = row[index] ?? \"\";\n\t\t\t});\n\t\t\treturn rowObj;\n\t\t});\n\t}\n\n\t/**\n\t * Waits for the table body to be empty (no body rows).\n\t * @param options - Polling options (`timeout`, default 30000 ms; `interval`, default 100 ms).\n\t * @returns A promise that resolves when table body is empty.\n\t * @throws Error if table is not empty within timeout period.\n\t *\n\t * @example\n\t * // Wait for table to clear after delete operation\n\t * await table.waitForEmpty({ timeout: 5000 });\n\t *\n\t * @see {@link waitForNonEmpty} for waiting until table has data\n\t *\n\t * @remarks\n\t * **Alternative:** Consider using Playwright's `expect.poll` for more flexibility. Count the rows with\n\t * `getRowCount()`: the methods that read the table throw while the body is empty.\n\t * ```ts\n\t * await expect.poll(async () => (await table.getRowCount()).body).toBe(0);\n\t * ```\n\t */\n\tasync waitForEmpty(options?: PollingOptions): Promise<void> {\n\t\tawait pollTable(async () => {\n\t\t\tconst rows = await this._bodyRowLocator.all();\n\t\t\tif (rows.length > 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Expected table to be empty, but found ${rows.length} body rows.\\n` +\n\t\t\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}`\n\t\t\t\t);\n\t\t\t}\n\t\t}, options);\n\t}\n\n\t/**\n\t * Waits for the table body to be non-empty (at least one body row with content).\n\t * A row is considered valid if it has at least one cell containing text.\n\t * @param options - Polling options (`timeout`, default 30000 ms; `interval`, default 100 ms).\n\t * @returns A promise that resolves when table has at least one body row with content.\n\t * @throws Error if table remains empty or has no rows with content within timeout period.\n\t *\n\t * @example\n\t * // Wait for table to populate after search\n\t * await table.waitForNonEmpty({ timeout: 5000 });\n\t *\n\t * @see {@link waitForEmpty} for waiting until table is cleared\n\t *\n\t * @remarks\n\t * **Alternative:** Consider using Playwright's `expect.poll` for more flexibility:\n\t * ```ts\n\t * await expect.poll(async () => (await table.getBodyRows()).length).toBeGreaterThan(0);\n\t * ```\n\t */\n\tasync waitForNonEmpty(options?: PollingOptions): Promise<void> {\n\t\tawait pollTable(async () => {\n\t\t\tconst rowCount = await this._bodyRowLocator.count();\n\t\t\tif (rowCount === 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Expected table to be non-empty, but found 0 body rows.\\n` +\n\t\t\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check if at least one row has content in at least one cell, in one round trip\n\t\t\tconst hasRowWithContent = await this._bodyRowLocator\n\t\t\t\t.locator(this._bodyRowColumnSelector)\n\t\t\t\t.evaluateAll(cells =>\n\t\t\t\t\tcells.some(cell => (\"innerText\" in cell ? cell.innerText : cell.textContent).trim() !== \"\")\n\t\t\t\t);\n\n\t\t\tif (!hasRowWithContent) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Expected table to have at least one row with content, but all ${rowCount} rows are empty.\\n` +\n\t\t\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}`\n\t\t\t\t);\n\t\t\t}\n\t\t}, options);\n\t}\n\n\t/**\n\t * Waits for the table body to have exactly N rows.\n\t * @param count - The exact number of body rows expected.\n\t * @param options - Polling options (`timeout`, default 30000 ms; `interval`, default 100 ms).\n\t * @returns A promise that resolves when the table has exactly the specified number of rows.\n\t * @throws Error if row count doesn't match within timeout period.\n\t *\n\t * @example\n\t * // Wait for exactly 10 rows after pagination\n\t * await table.waitForExactRowCount(10, { timeout: 5000 });\n\t *\n\t * @example\n\t * // Verify table has exactly 0 rows (alternative to waitForEmpty)\n\t * await table.waitForExactRowCount(0);\n\t *\n\t * @see {@link getRowCount} for getting current row counts\n\t *\n\t * @remarks\n\t * **Alternative:** Consider using Playwright's `expect.poll` for more flexibility:\n\t * ```ts\n\t * await expect.poll(async () => (await table.getBodyRows()).length).toBe(10);\n\t * ```\n\t */\n\tasync waitForExactRowCount(count: number, options?: PollingOptions): Promise<void> {\n\t\tif (count < 0 || !Number.isInteger(count)) {\n\t\t\tthrow new Error(`Row count must be a non-negative integer, got: ${count}`);\n\t\t}\n\n\t\tawait pollTable(async () => {\n\t\t\tconst rows = await this._bodyRowLocator.all();\n\t\t\tif (rows.length !== count) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Expected exactly ${count} rows, but found ${rows.length}.\\n` +\n\t\t\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}`\n\t\t\t\t);\n\t\t\t}\n\t\t}, options);\n\t}\n\n\t/**\n\t * Gets the count of header and body rows in the table.\n\t * Lightweight method that doesn't fetch cell data, only counts rows.\n\t * @returns A promise that resolves to an object with header and body row counts.\n\t *\n\t * @example\n\t * // Get current row counts\n\t * const counts = await table.getRowCount();\n\t * console.log(`Headers: ${counts.header}, Body: ${counts.body}`);\n\t *\n\t * @example\n\t * // Assert specific row count\n\t * const { body } = await table.getRowCount();\n\t * expect(body).toBe(10);\n\t */\n\tasync getRowCount(): Promise<{ header: number; body: number }> {\n\t\tconst [header, body] = await Promise.all([this._headerRowLocator.count(), this._bodyRowLocator.count()]);\n\t\treturn { header, body };\n\t}\n\n\t/**\n\t * Gets all distinct (unique) values from a specific column.\n\t * Returns a sorted array of unique string values, excluding empty values.\n\t * @param headerName - The header name of the column to extract distinct values from.\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to a sorted array of distinct values.\n\t * @throws Error if the header is not found, or if the table has no header rows or no body rows.\n\t *\n\t * @example\n\t * // Get all unique status values\n\t * const statuses = await table.getDistinctColumnValues(\"Status\");\n\t * // Result: [\"Active\", \"Inactive\", \"Pending\"]\n\t *\n\t * @example\n\t * // Get distinct countries for filtering\n\t * const countries = await table.getDistinctColumnValues(\"Country\");\n\t * console.log(`Available countries: ${countries.join(\", \")}`);\n\t *\n\t * @example\n\t * // Verify expected values exist\n\t * const roles = await table.getDistinctColumnValues(\"Role\");\n\t * expect(roles).toContain(\"Admin\");\n\t * expect(roles).toHaveLength(3);\n\t *\n\t * @see {@link getAllBodyCellLocatorsByHeaderName} for getting all cell locators in a column\n\t * @see {@link getJson} for getting full table data\n\t */\n\tasync getDistinctColumnValues(headerName: string, options?: TableOptions): Promise<string[]> {\n\t\tconst table = await this.getTable(this.resolveTableOptionsForHeaderKeyMethods(options));\n\t\tconst mainHeader = this.mainHeaderRow(table.headerRows);\n\t\tconst headerIndex = this.getHeaderIndex(headerName, mainHeader);\n\n\t\tconst values = new Set<string>();\n\t\tfor (const row of table.bodyRows) {\n\t\t\tconst value = String(row[headerIndex] ?? \"\").trim();\n\t\t\tif (value) values.add(value);\n\t\t}\n\n\t\treturn Array.from(values).sort();\n\t}\n\n\t/**\n\t * Finds the index of the first body row matching the specified conditions.\n\t * Returns -1 if no matching row is found.\n\t * @param conditions - Record of header names and expected cell values to match.\n\t * @param options - Optional table loading options. See {@link TableOptions}.\n\t * @returns A promise that resolves to the 0-based index of the first matching row, or -1 if not found.\n\t * @throws Error if specified headers don't exist, or if the table has no header rows or no body rows.\n\t *\n\t * @example\n\t * // Find index of row where Status is \"Active\"\n\t * const index = await table.findRowIndex({ Status: \"Active\" });\n\t * if (index >= 0) {\n\t * console.log(`Found at row ${index}`);\n\t * }\n\t *\n\t * @example\n\t * // Find row and interact with it\n\t * const rowIndex = await table.findRowIndex({ Username: \"john.doe\" });\n\t * if (rowIndex >= 0) {\n\t * const cell = table.getBodyCellLocator(rowIndex, 0);\n\t * await cell.click();\n\t * }\n\t *\n\t * @see {@link getBodyCellLocatorByRowConditions} for getting cell locators from matching rows\n\t */\n\tasync findRowIndex(conditions: Record<string, string>, options?: TableOptions): Promise<number> {\n\t\tconst table = await this.getTable(this.resolveTableOptionsForHeaderKeyMethods(options));\n\t\tconst mainHeader = this.mainHeaderRow(table.headerRows);\n\n\t\t// Validate all condition headers exist and get their indices\n\t\tconst expected = Object.entries(conditions).map(([header, value]) => ({\n\t\t\theaderIndex: this.getHeaderIndex(header, mainHeader),\n\t\t\tvalue,\n\t\t}));\n\n\t\t// Find first matching row\n\t\tfor (const [rowIndex, row] of table.bodyRows.entries()) {\n\t\t\tlet rowMatches = true;\n\n\t\t\tfor (const { headerIndex, value: expectedValue } of expected) {\n\t\t\t\tconst cellValue = String(row[headerIndex] ?? \"\");\n\t\t\t\tif (cellValue !== expectedValue) {\n\t\t\t\t\trowMatches = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (rowMatches) {\n\t\t\t\treturn rowIndex;\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t}\n\n\tprivate async getTable(\n\t\toptions?: TableOptions\n\t): Promise<{ headerRows: HeaderRow[]; bodyRows: BodyRow[]; sources: (CellSource | undefined)[][] }> {\n\t\tconst [headerRows, { rows: bodyRows, sources }] = await Promise.all([\n\t\t\tTableHeader.getRows(this._headerRowLocator, this._headerColumnSelector, options?.headerRowOptions),\n\t\t\tTableBody.getRowsWithSources(this._bodyRowLocator, this._bodyRowColumnSelector, options?.bodyRowOptions),\n\t\t]);\n\n\t\tif (headerRows.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`No header rows found, is table loaded completely?\\n` +\n\t\t\t\t\t`Header row locator: ${this._headerRowLocator.toString()}\\n` +\n\t\t\t\t\t`Table locator: ${this._tableLocator.toString()}`\n\t\t\t);\n\t\t}\n\t\tif (bodyRows.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`No body rows found, is table loaded completely?\\n` +\n\t\t\t\t\t`Body row locator: ${this._bodyRowLocator.toString()}\\n` +\n\t\t\t\t\t`Table locator: ${this._tableLocator.toString()}`\n\t\t\t);\n\t\t}\n\n\t\treturn { headerRows, bodyRows, sources };\n\t}\n\n\t/**\n\t * The locator of the DOM cell at a grid position, so colspan and rowspan don't shift it. A cell that\n\t * spans rows is located in the row it starts in.\n\t */\n\tprivate gridCellLocator(sources: (CellSource | undefined)[][], rowIndex: number, columnIndex: number): Locator {\n\t\tconst source = sources[rowIndex]?.[columnIndex];\n\t\treturn source === undefined\n\t\t\t? this.getBodyCellLocator(rowIndex, columnIndex)\n\t\t\t: this.getBodyCellLocator(source.row, source.cell);\n\t}\n\n\tprivate normalizeGetBodyRowsOptions(options?: TableOptions): TableOptions {\n\t\tif (!options) {\n\t\t\treturn {};\n\t\t}\n\n\t\t// oxlint-disable-next-line typescript/no-deprecated -- still supported for backwards compatibility\n\t\tconst { cellContentType } = options;\n\t\t// The deprecated option applies to the body cells, unless `bodyRowOptions` sets its own.\n\t\tif (cellContentType === undefined || options.bodyRowOptions?.cellContentType !== undefined) {\n\t\t\treturn options;\n\t\t}\n\t\treturn {\n\t\t\t...options,\n\t\t\tbodyRowOptions: { ...options.bodyRowOptions, cellContentType },\n\t\t};\n\t}\n\n\tprivate resolveHeaderRowOptionsForJsonKeys(headerOptions?: HeaderRowOptions): HeaderRowOptions {\n\t\treturn this.resolveHeaderRowOptions(headerOptions, {\n\t\t\tdefaultColspanEnabled: true,\n\t\t\tdefaultColspanSuffix: true,\n\t\t\tdefaultDuplicateSuffix: true,\n\t\t\tdefaultEmptyCellReplacement: true,\n\t\t\tdefaultNormalizeWhitespace: false,\n\t\t\tdefaultStripIconGlyphs: false,\n\t\t});\n\t}\n\n\tprivate resolveTableOptionsForHeaderKeyMethods(options?: TableOptions): TableOptions {\n\t\tconst tableOptions = this.normalizeGetBodyRowsOptions(options);\n\t\treturn {\n\t\t\tbodyRowOptions: tableOptions.bodyRowOptions,\n\t\t\theaderRowOptions: this.resolveHeaderRowOptionsForJsonKeys(tableOptions.headerRowOptions),\n\t\t};\n\t}\n\n\tprivate resolveHeaderRowOptions(\n\t\theaderOptions: HeaderRowOptions = {},\n\t\tdefaults: HeaderRowOptionDefaults = {}\n\t): HeaderRowOptions {\n\t\treturn {\n\t\t\tcellContentType: headerOptions.cellContentType,\n\t\t\temptyCellReplacement: headerOptions.emptyCellReplacement ?? defaults.defaultEmptyCellReplacement,\n\t\t\tduplicateSuffix: headerOptions.duplicateSuffix ?? defaults.defaultDuplicateSuffix,\n\t\t\tnormalizeWhitespace: headerOptions.normalizeWhitespace ?? defaults.defaultNormalizeWhitespace,\n\t\t\tstripIconGlyphs: headerOptions.stripIconGlyphs ?? defaults.defaultStripIconGlyphs,\n\t\t\tcolspan: this.resolveColspanOptions(headerOptions.colspan, defaults),\n\t\t};\n\t}\n\n\tprivate resolveColspanOptions(\n\t\tcolspan: HeaderRowOptions[\"colspan\"] = {},\n\t\tdefaults: HeaderRowOptionDefaults\n\t): NonNullable<HeaderRowOptions[\"colspan\"]> {\n\t\treturn {\n\t\t\tenabled: defaults.forceColspanEnabled === true ? true : (colspan.enabled ?? defaults.defaultColspanEnabled),\n\t\t\tsuffix: colspan.suffix ?? defaults.defaultColspanSuffix,\n\t\t};\n\t}\n\n\tprivate mainHeaderRow(headers: HeaderRow[]): HeaderRow {\n\t\tif (headers.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`No header rows available. Ensure table has been loaded.\\n` +\n\t\t\t\t\t`Header row locator: ${this._headerRowLocator.toString()}`\n\t\t\t);\n\t\t}\n\n\t\tconst headerIndex = this._options?.header?.setMainHeaderRow ?? headers.length - 1;\n\t\tconst mainHeader = headers[headerIndex];\n\t\tif (mainHeader === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`Header row index ${headerIndex} out of bounds. Table has ${headers.length} header rows.\\n` +\n\t\t\t\t\t`Header row locator: ${this._headerRowLocator.toString()}`\n\t\t\t);\n\t\t}\n\n\t\treturn mainHeader;\n\t}\n\n\t/**\n\t * Gets the index of a header in the main header row, throwing an error if not found.\n\t * @param header - The header name to find.\n\t * @param mainHeader - The main header row to search in.\n\t * @returns The 0-based index of the header.\n\t * @throws Error if the header is not found.\n\t */\n\tprivate getHeaderIndex(header: string, mainHeader: HeaderRow): number {\n\t\tconst index = mainHeader.indexOf(header);\n\t\tif (index === -1) {\n\t\t\tthrow new Error(\n\t\t\t\t`Header \"${header}\" not found.\\n` +\n\t\t\t\t\t`Available headers: [${mainHeader.join(\", \")}]\\n` +\n\t\t\t\t\t`Header row locator: ${this._headerRowLocator.toString()}`\n\t\t\t);\n\t\t}\n\t\treturn index;\n\t}\n}\n","import type {\n\tDecimalSeparator,\n\tEngineConfig,\n\tEngineFindRequest,\n\tEngineFindResult,\n\tEngineFingerprint,\n\tEngineFingerprintRequest,\n\tEngineKeysRequest,\n\tEngineMatchRequest,\n\tEngineMatchResult,\n\tEngineMatrixRequest,\n\tEngineMatrixResult,\n\tEngineTotal,\n\tEngineTotalRequest,\n\tEngineQuery,\n\tEngineTextRequest,\n\tEngineTexts,\n\tEngineTextsRequest,\n\tEngineValues,\n\tEngineValuesRequest,\n\tEngineWindow,\n\tEngineWindowRequest,\n\tSelectorEngine,\n\tSerializedMatcher,\n\tSerializedSelector,\n\tSerializedText,\n\tSerializedWhere,\n} from \"./table-locator.types\";\n\n/**\n * Name under which the engine is registered with `selectors.register`.\n *\n * A second copy of this package that registers the same name reuses the engine that was registered\n * first (see `registerTableSelectors`). So whenever the wire format changes (a new query `op`, condition\n * kind or config field), give the engine a new name, such as `pw-table-v2` after `pw-table-v1`: otherwise an older engine\n * silently matches nothing for the queries it doesn't know.\n */\nexport const TABLE_SELECTOR_ENGINE_NAME = \"pw-table-v1\";\n\n/**\n * The `pw-table-v1` custom selector engine.\n *\n * This function is serialized with `toString()` and executed in the browser, so it must stay\n * self-contained: no imports (type imports are erased), no references to module scope, and no syntax\n * that makes a bundler inject helpers (object spread, classes, class fields, ...).\n *\n * It has two modes:\n * - Called without arguments (what `selectors.register` does), it returns the selector engine.\n * - Called as `locator.evaluate(tableSelectorEngine, request)`, it reads the table exactly as the engine\n * resolves it: `{ op: \"keys\" }` returns the header keys, `{ op: \"texts\" }` the header keys and body cell\n * texts, `{ op: \"values\" }` the body cell texts of one column, and `{ op: \"match\" }` matches every body\n * row against its own conditions. `{ op: \"find\" }` counts the body rows that match one set of conditions,\n * and `{ op: \"matrix\" }` lists the body rows that match each of several sets; these three also report\n * problems with `predicate` conditions. `{ op: \"text\" }` reads one body cell, and `{ op: \"fingerprint\" }`\n * hashes the header keys and body cell texts, to tell whether the table changed.\n *\n * Header text is read on one line (`normalizeLine`); body cell text keeps its line breaks (`normalizeCell`).\n * Both leave out what the user doesn't see: icon glyphs, invisible characters and the text of the elements\n * matching the `ignore` option (screen reader only text and ligature icons by default).\n *\n * The engine never throws: invalid input or an unknown header simply yields no elements, so the\n * locator keeps waiting.\n *\n * @internal\n */\nexport function tableSelectorEngine(): SelectorEngine;\nexport function tableSelectorEngine(root: Element, request: EngineKeysRequest): string[];\nexport function tableSelectorEngine(root: Element, request: EngineTextsRequest): EngineTexts;\nexport function tableSelectorEngine(root: Element, request: EngineMatchRequest): EngineMatchResult;\nexport function tableSelectorEngine(root: Element, request: EngineValuesRequest): EngineValues;\nexport function tableSelectorEngine(root: Element, request: EngineFindRequest): EngineFindResult;\nexport function tableSelectorEngine(root: Element, request: EngineTextRequest): string;\nexport function tableSelectorEngine(root: Element, request: EngineFingerprintRequest): EngineFingerprint;\nexport function tableSelectorEngine(root: Element, request: EngineMatrixRequest): EngineMatrixResult;\nexport function tableSelectorEngine(root: Element, request: EngineWindowRequest): EngineWindow;\nexport function tableSelectorEngine(root: Element, request: EngineTotalRequest): EngineTotal;\nexport function tableSelectorEngine(\n\troot?: Element,\n\trequest?:\n\t\t| EngineKeysRequest\n\t\t| EngineTextsRequest\n\t\t| EngineMatchRequest\n\t\t| EngineValuesRequest\n\t\t| EngineFindRequest\n\t\t| EngineTextRequest\n\t\t| EngineFingerprintRequest\n\t\t| EngineMatrixRequest\n\t\t| EngineWindowRequest\n\t\t| EngineTotalRequest\n):\n\t| SelectorEngine\n\t| string[]\n\t| string\n\t| EngineTexts\n\t| EngineMatchResult\n\t| EngineValues\n\t| EngineFindResult\n\t| EngineFingerprint\n\t| EngineMatrixResult\n\t| EngineWindow\n\t| EngineTotal {\n\ttype GridCell = { el: Element; rowOffset: number; colOffset: number };\n\t/** One row of the visual grid. Positions without a cell are holes. */\n\ttype GridLine = (GridCell | undefined)[];\n\t/** The elements of one logical row: one element, or several for a row split over several containers. */\n\ttype RowGroup = [Element, ...Element[]];\n\t/** A compiled cell condition. `raw` returns the unnormalized cell text, read on first use. */\n\ttype TextTest = (text: string, raw: () => string) => boolean;\n\t/** A row condition with the grid column of its header. */\n\ttype ColumnCondition = { column: number; test: TextTest };\n\t/**\n\t * A compiled {@link SerializedSelector}: `css` finds the candidates, and `test`, if set, narrows them\n\t * down. An empty `css` matches nothing. `key` tells selectors apart in caches.\n\t */\n\ttype Sel = { css: string; test: ((el: Element) => boolean) | null; key: string };\n\t/** How `readDomText` reads text without layout. */\n\ttype DomTextOptions = { ignore: Sel; transform: boolean; inputs: boolean };\n\t/** An {@link EngineConfig} with the defaults filled in. */\n\ttype Config = {\n\t\theaderRow: Sel;\n\t\theaderCell: Sel;\n\t\tbodyRow: Sel;\n\t\tbodyCell: Sel;\n\t\t/** Footer rows, or nothing for none. */\n\t\tfooterRow: Sel;\n\t\tmainHeaderRow: number | null;\n\t\ttextContent: boolean;\n\t\t/** The elements inside a cell whose text is left out. */\n\t\tignore: Sel;\n\t\t/** Placeholder rows that are never body rows. */\n\t\temptyRow: Sel;\n\t\t/** Whether the value of text inputs and text areas in body cells is read as their text. */\n\t\tinputs: boolean;\n\t};\n\ttype TableBody = {\n\t\t/** One element per logical body row: the first element of a row split over several containers. */\n\t\trows: Element[];\n\t\t/** The logical body row of every body row element, including the other parts of a split row. */\n\t\trowOf: Map<Element, number>;\n\t\tgrid: GridLine[];\n\t};\n\ttype TableModel = {\n\t\t/** Whether the table has header rows of its own (not inside a cell). */\n\t\thasHeader: boolean;\n\t\tkeys: string[];\n\t\theaderCells: (Element | undefined)[];\n\t\t/** The body rows, read on first use: header-only reads don't need them. */\n\t\tbody: () => TableBody;\n\t\t/** The footer rows, read on first use. */\n\t\tfooter: () => TableBody;\n\t\t/** Normalized body cell texts, by cell. */\n\t\ttexts: Map<Element, string>;\n\t\t/** Raw body cell texts, by cell. */\n\t\traws: Map<Element, string>;\n\t\tcfg: Config;\n\t};\n\n\tconst EMPTY_HEADER = \"{{Empty}}\";\n\tconst COLSPAN_SUFFIX = \"__C\";\n\tconst DUPLICATE_SUFFIX = \"__D\";\n\t// Unicode private use areas, where icon fonts put their glyphs.\n\tconst ICON_GLYPHS = /[\\uE000-\\uF8FF\\u{F0000}-\\u{FFFFD}\\u{100000}-\\u{10FFFD}]/gu;\n\t// Characters that take no space on screen: soft hyphen, zero width space, word joiner, byte order mark,\n\t// and bidi marks, embeddings and isolates. Zero width (non-)joiners stay: emoji sequences and some\n\t// scripts need them.\n\tconst INVISIBLE = /[\\u00AD\\u061C\\u180E\\u200B\\u200E\\u200F\\u202A-\\u202E\\u2060\\u2066-\\u2069\\uFEFF]/g;\n\t// Whitespace that CSS `white-space: normal` collapses. Unlike `\\s`, it leaves non-breaking spaces alone.\n\tconst CSS_WHITESPACE = /[ \\t\\n\\r\\f]+/g;\n\t// Elements that start on a new line, for reading text without layout.\n\tconst BLOCK_TAGS =\n\t\t/^(address|article|aside|blockquote|dd|div|dl|dt|fieldset|figcaption|figure|footer|form|h[1-6]|header|hr|li|main|nav|ol|p|pre|section|table|tbody|td|tfoot|th|thead|tr|ul)$/;\n\tconst SKIPPED_TAGS = /^(script|style|template|noscript)$/;\n\t// The controls whose value is text, read with the `inputs` config: text areas and text-like inputs, not\n\t// checkboxes, buttons, files or passwords.\n\tconst TEXT_INPUTS =\n\t\t\"textarea, input:not([type]), input[type=text], input[type=email], input[type=number], input[type=search], \" +\n\t\t\"input[type=tel], input[type=url], input[type=date], input[type=time], input[type=datetime-local], \" +\n\t\t\"input[type=month], input[type=week]\";\n\t// Elements inside a cell whose text the user doesn't read: screen reader only text (Bootstrap, Tailwind),\n\t// ligature icons (Material Icons and Material Symbols draw a word such as `arrow_upward` as an icon), and\n\t// content hidden from assistive technology, which is how decorative icons are marked.\n\tconst DEFAULT_IGNORE = [\n\t\t\".sr-only\",\n\t\t\".visually-hidden\",\n\t\t\".material-icons\",\n\t\t\".material-icons-outlined\",\n\t\t\".material-icons-round\",\n\t\t\".material-icons-sharp\",\n\t\t\".material-icons-two-tone\",\n\t\t\".material-symbols-outlined\",\n\t\t\".material-symbols-rounded\",\n\t\t\".material-symbols-sharp\",\n\t\t\"[aria-hidden=true]\",\n\t];\n\n\t/**\n\t * Header rows of a table without a `<thead>`: the leading rows of its first `<tbody>` that have `<th>`\n\t * cells and no `<td>`. A row with both (a row header and data) stays a body row.\n\t */\n\tconst TBODY_HEADER_ROW =\n\t\t\"table:not(:has(> thead)) > tbody:first-of-type > tr:has(> th):not(:has(> td)):not(tr:has(> td) ~ tr)\";\n\t/**\n\t * The same for rows right inside a `<table>`, without a `<tbody>`. The HTML parser always adds one, but a\n\t * table built with DOM methods (`table.appendChild(tr)`) has none.\n\t */\n\tconst TABLE_HEADER_ROW = \"table:not(:has(> thead)) > tr:has(> th):not(:has(> td)):not(tr:has(> td) ~ tr)\";\n\t// Default selectors for HTML tables. Row header cells (`<th>` in a body row) are body cells too.\n\tconst HTML_SELECTORS = {\n\t\theaderRow: \"thead>tr, \" + TBODY_HEADER_ROW + \", \" + TABLE_HEADER_ROW,\n\t\theaderCell: \"th, td\",\n\t\tbodyRow: \"tbody>tr:not(\" + TBODY_HEADER_ROW + \"), table>tr:not(\" + TABLE_HEADER_ROW + \")\",\n\t\tbodyCell: \"td, th\",\n\t\tfooterRow: \"tfoot>tr\",\n\t};\n\t// Default selectors for ARIA grids (`role=\"grid\"`, `\"treegrid\"` or `\"table\"` built from other elements).\n\tconst ARIA_SELECTORS = {\n\t\theaderRow: \"[role=row]:has([role=columnheader])\",\n\t\theaderCell: \"[role=columnheader]\",\n\t\tbodyRow: \"[role=row]:not(:has([role=columnheader]))\",\n\t\tbodyCell: \"[role=gridcell], [role=cell], [role=rowheader]\",\n\t\tfooterRow: \"\",\n\t};\n\t/** The selector that matches nothing. */\n\tconst NOTHING: Sel = { css: \"\", test: null, key: \"\" };\n\t/** Every row of an HTML table or ARIA grid. */\n\tconst ANY_ROW: Sel = { css: \"[role=row], tr\", test: null, key: \"[role=row], tr\" };\n\t// The table elements that can have a role without a `role` attribute, by role.\n\tconst IMPLICIT_ROLE_TAGS: Record<string, string> = {\n\t\ttable: \"table\",\n\t\trowgroup: \"thead, tbody, tfoot\",\n\t\trow: \"tr\",\n\t\tcell: \"td\",\n\t\tgridcell: \"td\",\n\t\tcolumnheader: \"th\",\n\t\trowheader: \"th\",\n\t};\n\n\t// Models are cached for the duration of one synchronous selector evaluation. The DOM cannot change\n\t// while an evaluation runs, and the cache is dropped on the next microtask, so retries always see\n\t// a fresh DOM.\n\tlet modelCache: Map<Node, Map<string, TableModel | null>> | null = null;\n\t// Whether an element has a header row, by header row selector. Cached and dropped like the models.\n\tlet headerRowCache: Map<Node, Map<string, boolean>> | null = null;\n\t// Whether a node has a shadow host inside it. Cached and dropped like the models: a cell lookup asks\n\t// it of every ancestor, and each answer scans the whole subtree.\n\tlet shadowHostCache: Map<Node, boolean> | null = null;\n\tconst predicateCache = new Map<string, ((text: string, raw: string) => unknown) | null>();\n\t// Problems with `predicate` conditions, collected while the engine function is evaluated directly, so\n\t// the matchers can report them. `null` while the engine runs as a selector engine.\n\tlet predicateErrors: string[] | null = null;\n\n\tfunction getModelCache(): Map<Node, Map<string, TableModel | null>> {\n\t\tif (modelCache === null) {\n\t\t\tmodelCache = new Map();\n\t\t\theaderRowCache = new Map();\n\t\t\tshadowHostCache = new Map();\n\t\t\tvoid Promise.resolve().then(function () {\n\t\t\t\tmodelCache = null;\n\t\t\t\theaderRowCache = null;\n\t\t\t\tshadowHostCache = null;\n\t\t\t});\n\t\t}\n\t\treturn modelCache;\n\t}\n\n\tfunction resolveConfig(cfg: EngineConfig): Config {\n\t\tconst defaults = cfg.aria === 1 ? ARIA_SELECTORS : HTML_SELECTORS;\n\t\treturn {\n\t\t\theaderRow: compileSelector(cfg.headerRow ?? defaults.headerRow),\n\t\t\theaderCell: compileSelector(cfg.headerCell ?? defaults.headerCell),\n\t\t\tbodyRow: compileSelector(cfg.bodyRow ?? defaults.bodyRow),\n\t\t\tbodyCell: compileSelector(cfg.bodyCell ?? defaults.bodyCell),\n\t\t\tfooterRow: compileSelector(cfg.footerRow ?? defaults.footerRow),\n\t\t\tmainHeaderRow: cfg.mainHeaderRow ?? null,\n\t\t\ttextContent: cfg.textContent === 1,\n\t\t\tignore: (cfg.ignore ?? DEFAULT_IGNORE).map(compileSelector).reduce(unionSel, NOTHING),\n\t\t\temptyRow: compileSelector(cfg.emptyRow ?? \"\"),\n\t\t\tinputs: cfg.inputs === 1,\n\t\t};\n\t}\n\n\t/**\n\t * Compiles a selector. A descriptor finds the elements that match its CSS selector and could have one of\n\t * its roles, and tests them for the exact role and the text.\n\t */\n\tfunction compileSelector(selector: SerializedSelector): Sel {\n\t\tif (typeof selector === \"string\") return { css: selector, test: null, key: selector };\n\t\tconst roles = selector.r;\n\t\tconst hasText = selector.t === undefined ? null : compileText(selector.t);\n\t\tconst hasNotText = selector.n === undefined ? null : compileText(selector.n);\n\t\tlet css = selector.c ?? \"*\";\n\t\tif (roles !== undefined) {\n\t\t\tconst candidates = roles.map(function (role) {\n\t\t\t\tconst tags = IMPLICIT_ROLE_TAGS[role];\n\t\t\t\treturn \"[role~=\" + JSON.stringify(role) + \"]\" + (tags === undefined ? \"\" : \", \" + tags);\n\t\t\t});\n\t\t\tcss = \":is(\" + css + \"):is(\" + candidates.join(\", \") + \")\";\n\t\t}\n\t\treturn {\n\t\t\tcss: css,\n\t\t\ttest: function (el) {\n\t\t\t\tif (roles !== undefined && roles.indexOf(roleOf(el)) === -1) return false;\n\t\t\t\tif (hasText === null && hasNotText === null) return true;\n\t\t\t\tconst text = normalizeLine(el.textContent);\n\t\t\t\treturn (hasText === null || hasText(text)) && (hasNotText === null || !hasNotText(text));\n\t\t\t},\n\t\t\tkey: JSON.stringify(selector),\n\t\t};\n\t}\n\n\t/** Compiles the text of a descriptor: a string is found case-insensitively in the text, a RegExp tested on it. */\n\tfunction compileText(text: SerializedText): (value: string) => boolean {\n\t\tif (\"s\" in text) {\n\t\t\tconst expected = normalizeLine(text.s).toLowerCase();\n\t\t\treturn function (value) {\n\t\t\t\treturn value.toLowerCase().indexOf(expected) !== -1;\n\t\t\t};\n\t\t}\n\t\tconst regexp = new RegExp(text.r, text.f);\n\t\treturn function (value) {\n\t\t\t// A global or sticky RegExp keeps its position between calls.\n\t\t\tregexp.lastIndex = 0;\n\t\t\treturn regexp.test(value);\n\t\t};\n\t}\n\n\t/** The role of `el`: the first role of its `role` attribute, or else the role of a table element, or `\"\"`. */\n\tfunction roleOf(el: Element): string {\n\t\tconst explicit = (el.getAttribute(\"role\") ?? \"\").trim().split(/\\s+/)[0] ?? \"\";\n\t\tif (explicit !== \"\") return explicit;\n\t\tswitch (el.localName) {\n\t\t\tcase \"table\":\n\t\t\t\treturn \"table\";\n\t\t\tcase \"thead\":\n\t\t\tcase \"tbody\":\n\t\t\tcase \"tfoot\":\n\t\t\t\treturn \"rowgroup\";\n\t\t\tcase \"tr\":\n\t\t\t\treturn \"row\";\n\t\t\tcase \"td\":\n\t\t\t\treturn isGridCell(el) ? \"gridcell\" : \"cell\";\n\t\t\tcase \"th\":\n\t\t\t\treturn isRowHeader(el) ? \"rowheader\" : \"columnheader\";\n\t\t}\n\t\treturn \"\";\n\t}\n\n\t/** Whether a `<td>` is in a table with the `grid` or `treegrid` role. */\n\tfunction isGridCell(td: Element): boolean {\n\t\tconst table = td.closest(\"table\");\n\t\tconst role = table === null ? \"\" : (table.getAttribute(\"role\") ?? \"\").trim().split(/\\s+/)[0];\n\t\treturn role === \"grid\" || role === \"treegrid\";\n\t}\n\n\t/** Whether a `<th>` heads its row: with `scope=\"row\"`, or in a row outside a `<thead>` that also has a `<td>`. */\n\tfunction isRowHeader(th: Element): boolean {\n\t\tconst scope = (th.getAttribute(\"scope\") ?? \"\").toLowerCase();\n\t\tif (scope === \"row\" || scope === \"rowgroup\") return true;\n\t\tif (scope === \"col\" || scope === \"colgroup\") return false;\n\t\tconst row = th.parentElement;\n\t\tif (row === null || row.localName !== \"tr\" || row.parentElement?.localName === \"thead\") return false;\n\t\treturn Array.from(row.children).some(function (cell) {\n\t\t\treturn cell.localName === \"td\";\n\t\t});\n\t}\n\n\t/** Whether `el` matches `sel`. */\n\tfunction matchesSel(el: Element, sel: Sel): boolean {\n\t\treturn sel.css !== \"\" && el.matches(sel.css) && (sel.test === null || sel.test(el));\n\t}\n\n\t/** The elements that match either selector. */\n\tfunction unionSel(a: Sel, b: Sel): Sel {\n\t\tif (a.css === \"\") return b;\n\t\tif (b.css === \"\") return a;\n\t\treturn {\n\t\t\tcss: a.css + \", \" + b.css,\n\t\t\ttest:\n\t\t\t\ta.test === null && b.test === null\n\t\t\t\t\t? null\n\t\t\t\t\t: function (el) {\n\t\t\t\t\t\t\treturn matchesSel(el, a) || matchesSel(el, b);\n\t\t\t\t\t\t},\n\t\t\tkey: a.key + \"\\n\" + b.key,\n\t\t};\n\t}\n\n\t/** Removes what takes no space on screen (icon glyphs and invisible characters), and composes accents (NFC). */\n\tfunction clean(value: string | null | undefined): string {\n\t\treturn (value ?? \"\").replace(ICON_GLYPHS, \"\").replace(INVISIBLE, \"\").normalize(\"NFC\");\n\t}\n\n\t/** Text on one line: every run of whitespace, line breaks included, becomes one space. For header text. */\n\tfunction normalizeLine(value: string | null | undefined): string {\n\t\treturn clean(value).replace(/\\s+/g, \" \").trim();\n\t}\n\n\t/**\n\t * Text that keeps its line breaks: one `\\n` between lines, each line collapsed and trimmed, and no\n\t * empty lines. For body cell text.\n\t */\n\tfunction normalizeCell(value: string | null | undefined): string {\n\t\tconst lines: string[] = [];\n\t\tfor (const line of clean(value).split(/\\r\\n|[\\r\\n\\u2028\\u2029]/)) {\n\t\t\tconst text = line.replace(/\\s+/g, \" \").trim();\n\t\t\tif (text !== \"\") lines.push(text);\n\t\t}\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\t// A minus sign in front of a number, possibly with a currency symbol in between, that is not part of a\n\t// word such as \"Item-5\".\n\tconst MINUS_BEFORE = /(?:^|[^\\p{L}\\p{N}])[-−]\\s*\\p{Sc}?\\s*$/u;\n\n\t/**\n\t * The one number in `value`, or `NaN` if it has no number or more than one. Digits may be grouped by\n\t * thousands with the other separator, `'` or a (non-breaking) space, so with `\".\"` both `\"€ 1,200.50\"`\n\t * and `\"1 200.5\"` are numbers, and `\"12:30\"` or `\"5 of 10\"` are not.\n\t */\n\tfunction parseNumber(value: string, decimal: DecimalSeparator): number {\n\t\tconst text = clean(value);\n\t\tconst pattern = numberPattern(decimal);\n\t\t// A global RegExp keeps its position between calls.\n\t\tpattern.lastIndex = 0;\n\t\tconst first = pattern.exec(text);\n\t\tif (first === null || pattern.exec(text) !== null) return NaN;\n\t\tconst integer = (first[1] ?? \"0\").replace(/\\D/g, \"\");\n\t\tconst fraction = first[2] ?? first[3] ?? \"0\";\n\t\tconst number = Number(integer + \".\" + fraction);\n\t\treturn MINUS_BEFORE.test(text.slice(0, first.index)) ? -number : number;\n\t}\n\n\t// The patterns of `parseNumber` by decimal separator, built once: numeric conditions parse every cell.\n\tconst numberPatterns = new Map<string, RegExp>();\n\n\t/** The pattern of the numbers in a text with this decimal separator, global so a second number is found. */\n\tfunction numberPattern(decimal: DecimalSeparator): RegExp {\n\t\tlet pattern = numberPatterns.get(decimal);\n\t\tif (pattern === undefined) {\n\t\t\tconst group = decimal === \",\" ? \"[.'\\\\u00a0\\\\u202f ]\" : \"[,'\\\\u00a0\\\\u202f ]\";\n\t\t\tconst separator = decimal === \",\" ? \",\" : \"\\\\.\";\n\t\t\tpattern = new RegExp(\n\t\t\t\t\"(\\\\d{1,3}(?:\" + group + \"\\\\d{3})+|\\\\d+)(?:\" + separator + \"(\\\\d+))?|\" + separator + \"(\\\\d+)\",\n\t\t\t\t\"g\"\n\t\t\t);\n\t\t\tnumberPatterns.set(decimal, pattern);\n\t\t}\n\t\treturn pattern;\n\t}\n\n\t/** The text of `el` as the browser reads it (`innerText` or `textContent`), without any changes. */\n\tfunction rawText(el: Element, textContent: boolean): string {\n\t\tif (!textContent && \"innerText\" in el) return (el as HTMLElement).innerText;\n\t\treturn el.textContent;\n\t}\n\n\t/**\n\t * The text of `el` as it is shown, before normalization: `innerText` without the text of the elements\n\t * matching `cfg.ignore`, and with the selected option of a `<select>`. With `textContent`, all text in\n\t * the DOM except the ignored elements, with line breaks for `<br>` and block elements. With `inputs`,\n\t * text inputs and text areas read as their value.\n\t */\n\tfunction readText(el: Element, cfg: Config, inputs: boolean): string {\n\t\t// An element that is not rendered has no layout, and its innerText is its textContent. Its CSS\n\t\t// `text-transform` is applied anyway, so a header reads the same whether it is shown or not.\n\t\tif (cfg.textContent || !(\"innerText\" in el) || el.getClientRects().length === 0) {\n\t\t\tconst parts: string[] = [];\n\t\t\treadDomText(el, false, parts, {\n\t\t\t\tignore: cfg.ignore,\n\t\t\t\ttransform: !cfg.textContent && \"innerText\" in el,\n\t\t\t\tinputs: inputs,\n\t\t\t});\n\t\t\treturn parts.join(\"\");\n\t\t}\n\t\tconst special = specialElements(el, cfg.ignore, inputs);\n\t\tif (special.length === 0) return (el as HTMLElement).innerText;\n\t\tconst parts: string[] = [];\n\t\treadShownText(el, special, parts);\n\t\treturn parts.join(\"\");\n\t}\n\n\t/** Whether `el` matches the `ignore` selector. */\n\tfunction isIgnored(el: Element, ignore: Sel): boolean {\n\t\treturn matchesSel(el, ignore);\n\t}\n\n\t/**\n\t * Reads the text of the children of `node` without layout into `parts`: leaving out the elements that\n\t * match `options.ignore`; with `options.transform`, applying the computed `text-transform` of each text,\n\t * as `innerText` does; and with `options.inputs`, reading text inputs and text areas as their value.\n\t */\n\tfunction readDomText(node: Node, pre: boolean, parts: string[], options: DomTextOptions): void {\n\t\tconst textTransform = options.transform && isElement(node) ? getComputedStyle(node).textTransform : \"none\";\n\t\tfor (const child of Array.from(node.childNodes)) {\n\t\t\tif (child.nodeType === 3) {\n\t\t\t\tconst value = child.nodeValue ?? \"\";\n\t\t\t\tparts.push(transformText(pre ? value : value.replace(CSS_WHITESPACE, \" \"), textTransform));\n\t\t\t} else if (isElement(child)) {\n\t\t\t\treadDomElement(child, pre, parts, options);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Reads the text of `el`, a child in {@link readDomText}, into `parts`. */\n\tfunction readDomElement(el: Element, pre: boolean, parts: string[], options: DomTextOptions): void {\n\t\tconst name = el.localName;\n\t\tif (name === \"br\") {\n\t\t\tparts.push(\"\\n\");\n\t\t\treturn;\n\t\t}\n\t\tif (SKIPPED_TAGS.test(name) || isIgnored(el, options.ignore)) return;\n\t\tif (options.inputs && el.matches(TEXT_INPUTS)) {\n\t\t\tparts.push(inputValue(el));\n\t\t\treturn;\n\t\t}\n\t\tconst block = BLOCK_TAGS.test(name);\n\t\tif (block) parts.push(\"\\n\");\n\t\treadDomText(el, pre || name === \"pre\" || name === \"textarea\", parts, options);\n\t\tif (block) parts.push(\"\\n\");\n\t}\n\n\t/**\n\t * The descendants of `cell` whose text is not read with `innerText`: the elements matching `ignore`\n\t * (left out), `<select>`s (read as their selected options), and with `inputs`, text inputs and text\n\t * areas (read as their value). Not their descendants.\n\t */\n\tfunction specialElements(cell: Element, ignore: Sel, inputs: boolean): Element[] {\n\t\tconst found: Element[] = [];\n\t\tif (cell.firstElementChild === null) return found;\n\t\tconst read = \"select\" + (inputs ? \", \" + TEXT_INPUTS : \"\");\n\t\tconst selector = ignore.css === \"\" ? read : ignore.css + \", \" + read;\n\t\tfor (const el of Array.from(cell.querySelectorAll(selector))) {\n\t\t\t// A candidate of an ignore descriptor that it doesn't match\n\t\t\tif (ignore.test !== null && !el.matches(read) && !ignore.test(el)) continue;\n\t\t\tconst inFound = found.some(function (outer) {\n\t\t\t\treturn outer.contains(el);\n\t\t\t});\n\t\t\tif (!inFound) found.push(el);\n\t\t}\n\t\treturn found;\n\t}\n\n\t/** Reads the shown text of the children of `node`, leaving out `special` elements, into `parts`. */\n\tfunction readShownText(node: Element, special: Element[], parts: string[]): void {\n\t\tconst style = getComputedStyle(node);\n\t\tconst pre = style.whiteSpace.slice(0, 3) === \"pre\";\n\t\tconst shown = style.visibility === \"visible\";\n\t\tfor (const child of Array.from(node.childNodes)) {\n\t\t\tif (child.nodeType === 3) {\n\t\t\t\tconst value = child.nodeValue ?? \"\";\n\t\t\t\tif (shown) parts.push(transformText(pre ? value : value.replace(CSS_WHITESPACE, \" \"), style.textTransform));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isElement(child)) readShownElement(child, special, parts);\n\t\t}\n\t}\n\n\t/** Reads the shown text of `el`, a child of an element with `special` descendants, into `parts`. */\n\tfunction readShownElement(el: Element, special: Element[], parts: string[]): void {\n\t\tif (el.localName === \"br\") {\n\t\t\tparts.push(\"\\n\");\n\t\t\treturn;\n\t\t}\n\t\tconst style = getComputedStyle(el);\n\t\tif (style.display === \"none\") return;\n\t\tif (el.localName === \"select\" && \"selectedOptions\" in el) {\n\t\t\tparts.push(selectedText(el as HTMLSelectElement));\n\t\t\treturn;\n\t\t}\n\t\tif (special.indexOf(el) !== -1) {\n\t\t\t// A text input among the special elements is read as its value; the others are left out.\n\t\t\tif (el.matches(TEXT_INPUTS) && style.visibility === \"visible\") parts.push(inputValue(el));\n\t\t\treturn;\n\t\t}\n\t\tconst block = style.display.slice(0, 6) !== \"inline\" && style.display !== \"contents\";\n\t\tif (block) parts.push(\"\\n\");\n\t\tconst mixed = special.some(function (inner) {\n\t\t\treturn el.contains(inner);\n\t\t});\n\t\tif (mixed) {\n\t\t\treadShownText(el, special, parts);\n\t\t} else {\n\t\t\tparts.push(rawText(el, false));\n\t\t}\n\t\tif (block) parts.push(\"\\n\");\n\t}\n\n\t/** The value of a text input or text area. */\n\tfunction inputValue(el: Element): string {\n\t\treturn \"value\" in el ? String((el as HTMLInputElement).value) : \"\";\n\t}\n\n\tfunction selectedText(select: HTMLSelectElement): string {\n\t\treturn Array.from(select.selectedOptions)\n\t\t\t.map(function (option) {\n\t\t\t\treturn option.text;\n\t\t\t})\n\t\t\t.join(\"\\n\");\n\t}\n\n\t/** Applies a computed `text-transform`, like `innerText` does. */\n\tfunction transformText(text: string, transform: string): string {\n\t\tif (transform === \"uppercase\") return text.toUpperCase();\n\t\tif (transform === \"lowercase\") return text.toLowerCase();\n\t\tif (transform === \"capitalize\") {\n\t\t\treturn text.replace(/(^|\\s)(\\S)/g, function (_match, space: string, letter: string) {\n\t\t\t\treturn space + letter.toUpperCase();\n\t\t\t});\n\t\t}\n\t\treturn text;\n\t}\n\n\t/** The normalized text of a body cell. */\n\tfunction textOf(model: TableModel, el: Element): string {\n\t\tconst cached = model.texts.get(el);\n\t\tif (cached !== undefined) return cached;\n\t\tconst text = normalizeCell(readText(el, model.cfg, model.cfg.inputs));\n\t\tmodel.texts.set(el, text);\n\t\treturn text;\n\t}\n\n\t/** The raw text of a body cell. */\n\tfunction rawOf(model: TableModel, el: Element): string {\n\t\tconst cached = model.raws.get(el);\n\t\tif (cached !== undefined) return cached;\n\t\tconst text = rawText(el, model.cfg.textContent);\n\t\tmodel.raws.set(el, text);\n\t\treturn text;\n\t}\n\n\t/** `value`, or `null` if it is an empty string. */\n\tfunction nonEmpty(value: string | null): string | null {\n\t\treturn value === \"\" ? null : value;\n\t}\n\n\t/**\n\t * A `rowspan`/`colspan` attribute, or its `aria-rowspan`/`aria-colspan` counterpart, capped like the\n\t * browser caps it (1000 columns, 65534 rows). A `rowspan` of 0 is 0: the cell spans to the end of its row\n\t * group. Anything else invalid is 1.\n\t */\n\tfunction span(el: Element, name: \"rowspan\" | \"colspan\"): number {\n\t\tconst value = parseInt(nonEmpty(el.getAttribute(name)) ?? nonEmpty(el.getAttribute(\"aria-\" + name)) ?? \"1\", 10);\n\t\tif (isNaN(value) || value < 0) return 1;\n\t\tif (name === \"colspan\") return value === 0 ? 1 : Math.min(value, 1000);\n\t\treturn Math.min(value, 65534);\n\t}\n\n\t/** The parent element of `node` in the composed tree: the host stands in for a shadow root. */\n\tfunction parentOf(node: Node): Element | null {\n\t\tconst parent = node.parentNode;\n\t\tif (parent === null) return null;\n\t\tif (isShadowRoot(parent)) return parent.host;\n\t\treturn isElement(parent) ? parent : null;\n\t}\n\n\tfunction isElement(node: Node): node is Element {\n\t\treturn node.nodeType === 1;\n\t}\n\n\tfunction isShadowRoot(node: Node): node is ShadowRoot {\n\t\treturn node.nodeType === 11 && \"host\" in node;\n\t}\n\n\t/** Whether `node` can contain elements: an element, a document or a document fragment (such as a shadow root). */\n\tfunction isParentNode(node: Node): node is Node & ParentNode {\n\t\treturn node.nodeType === 1 || node.nodeType === 9 || node.nodeType === 11;\n\t}\n\n\t/** The shadow root of `scope`, or `null` if it is not a shadow host. */\n\tfunction shadowRootOf(scope: Node): ShadowRoot | null {\n\t\treturn isElement(scope) ? scope.shadowRoot : null;\n\t}\n\n\t/** Whether `scope` is a shadow host or has one inside it (outside of shadow roots). */\n\tfunction hasShadowHost(scope: Node & ParentNode): boolean {\n\t\tconst cached = shadowHostCache === null ? undefined : shadowHostCache.get(scope);\n\t\tif (cached !== undefined) return cached;\n\t\tlet found = shadowRootOf(scope) !== null;\n\t\tif (!found) {\n\t\t\tfor (const el of scope.querySelectorAll(\"*\")) {\n\t\t\t\tif (el.shadowRoot !== null) {\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (shadowHostCache !== null) shadowHostCache.set(scope, found);\n\t\treturn found;\n\t}\n\n\t/**\n\t * The elements matching `selector` in `scope`, its shadow root and every open shadow root inside it,\n\t * in composed tree order: the shadow content of a host comes right after the host. Like Playwright\n\t * CSS, a selector matches within one tree; combinators don't cross a shadow boundary.\n\t */\n\tfunction deepQueryAll(scope: Node & ParentNode, selector: string): Element[] {\n\t\tconst result: Element[] = [];\n\t\tconst shadow = shadowRootOf(scope);\n\t\tif (shadow !== null) collectDeep(shadow, selector, result);\n\t\tcollectDeep(scope, selector, result);\n\t\treturn result;\n\t}\n\n\tfunction collectDeep(scope: ParentNode, selector: string, result: Element[]): void {\n\t\tconst matched = new Set<Element>(scope.querySelectorAll(selector));\n\t\tfor (const el of scope.querySelectorAll(\"*\")) {\n\t\t\tif (matched.has(el)) result.push(el);\n\t\t\tif (el.shadowRoot !== null) collectDeep(el.shadowRoot, selector, result);\n\t\t}\n\t}\n\n\t/** The elements matching `selector` in `scope`, also inside open shadow roots when `deep` is set. */\n\tfunction queryIn(scope: Node & ParentNode, selector: string, deep: boolean): Element[] {\n\t\treturn deep ? deepQueryAll(scope, selector) : Array.from(scope.querySelectorAll(selector));\n\t}\n\n\t/** The elements matching `sel` in `scope`, also inside open shadow roots when `deep` is set. */\n\tfunction querySel(scope: Node & ParentNode, sel: Sel, deep: boolean): Element[] {\n\t\tif (sel.css === \"\") return [];\n\t\tconst found = queryIn(scope, sel.css, deep);\n\t\treturn sel.test === null ? found : found.filter(sel.test);\n\t}\n\n\t/** Whether `el` has a header row, also inside open shadow roots. */\n\tfunction hasHeaderRow(el: Element, sel: Sel): boolean {\n\t\tgetModelCache();\n\t\tconst cache = headerRowCache as Map<Node, Map<string, boolean>>;\n\t\tlet bySelector = cache.get(el);\n\t\tif (bySelector === undefined) {\n\t\t\tbySelector = new Map();\n\t\t\tcache.set(el, bySelector);\n\t\t}\n\t\tlet found = bySelector.get(sel.key);\n\t\tif (found === undefined) {\n\t\t\tfound =\n\t\t\t\tsel.test === null\n\t\t\t\t\t? el.querySelector(sel.css) !== null || (hasShadowHost(el) && deepQueryAll(el, sel.css).length > 0)\n\t\t\t\t\t: querySel(el, sel, hasShadowHost(el)).length > 0;\n\t\t\tbySelector.set(sel.key, found);\n\t\t}\n\t\treturn found;\n\t}\n\n\t/**\n\t * Whether `el` is part of `container` itself, rather than content of a cell inside it (such as a\n\t * nested table). `cellSel` matches the header and body cells of the table.\n\t */\n\tfunction owned(el: Element, container: Node, cellSel: Sel): boolean {\n\t\tlet node = parentOf(el);\n\t\twhile (node !== null && node !== container) {\n\t\t\tif (matchesSel(node, cellSel)) return false;\n\t\t\tnode = parentOf(node);\n\t\t}\n\t\treturn true;\n\t}\n\n\t/** The rows of `scope` that match `sel` and are not inside a cell. */\n\tfunction ownRows(scope: Node & ParentNode, sel: Sel, cellSel: Sel, deep: boolean): Element[] {\n\t\treturn querySel(scope, sel, deep).filter(function (row) {\n\t\t\treturn owned(row, scope, cellSel);\n\t\t});\n\t}\n\n\t/**\n\t * Groups row elements into logical rows. Rows that share an `aria-rowindex` are one row split over\n\t * several containers (for example pinned columns). When every row has an `aria-rowindex`, rows are\n\t * ordered by it, because virtualized grids don't always keep the DOM in visual order.\n\t */\n\tfunction groupRows(rows: Element[]): RowGroup[] {\n\t\tconst groups: RowGroup[] = [];\n\t\tconst byIndex = new Map<string, RowGroup>();\n\t\tlet indexed = true;\n\t\tfor (const row of rows) {\n\t\t\tconst key = row.getAttribute(\"aria-rowindex\");\n\t\t\tconst group = key === null ? undefined : byIndex.get(key);\n\t\t\tif (group !== undefined) {\n\t\t\t\tgroup.push(row);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst created: RowGroup = [row];\n\t\t\tif (key === null || isNaN(parseInt(key, 10))) indexed = false;\n\t\t\tif (key !== null) byIndex.set(key, created);\n\t\t\tgroups.push(created);\n\t\t}\n\t\tif (indexed) {\n\t\t\tgroups.sort(function (a, b) {\n\t\t\t\treturn (\n\t\t\t\t\tparseInt(a[0].getAttribute(\"aria-rowindex\") ?? \"\", 10) -\n\t\t\t\t\tparseInt(b[0].getAttribute(\"aria-rowindex\") ?? \"\", 10)\n\t\t\t\t);\n\t\t\t});\n\t\t}\n\t\treturn groups;\n\t}\n\n\t/**\n\t * Lays out logical rows on a visual grid that respects rowspan and colspan. A cell with an\n\t * `aria-colindex` is placed in that column, so cells of virtualized and split rows line up.\n\t */\n\tfunction buildGrid(rows: RowGroup[], cellSel: Sel, ownCellSel: Sel, deep: boolean): GridLine[] {\n\t\tconst grid = rows.map(function (): GridLine {\n\t\t\treturn [];\n\t\t});\n\t\tconst ends = rowGroupEnds(rows);\n\t\trows.forEach(function (group, r) {\n\t\t\tlet c = 0;\n\t\t\t// Like in HTML, a rowspan stops at the end of its row group (`<tbody>`), and 0 spans to it.\n\t\t\tconst end = ends[r] ?? rows.length;\n\t\t\tfor (const el of ownCells(group, cellSel, ownCellSel, deep)) {\n\t\t\t\tconst colindex = parseInt(el.getAttribute(\"aria-colindex\") ?? \"\", 10);\n\t\t\t\tif (colindex >= 1) {\n\t\t\t\t\tc = colindex - 1;\n\t\t\t\t} else {\n\t\t\t\t\twhile (grid[r]?.[c] !== undefined) c++;\n\t\t\t\t}\n\t\t\t\tconst spanned = span(el, \"rowspan\");\n\t\t\t\tconst rowspan = spanned === 0 ? end - r : Math.min(spanned, end - r);\n\t\t\t\tconst colspan = span(el, \"colspan\");\n\t\t\t\tfor (let dr = 0; dr < rowspan; dr++) {\n\t\t\t\t\tconst line = grid[r + dr];\n\t\t\t\t\tif (line === undefined) break;\n\t\t\t\t\tfor (let dc = 0; dc < colspan; dc++) {\n\t\t\t\t\t\tline[c + dc] = { el: el, rowOffset: dr, colOffset: dc };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tc += colspan;\n\t\t\t}\n\t\t});\n\t\treturn grid;\n\t}\n\n\t/**\n\t * For each logical row, the index after the last row of its HTML row group: the rows that follow it in\n\t * the same `<thead>`, `<tbody>` or `<tfoot>`. Rows outside one (such as ARIA rows) are one group.\n\t */\n\tfunction rowGroupEnds(rows: RowGroup[]): number[] {\n\t\tconst sections = rows.map(function (group) {\n\t\t\tconst parent = group[0].parentElement;\n\t\t\treturn parent !== null && /^(thead|tbody|tfoot)$/.test(parent.localName) ? parent : null;\n\t\t});\n\t\tconst ends: number[] = [];\n\t\tfor (let r = rows.length - 1; r >= 0; r--) {\n\t\t\tconst next = ends[r + 1];\n\t\t\tends[r] = next !== undefined && sections[r] === sections[r + 1] ? next : r + 1;\n\t\t}\n\t\treturn ends;\n\t}\n\n\t/** The cells of a logical row that match `cellSel` and are not inside a nested cell. */\n\tfunction ownCells(group: RowGroup, cellSel: Sel, ownCellSel: Sel, deep: boolean): Element[] {\n\t\tconst cells: Element[] = [];\n\t\tfor (const part of group) {\n\t\t\tfor (const cell of querySel(part, cellSel, deep)) {\n\t\t\t\tif (owned(cell, part, ownCellSel)) cells.push(cell);\n\t\t\t}\n\t\t}\n\t\treturn cells;\n\t}\n\n\t/** Header keys of one header row, with the same rules as `PlaywrightTable.getJson()`. */\n\tfunction headerKeys(line: GridLine, cfg: Config): string[] {\n\t\tconst keys: string[] = [];\n\t\t// A `for...of` loop visits holes too, as `undefined`.\n\t\tfor (const cell of line) {\n\t\t\tif (cell === undefined) {\n\t\t\t\tkeys.push(EMPTY_HEADER);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Header cells never read their inputs, such as filter fields\n\t\t\tconst base = normalizeLine(readText(cell.el, cfg, false)) || EMPTY_HEADER;\n\t\t\t// Headers carried down by rowspan keep their plain text; colspan continuations get a suffix.\n\t\t\tkeys.push(cell.rowOffset === 0 && cell.colOffset > 0 ? base + COLSPAN_SUFFIX + cell.colOffset : base);\n\t\t}\n\t\tconst seen = new Map<string, number>();\n\t\treturn keys.map(function (key) {\n\t\t\tconst count = seen.get(key);\n\t\t\tseen.set(key, (count ?? 0) + 1);\n\t\t\treturn count === undefined ? key : key + DUPLICATE_SUFFIX + count;\n\t\t});\n\t}\n\n\t/**\n\t * Builds the model of a table. A table without header rows (or with an out of range main header row)\n\t * has no header keys: only column indexes resolve in it.\n\t */\n\tfunction buildModel(scope: Node, cfg: Config): TableModel | null {\n\t\tif (!isParentNode(scope)) return null;\n\t\tconst deep = hasShadowHost(scope);\n\t\tconst anyCell = unionSel(cfg.headerCell, cfg.bodyCell);\n\t\tconst headerRows = groupRows(ownRows(scope, cfg.headerRow, anyCell, deep));\n\t\tconst mainIndex = cfg.mainHeaderRow ?? headerRows.length - 1;\n\t\tconst mainLine =\n\t\t\t(mainIndex >= 0 && mainIndex < headerRows.length\n\t\t\t\t? buildGrid(headerRows, cfg.headerCell, anyCell, deep)[mainIndex]\n\t\t\t\t: undefined) ?? [];\n\t\t// A row without header cells that shares its aria-rowindex with a header row is part of that header\n\t\t// row (such as an empty pinned container), not a body row.\n\t\tconst headerIndexes = new Set<string>();\n\t\tfor (const group of headerRows) {\n\t\t\tconst key = group[0].getAttribute(\"aria-rowindex\");\n\t\t\tif (key !== null) headerIndexes.add(key);\n\t\t}\n\t\tlet body: TableBody | null = null;\n\t\tlet footer: TableBody | null = null;\n\t\treturn {\n\t\t\thasHeader: headerRows.length > 0,\n\t\t\tkeys: headerKeys(mainLine, cfg),\n\t\t\theaderCells: mainLine.map(function (cell) {\n\t\t\t\treturn cell === undefined ? undefined : cell.el;\n\t\t\t}),\n\t\t\tbody: function (): TableBody {\n\t\t\t\treturn (body ??= buildBody(scope, cfg, cfg.bodyRow, cfg.emptyRow, headerIndexes, deep));\n\t\t\t},\n\t\t\tfooter: function (): TableBody {\n\t\t\t\treturn (footer ??= buildBody(scope, cfg, cfg.footerRow, NOTHING, headerIndexes, deep));\n\t\t\t},\n\t\t\ttexts: new Map(),\n\t\t\traws: new Map(),\n\t\t\tcfg: cfg,\n\t\t};\n\t}\n\n\t/**\n\t * The body rows of the table, or with the footer row selector, its footer rows. Rows matching `empty`\n\t * (placeholder rows such as \"No data\") are left out.\n\t */\n\tfunction buildBody(\n\t\tscope: Node & ParentNode,\n\t\tcfg: Config,\n\t\trowSel: Sel,\n\t\tempty: Sel,\n\t\theaderIndexes: Set<string>,\n\t\tdeep: boolean\n\t): TableBody {\n\t\tif (rowSel.css === \"\") return { rows: [], rowOf: new Map(), grid: [] };\n\t\tconst anyCell = unionSel(cfg.headerCell, cfg.bodyCell);\n\t\tconst groups = groupRows(ownRows(scope, rowSel, anyCell, deep)).filter(function (group) {\n\t\t\tconst key = group[0].getAttribute(\"aria-rowindex\");\n\t\t\tif (matchesSel(group[0], empty)) return false;\n\t\t\treturn key === null || !headerIndexes.has(key);\n\t\t});\n\t\tconst rows: Element[] = [];\n\t\tconst rowOf = new Map<Element, number>();\n\t\tgroups.forEach(function (group, r) {\n\t\t\trows.push(group[0]);\n\t\t\tfor (const part of group) {\n\t\t\t\trowOf.set(part, r);\n\t\t\t}\n\t\t});\n\t\treturn { rows: rows, rowOf: rowOf, grid: buildGrid(groups, cfg.bodyCell, anyCell, deep) };\n\t}\n\n\tfunction getModel(table: Node, cfg: EngineConfig): TableModel | null {\n\t\tconst cache = getModelCache();\n\t\tlet byConfig = cache.get(table);\n\t\tif (byConfig === undefined) {\n\t\t\tbyConfig = new Map();\n\t\t\tcache.set(table, byConfig);\n\t\t}\n\t\tconst cfgKey = JSON.stringify(cfg);\n\t\tlet model = byConfig.get(cfgKey);\n\t\tif (model === undefined) {\n\t\t\tmodel = buildModel(table, resolveConfig(cfg));\n\t\t\tbyConfig.set(cfgKey, model);\n\t\t}\n\t\treturn model;\n\t}\n\n\tfunction compilePredicate(src: string): ((text: string, raw: string) => unknown) | null {\n\t\tif (predicateCache.has(src)) return predicateCache.get(src) ?? null;\n\t\tlet fn: ((text: string, raw: string) => unknown) | null = null;\n\t\t// `predicate` conditions are serialized functions, so compiling them is the feature. The engine is\n\t\t// registered in an isolated world, where a strict page CSP does not block this.\n\t\ttry {\n\t\t\t// oxlint-disable-next-line typescript/no-implied-eval -- compiles a `predicate` condition, see above\n\t\t\tconst value: unknown = new Function(\"return (\" + src + \");\")();\n\t\t\tif (typeof value === \"function\") fn = value as (text: string, raw: string) => unknown;\n\t\t} catch {\n\t\t\t// Method shorthand (`predicate(t) { ... }`) is not a valid expression on its own.\n\t\t\ttry {\n\t\t\t\t// oxlint-disable-next-line typescript/no-implied-eval -- compiles a `predicate` condition, see above\n\t\t\t\tconst holder: unknown = new Function(\"return ({\" + src + \"});\")();\n\t\t\t\tif (holder !== null && typeof holder === \"object\") {\n\t\t\t\t\tconst values = Object.keys(holder).map(function (key) {\n\t\t\t\t\t\treturn (holder as Record<string, unknown>)[key];\n\t\t\t\t\t});\n\t\t\t\t\tif (typeof values[0] === \"function\") fn = values[0] as (text: string, raw: string) => unknown;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tfn = null;\n\t\t\t}\n\t\t}\n\t\tpredicateCache.set(src, fn);\n\t\treturn fn;\n\t}\n\n\t/**\n\t * Compiles a condition once per query, so RegExps and expected texts are not rebuilt for every cell.\n\t * Throws for an invalid RegExp; the selector engine turns that into no match.\n\t */\n\tfunction compileMatcher(matcher: SerializedMatcher, header: string): TextTest {\n\t\tswitch (matcher.t) {\n\t\t\tcase \"s\": {\n\t\t\t\tconst expected = normalizeCell(matcher.v);\n\t\t\t\treturn function (text) {\n\t\t\t\t\treturn text === expected;\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase \"r\": {\n\t\t\t\tconst regexp = new RegExp(matcher.s, matcher.f);\n\t\t\t\treturn function (text) {\n\t\t\t\t\t// A global or sticky RegExp keeps its position between calls.\n\t\t\t\t\tregexp.lastIndex = 0;\n\t\t\t\t\treturn regexp.test(text);\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase \"c\":\n\t\t\t\treturn compileTextMatcher(matcher);\n\t\t\tcase \"o\": {\n\t\t\t\tconst ignoreCase = matcher.i === true;\n\t\t\t\tconst values = matcher.v.map(function (value) {\n\t\t\t\t\treturn ignoreCase ? normalizeCell(value).toLowerCase() : normalizeCell(value);\n\t\t\t\t});\n\t\t\t\treturn function (text) {\n\t\t\t\t\treturn values.indexOf(ignoreCase ? text.toLowerCase() : text) !== -1;\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase \"e\":\n\t\t\t\treturn function (text) {\n\t\t\t\t\treturn text === \"\";\n\t\t\t\t};\n\t\t\tcase \"f\":\n\t\t\t\treturn compilePredicateMatcher(matcher.src, header);\n\t\t\tcase \"g\":\n\t\t\t\treturn compileNumberMatcher(matcher);\n\t\t\tcase \"n\": {\n\t\t\t\tconst inner = compileMatcher(matcher.m, header);\n\t\t\t\treturn function (text, raw) {\n\t\t\t\t\treturn !inner(text, raw);\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase \"a\": {\n\t\t\t\tconst tests = compileAll(matcher.m, header);\n\t\t\t\treturn function (text, raw) {\n\t\t\t\t\treturn tests.some(function (test) {\n\t\t\t\t\t\treturn test(text, raw);\n\t\t\t\t\t});\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase \"l\": {\n\t\t\t\tconst tests = compileAll(matcher.m, header);\n\t\t\t\t// An empty list never matches.\n\t\t\t\treturn function (text, raw) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\ttests.length > 0 &&\n\t\t\t\t\t\ttests.every(function (test) {\n\t\t\t\t\t\t\treturn test(text, raw);\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn function () {\n\t\t\t\t\treturn false;\n\t\t\t\t};\n\t\t}\n\t}\n\n\tfunction compileTextMatcher(matcher: Extract<SerializedMatcher, { t: \"c\" }>): TextTest {\n\t\tconst expected = matcher.i ? normalizeCell(matcher.v).toLowerCase() : normalizeCell(matcher.v);\n\t\tconst op = matcher.op;\n\t\treturn function (text) {\n\t\t\tconst actual = matcher.i ? text.toLowerCase() : text;\n\t\t\tif (op === \"equals\") return actual === expected;\n\t\t\tif (op === \"contains\") return actual.indexOf(expected) !== -1;\n\t\t\tif (op === \"startsWith\") return actual.slice(0, expected.length) === expected;\n\t\t\treturn expected.length <= actual.length && actual.slice(actual.length - expected.length) === expected;\n\t\t};\n\t}\n\n\t/** A numeric condition. A cell that is not a number never matches. */\n\tfunction compileNumberMatcher(matcher: Extract<SerializedMatcher, { t: \"g\" }>): TextTest {\n\t\tconst op = matcher.op;\n\t\tconst low = matcher.v;\n\t\tconst high = matcher.w;\n\t\tconst decimal = matcher.d;\n\t\treturn function (text) {\n\t\t\tconst value = parseNumber(text, decimal);\n\t\t\tif (isNaN(value)) return false;\n\t\t\tif (op === \"gt\") return value > low;\n\t\t\tif (op === \"gte\") return value >= low;\n\t\t\tif (op === \"lt\") return value < low;\n\t\t\tif (op === \"lte\") return value <= low;\n\t\t\treturn value >= low && value <= high;\n\t\t};\n\t}\n\n\tfunction compileAll(matchers: SerializedMatcher[], header: string): TextTest[] {\n\t\treturn matchers.map(function (matcher) {\n\t\t\treturn compileMatcher(matcher, header);\n\t\t});\n\t}\n\n\t/**\n\t * A `predicate` condition. A predicate that cannot be compiled, throws, or returns a promise fails the\n\t * whole row, also inside `not`, `anyOf` or `allOf`: a broken predicate must not turn into a match. The\n\t * problem is reported when the engine function is evaluated directly.\n\t */\n\tfunction compilePredicateMatcher(src: string, header: string): TextTest {\n\t\tconst predicate = compilePredicate(src);\n\t\tif (predicate === null) reportPredicate(header, \"is not a function expression: \" + src.slice(0, 80));\n\t\treturn function (text, raw) {\n\t\t\tif (predicate === null) throw PREDICATE_FAILED;\n\t\t\tlet result: unknown;\n\t\t\ttry {\n\t\t\t\tresult = predicate(text, raw());\n\t\t\t} catch (error) {\n\t\t\t\treportPredicate(header, \"threw \" + describeError(error));\n\t\t\t\tthrow PREDICATE_FAILED;\n\t\t\t}\n\t\t\tif (result !== null && typeof result === \"object\" && typeof (result as { then?: unknown }).then === \"function\") {\n\t\t\t\treportPredicate(header, \"returned a promise; predicates must be synchronous\");\n\t\t\t\tthrow PREDICATE_FAILED;\n\t\t\t}\n\t\t\treturn Boolean(result);\n\t\t};\n\t}\n\n\t/** Thrown by a predicate that cannot run, and caught per row by `rowMatches`. */\n\tconst PREDICATE_FAILED = new Error(\"predicate failed\");\n\n\t/** Maximum number of predicate problems reported, so a predicate that throws for every row stays readable. */\n\tconst MAX_PREDICATE_ERRORS = 5;\n\n\tfunction reportPredicate(header: string, problem: string): void {\n\t\tif (predicateErrors === null || predicateErrors.length >= MAX_PREDICATE_ERRORS) return;\n\t\tconst message = \"Predicate for \" + JSON.stringify(header) + \" \" + problem;\n\t\tif (predicateErrors.indexOf(message) === -1) predicateErrors.push(message);\n\t}\n\n\tfunction describeError(error: unknown): string {\n\t\tif (error instanceof Error) return error.name + \": \" + error.message;\n\t\treturn typeof error === \"string\" ? error : String(JSON.stringify(error));\n\t}\n\n\tfunction unique(elements: Element[]): Element[] {\n\t\tconst result: Element[] = [];\n\t\tconst seen = new Set<Element>();\n\t\tfor (const el of elements) {\n\t\t\tif (!seen.has(el)) {\n\t\t\t\tseen.add(el);\n\t\t\t\tresult.push(el);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t/** The grid column of a header key or column index, or -1 if there is none. */\n\tfunction columnOf(model: TableModel, column: string | number): number {\n\t\tif (typeof column === \"number\") return column >= 0 && column % 1 === 0 ? column : -1;\n\t\treturn model.keys.indexOf(normalizeLine(column));\n\t}\n\n\t/** The text of body row `r` in grid column `c`. Positions without a cell read as an empty string. */\n\tfunction cellText(model: TableModel, r: number, c: number): string {\n\t\tconst cell = model.body().grid[r]?.[c];\n\t\treturn cell === undefined ? \"\" : textOf(model, cell.el);\n\t}\n\n\t/** The raw text of body row `r` in grid column `c`. Positions without a cell read as an empty string. */\n\tfunction cellRaw(model: TableModel, r: number, c: number): string {\n\t\tconst cell = model.body().grid[r]?.[c];\n\t\treturn cell === undefined ? \"\" : rawOf(model, cell.el);\n\t}\n\n\t/** The number of grid columns: the header keys, or the widest body row if that is wider. */\n\tfunction gridWidth(model: TableModel): number {\n\t\tlet width = model.keys.length;\n\t\tfor (const line of model.body().grid) {\n\t\t\tif (line.length > width) width = line.length;\n\t\t}\n\t\treturn width;\n\t}\n\n\t/**\n\t * The grid column of a condition: of its header key, or its column index (up to the widest body row),\n\t * or -1 if the table has no such column.\n\t */\n\tfunction conditionColumn(model: TableModel, header: string | number): number {\n\t\tif (typeof header === \"string\") return model.keys.indexOf(normalizeLine(header));\n\t\treturn header >= 0 && header % 1 === 0 && header < gridWidth(model) ? header : -1;\n\t}\n\n\t/** The conditions of `where` with the grid columns of their headers, or `null` if a header is unknown. */\n\tfunction whereColumns(model: TableModel, where: SerializedWhere): ColumnCondition[] | null {\n\t\tconst conditions: ColumnCondition[] = [];\n\t\tfor (const condition of where) {\n\t\t\tconst column = conditionColumn(model, condition.h);\n\t\t\tif (column === -1) return null;\n\t\t\tconditions.push({ column: column, test: compileMatcher(condition.m, String(condition.h)) });\n\t\t}\n\t\treturn conditions;\n\t}\n\n\t/** The headers (or column indexes) of the conditions in `expected` that the table doesn't have. */\n\tfunction unknownHeaders(model: TableModel, expected: SerializedWhere[]): (string | number)[] {\n\t\tconst unknown: (string | number)[] = [];\n\t\tfor (const where of expected) {\n\t\t\tfor (const condition of where) {\n\t\t\t\tconst header = condition.h;\n\t\t\t\tif (conditionColumn(model, header) === -1 && unknown.indexOf(header) === -1) unknown.push(header);\n\t\t\t}\n\t\t}\n\t\treturn unknown;\n\t}\n\n\t/** Whether row `r` matches every condition. A predicate that cannot run fails the row. */\n\tfunction rowMatches(model: TableModel, r: number, conditions: ColumnCondition[]): boolean {\n\t\ttry {\n\t\t\treturn conditions.every(function (condition) {\n\t\t\t\treturn condition.test(cellText(model, r, condition.column), function () {\n\t\t\t\t\treturn cellRaw(model, r, condition.column);\n\t\t\t\t});\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error === PREDICATE_FAILED) return false;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tfunction queryRows(root: Node, query: Extract<EngineQuery, { op: \"row\" }>): Element[] {\n\t\tconst model = getModel(root, query.cfg);\n\t\tif (model === null || query.where.length === 0) return [];\n\t\tconst conditions = whereColumns(model, query.where);\n\t\tif (conditions === null) return [];\n\t\treturn model.body().rows.filter(function (_row, r) {\n\t\t\treturn rowMatches(model, r, conditions);\n\t\t});\n\t}\n\n\tfunction queryCell(root: Node, query: Extract<EngineQuery, { op: \"cell\" }>): Element[] {\n\t\tif (!isElement(root)) return [];\n\t\tconst row = root;\n\t\t// The owning table is the first ancestor with its own header row that contains this row as a body\n\t\t// row and has the column. A container of a split row (such as pinned columns) can look like a table\n\t\t// with only some of the columns, so the search goes on when the column is missing. Column indexes\n\t\t// don't need a header row, so without one they fall back to the first ancestor that has the row.\n\t\t// The search goes up through shadow hosts, so a row inside a shadow root finds its table.\n\t\t// Only a row with an `aria-rowindex` can be split, so any other row stops at the first table that\n\t\t// has it: further up, the header rows of other tables would mix in.\n\t\tconst byIndex = typeof query.header === \"number\";\n\t\tconst splittable = row.hasAttribute(\"aria-rowindex\");\n\t\tconst headerRow = resolveConfig(query.cfg).headerRow;\n\t\tlet fallback: Element[] | null = null;\n\t\tlet ancestor = parentOf(row);\n\t\twhile (ancestor !== null) {\n\t\t\tif ((byIndex && fallback === null) || hasHeaderRow(ancestor, headerRow)) {\n\t\t\t\tconst model = getModel(ancestor, query.cfg);\n\t\t\t\tif (model !== null && (model.body().rowOf.has(row) || model.footer().rowOf.has(row))) {\n\t\t\t\t\tconst cell = cellAt(model, row, query.header);\n\t\t\t\t\tif (model.hasHeader && (cell.length > 0 || !splittable)) return cell;\n\t\t\t\t\tif (!model.hasHeader && fallback === null) fallback = cell;\n\t\t\t\t}\n\t\t\t}\n\t\t\tancestor = parentOf(ancestor);\n\t\t}\n\t\treturn fallback ?? [];\n\t}\n\n\tfunction cellAt(model: TableModel, row: Element, header: string | number): Element[] {\n\t\tconst body = model.body().rowOf.has(row) ? model.body() : model.footer();\n\t\tconst rowIndex = body.rowOf.get(row);\n\t\tconst column = columnOf(model, header);\n\t\tconst cell = rowIndex === undefined || column === -1 ? undefined : body.grid[rowIndex]?.[column];\n\t\treturn cell === undefined ? [] : [cell.el];\n\t}\n\n\tfunction queryAllRows(root: Node, query: Extract<EngineQuery, { op: \"rows\" }>): Element[] {\n\t\tconst model = getModel(root, query.cfg);\n\t\treturn model === null ? [] : model.body().rows;\n\t}\n\n\tfunction queryColumn(root: Node, query: Extract<EngineQuery, { op: \"column\" }>): Element[] {\n\t\tconst model = getModel(root, query.cfg);\n\t\tif (model === null) return [];\n\t\tconst column = columnOf(model, query.header);\n\t\tif (column === -1) return [];\n\t\tconst cells: Element[] = [];\n\t\tconst lines = query.f === 1 ? model.body().grid.concat(model.footer().grid) : model.body().grid;\n\t\tfor (const line of lines) {\n\t\t\tconst cell = line[column];\n\t\t\tif (cell !== undefined) cells.push(cell.el);\n\t\t}\n\t\treturn unique(cells);\n\t}\n\n\tfunction queryFooter(root: Node, query: Extract<EngineQuery, { op: \"footer\" }>): Element[] {\n\t\tconst model = getModel(root, query.cfg);\n\t\treturn model === null ? [] : model.footer().rows;\n\t}\n\n\tfunction queryHeader(root: Node, query: Extract<EngineQuery, { op: \"header\" }>): Element[] {\n\t\tconst model = getModel(root, query.cfg);\n\t\tif (model === null) return [];\n\t\tconst column = columnOf(model, query.header);\n\t\tconst cell = column === -1 ? undefined : model.headerCells[column];\n\t\treturn cell === undefined ? [] : [cell];\n\t}\n\n\t/**\n\t * Header keys and the text of every body cell (or only under `columns`, in that order): normalized, or\n\t * with `raw`, as the browser reads it. Without `columns`, a row has a text for every grid column, also\n\t * in a table without header rows or with body rows wider than the header.\n\t */\n\tfunction readTexts(model: TableModel, raw: boolean, columns?: string[]): EngineTexts {\n\t\tconst indexes: number[] = [];\n\t\tif (columns === undefined) {\n\t\t\tconst width = gridWidth(model);\n\t\t\tfor (let c = 0; c < width; c++) indexes.push(c);\n\t\t} else {\n\t\t\tfor (const key of columns) indexes.push(model.keys.indexOf(normalizeLine(key)));\n\t\t}\n\t\tconst rows: string[][] = [];\n\t\tfor (let r = 0; r < model.body().rows.length; r++) {\n\t\t\tconst texts: string[] = [];\n\t\t\tfor (const c of indexes) {\n\t\t\t\ttexts.push(c === -1 ? \"\" : raw ? cellRaw(model, r, c) : cellText(model, r, c));\n\t\t\t}\n\t\t\trows.push(texts);\n\t\t}\n\t\treturn { keys: model.keys, rows: rows };\n\t}\n\n\t/**\n\t * A hash (FNV-1a) of the header keys and the text of every body cell, with the number of body rows. The\n\t * texts are hashed one by one, without building one string of the whole table.\n\t */\n\tfunction fingerprint(model: TableModel): EngineFingerprint {\n\t\tlet hash = 0x811c9dc5;\n\t\tlet length = 0;\n\t\t// Separators between cells (1) and rows (2), so [\"ab\", \"\"] and [\"a\", \"b\"] hash differently.\n\t\tfunction add(text: string, separator: number): void {\n\t\t\tfor (let i = 0; i < text.length; i++) {\n\t\t\t\thash ^= text.charCodeAt(i);\n\t\t\t\thash = Math.imul(hash, 0x01000193);\n\t\t\t}\n\t\t\thash ^= separator;\n\t\t\thash = Math.imul(hash, 0x01000193);\n\t\t\tlength += text.length + 1;\n\t\t}\n\t\tfor (const key of model.keys) add(key, 1);\n\t\tadd(\"\", 2);\n\t\tconst rows = model.body().rows.length;\n\t\tconst width = gridWidth(model);\n\t\tfor (let r = 0; r < rows; r++) {\n\t\t\tfor (let c = 0; c < width; c++) add(cellText(model, r, c), 1);\n\t\t\tadd(\"\", 2);\n\t\t}\n\t\treturn { rows: rows, hash: (hash >>> 0).toString(16) + \":\" + length };\n\t}\n\n\t/** Attributes that identify a row in virtualized grids, in the order they are tried. */\n\tconst ROW_KEY_ATTRIBUTES = [\"aria-rowindex\", \"row-index\", \"data-rowindex\", \"data-index\", \"data-id\"];\n\t/** The row key attributes that hold the position of the row, so rows can be ordered by them. */\n\tconst ROW_POSITION_ATTRIBUTES = [\"aria-rowindex\", \"row-index\", \"data-rowindex\", \"data-index\"];\n\n\t/**\n\t * The body rows in view, with a key per row: the `rowKey` attribute, or the first of the default key\n\t * attributes, or else the normalized cell texts and how often the same texts came before in this view,\n\t * so identical rows stay apart. Only a position attribute gives a row an `index` to order by: an id\n\t * such as `data-id` says nothing about where the row is shown.\n\t */\n\tfunction readWindow(model: TableModel, request: EngineWindowRequest): EngineWindow {\n\t\tconst texts = readTexts(model, request.raw === true, request.columns);\n\t\tlet all: string[][] | null = request.raw !== true && request.columns === undefined ? texts.rows : null;\n\t\tconst names = request.rowKey === undefined ? ROW_KEY_ATTRIBUTES : [request.rowKey];\n\t\tconst seen = new Map<string, number>();\n\t\tconst rows = model.body().rows.map(function (row, r) {\n\t\t\tlet attribute: string | null = null;\n\t\t\tlet name = \"\";\n\t\t\tfor (const candidate of names) {\n\t\t\t\tattribute = nonEmpty(row.getAttribute(candidate));\n\t\t\t\tname = candidate;\n\t\t\t\tif (attribute !== null) break;\n\t\t\t}\n\t\t\tconst cells = texts.rows[r] ?? [];\n\t\t\tif (attribute === null) {\n\t\t\t\tall ??= readTexts(model, false).rows;\n\t\t\t\tconst text = JSON.stringify(all[r] ?? []);\n\t\t\t\tconst count = seen.get(text) ?? 0;\n\t\t\t\tseen.set(text, count + 1);\n\t\t\t\treturn { key: \"text:\" + text + \"#\" + count, index: null, texts: cells };\n\t\t\t}\n\t\t\tconst index = ROW_POSITION_ATTRIBUTES.indexOf(name) === -1 ? NaN : Number(attribute);\n\t\t\treturn { key: attribute, index: isFinite(index) ? index : null, texts: cells };\n\t\t});\n\t\treturn { keys: texts.keys, rows: rows };\n\t}\n\n\t/**\n\t * The `aria-rowcount` of the grid (on `root`, inside it, or around it), and the number of rows it counts\n\t * that are not body rows: the other rows of the grid, by `aria-rowindex` when they have one.\n\t */\n\tfunction readTotal(root: Element, model: TableModel): EngineTotal {\n\t\tconst body = model.body();\n\t\tconst anyCell = unionSel(model.cfg.headerCell, model.cfg.bodyCell);\n\t\t// Not the aria-rowcount of a grid nested in a cell of this one\n\t\tconst inside = Array.from(root.querySelectorAll(\"[aria-rowcount]\")).find(function (el) {\n\t\t\treturn owned(el, root, anyCell) && !matchesSel(el, anyCell);\n\t\t});\n\t\tconst holder = root.hasAttribute(\"aria-rowcount\") ? root : (inside ?? root.closest(\"[aria-rowcount]\"));\n\t\tconst count = holder === null ? NaN : parseInt(holder.getAttribute(\"aria-rowcount\") ?? \"\", 10);\n\t\tconst scope = holder !== null && holder.contains(root) ? holder : root;\n\t\tconst others = new Set<string>();\n\t\townRows(scope, ANY_ROW, anyCell, hasShadowHost(scope)).forEach(function (row, i) {\n\t\t\tif (body.rowOf.has(row)) return;\n\t\t\tothers.add(row.getAttribute(\"aria-rowindex\") ?? \"row \" + i);\n\t\t});\n\t\treturn {\n\t\t\tariaRowCount: isNaN(count) || count < 0 ? null : count,\n\t\t\totherRows: others.size,\n\t\t\tbodyRows: body.rows.length,\n\t\t};\n\t}\n\n\t/**\n\t * The text of every body cell in `column`, or `null` if there is no such column. A column index works\n\t * without header rows, up to the widest body row.\n\t */\n\tfunction readValues(model: TableModel, column: string | number): EngineValues {\n\t\tconst body = model.body();\n\t\tconst c = columnOf(model, column);\n\t\tif (c === -1 || c >= gridWidth(model)) return { keys: model.keys, values: null };\n\t\tconst values: string[] = [];\n\t\tfor (let r = 0; r < body.rows.length; r++) {\n\t\t\tvalues.push(cellText(model, r, c));\n\t\t}\n\t\treturn { keys: model.keys, values: values };\n\t}\n\n\tfunction matchRows(model: TableModel, expected: SerializedWhere[], withTexts: boolean): EngineMatchResult {\n\t\tconst unknown = unknownHeaders(model, expected);\n\t\tconst count = model.body().rows.length;\n\t\t// Only rows that exist both in the table and in `expected` are matched.\n\t\tconst matched = expected.slice(0, count).map(function (where, r) {\n\t\t\tconst conditions = whereColumns(model, where);\n\t\t\treturn conditions !== null && rowMatches(model, r, conditions);\n\t\t});\n\t\tconst pass =\n\t\t\tunknown.length === 0 &&\n\t\t\tcount === expected.length &&\n\t\t\tmatched.every(function (ok) {\n\t\t\t\treturn ok;\n\t\t\t});\n\t\t// The texts are only needed to describe a mismatch, and only once: on request, and never for a match.\n\t\tconst rows = pass || !withTexts ? [] : readTexts(model, false).rows;\n\t\treturn {\n\t\t\tkeys: model.keys,\n\t\t\trows: rows,\n\t\t\tcount: count,\n\t\t\tmatched: matched,\n\t\t\tunknown: unknown,\n\t\t\terrors: predicateErrors ?? [],\n\t\t};\n\t}\n\n\t/** Runs the conditions of `where` against every body row, to count the matches and collect predicate problems. */\n\tfunction findRows(model: TableModel, where: SerializedWhere): EngineFindResult {\n\t\tconst conditions = whereColumns(model, where);\n\t\tlet matches = 0;\n\t\tif (conditions !== null) {\n\t\t\tfor (let r = 0; r < model.body().rows.length; r++) {\n\t\t\t\tif (rowMatches(model, r, conditions)) matches++;\n\t\t\t}\n\t\t}\n\t\treturn { matches: matches, errors: predicateErrors ?? [] };\n\t}\n\n\t/**\n\t * For each set of conditions in `expected`, the indexes of the body rows that match it. With `assign`,\n\t * instead the body row each set gets in {@link assignRows}.\n\t */\n\tfunction matrixRows(model: TableModel, expected: SerializedWhere[], assign: boolean): EngineMatrixResult {\n\t\tconst count = model.body().rows.length;\n\t\tif (assign) {\n\t\t\treturn {\n\t\t\t\tkeys: model.keys,\n\t\t\t\tcount: count,\n\t\t\t\tmatches: [],\n\t\t\t\tassigned: assignRows(\n\t\t\t\t\tmodel,\n\t\t\t\t\texpected.map(function (where) {\n\t\t\t\t\t\treturn whereColumns(model, where);\n\t\t\t\t\t})\n\t\t\t\t),\n\t\t\t\tunknown: unknownHeaders(model, expected),\n\t\t\t\terrors: predicateErrors ?? [],\n\t\t\t};\n\t\t}\n\t\tconst matches = expected.map(function (where) {\n\t\t\tconst conditions = whereColumns(model, where);\n\t\t\tconst found: number[] = [];\n\t\t\tif (conditions === null) return found;\n\t\t\tfor (let r = 0; r < count; r++) {\n\t\t\t\tif (rowMatches(model, r, conditions)) found.push(r);\n\t\t\t}\n\t\t\treturn found;\n\t\t});\n\t\treturn {\n\t\t\tkeys: model.keys,\n\t\t\tcount: count,\n\t\t\tmatches: matches,\n\t\t\tunknown: unknownHeaders(model, expected),\n\t\t\terrors: predicateErrors ?? [],\n\t\t};\n\t}\n\n\t/**\n\t * Gives each entry a different body row it matches, as many as possible (a maximum bipartite matching),\n\t * so overlapping entries such as `{ Status: \"Active\" }` and `{ Name: \"John\" }` don't take each other's\n\t * rows. Returns the body row of every entry, or -1 for the ones left without (and for an entry with an\n\t * unknown header, `null` in `entries`).\n\t *\n\t * Rows are tested only when needed, so thousands of entries don't test every row: a greedy pass gives\n\t * each entry the first free row it matches, and only the entries left without one search for a chain\n\t * of rows to swap (an augmenting path), with a stack instead of recursion.\n\t */\n\tfunction assignRows(model: TableModel, entries: (ColumnCondition[] | null)[]): number[] {\n\t\tconst count = model.body().rows.length;\n\t\tconst assigned: number[] = [];\n\t\tconst owner = new Map<number, number>();\n\t\tentries.forEach(function (conditions, entry) {\n\t\t\tassigned.push(-1);\n\t\t\tif (conditions === null) return;\n\t\t\tfor (let r = 0; r < count; r++) {\n\t\t\t\tif (!owner.has(r) && rowMatches(model, r, conditions)) {\n\t\t\t\t\towner.set(r, entry);\n\t\t\t\t\tassigned[entry] = r;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tentries.forEach(function (conditions, entry) {\n\t\t\tif (conditions !== null && assigned[entry] === -1) augment(model, entries, entry, owner, assigned);\n\t\t});\n\t\treturn assigned;\n\t}\n\n\t/**\n\t * Gives entry `start` a row: a free one it matches, or one whose owner moves to another row it matches,\n\t * and so on (searched depth first). Updates `owner` and `assigned`.\n\t */\n\tfunction augment(\n\t\tmodel: TableModel,\n\t\tentries: (ColumnCondition[] | null)[],\n\t\tstart: number,\n\t\towner: Map<number, number>,\n\t\tassigned: number[]\n\t): void {\n\t\tconst count = model.body().rows.length;\n\t\tconst seen = new Set<number>();\n\t\t// The entries on the path, with the next row each one tries, and the row each one takes\n\t\tconst path: { entry: number; next: number }[] = [{ entry: start, next: 0 }];\n\t\tconst taken: number[] = [];\n\t\twhile (path.length > 0) {\n\t\t\tconst level = path.length - 1;\n\t\t\tconst step = path[level] as { entry: number; next: number };\n\t\t\tconst conditions = entries[step.entry];\n\t\t\tif (step.next >= count || conditions === null || conditions === undefined) {\n\t\t\t\tpath.pop();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst r = step.next++;\n\t\t\tif (seen.has(r) || !rowMatches(model, r, conditions)) continue;\n\t\t\tseen.add(r);\n\t\t\ttaken[level] = r;\n\t\t\tconst current = owner.get(r);\n\t\t\tif (current !== undefined) {\n\t\t\t\tpath.push({ entry: current, next: 0 });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// A free row: every entry on the path takes its row, and the owner of that row moves on.\n\t\t\tfor (let i = 0; i < path.length; i++) {\n\t\t\t\tconst entry = (path[i] as { entry: number }).entry;\n\t\t\t\tconst row = taken[i] as number;\n\t\t\t\towner.set(row, entry);\n\t\t\t\tassigned[entry] = row;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\n\tfunction queryAll(root: Node, body: string): Element[] {\n\t\ttry {\n\t\t\tconst query = JSON.parse(body) as EngineQuery;\n\t\t\tswitch (query.op) {\n\t\t\t\tcase \"rows\":\n\t\t\t\t\treturn queryAllRows(root, query);\n\t\t\t\tcase \"row\":\n\t\t\t\t\treturn queryRows(root, query);\n\t\t\t\tcase \"cell\":\n\t\t\t\t\treturn queryCell(root, query);\n\t\t\t\tcase \"column\":\n\t\t\t\t\treturn queryColumn(root, query);\n\t\t\t\tcase \"header\":\n\t\t\t\t\treturn queryHeader(root, query);\n\t\t\t\tcase \"footer\":\n\t\t\t\t\treturn queryFooter(root, query);\n\t\t\t\tdefault:\n\t\t\t\t\treturn [];\n\t\t\t}\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}\n\n\t/** Answers a request that reads the table. */\n\tfunction read(\n\t\tmodel: TableModel | null,\n\t\trequest:\n\t\t\t| EngineKeysRequest\n\t\t\t| EngineTextsRequest\n\t\t\t| EngineValuesRequest\n\t\t\t| EngineFingerprintRequest\n\t\t\t| EngineWindowRequest\n\t): string[] | EngineTexts | EngineValues | EngineFingerprint | EngineWindow {\n\t\tif (request.op === \"keys\") return model === null ? [] : model.keys;\n\t\tif (request.op === \"texts\") {\n\t\t\treturn model === null ? { keys: [], rows: [] } : readTexts(model, request.raw === true, request.columns);\n\t\t}\n\t\tif (request.op === \"values\") return model === null ? { keys: [], values: null } : readValues(model, request.column);\n\t\tif (request.op === \"window\") return model === null ? { keys: [], rows: [] } : readWindow(model, request);\n\t\treturn model === null ? { rows: 0, hash: \"\" } : fingerprint(model);\n\t}\n\n\t/** Answers a request that matches conditions, collecting the problems with `predicate` conditions. */\n\tfunction match(\n\t\tmodel: TableModel | null,\n\t\trequest: EngineFindRequest | EngineMatchRequest | EngineMatrixRequest\n\t): EngineFindResult | EngineMatchResult | EngineMatrixResult {\n\t\tpredicateErrors = [];\n\t\tif (request.op === \"find\") return model === null ? { matches: 0, errors: [] } : findRows(model, request.where);\n\t\tif (request.op === \"matrix\") {\n\t\t\treturn model === null\n\t\t\t\t? { keys: [], count: 0, matches: [], unknown: [], errors: [] }\n\t\t\t\t: matrixRows(model, request.rows, request.assign === 1);\n\t\t}\n\t\treturn model === null\n\t\t\t? { keys: [], rows: [], count: 0, matched: [], unknown: [], errors: [] }\n\t\t\t: matchRows(model, request.rows, request.texts === 1);\n\t}\n\n\tif (root !== undefined && request !== undefined) {\n\t\tconst cfg = resolveConfig(request.cfg);\n\t\tif (request.op === \"text\") return normalizeCell(readText(root, cfg, cfg.inputs));\n\t\tif (request.op === \"total\") {\n\t\t\tconst totalModel = buildModel(root, cfg);\n\t\t\treturn totalModel === null ? { ariaRowCount: null, otherRows: 0, bodyRows: 0 } : readTotal(root, totalModel);\n\t\t}\n\t\tconst model = buildModel(root, cfg);\n\t\tif (request.op === \"find\" || request.op === \"match\" || request.op === \"matrix\") return match(model, request);\n\t\treturn read(model, request);\n\t}\n\n\treturn {\n\t\tquery: function (root: Node, body: string): Element | null {\n\t\t\treturn queryAll(root, body)[0] ?? null;\n\t\t},\n\t\tqueryAll: queryAll,\n\t\tnormalizeLine: normalizeLine,\n\t\tnormalizeCell: normalizeCell,\n\t\tparseNumber: parseNumber,\n\t\tdefaultIgnore: DEFAULT_IGNORE.slice(),\n\t};\n}\n\n/**\n * The engine function typed for its \"keys\" mode, for use with `locator.evaluate`.\n * Same function object as {@link tableSelectorEngine}.\n *\n * @internal\n */\nexport const readTableHeaderKeys: (root: Element, request: EngineKeysRequest) => string[] = tableSelectorEngine;\n\n/**\n * The engine function typed for its \"texts\" mode, for use with `locator.evaluate`.\n * Same function object as {@link tableSelectorEngine}.\n *\n * @internal\n */\nexport const readTableTexts: (root: Element, request: EngineTextsRequest) => EngineTexts = tableSelectorEngine;\n\n/**\n * The engine function typed for its \"match\" mode, for use with `locator.evaluate`.\n * Same function object as {@link tableSelectorEngine}.\n *\n * @internal\n */\nexport const matchTableRows: (root: Element, request: EngineMatchRequest) => EngineMatchResult = tableSelectorEngine;\n\n/**\n * The engine function typed for its \"values\" mode, for use with `locator.evaluate`.\n * Same function object as {@link tableSelectorEngine}.\n *\n * @internal\n */\nexport const readColumnValues: (root: Element, request: EngineValuesRequest) => EngineValues = tableSelectorEngine;\n\n/**\n * The engine function typed for its \"find\" mode, for use with `locator.evaluate`.\n * Same function object as {@link tableSelectorEngine}.\n *\n * @internal\n */\nexport const findTableRows: (root: Element, request: EngineFindRequest) => EngineFindResult = tableSelectorEngine;\n\n/**\n * The engine function typed for its \"text\" mode, for use with `locator.evaluate` on a body cell.\n * Same function object as {@link tableSelectorEngine}.\n *\n * @internal\n */\nexport const readCellText: (root: Element, request: EngineTextRequest) => string = tableSelectorEngine;\n\n/**\n * The engine function typed for its \"fingerprint\" mode, for use with `locator.evaluate`.\n * Same function object as {@link tableSelectorEngine}.\n *\n * @internal\n */\nexport const readTableFingerprint: (root: Element, request: EngineFingerprintRequest) => EngineFingerprint =\n\ttableSelectorEngine;\n\n/**\n * The engine function typed for its \"matrix\" mode, for use with `locator.evaluate`.\n * Same function object as {@link tableSelectorEngine}.\n *\n * @internal\n */\nexport const matchTableMatrix: (root: Element, request: EngineMatrixRequest) => EngineMatrixResult =\n\ttableSelectorEngine;\n\n/**\n * The engine function typed for its \"window\" mode, for use with `locator.evaluate`.\n * Same function object as {@link tableSelectorEngine}.\n *\n * @internal\n */\nexport const readTableWindow: (root: Element, request: EngineWindowRequest) => EngineWindow = tableSelectorEngine;\n\n/**\n * The engine function typed for its \"total\" mode, for use with `locator.evaluate`.\n * Same function object as {@link tableSelectorEngine}.\n *\n * @internal\n */\nexport const readTableTotal: (root: Element, request: EngineTotalRequest) => EngineTotal = tableSelectorEngine;\n\nconst engine = tableSelectorEngine();\n\n/**\n * Normalizes text to one line, exactly as the engine normalizes header text: icon glyphs and invisible\n * characters are removed, accents are composed (NFC), and every run of whitespace (line breaks included)\n * becomes one space. Header names passed to {@link TableLocator} are normalized with it.\n *\n * @internal\n */\nexport const normalizeLine: (text: string) => string = engine.normalizeLine;\n\n/**\n * Normalizes text exactly as the engine normalizes body cell text: like {@link normalizeLine}, but line\n * breaks stay, as one `\\n` between trimmed, non-empty lines.\n *\n * @internal\n */\nexport const normalizeCell: (text: string) => string = engine.normalizeCell;\n\n/**\n * Parses the one number in a text exactly as numeric cell conditions do, or returns `NaN`. See\n * {@link DecimalSeparator} for the rules.\n *\n * @internal\n */\nexport const parseNumber: (text: string, decimal: DecimalSeparator) => number = engine.parseNumber;\n\n/**\n * The default `ignore` option of {@link TableLocator}: CSS selectors of the elements inside a cell whose\n * text is left out. They cover screen reader only text (`.sr-only`, `.visually-hidden`), ligature icons\n * (Material Icons and Material Symbols, whose text such as `arrow_upward` is drawn as an icon) and\n * decorative content (`[aria-hidden=true]`).\n *\n * Spread it to add your own selectors: `ignore: [...DEFAULT_IGNORE, \".sort-icon\"]`.\n */\nexport const DEFAULT_IGNORE: readonly string[] = Object.freeze(engine.defaultIgnore);\n","import {\n\tCellCondition,\n\tCellMatcher,\n\tDecimalSeparator,\n\tElementSelector,\n\tRowWhere,\n\tSerializedMatcher,\n\tSerializedSelector,\n\tSerializedText,\n\tSerializedWhere,\n} from \"./table-locator.types\";\nimport { normalizeLine } from \"./table-selector-engine\";\n\n/**\n * Converts row conditions to the wire format of the `pw-table-v1` engine. Headers without a value are\n * skipped. Header names are normalized like header text, so `\"First\\nname\"` finds `First name`.\n *\n * @internal\n */\nexport function serializeWhere(where: RowWhere<string>): SerializedWhere {\n\tconst conditions: SerializedWhere = [];\n\tconst entries: [string, CellMatcher | undefined][] = Object.entries(where);\n\tfor (const [header, matcher] of entries) {\n\t\tif (matcher !== undefined) {\n\t\t\tconditions.push({ h: normalizeLine(header), m: serializeMatcher(header, matcher) });\n\t\t}\n\t}\n\treturn conditions;\n}\n\n/**\n * Describes row conditions for messages and locator descriptions, such as `{ \"Name\": \"John\" }`.\n *\n * @internal\n */\nexport function describeWhere(where: RowWhere<string>): string {\n\tconst entries: [string, CellMatcher | undefined][] = Object.entries(where);\n\tconst parts = entries\n\t\t.filter((entry): entry is [string, CellMatcher] => entry[1] !== undefined)\n\t\t.map(([header, matcher]) => `${JSON.stringify(header)}: ${describeMatcher(matcher)}`);\n\treturn `{ ${parts.join(\", \")} }`;\n}\n\n/**\n * Describes one cell matcher for messages, such as `\"John\"`, `/^J/` or `{ \"gt\": 5 }`.\n *\n * @internal\n */\nexport function describeMatcher(matcher: CellMatcher): string {\n\tif (typeof matcher === \"string\") return JSON.stringify(matcher);\n\tif (matcher instanceof RegExp) return String(matcher);\n\tif (matcher.predicate !== undefined) return `{ predicate: ${matcher.predicate.toString()} }`;\n\tif (matcher.not !== undefined) return `{ not: ${describeMatcher(matcher.not)} }`;\n\tif (matcher.anyOf !== undefined) return `{ anyOf: [${matcher.anyOf.map(describeMatcher).join(\", \")}] }`;\n\tif (matcher.allOf !== undefined) return `{ allOf: [${matcher.allOf.map(describeMatcher).join(\", \")}] }`;\n\treturn JSON.stringify(matcher);\n}\n\n/**\n * Converts one cell matcher to the wire format of the `pw-table-v1` engine.\n *\n * @internal\n */\nexport function serializeMatcher(header: string, matcher: CellMatcher): SerializedMatcher {\n\t// Typed as a matcher, but JavaScript callers can pass anything, such as `null` from a missing value.\n\tconst value: unknown = matcher;\n\tif (value === null || (typeof value !== \"string\" && typeof value !== \"object\")) {\n\t\tthrow new TypeError(`Condition for header \"${header}\" is not a supported cell matcher: ${String(value)}.`);\n\t}\n\tif (typeof matcher === \"string\") {\n\t\treturn { t: \"s\", v: matcher };\n\t}\n\tif (matcher instanceof RegExp) {\n\t\treturn { t: \"r\", s: matcher.source, f: matcher.flags };\n\t}\n\tif (matcher.predicate !== undefined) {\n\t\treturn serializePredicate(header, matcher.predicate);\n\t}\n\tif (matcher.empty !== undefined) {\n\t\treturn matcher.empty ? { t: \"e\" } : { t: \"n\", m: { t: \"e\" } };\n\t}\n\tconst text = serializeTextCondition(header, matcher);\n\tif (text !== undefined) return text;\n\tconst number = serializeNumberCondition(header, matcher);\n\tif (number !== undefined) return number;\n\tif (matcher.not !== undefined) {\n\t\treturn { t: \"n\", m: serializeMatcher(header, matcher.not) };\n\t}\n\tif (matcher.anyOf !== undefined) {\n\t\treturn { t: \"a\", m: serializeMatchers(header, \"anyOf\", matcher.anyOf) };\n\t}\n\tif (matcher.allOf !== undefined) {\n\t\treturn { t: \"l\", m: serializeMatchers(header, \"allOf\", matcher.allOf) };\n\t}\n\t// The type covers every kind of condition, but JavaScript callers can pass any object.\n\tthrow new TypeError(`Condition for header \"${header}\" is not a supported cell matcher.`);\n}\n\nfunction serializePredicate(header: string, predicate: unknown): SerializedMatcher {\n\t// Typed as a function, but JavaScript callers can pass anything.\n\tif (typeof predicate !== \"function\") {\n\t\tthrow new TypeError(`Condition for header \"${header}\": predicate must be a function.`);\n\t}\n\t// A generator or async function returns an object, which would match every row.\n\tconst kind = (predicate as { constructor?: { name?: string } }).constructor?.name;\n\tif (kind === \"GeneratorFunction\" || kind === \"AsyncFunction\" || kind === \"AsyncGeneratorFunction\") {\n\t\tthrow new TypeError(`Condition for header \"${header}\": predicate must be a synchronous function, not a ${kind}.`);\n\t}\n\tconst src = predicate.toString();\n\t// Bound and built-in functions have no source to send to the browser.\n\tif (src.includes(\"[native code]\")) {\n\t\tthrow new TypeError(\n\t\t\t`Condition for header \"${header}\": predicate must be a plain function, not a bound or built-in one.`\n\t\t);\n\t}\n\treturn { t: \"f\", src };\n}\n\n/**\n * The wire format of a text condition (`equals`, `contains`, `startsWith`, `endsWith` or `oneOf`, each\n * with `ignoreCase`), or `undefined` if `matcher` is another kind of condition.\n */\nfunction serializeTextCondition(header: string, matcher: CellCondition): SerializedMatcher | undefined {\n\tconst i = matcher.ignoreCase === true;\n\tif (matcher.oneOf !== undefined) {\n\t\tif (matcher.oneOf.length === 0) {\n\t\t\tthrow new TypeError(`Condition for header \"${header}\": oneOf needs at least one value.`);\n\t\t}\n\t\treturn i ? { t: \"o\", v: [...matcher.oneOf], i } : { t: \"o\", v: [...matcher.oneOf] };\n\t}\n\tif (matcher.equals !== undefined) return { t: \"c\", op: \"equals\", v: matcher.equals, i };\n\tif (matcher.contains !== undefined) return { t: \"c\", op: \"contains\", v: matcher.contains, i };\n\tif (matcher.startsWith !== undefined) return { t: \"c\", op: \"startsWith\", v: matcher.startsWith, i };\n\tif (matcher.endsWith !== undefined) return { t: \"c\", op: \"endsWith\", v: matcher.endsWith, i };\n\treturn undefined;\n}\n\n/** The wire format of a {@link NumberCondition}, or `undefined` if `matcher` is another kind of condition. */\nfunction serializeNumberCondition(header: string, matcher: CellCondition): SerializedMatcher | undefined {\n\tconst { decimal } = matcher;\n\tif (matcher.gt !== undefined) return serializeNumber(header, \"gt\", matcher.gt, matcher.gt, decimal);\n\tif (matcher.gte !== undefined) return serializeNumber(header, \"gte\", matcher.gte, matcher.gte, decimal);\n\tif (matcher.lt !== undefined) return serializeNumber(header, \"lt\", matcher.lt, matcher.lt, decimal);\n\tif (matcher.lte !== undefined) return serializeNumber(header, \"lte\", matcher.lte, matcher.lte, decimal);\n\tif (matcher.between === undefined) return undefined;\n\t// Typed as a pair, but JavaScript callers can pass anything.\n\tconst range: unknown = matcher.between;\n\tif (!Array.isArray(range) || range.length !== 2) {\n\t\tthrow new TypeError(`Condition for header \"${header}\": between must be a [min, max] pair.`);\n\t}\n\tconst [min, max] = matcher.between;\n\treturn serializeNumber(header, \"between\", min, max, decimal);\n}\n\nfunction serializeNumber(\n\theader: string,\n\top: \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"between\",\n\tvalue: number,\n\tupper: number,\n\tdecimal: DecimalSeparator | undefined\n): SerializedMatcher {\n\t// JSON turns NaN and Infinity into null, so they could never match as the caller meant.\n\tif (!Number.isFinite(value) || !Number.isFinite(upper)) {\n\t\tthrow new TypeError(`Condition for header \"${header}\": ${op} needs finite numbers.`);\n\t}\n\t// Typed as a separator, but JavaScript callers can pass anything.\n\tconst separator: unknown = decimal ?? \".\";\n\tif (separator !== \".\" && separator !== \",\") {\n\t\tthrow new TypeError(`Condition for header \"${header}\": decimal must be \".\" or \",\".`);\n\t}\n\treturn { t: \"g\", op, v: value, w: upper, d: separator };\n}\n\nfunction serializeMatchers(header: string, kind: string, matchers: readonly CellMatcher[]): SerializedMatcher[] {\n\tif (matchers.length === 0) {\n\t\tthrow new TypeError(`Condition for header \"${header}\": ${kind} needs at least one matcher.`);\n\t}\n\treturn matchers.map(matcher => serializeMatcher(header, matcher));\n}\n\nconst DESCRIPTOR_KEYS = [\"css\", \"role\", \"hasText\", \"hasNotText\"];\n\n/**\n * Converts an {@link ElementSelector} to the wire format of the `pw-table-v1` engine. A CSS selector stays\n * as it is. `option` names the option in errors, such as `\"row.rowSelector\"`.\n *\n * @internal\n */\nexport function serializeSelector(option: string, selector: ElementSelector): SerializedSelector {\n\tif (typeof selector === \"string\") return selector;\n\tcheckDescriptor(option, selector);\n\tconst serialized: Exclude<SerializedSelector, string> = {};\n\tif (selector.css !== undefined) serialized.c = serializeCss(option, selector.css);\n\tif (selector.role !== undefined) serialized.r = serializeRoles(option, selector.role);\n\tif (selector.hasText !== undefined) serialized.t = serializeText(option, \"hasText\", selector.hasText);\n\tif (selector.hasNotText !== undefined) serialized.n = serializeText(option, \"hasNotText\", selector.hasNotText);\n\tif (Object.keys(serialized).length === 0) {\n\t\tthrow new TypeError(`${option} is an empty descriptor: give it css, role, hasText or hasNotText.`);\n\t}\n\treturn serialized;\n}\n\n/** @throws TypeError if `selector` is not a plain object with only descriptor keys, such as a Locator. */\nfunction checkDescriptor(option: string, selector: unknown): void {\n\t// Typed as a descriptor, but JavaScript callers can pass anything.\n\tif (selector === null || typeof selector !== \"object\" || Array.isArray(selector) || selector instanceof RegExp) {\n\t\tthrow new TypeError(\n\t\t\t`${option} must be a CSS selector or a descriptor such as { role: \"row\" }, not ${String(selector)}.`\n\t\t);\n\t}\n\tconst unknown = Object.keys(selector).filter(key => !DESCRIPTOR_KEYS.includes(key));\n\tif (unknown.length > 0) {\n\t\tthrow new TypeError(\n\t\t\t`${option} has unknown keys (${unknown.join(\", \")}): a descriptor has css, role, hasText and hasNotText. ` +\n\t\t\t\t`A Playwright Locator can't be used here, because the table is read in the browser.`\n\t\t);\n\t}\n}\n\nfunction serializeCss(option: string, css: unknown): string {\n\tif (typeof css !== \"string\" || css.trim() === \"\") {\n\t\tthrow new TypeError(`${option}: css must be a non-empty CSS selector.`);\n\t}\n\treturn css;\n}\n\nfunction serializeRoles(option: string, role: unknown): string[] {\n\tconst roles: unknown = typeof role === \"string\" ? [role] : role;\n\tif (!Array.isArray(roles) || roles.length === 0 || !roles.every(item => typeof item === \"string\" && item !== \"\")) {\n\t\tthrow new TypeError(`${option}: role must be a role, such as \"row\", or a non-empty list of roles.`);\n\t}\n\treturn roles as string[];\n}\n\nfunction serializeText(option: string, key: string, text: string | RegExp): SerializedText {\n\tif (typeof text === \"string\") return { s: text };\n\tif (text instanceof RegExp) return { r: text.source, f: text.flags };\n\tthrow new TypeError(`${option}: ${key} must be a string or a RegExp.`);\n}\n","import { describeLastError, pollUntil } from \"./polling\";\nimport type { CellMatcher, RowWhere } from \"./table-locator.types\";\nimport { normalizeLine } from \"./table-selector-engine\";\n\n/** A table whose header keys can be read, such as a `TableLocator`. */\ntype HeaderSource = { headerKeys(options?: { timeout?: number }): Promise<string[]> };\n\n/**\n * Waits until the table has every header in `headers`, up to `deadline`. Returns the diagnostics for the\n * headers that are still unknown at the deadline, or `\"\"` once they are all known.\n *\n * @internal\n */\nexport async function waitForHeaders(\n\ttable: HeaderSource,\n\theaders: readonly string[],\n\tdeadline: number\n): Promise<string> {\n\tif (headers.length === 0) return \"\";\n\tconst missing = (keys: readonly string[]): string[] =>\n\t\theaders.filter(header => !keys.includes(normalizeLine(header)));\n\tconst poll = await pollUntil(\n\t\treadTimeout => table.headerKeys({ timeout: readTimeout }),\n\t\tkeys => missing(keys).length === 0,\n\t\t[] as string[],\n\t\tdeadline\n\t);\n\tconst unknown = missing(poll.value);\n\treturn unknown.length === 0 ? \"\" : describeUnknown(unknown, poll.value) + describeLastError(poll.error);\n}\n\n/**\n * A `Header \"…\" not found.` line per unknown header (or `Column … does not exist.` per column index), and the\n * available headers.\n *\n * @internal\n */\nexport function describeUnknown(unknown: readonly (string | number)[], available: readonly string[]): string {\n\treturn (\n\t\tunknown\n\t\t\t.map(header =>\n\t\t\t\ttypeof header === \"number\" ? `Column ${header} does not exist.\\n` : `Header \"${header}\" not found.\\n`\n\t\t\t)\n\t\t\t.join(\"\") + `Available headers: [${available.join(\", \")}]\\n`\n\t);\n}\n\n/**\n * The headers that have a condition.\n *\n * @internal\n */\nexport function conditionHeaders(where: RowWhere<string>): string[] {\n\tconst entries: [string, CellMatcher | undefined][] = Object.entries(where);\n\treturn entries.filter(entry => entry[1] !== undefined).map(entry => entry[0]);\n}\n","import type { EngineTexts } from \"./table-locator.types\";\nimport { normalizeLine } from \"./table-selector-engine\";\n\n/** Longest cell text shown in a formatted table. */\nconst MAX_CELL_WIDTH = 30;\n\n/** Options for {@link formatRows} and {@link formatMarkdown}. */\nexport type FormatOptions = {\n\t/** The rows to show, by index. Defaults to every row. */\n\tindexes?: readonly number[];\n\t/**\n\t * The columns to show, by header key or index. Columns the table doesn't have are skipped; when none is\n\t * left, every column is shown.\n\t */\n\tcolumns?: readonly (string | number)[];\n\t/** The most rows to show. */\n\tmaxRows: number;\n};\n\n/**\n * Body rows as an aligned text table, with the row index in front, for failure messages and logs. Line\n * breaks in a cell show as `↵`, and long cells are cut off.\n *\n * @example\n * # | Name | Status\n * 0 | John | Active\n *\n * @internal\n */\nexport function formatRows(body: EngineTexts, options: FormatOptions): string {\n\tconst indexes = options.indexes ?? body.rows.map((_row, index) => index);\n\tif (indexes.length === 0) return \" (none)\\n\";\n\tconst columns = pickColumns(body, options.columns);\n\tconst shown = indexes.slice(0, options.maxRows);\n\tconst cell = (text: string): string => {\n\t\tconst line = text.replace(/\\n/g, \"↵\");\n\t\treturn line.length > MAX_CELL_WIDTH ? `${line.slice(0, MAX_CELL_WIDTH - 1)}…` : line;\n\t};\n\tconst lines = [\n\t\t[\"#\", ...columns.map(column => cell(columnLabel(body, column)))],\n\t\t...shown.map(index => [String(index), ...columns.map(column => cell(body.rows[index]?.[column] ?? \"\"))]),\n\t];\n\tconst widths = (lines[0] ?? []).map((_text, c) => Math.max(...lines.map(line => line[c]?.length ?? 0)));\n\tlet table = lines\n\t\t.map(line => ` ${line.map((text, c) => text.padEnd(widths[c] ?? 0)).join(\" | \")}`.trimEnd() + \"\\n\")\n\t\t.join(\"\");\n\tif (indexes.length > shown.length) table += ` ... and ${indexes.length - shown.length} more rows\\n`;\n\treturn table;\n}\n\n/**\n * Body rows as a Markdown table, with the row index in front, for test report attachments. Cell text is\n * not cut off.\n *\n * @internal\n */\nexport function formatMarkdown(body: EngineTexts, options: FormatOptions): string {\n\tconst indexes = options.indexes ?? body.rows.map((_row, index) => index);\n\tconst columns = pickColumns(body, options.columns);\n\tconst cell = (text: string): string => text.replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \"<br>\");\n\tconst shown = indexes.slice(0, options.maxRows);\n\tconst lines = [\n\t\t`| # | ${columns.map(column => cell(columnLabel(body, column))).join(\" | \")} |`,\n\t\t`| --- | ${columns.map(() => \"---\").join(\" | \")} |`,\n\t\t...shown.map(\n\t\t\tindex => `| ${index} | ${columns.map(column => cell(body.rows[index]?.[column] ?? \"\")).join(\" | \")} |`\n\t\t),\n\t];\n\tif (indexes.length > shown.length) lines.push(\"\", `... and ${indexes.length - shown.length} more rows`);\n\treturn lines.join(\"\\n\") + \"\\n\";\n}\n\n/** The grid columns of `headers` that the table has, or every column if there are none. */\nfunction pickColumns(body: EngineTexts, headers: readonly (string | number)[] | undefined): number[] {\n\t// A table without header rows (or a body wider than its header) still has its body columns\n\tconst width = body.rows.reduce((widest, row) => Math.max(widest, row.length), body.keys.length);\n\tconst columns: number[] = [];\n\tfor (const header of headers ?? []) {\n\t\tconst column = typeof header === \"number\" ? header : body.keys.indexOf(normalizeLine(header));\n\t\tif (column >= 0 && column < width && !columns.includes(column)) columns.push(column);\n\t}\n\treturn columns.length > 0 ? columns : Array.from({ length: width }, (_value, index) => index);\n}\n\n/** The header key of a column, or its index for a column without one. */\nfunction columnLabel(body: EngineTexts, column: number): string {\n\treturn body.keys[column] ?? String(column);\n}\n","import type { Locator } from \"@playwright/test\";\n\nimport { describeLastError, MIN_READ_TIMEOUT } from \"./polling\";\nimport type { LocatorRef, PaginateOptions, ScrollOptions, StableOptions } from \"./table-locator.types\";\n\n/** Default time the table must stay the same after a scroll, in milliseconds. */\nconst DEFAULT_SCROLL_SETTLE = 50;\n\n/** Time the table must stay the same after a page change, in milliseconds. */\nconst PAGE_SETTLE = 200;\n\n/** How often the table is read while waiting for a page change, in milliseconds. */\nconst CHANGE_INTERVAL = 50;\n\n/**\n * How long the table may take to change after clicking `paginate.first`, in milliseconds. A table that\n * already shows the first page doesn't change, so this is how long that case waits.\n */\nconst FIRST_PAGE_WINDOW = 2_000;\n\n/**\n * For a table with a `loading` indicator: how long it may take to change, or to show the indicator, after\n * clicking `paginate.first`, in milliseconds.\n */\nconst FIRST_PAGE_CUTOFF = 500;\n\n/**\n * What {@link TableNavigator} needs from the table it navigates.\n * @internal\n */\nexport type NavigationHost = {\n\troot: Locator;\n\t/** The loading indicator of the table, if it has one. */\n\tloading: Locator | undefined;\n\t/** A fingerprint of the header keys and body cell texts, which changes when the table does, and the number of body rows. */\n\tfingerprint(timeout: number): Promise<{ rows: number; print: string }>;\n\twaitForStable(options: StableOptions): Promise<void>;\n\t/** Whether the loading indicator is visible now; `false` for a table without one. */\n\tloadingShown(): Promise<boolean>;\n};\n\n/**\n * A position of {@link TableNavigator.positions}: the page (0-based) and the scroll step on it (0 is the top).\n * @internal\n */\nexport type NavigationPosition = { page: number; step: number };\n\n/** `ref` as a locator: a function is called with the table root. */\nexport function resolveRef(ref: LocatorRef, root: Locator): Locator {\n\treturn typeof ref === \"function\" ? ref(root) : ref;\n}\n\n/**\n * Walks through every page (with `paginate`) and every scroll position (with `scroll`) of a table, so the\n * caller can read the rows in view at each position. Without either option, there is one position.\n * @internal\n */\nexport class TableNavigator {\n\tconstructor(\n\t\tprivate readonly host: NavigationHost,\n\t\tprivate readonly paginate: PaginateOptions | undefined,\n\t\tprivate readonly scroll: ScrollOptions | undefined\n\t) {\n\t\tcheckLimit(\"paginate.maxPages\", paginate?.maxPages);\n\t\tcheckLimit(\"scroll.maxSteps\", scroll?.maxSteps);\n\t\t// A step of 0 or less would be silently replaced by the default step.\n\t\tif (scroll?.step !== undefined && !(scroll.step > 0 && Number.isFinite(scroll.step))) {\n\t\t\tthrow new Error(`scroll.step must be a positive number of pixels, got: ${scroll.step}`);\n\t\t}\n\t\tif (scroll?.settle !== undefined && !(scroll.settle >= 0 && Number.isFinite(scroll.settle))) {\n\t\t\tthrow new Error(`scroll.settle must be a non-negative number of milliseconds, got: ${scroll.settle}`);\n\t\t}\n\t}\n\n\t/** Whether the table has pages or scrolls, so the rows in view may not be all rows. */\n\tget active(): boolean {\n\t\treturn this.paginate !== undefined || this.scroll !== undefined;\n\t}\n\n\t/**\n\t * Waits until the table settles, goes to the first page (if `paginate.first` is set) and the top, then\n\t * yields every position in turn: each scroll step down, then the next page, until the last page,\n\t * `paginate.maxPages` or `deadline`. On each page, it scrolls down until the bottom or `scroll.maxSteps`.\n\t * The table has settled at every position. Stops early when the caller breaks out of the loop.\n\t *\n\t * @throws Error if the table doesn't change after going to the next page, or the deadline passes.\n\t */\n\tasync *positions(deadline: number): AsyncGenerator<NavigationPosition> {\n\t\t// A table that is still loading would be read as an empty first page, and its pager as missing.\n\t\tawait this.settle(PAGE_SETTLE, deadline);\n\t\tawait this.goToFirstPage(deadline);\n\t\tconst maxPages = this.paginate?.maxPages ?? Infinity;\n\t\tconst maxSteps = this.scroll?.maxSteps ?? Infinity;\n\t\tfor (let page = 0; ; page++) {\n\t\t\tif (this.scroll !== undefined) await this.scrollToTop(deadline);\n\t\t\tyield { page, step: 0 };\n\t\t\tfor (let step = 1; this.scroll !== undefined && step <= maxSteps; step++) {\n\t\t\t\tif (!(await this.scrollDown(deadline))) break;\n\t\t\t\tyield { page, step };\n\t\t\t}\n\t\t\tif (this.paginate === undefined || page + 1 >= maxPages || (await this.isLastPage(deadline))) return;\n\t\t\tawait this.nextPage(deadline);\n\t\t}\n\t}\n\n\t/**\n\t * How far the navigation got, for a message: the pages (with `paginate`), the scroll steps (with\n\t * `scroll`) and the limits that ended it, such as ` on 3 pages (2 scroll steps on the last page;\n\t * paginate.maxPages is 3)`, or `\"\"` without navigation.\n\t */\n\tdescribeSearch(last: NavigationPosition): string {\n\t\tconst notes: string[] = [];\n\t\tif (this.scroll !== undefined) {\n\t\t\tnotes.push(\n\t\t\t\t`${last.step} scroll step${last.step === 1 ? \"\" : \"s\"}${this.paginate === undefined ? \"\" : \" on the last page\"}`\n\t\t\t);\n\t\t}\n\t\tif (this.paginate?.maxPages === last.page + 1) notes.push(`paginate.maxPages is ${this.paginate.maxPages}`);\n\t\tif (this.scroll?.maxSteps === last.step) notes.push(`scroll.maxSteps is ${this.scroll.maxSteps}`);\n\t\tconst pages = this.paginate === undefined ? \"\" : ` on ${last.page + 1} page${last.page === 0 ? \"\" : \"s\"}`;\n\t\treturn pages + (notes.length === 0 ? \"\" : ` (${notes.join(\"; \")})`);\n\t}\n\n\t/**\n\t * Clicks `paginate.first`, unless the table shows the first page: with `paginate.isFirstPage`, as it\n\t * says, and otherwise when the control is disabled. Then waits until the table shows the first page.\n\t */\n\tprivate async goToFirstPage(deadline: number): Promise<void> {\n\t\tconst first = this.paginate?.first;\n\t\tif (first === undefined) return;\n\t\tconst resolved = resolveRef(first, this.host.root);\n\t\t// A pager above and below the table matches twice, and both do the same.\n\t\tconst control = resolved.first();\n\t\tconst isFirstPage = this.paginate?.isFirstPage;\n\t\tif (isFirstPage === undefined ? await isUnavailable(control, deadline) : await isFirstPage(resolved)) return;\n\t\tconst before = await this.host.fingerprint(remaining(deadline));\n\t\tawait control.click({ timeout: remaining(deadline) });\n\t\tif (isFirstPage === undefined) {\n\t\t\tawait this.waitForFirstPageChange(before.print, deadline);\n\t\t} else {\n\t\t\tawait this.waitForFirstPage(resolved, isFirstPage, deadline);\n\t\t}\n\t\tawait this.settle(PAGE_SETTLE, deadline);\n\t}\n\n\t/**\n\t * Waits until `isFirstPage` says the table shows the first page.\n\t * @throws Error at `deadline` if it never does.\n\t */\n\tprivate async waitForFirstPage(\n\t\tfirst: Locator,\n\t\tisFirstPage: (first: Locator) => Promise<boolean>,\n\t\tdeadline: number\n\t): Promise<void> {\n\t\tlet lastError: unknown;\n\t\tfor (;;) {\n\t\t\ttry {\n\t\t\t\tif (await isFirstPage(first)) return;\n\t\t\t\tlastError = undefined;\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error;\n\t\t\t}\n\t\t\tif (Date.now() >= deadline) break;\n\t\t\tawait new Promise(resolve => setTimeout(resolve, CHANGE_INTERVAL));\n\t\t}\n\t\tthrow new Error(\n\t\t\t`TableLocator: the table did not show the first page after clicking paginate.first ` +\n\t\t\t\t`(paginate.isFirstPage stayed false).\\n` +\n\t\t\t\tdescribeLastError(lastError) +\n\t\t\t\t`First page locator: ${first.toString()}\\n` +\n\t\t\t\t`Table locator: ${this.host.root.toString()}`\n\t\t);\n\t}\n\n\t/**\n\t * After clicking `paginate.first` without `paginate.isFirstPage`: waits for the table to change, which it\n\t * doesn't when it already showed the first page and the control stays enabled. So the wait has a window:\n\t * {@link FIRST_PAGE_WINDOW}, or, for a table with a `loading` indicator, {@link FIRST_PAGE_CUTOFF} as long\n\t * as the indicator doesn't show (a page that loads shows it).\n\t */\n\tprivate async waitForFirstPageChange(before: string, deadline: number): Promise<void> {\n\t\tconst window = Math.min(deadline, Date.now() + FIRST_PAGE_WINDOW);\n\t\tconst cutoff = this.host.loading === undefined ? window : Math.min(window, Date.now() + FIRST_PAGE_CUTOFF);\n\t\tlet loading = false;\n\t\tfor (;;) {\n\t\t\tconst current = await this.host.fingerprint(remaining(window)).catch(() => undefined);\n\t\t\tif (current !== undefined && current.print !== before) return;\n\t\t\tif (!loading && this.host.loading !== undefined) loading = await this.host.loadingShown().catch(() => false);\n\t\t\tif (Date.now() >= (loading ? window : cutoff)) return;\n\t\t\tawait new Promise(resolve => setTimeout(resolve, CHANGE_INTERVAL));\n\t\t}\n\t}\n\n\tprivate async isLastPage(deadline: number): Promise<boolean> {\n\t\tif (this.paginate === undefined) return true;\n\t\tconst next = resolveRef(this.paginate.next, this.host.root);\n\t\treturn this.paginate.isLastPage === undefined\n\t\t\t? isUnavailable(next.first(), deadline)\n\t\t\t: this.paginate.isLastPage(next);\n\t}\n\n\tprivate async nextPage(deadline: number): Promise<void> {\n\t\tif (this.paginate === undefined) return;\n\t\t// A pager above and below the table matches twice, and both do the same.\n\t\tconst next = resolveRef(this.paginate.next, this.host.root).first();\n\t\tconst before = await this.host.fingerprint(remaining(deadline));\n\t\tawait next.click({ timeout: remaining(deadline) });\n\t\tawait this.waitForChange(before.print, deadline, true);\n\t\tawait this.settle(PAGE_SETTLE, deadline);\n\t}\n\n\tprivate container(): Locator {\n\t\tconst container = this.scroll?.container;\n\t\treturn container === undefined ? this.host.root : resolveRef(container, this.host.root);\n\t}\n\n\tprivate async scrollToTop(deadline: number): Promise<void> {\n\t\tawait this.checkScrollable(deadline);\n\t\tawait this.scrollTo(null, deadline);\n\t}\n\n\t/**\n\t * @throws Error if the scroll container can never scroll (`overflow-y: visible` or `clip`), which would\n\t * read only the rows in view, naming the nearest element around or inside it that does scroll.\n\t */\n\tprivate async checkScrollable(deadline: number): Promise<void> {\n\t\tconst problem = await this.container().evaluate(\n\t\t\t(element: Element) => {\n\t\t\t\t// The page itself scrolls with any overflow.\n\t\t\t\tif (element === document.scrollingElement) return null;\n\t\t\t\tconst overflow = getComputedStyle(element).overflowY;\n\t\t\t\tif (overflow !== \"visible\" && overflow !== \"clip\") return null;\n\t\t\t\t// This function runs in the browser, so it cannot use module functions.\n\t\t\t\tconst scrolls = (el: Element): boolean =>\n\t\t\t\t\t/^(auto|scroll|overlay)$/.test(getComputedStyle(el).overflowY) && el.scrollHeight > el.clientHeight;\n\t\t\t\tlet hint: Element | null = null;\n\t\t\t\tfor (let el = element.parentElement; el !== null && hint === null; el = el.parentElement) {\n\t\t\t\t\tif (el !== document.scrollingElement && scrolls(el)) hint = el;\n\t\t\t\t}\n\t\t\t\thint ??= Array.from(element.querySelectorAll(\"*\")).find(scrolls) ?? null;\n\t\t\t\tconst name =\n\t\t\t\t\thint === null\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: hint.localName +\n\t\t\t\t\t\t\t(hint.id === \"\" ? \"\" : \"#\" + hint.id) +\n\t\t\t\t\t\t\tArray.from(hint.classList)\n\t\t\t\t\t\t\t\t.slice(0, 2)\n\t\t\t\t\t\t\t\t.map(name => \".\" + name)\n\t\t\t\t\t\t\t\t.join(\"\");\n\t\t\t\treturn { overflow, hint: name };\n\t\t\t},\n\t\t\tundefined,\n\t\t\t{ timeout: remaining(deadline) }\n\t\t);\n\t\tif (problem === null) return;\n\t\tthrow new Error(\n\t\t\t`TableLocator: the scroll container can't scroll (overflow-y: ${problem.overflow}), so only the rows in view ` +\n\t\t\t\t`would be read. Point scroll.container at the element that scrolls` +\n\t\t\t\t(problem.hint === null ? \".\" : `, such as ${problem.hint}.`) +\n\t\t\t\t`\\nScroll container: ${this.container().toString()}` +\n\t\t\t\t(this.scroll?.container === undefined ? \" (the table root, as scroll.container is not set)\" : \"\") +\n\t\t\t\t`\\nTable locator: ${this.host.root.toString()}`\n\t\t);\n\t}\n\n\t/** Scrolls one step down. Returns `false` at the bottom. */\n\tprivate scrollDown(deadline: number): Promise<boolean> {\n\t\treturn this.scrollTo(this.scroll?.step ?? 0, deadline);\n\t}\n\n\t/**\n\t * Scrolls to the top (`step` is `null`) or one step down (`0` for the default step), and waits until the\n\t * grid has rendered the rows in view: two animation frames, which is when grids render after a scroll\n\t * event, and then until the table stays the same for `settle` (and the loading indicator is hidden).\n\t * Returns whether the container scrolled.\n\t */\n\tprivate async scrollTo(step: number | null, deadline: number): Promise<boolean> {\n\t\tconst moved = await this.container().evaluate(\n\t\t\tasync (element: Element, delta: number | null) => {\n\t\t\t\tconst top = element.scrollTop;\n\t\t\t\tconst by = delta !== null && delta > 0 ? delta : Math.max(1, Math.floor(element.clientHeight * 0.9));\n\t\t\t\t// With `scroll-behavior: smooth`, setting scrollTop would only start an animation.\n\t\t\t\telement.scrollTo({ top: delta === null ? 0 : top + by, behavior: \"instant\" });\n\t\t\t\tif (element.scrollTop === top) return false;\n\t\t\t\t// Animation frames don't run in a page that is not shown, so a timer ends the wait too. This\n\t\t\t\t// function runs in the browser, so it cannot use module constants.\n\t\t\t\tconst frame = (): Promise<void> =>\n\t\t\t\t\tnew Promise(resolve => {\n\t\t\t\t\t\trequestAnimationFrame(() => resolve());\n\t\t\t\t\t\tsetTimeout(resolve, 50);\n\t\t\t\t\t});\n\t\t\t\tawait frame();\n\t\t\t\tawait frame();\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\tstep,\n\t\t\t{ timeout: remaining(deadline) }\n\t\t);\n\t\tconst settle = this.scroll?.settle ?? DEFAULT_SCROLL_SETTLE;\n\t\tif (moved && (settle > 0 || this.host.loading !== undefined)) await this.settle(settle, deadline);\n\t\treturn moved;\n\t}\n\n\tprivate settle(quiet: number, deadline: number): Promise<void> {\n\t\treturn this.host.waitForStable({ quiet, timeout: remaining(deadline), loading: this.host.loading });\n\t}\n\n\t/**\n\t * Waits until the fingerprint differs from `before`. With `required` (after going to the next page), it\n\t * also waits until the table has body rows again: a table that clears its rows while it loads the next\n\t * page has changed, but doesn't show that page yet.\n\t * @throws Error at `deadline` if `required` and the table didn't change.\n\t */\n\tprivate async waitForChange(before: string, deadline: number, required: boolean): Promise<void> {\n\t\tlet lastError: unknown;\n\t\tlet changed = false;\n\t\tfor (;;) {\n\t\t\ttry {\n\t\t\t\tconst current = await this.host.fingerprint(remaining(deadline));\n\t\t\t\tlastError = undefined;\n\t\t\t\tif (current.print !== before) {\n\t\t\t\t\tchanged = true;\n\t\t\t\t\tif (!required || current.rows > 0) return;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// The table may be rendered again while it changes pages: keep trying, but remember why.\n\t\t\t\tlastError = error;\n\t\t\t}\n\t\t\tif (Date.now() >= deadline) break;\n\t\t\tawait new Promise(resolve => setTimeout(resolve, CHANGE_INTERVAL));\n\t\t}\n\t\t// It changed but stayed empty: an empty next page, rare as that is.\n\t\tif (!required || changed) return;\n\t\tthrow new Error(\n\t\t\t`TableLocator: the table did not change after going to the next page.\\n` +\n\t\t\t\t`Next page locator: ${this.paginate === undefined ? \"\" : resolveRef(this.paginate.next, this.host.root).toString()}\\n` +\n\t\t\t\tdescribeLastError(lastError) +\n\t\t\t\t`Table locator: ${this.host.root.toString()}`\n\t\t);\n\t}\n}\n\n/** @throws Error if a limit is set, but is not a positive integer. */\nfunction checkLimit(name: string, limit: number | undefined): void {\n\tif (limit !== undefined && !(Number.isInteger(limit) && limit > 0)) {\n\t\tthrow new Error(`${name} must be a positive integer, got: ${limit}`);\n\t}\n}\n\n/**\n * Whether a control (one element) is missing, hidden or disabled: with `disabled`, `aria-disabled=\"true\"`\n * or the `disabled` class, on the control or an element around it, such as a Bootstrap\n * `<li class=\"disabled\">` around a link. Doesn't wait for the control to show up.\n */\nasync function isUnavailable(control: Locator, deadline: number): Promise<boolean> {\n\tif ((await control.count()) === 0 || !(await control.isVisible())) return true;\n\ttry {\n\t\treturn await control.evaluate(\n\t\t\telement => element.closest(\":disabled, [aria-disabled=true], .disabled\") !== null,\n\t\t\tundefined,\n\t\t\t{ timeout: remaining(deadline) }\n\t\t);\n\t} catch (error) {\n\t\t// Gone since it was counted (the pager was rendered again): missing. Otherwise the read failed, and\n\t\t// guessing \"enabled\" would click a disabled control and wait for a page that never comes.\n\t\tif ((await control.count()) === 0) return true;\n\t\tthrow error;\n\t}\n}\n\n/** The time left until `deadline`, at least {@link MIN_READ_TIMEOUT}. */\nfunction remaining(deadline: number): number {\n\treturn Math.max(MIN_READ_TIMEOUT, deadline - Date.now());\n}\n","import { Locator } from \"@playwright/test\";\n\nimport { CellContentType } from \"./cell-content-type\";\nimport { describeWhere, serializeSelector, serializeWhere } from \"./cell-matcher-serializer\";\nimport { checkTimeout, describeLastError, MIN_READ_TIMEOUT, pollUntil } from \"./polling\";\nimport { conditionHeaders, waitForHeaders } from \"./table-diagnostics\";\nimport { formatRows } from \"./table-format\";\nimport {\n\tColumnKey,\n\tColumnParser,\n\tColumnParsers,\n\tDecimalSeparator,\n\tEngineConfig,\n\tEngineFindRequest,\n\tEngineFingerprint,\n\tEngineFingerprintRequest,\n\tEngineKeysRequest,\n\tEngineQuery,\n\tEngineTexts,\n\tEngineTextsRequest,\n\tEngineTotalRequest,\n\tEngineValuesRequest,\n\tEngineWindow,\n\tEngineWindowRequest,\n\tHeaderKey,\n\tLocatorRef,\n\tNavigationOptions,\n\tRowWhere,\n\tStableOptions,\n\tTableJsonOptions,\n\tTableJsonRow,\n\tTableLocatorOptions,\n\tValidRowWhere,\n} from \"./table-locator.types\";\nimport { NavigationHost, NavigationPosition, resolveRef, TableNavigator } from \"./table-navigation\";\nimport {\n\tfindTableRows,\n\tnormalizeCell,\n\tnormalizeLine,\n\tparseNumber,\n\treadColumnValues,\n\treadTableFingerprint,\n\treadTableHeaderKeys,\n\treadTableTexts,\n\treadTableTotal,\n\treadTableWindow,\n\tTABLE_SELECTOR_ENGINE_NAME,\n} from \"./table-selector-engine\";\nimport { TableUtils } from \"./table-utils\";\n\n/** Filter options accepted by `Locator.filter()`. */\nexport type RowFilterOptions = Parameters<Locator[\"filter\"]>[0];\n\n/**\n * One or more body rows of a {@link TableLocator}, with typed access to their cells.\n *\n * Instances are created by {@link TableLocator.row}, {@link TableLocator.rowAt} and {@link TableLocator.rows}.\n * Their locators read like your code in error messages and traces, such as\n * `locator('#users').row({ \"Name\": \"John\" }).cell(\"Status\")` (Playwright 1.53 and later).\n *\n * @example\n * const row = table.row({ Name: \"John\" });\n * await expect(row.locator).toBeVisible();\n * await expect(row.cell(\"Status\")).toHaveText(\"Active\");\n */\nexport class TableRow<H extends string = string> {\n\t/**\n\t * @param table - The table this row belongs to.\n\t * @param locator - The Playwright `Locator` for the row element(s). Its `toString()` is used to describe\n\t * the locators built from this row.\n\t */\n\tconstructor(\n\t\treadonly table: TableLocator<H>,\n\t\treadonly locator: Locator\n\t) {}\n\n\t/**\n\t * Returns the cell of this row under `column`.\n\t * If this row locator matches several rows, the cell locator matches one cell per row.\n\t *\n\t * @param column - The header key of the column, or its 0-based index (also works without header rows).\n\t * @returns A Playwright Locator for the cell.\n\t *\n\t * @example\n\t * await table.row({ Name: \"John\" }).cell(\"Email\").click();\n\t *\n\t * @example\n\t * // By column index, for example in a table without header rows\n\t * await expect(table.rowAt(0).cell(2)).toHaveText(\"john@example.com\");\n\t */\n\tcell(column: ColumnKey<H>): Locator {\n\t\treturn this.table.cell(this.locator, column);\n\t}\n\n\t/**\n\t * The first of these rows, with typed cell access. Use it when several rows may match and any is fine.\n\t *\n\t * @example\n\t * await table.row({ Status: \"Active\" }).first().cell(\"Edit\").click();\n\t */\n\tfirst(): TableRow<H> {\n\t\treturn new TableRow(this.table, described(this.locator.first(), `${this.locator.toString()}.first()`));\n\t}\n\n\t/**\n\t * The last of these rows, with typed cell access.\n\t *\n\t * @example\n\t * await expect(table.rows.last().cell(\"Name\")).toHaveText(\"Jane\");\n\t */\n\tlast(): TableRow<H> {\n\t\treturn new TableRow(this.table, described(this.locator.last(), `${this.locator.toString()}.last()`));\n\t}\n\n\t/**\n\t * The row at `index` among these rows, with typed cell access. Negative indexes count from the end,\n\t * like `Locator.nth()`.\n\t *\n\t * @param index - The 0-based index among these rows.\n\t * @returns A {@link TableRow} for the row.\n\t * @throws Error if index is not an integer.\n\t *\n\t * @example\n\t * await expect(table.row({ Status: \"Active\" }).nth(1).cell(\"Name\")).toHaveText(\"Joe\");\n\t */\n\tnth(index: number): TableRow<H> {\n\t\tif (!Number.isInteger(index)) {\n\t\t\tthrow new Error(`Row index must be an integer, got: ${index}`);\n\t\t}\n\t\treturn new TableRow(this.table, described(this.locator.nth(index), `${this.locator.toString()}.nth(${index})`));\n\t}\n\n\t/**\n\t * Narrows these rows with `Locator.filter()` and keeps typed cell access.\n\t *\n\t * @param options - The same options as `Locator.filter()`.\n\t * @returns A new {@link TableRow} for the filtered rows.\n\t *\n\t * @example\n\t * await expect(table.rows.filter({ hasText: \"Jane\" }).cell(\"Status\")).toHaveText(\"Active\");\n\t */\n\tfilter(options?: RowFilterOptions): TableRow<H> {\n\t\tconst description = `${this.locator.toString()}.filter(${describeFilter(options)})`;\n\t\treturn new TableRow(this.table, described(this.locator.filter(options), description));\n\t}\n\n\t/**\n\t * Fills the controls in the cells of this row, one column after the other. A boolean checks or unchecks\n\t * a checkbox or switch; a string selects an option of a `<select>`, or fills an input, a text area or\n\t * an editable element.\n\t *\n\t * A cell without a control is edited in place, as data grids do: it is double-clicked, the editor that\n\t * appears in the cell is filled, and `commit` is pressed. Editors that open outside the cell (a popup)\n\t * are not found.\n\t *\n\t * Columns are filled in the order of `values`. When the row is found by the value of a column you fill,\n\t * fill that column last: after it changes, the row no longer matches.\n\t *\n\t * @param values - The value per column.\n\t * @param options - Optional settings.\n\t * @param options.commit - (Optional) The key that ends in-place editing. Defaults to `\"Enter\"`; `false` presses nothing.\n\t * @param options.timeout - (Optional) The time per action, in milliseconds. Defaults to 5000.\n\t * @throws Error if a cell has no control, also not after a double-click.\n\t *\n\t * @example\n\t * await users.row({ Name: \"John\" }).fill({ Email: \"john@example.org\", Active: false, Role: \"Admin\" });\n\t */\n\tasync fill(\n\t\tvalues: { [K in HeaderKey<H>]?: string | boolean },\n\t\toptions?: { commit?: string | false; timeout?: number }\n\t): Promise<void> {\n\t\tconst entries: [string, string | boolean | undefined][] = Object.entries(values);\n\t\tfor (const [column, value] of entries) {\n\t\t\tif (value !== undefined) await fillCell(this.cell(column as HeaderKey<H>), column, value, options);\n\t\t}\n\t}\n\n\t/**\n\t * Selects this row: checks its selection checkbox (see the `select` option of {@link TableLocator}), or\n\t * clicks the row if it has none, and waits until the row is selected (see {@link isSelected}). A\n\t * selected row is left as it is.\n\t *\n\t * @param options - Optional timeout, in milliseconds. Defaults to 5000.\n\t * @throws Error if the row is not selected within the timeout.\n\t *\n\t * @example\n\t * await users.row({ Name: \"John\" }).select();\n\t * await expect(users.row({ Name: \"John\" })).toBeSelected();\n\t */\n\tasync select(options?: { timeout?: number }): Promise<void> {\n\t\tawait this.setSelected(true, options?.timeout ?? 5_000);\n\t}\n\n\t/**\n\t * Deselects this row: unchecks its selection checkbox, or clicks the row if it has none, and waits\n\t * until the row is not selected. A row that is not selected is left as it is.\n\t *\n\t * @param options - Optional timeout, in milliseconds. Defaults to 5000.\n\t * @throws Error if the row is still selected after the timeout.\n\t */\n\tasync deselect(options?: { timeout?: number }): Promise<void> {\n\t\tawait this.setSelected(false, options?.timeout ?? 5_000);\n\t}\n\n\t/**\n\t * Whether this row is selected. A row with `aria-selected` is selected when it is `\"true\"`. Otherwise,\n\t * the row is selected when its selection checkbox is checked (see the `select` option of\n\t * {@link TableLocator}). Reads the row once; for a retrying check, use `expect(row).toBeSelected()`.\n\t *\n\t * @param options - Optional timeout for finding the row, in milliseconds.\n\t * @returns A promise that resolves to whether the row is selected.\n\t */\n\tasync isSelected(options?: { timeout?: number }): Promise<boolean> {\n\t\tconst deadline = options?.timeout === undefined ? undefined : Date.now() + options.timeout;\n\t\tconst left = (): number | undefined =>\n\t\t\tdeadline === undefined ? undefined : Math.max(MIN_READ_TIMEOUT, deadline - Date.now());\n\t\tconst ariaSelected = await this.locator.getAttribute(\"aria-selected\", { timeout: left() });\n\t\tif (ariaSelected !== null) return ariaSelected === \"true\";\n\t\tconst control = await this.selectionControl(left());\n\t\tif (control === undefined || !(await isCheckbox(control, left()))) return false;\n\t\treturn control.isChecked({ timeout: left() });\n\t}\n\n\t/**\n\t * Expands this row of a tree grid, and waits until it is expanded. An expanded row is left as it is.\n\t * It clicks `toggle`, or else the element in the row with `aria-expanded` (not a menu button, which has\n\t * `aria-haspopup`), or else, when the row itself has `aria-expanded`, the button in its first cell.\n\t * Without any of them, it focuses the row and presses `ArrowRight`, as tree grids do.\n\t *\n\t * @param options - Optional settings.\n\t * @param options.toggle - (Optional) The control that expands and collapses the row, from the row locator.\n\t * @param options.timeout - (Optional) The time to wait, in milliseconds. Defaults to 5000.\n\t * @throws Error if the row has no `aria-expanded` (on the row or an element in it), or doesn't expand.\n\t *\n\t * @example\n\t * await files.row({ Name: \"src\" }).expand();\n\t * await expect(files.row({ Name: \"index.ts\" }).locator).toBeVisible();\n\t */\n\tasync expand(options?: { toggle?: (row: Locator) => Locator; timeout?: number }): Promise<void> {\n\t\tawait this.setExpanded(true, options);\n\t}\n\n\t/**\n\t * Collapses this row of a tree grid, like {@link expand} does, but with `ArrowLeft` as the fallback.\n\t *\n\t * @param options - Optional settings, the same as for {@link expand}.\n\t * @throws Error if the row has no `aria-expanded` (on the row or an element in it), or doesn't collapse.\n\t */\n\tasync collapse(options?: { toggle?: (row: Locator) => Locator; timeout?: number }): Promise<void> {\n\t\tawait this.setExpanded(false, options);\n\t}\n\n\t/**\n\t * Whether this row is expanded: the `aria-expanded` of the row, or else of the first element in it that\n\t * has one and is not a menu button (with `aria-haspopup`). `null` if there is none, for a row that\n\t * cannot expand.\n\t *\n\t * @param options - Optional settings.\n\t * @param options.timeout - (Optional) The time to wait for the row, in milliseconds.\n\t * @returns A promise that resolves to `true`, `false` or `null`.\n\t */\n\tasync isExpanded(options?: { timeout?: number }): Promise<boolean | null> {\n\t\treturn this.locator.evaluate(readExpanded, undefined, options);\n\t}\n\n\t/**\n\t * The `aria-level` of this row in a tree grid (1 for the top level), or `null` if it has none.\n\t *\n\t * @param options - Optional settings.\n\t * @param options.timeout - (Optional) The time to wait for the row, in milliseconds.\n\t * @example\n\t * expect(await files.row({ Name: \"index.ts\" }).level()).toBe(2);\n\t */\n\tasync level(options?: { timeout?: number }): Promise<number | null> {\n\t\tconst level = await this.locator.getAttribute(\"aria-level\", options);\n\t\tconst value = level === null ? NaN : parseInt(level, 10);\n\t\treturn isNaN(value) ? null : value;\n\t}\n\n\t/**\n\t * The control that selects this row: the `select` option of the table, or else the checkbox in the\n\t * first column without header text (in a table without header rows, the first column) that has one.\n\t * `undefined` if there is none.\n\t */\n\tprivate async selectionControl(timeout: number | undefined): Promise<Locator | undefined> {\n\t\t// `_select` is private to TableLocator; its rows read it.\n\t\tconst select = this.table[\"_select\"];\n\t\tif (select !== undefined) return select(this.locator);\n\t\tconst keys = await this.table.headerKeys({ timeout });\n\t\tconst columns: (string | number)[] = keys.length === 0 ? [0] : keys.filter(isEmptyHeaderKey);\n\t\tfor (const column of columns) {\n\t\t\t// A header key read from the table, which `H` may not list (such as `{{Empty}}`)\n\t\t\tconst checkbox = this.table\n\t\t\t\t.cell(this.locator, column as ColumnKey<H>)\n\t\t\t\t.locator(CHECKBOX)\n\t\t\t\t.first();\n\t\t\tif ((await checkbox.count()) > 0) return checkbox;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * The control that expands and collapses this row: `toggle` (waited for, as you passed it), or else the\n\t * element in the row with `aria-expanded` that is not a menu button, or else, when the row itself has\n\t * `aria-expanded`, the button in its first cell. `undefined` if there is none.\n\t * @throws Error if `toggle` doesn't show up.\n\t */\n\tprivate async expandToggle(\n\t\ttoggle: ((row: Locator) => Locator) | undefined,\n\t\ttimeout: number\n\t): Promise<Locator | undefined> {\n\t\tif (toggle !== undefined) {\n\t\t\tconst control = toggle(this.locator).first();\n\t\t\ttry {\n\t\t\t\tawait control.waitFor({ state: \"visible\", timeout });\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`TableRow: the toggle of the row was not found.\\n` +\n\t\t\t\t\t\tdescribeLastError(error) +\n\t\t\t\t\t\t`Toggle locator: ${control.toString()}\\n` +\n\t\t\t\t\t\t`Row locator: ${this.locator.toString()}`\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn control;\n\t\t}\n\t\tconst inner = this.locator.locator(EXPAND_TOGGLE).first();\n\t\tif ((await inner.count()) > 0) return inner;\n\t\tconst ownState = await this.locator.getAttribute(\"aria-expanded\", { timeout });\n\t\tif (ownState === null) return undefined;\n\t\t// Tree grids put the toggle in the first cell, in front of the name. Other buttons in the row (edit,\n\t\t// delete) are never clicked.\n\t\tconst button = this.locator.locator(\":scope > :first-child\").locator(\"button, [role=button]\").first();\n\t\treturn (await button.count()) > 0 ? button : undefined;\n\t}\n\n\tprivate async setSelected(selected: boolean, timeout: number): Promise<void> {\n\t\tconst deadline = Date.now() + checkTimeout(timeout);\n\t\tconst left = (): number => Math.max(MIN_READ_TIMEOUT, deadline - Date.now());\n\t\tif ((await this.isSelected({ timeout: left() })) === selected) return;\n\t\tconst control = await this.selectionControl(left());\n\t\tif (control === undefined) {\n\t\t\tawait this.locator.click({ timeout: left() });\n\t\t} else if (await isCheckbox(control, left())) {\n\t\t\tawait control.setChecked(selected, { timeout: left() });\n\t\t} else {\n\t\t\tawait control.click({ timeout: left() });\n\t\t}\n\t\tconst poll = await pollUntil(\n\t\t\treadTimeout => this.isSelected({ timeout: readTimeout }),\n\t\t\tvalue => value === selected,\n\t\t\t!selected,\n\t\t\tdeadline\n\t\t);\n\t\tif (poll.value !== selected) {\n\t\t\tthrow new Error(\n\t\t\t\t`TableRow.${selected ? \"select\" : \"deselect\"}() timed out: the row is ${selected ? \"not \" : \"\"}selected.\\n` +\n\t\t\t\t\tdescribeLastError(poll.error) +\n\t\t\t\t\t`Row locator: ${this.locator.toString()}`\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async setExpanded(\n\t\texpanded: boolean,\n\t\toptions: { toggle?: (row: Locator) => Locator; timeout?: number } | undefined\n\t): Promise<void> {\n\t\tconst deadline = Date.now() + checkTimeout(options?.timeout ?? 5_000);\n\t\tconst left = (): number => Math.max(MIN_READ_TIMEOUT, deadline - Date.now());\n\t\tconst name = expanded ? \"expand\" : \"collapse\";\n\t\tconst state = await this.isExpanded({ timeout: left() });\n\t\tif (state === null) {\n\t\t\tthrow new Error(\n\t\t\t\t`TableRow.${name}(): the row has no aria-expanded, so it cannot expand or collapse.\\n` +\n\t\t\t\t\t`Row locator: ${this.locator.toString()}`\n\t\t\t);\n\t\t}\n\t\tif (state === expanded) return;\n\t\tconst toggle = await this.expandToggle(options?.toggle, left());\n\t\tif (toggle !== undefined) {\n\t\t\tawait toggle.click({ timeout: left() });\n\t\t} else {\n\t\t\tawait this.locator.focus({ timeout: left() });\n\t\t\tawait this.locator.press(expanded ? \"ArrowRight\" : \"ArrowLeft\", { timeout: left() });\n\t\t}\n\t\tconst poll = await pollUntil(\n\t\t\treadTimeout => this.isExpanded({ timeout: readTimeout }),\n\t\t\tvalue => value === expanded,\n\t\t\tstate,\n\t\t\tdeadline\n\t\t);\n\t\tif (poll.value !== expanded) {\n\t\t\tthrow new Error(\n\t\t\t\t`TableRow.${name}() timed out: the row is ${expanded ? \"still collapsed\" : \"still expanded\"}.\\n` +\n\t\t\t\t\tdescribeLastError(poll.error) +\n\t\t\t\t\t`Row locator: ${this.locator.toString()}`\n\t\t\t);\n\t\t}\n\t}\n}\n\n/** The checkboxes that select a row. */\nconst CHECKBOX = \"input[type=checkbox], [role=checkbox]\";\n\n/** The elements in a row that expand it: not menu buttons, which also have `aria-expanded`. */\nconst EXPAND_TOGGLE = \"[aria-expanded]:not([aria-haspopup])\";\n\n/** The controls {@link TableRow.fill} fills. */\nconst CONTROLS =\n\t\"input:not([type=hidden]), textarea, select, [contenteditable=''], [contenteditable='true'], \" +\n\t\"[role=checkbox], [role=switch], [role=textbox], [role=combobox]\";\n\n/** Whether a header key is of a column without header text, such as a selection column: `{{Empty}}`, `{{Empty}}__D1`. */\nfunction isEmptyHeaderKey(key: string): boolean {\n\treturn /^\\{\\{Empty\\}\\}(__[CD]\\d+)*$/.test(key);\n}\n\n/** Whether `control` is a checkbox, which is checked rather than clicked. */\nfunction isCheckbox(control: Locator, timeout: number | undefined): Promise<boolean> {\n\treturn control.evaluate(element => element.matches(\"input[type=checkbox], [role=checkbox]\"), undefined, {\n\t\ttimeout,\n\t});\n}\n\n/**\n * Whether a row element is expanded, or `null` if it has no `aria-expanded`: on the row, or else on the\n * first element in it that is not a menu button. Runs in the browser.\n */\nfunction readExpanded(row: Element): boolean | null {\n\tconst value =\n\t\trow.getAttribute(\"aria-expanded\") ??\n\t\trow.querySelector(\"[aria-expanded]:not([aria-haspopup])\")?.getAttribute(\"aria-expanded\");\n\treturn value === null || value === undefined ? null : value === \"true\";\n}\n\n/** Fills the control in `cell`, after double-clicking the cell if it has none. */\nasync function fillCell(\n\tcell: Locator,\n\tcolumn: string,\n\tvalue: string | boolean,\n\toptions: { commit?: string | false; timeout?: number } | undefined\n): Promise<void> {\n\tconst timeout = options?.timeout ?? 5_000;\n\tconst control = cell.locator(CONTROLS).first();\n\tlet editing = false;\n\t// The control renders with the cell; a cell that is not there yet would look like one without a control.\n\tawait cell.waitFor({ state: \"visible\", timeout });\n\tif ((await control.count()) === 0) {\n\t\tawait cell.dblclick({ timeout });\n\t\tediting = true;\n\t\ttry {\n\t\t\tawait control.waitFor({ state: \"visible\", timeout });\n\t\t} catch {\n\t\t\tthrow new Error(\n\t\t\t\t`TableRow.fill(): the cell under \"${column}\" has no input, also not after a double-click.\\n` +\n\t\t\t\t\t`Cell locator: ${cell.toString()}`\n\t\t\t);\n\t\t}\n\t}\n\tconst kind = await control.evaluate(\n\t\telement =>\n\t\t\telement.localName === \"select\"\n\t\t\t\t? \"select\"\n\t\t\t\t: element.matches(\"input[type=checkbox], input[type=radio], [role=checkbox], [role=switch], [role=radio]\")\n\t\t\t\t\t? \"check\"\n\t\t\t\t\t: \"text\",\n\t\tundefined,\n\t\t{ timeout }\n\t);\n\tconst fail = (problem: string): Error =>\n\t\tnew Error(`TableRow.fill(): the cell under \"${column}\" ${problem}\\nCell locator: ${cell.toString()}`);\n\tif ((typeof value === \"boolean\") !== (kind === \"check\")) {\n\t\tthrow fail(\n\t\t\ttypeof value === \"boolean\"\n\t\t\t\t? `has a ${kind === \"select\" ? \"select\" : \"text control\"}, which takes a string, not ${value}.`\n\t\t\t\t: `has a checkbox, which takes true or false, not ${JSON.stringify(value)}.`\n\t\t);\n\t}\n\ttry {\n\t\tif (typeof value === \"boolean\") {\n\t\t\tawait control.setChecked(value, { timeout });\n\t\t} else if (kind === \"select\") {\n\t\t\tawait control.selectOption(value, { timeout });\n\t\t} else {\n\t\t\tawait control.fill(value, { timeout });\n\t\t}\n\t} catch (error) {\n\t\t// Such as a file input, or a combobox that is not an input\n\t\tthrow fail(`could not be filled with ${JSON.stringify(value)}.\\n${describeLastError(error).trimEnd()}`);\n\t}\n\tconst commit = options?.commit ?? \"Enter\";\n\tif (editing && commit !== false) await control.press(commit, { timeout });\n}\n\n/**\n * A type-safe table API that only returns Playwright `Locator`s.\n *\n * Header names are resolved to columns inside the browser by the `pw-table-v1` selector engine on every\n * evaluation, so every locator auto-waits for late headers and rows, and keeps working when columns are\n * reordered at runtime. Building locators is synchronous.\n *\n * Text is read as the user sees it. Header text is one line: `First<br>name` is the header `\"First name\"`.\n * Body cells keep their line breaks as one `\\n`. Icon glyphs, invisible characters and the text of the elements\n * matching the `ignore` option (screen reader only text and icons by default) are left out. Header names\n * you pass are normalized the same way.\n *\n * The `pw-table-v1` selector engine must be registered first: import `test` from this package, or call\n * {@link registerTableSelectors} before the page is created.\n *\n * @example\n * import { test, expect, TableLocator } from \"@cerios/playwright-table\";\n *\n * test(\"user is active\", async ({ page }) => {\n * const users = new TableLocator(page.locator(\"table\"), { headers: [\"Name\", \"Status\", \"Email\"] });\n * await expect(users.row({ Name: \"John\" }).cell(\"Status\")).toHaveText(\"Active\");\n * });\n */\nexport class TableLocator<const H extends string = string> {\n\t/** The Playwright `Locator` pointing to the root table element. */\n\treadonly root: Locator;\n\tprivate readonly _config: EngineConfig;\n\tprivate readonly _headers: readonly H[] | undefined;\n\tprivate readonly _loading: Locator | undefined;\n\tprivate readonly _navigator: TableNavigator;\n\tprivate readonly _rowKey: string | undefined;\n\tprivate readonly _select: ((row: Locator) => Locator) | undefined;\n\n\t/**\n\t * Creates a table with customizable selectors for headers and rows.\n\t *\n\t * Rows and cells inside a cell (such as a nested table) never belong to this table, and both `<th>`\n\t * and `<td>` count as cells in header and body rows. `PlaywrightTable` only takes `<th>` in header rows\n\t * and `<td>` in body rows.\n\t *\n\t * @param root - The Playwright `Locator` pointing to the root table element.\n\t * @param options - Optional configuration. See {@link TableLocatorOptions}.\n\t * @param options.headers - (Optional) Header names, used for typed header keys and {@link validateHeaders}.\n\t * @param options.aria - (Optional) Use ARIA roles for the default selectors. Defaults to `false`.\n\t * @param options.header.setMainHeaderRow - (Optional) Index of the main header row. Defaults to the last header row.\n\t * @param options.header.rowSelector - (Optional) Header rows: a CSS selector or an {@link ElementSelector} descriptor. Defaults to `\"thead>tr\"`, plus the leading `<th>`-only rows of a table without `<thead>`.\n\t * @param options.header.columnSelector - (Optional) Header cells, see {@link ElementSelector}. Defaults to `\"th, td\"`.\n\t * @param options.row.rowSelector - (Optional) Body rows, see {@link ElementSelector}. Defaults to `\"tbody>tr\"`, without those header rows.\n\t * @param options.row.columnSelector - (Optional) Body cells, see {@link ElementSelector}. Defaults to `\"td, th\"`.\n\t * @param options.cellContentType - (Optional) How cell text is read. Defaults to `InnerText`.\n\t * @param options.ignore - (Optional) Elements inside cells whose text is left out, see {@link ElementSelector}. Defaults to {@link DEFAULT_IGNORE}.\n\t * @param options.footer.rowSelector - (Optional) Footer rows, see {@link ElementSelector}. Defaults to `\"tfoot>tr\"`, or none with `aria`.\n\t * @param options.paginate - (Optional) How to go to the next page, see {@link PaginateOptions}.\n\t * @param options.scroll - (Optional) How to scroll a virtualized grid, see {@link ScrollOptions}.\n\t * @param options.loading - (Optional) The loading indicator of the table.\n\t * @param options.emptyRow - (Optional) Placeholder rows, such as a \"No data\" row, that are never body rows, see {@link ElementSelector}.\n\t * @param options.readInputValues - (Optional) Read the value of text inputs in body cells as cell text. Defaults to `false`.\n\t * @param options.select - (Optional) The control that selects a row, from the row locator. Defaults to the checkbox in a selection column.\n\t *\n\t * @example\n\t * // Typed headers: header arguments are checked at compile time\n\t * const users = new TableLocator(page.locator(\"table\"), { headers: [\"Name\", \"Status\"] });\n\t *\n\t * @example\n\t * // Div based table with custom selectors\n\t * const table = new TableLocator(page.locator(\".divTable\"), {\n\t * header: { rowSelector: \".divTableHeading > .divTableRow\", columnSelector: \".divTableHead\" },\n\t * row: { rowSelector: \".divTableBody > .divTableRow\", columnSelector: \".divTableCell\" },\n\t * });\n\t *\n\t * @example\n\t * // ARIA grid, such as AG Grid or MUI Data Grid\n\t * const grid = new TableLocator(page.getByRole(\"grid\"), { aria: true });\n\t *\n\t * @example\n\t * // Rows by role and text instead of CSS\n\t * const orders = new TableLocator(page.locator(\"#orders\"), {\n\t * row: { rowSelector: { role: \"row\", hasNotText: \"Loading\" } },\n\t * emptyRow: { hasText: \"No data\" },\n\t * });\n\t */\n\tconstructor(root: Locator, options?: TableLocatorOptions<H>) {\n\t\tthis.root = root;\n\t\tthis._headers = options?.headers;\n\t\tthis._config = resolveEngineConfig(options);\n\t\tthis._loading = options?.loading === undefined ? undefined : resolveRef(options.loading, root);\n\t\tconst host: NavigationHost = {\n\t\t\troot,\n\t\t\tloading: this._loading,\n\t\t\tfingerprint: timeout => this.fingerprint(timeout),\n\t\t\twaitForStable: stable => this.waitForStable(stable),\n\t\t\tloadingShown: async () => this._loading !== undefined && (await isShown(this._loading)),\n\t\t};\n\t\tthis._navigator = new TableNavigator(host, options?.paginate, options?.scroll);\n\t\tthis._rowKey = options?.scroll?.rowKey;\n\t\tthis._select = options?.select;\n\t}\n\n\t/**\n\t * The footer rows of the table, such as a totals row, with typed cell access. Footer rows are not body\n\t * rows: `rows`, `row()`, `toJson()` and the matchers leave them out.\n\t *\n\t * @example\n\t * await expect(orders.footer.cell(\"Total\")).toHaveText(\"€ 1,295.75\");\n\t */\n\tget footer(): TableRow<H> {\n\t\tconst rows = this.root.locator(this.selector({ op: \"footer\", cfg: this._config }));\n\t\treturn new TableRow(this, described(rows, `${this.root.toString()}.footer`));\n\t}\n\n\t/**\n\t * All body rows of the table.\n\t *\n\t * @example\n\t * await expect(table.rows.locator).toHaveCount(3);\n\t *\n\t * @example\n\t * // Compose with Locator.filter and keep typed cell access\n\t * await expect(table.rows.filter({ hasText: \"Jane\" }).cell(\"Status\")).toHaveText(\"Active\");\n\t */\n\tget rows(): TableRow<H> {\n\t\tconst rows = this.root.locator(this.selector({ op: \"rows\", cfg: this._config }));\n\t\treturn new TableRow(this, described(rows, `${this.root.toString()}.rows`));\n\t}\n\n\t/**\n\t * Body rows where every condition matches. Conditions are keyed by header; values are an exact\n\t * string, a RegExp, or a {@link CellCondition}. Cell text is compared as the user sees it (see\n\t * {@link CellCondition}), and header names are normalized like header text.\n\t *\n\t * The returned locator follows Playwright's strict mode: acting on it when several rows match throws.\n\t *\n\t * @param where - At least one condition. Unknown headers are compile-time errors.\n\t * @returns A {@link TableRow} for the matching rows.\n\t * @throws Error if no condition has a value.\n\t *\n\t * @example\n\t * await expect(table.row({ Name: \"John\", Status: /active/i }).cell(\"Email\")).toHaveText(\"john@example.com\");\n\t *\n\t * @example\n\t * // Declarative conditions\n\t * await table.row({ Name: { startsWith: \"Jo\" }, Remarks: { empty: true } }).cell(\"Actions\").click();\n\t */\n\trow<W extends RowWhere<H>>(where: W & ValidRowWhere<H, W>): TableRow<H> {\n\t\treturn this.matchingRows(where);\n\t}\n\n\t/** {@link row}, without the compile-time checks of the conditions. */\n\tprivate matchingRows(where: RowWhere<string>): TableRow<H> {\n\t\tconst conditions = serializeWhere(where);\n\t\tif (conditions.length === 0) {\n\t\t\tthrow new Error(`TableLocator.row() requires at least one condition.\\nTable locator: ${this.root.toString()}`);\n\t\t}\n\t\tconst rows = this.root.locator(this.selector({ op: \"row\", cfg: this._config, where: conditions }));\n\t\treturn new TableRow(this, described(rows, `${this.root.toString()}.row(${describeWhere(where)})`));\n\t}\n\n\t/**\n\t * The body row at `index`.\n\t *\n\t * @param index - The row number (0-based).\n\t * @returns A {@link TableRow} for the row.\n\t * @throws Error if index is not a non-negative integer.\n\t *\n\t * @example\n\t * await expect(table.rowAt(0).cell(\"Name\")).toHaveText(\"John\");\n\t */\n\trowAt(index: number): TableRow<H> {\n\t\tif (index < 0 || !Number.isInteger(index)) {\n\t\t\tthrow new Error(`Row index must be a non-negative integer, got: ${index}`);\n\t\t}\n\t\tconst row = this.root.locator(this.selector({ op: \"rows\", cfg: this._config })).nth(index);\n\t\treturn new TableRow(this, described(row, `${this.root.toString()}.rowAt(${index})`));\n\t}\n\n\t/**\n\t * The cell under `column` for any row locator, for example one built with `filter()` or `nth()`.\n\t *\n\t * @param row - A locator for one or more body rows of this table.\n\t * @param column - The header key of the column, or its 0-based index (also works without header rows).\n\t * @returns A Playwright Locator for the cell.\n\t * @throws Error if column is a number that is not a non-negative integer.\n\t *\n\t * @example\n\t * const lastRow = table.rows.locator.last();\n\t * await expect(table.cell(lastRow, \"Name\")).toHaveText(\"Jane\");\n\t */\n\tcell(row: Locator, column: ColumnKey<H>): Locator {\n\t\tconst header = resolveColumn(column);\n\t\t// The engine finds the cell from the row alone, so it can't tell which table the row was meant to\n\t\t// be in. Intersecting with this table's column keeps it from resolving through another table.\n\t\tconst cell = row\n\t\t\t.locator(this.selector({ op: \"cell\", cfg: this._config, header }))\n\t\t\t.and(this.root.locator(this.selector({ op: \"column\", cfg: this._config, header, f: 1 })));\n\t\treturn described(cell, `${row.toString()}.cell(${JSON.stringify(column)})`);\n\t}\n\n\t/**\n\t * All body cells under `column`. A cell spanning several rows is included once.\n\t *\n\t * @param column - The header key of the column, or its 0-based index (also works without header rows).\n\t * @returns A Playwright Locator for the cells.\n\t * @throws Error if column is a number that is not a non-negative integer.\n\t *\n\t * @example\n\t * await expect(table.column(\"Status\")).toHaveText([\"Active\", \"Inactive\", \"Active\"]);\n\t * await expect(table.column(1)).toHaveText([\"Active\", \"Inactive\", \"Active\"]);\n\t */\n\tcolumn(column: ColumnKey<H>): Locator {\n\t\tconst cells = this.root.locator(this.selector({ op: \"column\", cfg: this._config, header: resolveColumn(column) }));\n\t\treturn described(cells, `${this.root.toString()}.column(${JSON.stringify(column)})`);\n\t}\n\n\t/**\n\t * The header cell element for `column` in the main header row.\n\t *\n\t * @param column - The header key of the column, or its 0-based index.\n\t * @returns A Playwright Locator for the header cell.\n\t * @throws Error if column is a number that is not a non-negative integer.\n\t *\n\t * @example\n\t * await table.header(\"Name\").click(); // sort by name\n\t */\n\theader(column: ColumnKey<H>): Locator {\n\t\tconst cell = this.root.locator(this.selector({ op: \"header\", cfg: this._config, header: resolveColumn(column) }));\n\t\treturn described(cell, `${this.root.toString()}.header(${JSON.stringify(column)})`);\n\t}\n\n\t/**\n\t * Reads the current header keys of the main header row, exactly as the engine resolves them\n\t * (including `__C`/`__D` suffixes and `{{Empty}}`). This is a snapshot, not a locator.\n\t *\n\t * @param options - Optional timeout for waiting until the table element is attached.\n\t * @returns A promise that resolves to the header keys, or an empty array if there are no header rows.\n\t *\n\t * @example\n\t * expect(await table.headerKeys()).toEqual([\"Name\", \"Status\", \"Email\"]);\n\t */\n\tasync headerKeys(options?: { timeout?: number }): Promise<string[]> {\n\t\tconst request: EngineKeysRequest = { op: \"keys\", cfg: this._config };\n\t\treturn this.root.evaluate(readTableHeaderKeys, request, options);\n\t}\n\n\t/**\n\t * Reads every body row as an object keyed by header key, like `PlaywrightTable.getJson()`. Cells that\n\t * span rows or columns are repeated in every position they cover; positions without a cell are `\"\"`.\n\t * Cell text is normalized as in row conditions: line breaks stay as one `\\n` between trimmed lines.\n\t * With `raw: true`, cells are returned exactly as the browser reads them.\n\t *\n\t * This is a snapshot, not a locator: without `minRows` or `stable` it reads the table once and does not\n\t * wait for rows. With `minRows`, it first waits for a header row and at least that many body rows with\n\t * content (a row where at least one cell has text), so empty placeholder rows don't count. With\n\t * `stable`, it then waits until the table stops changing (see {@link waitForStable}). To wait for\n\t * specific content, assert first (for example with `toHaveRow` or `toHaveRows`).\n\t *\n\t * @param options - Optional settings. See {@link TableJsonOptions}.\n\t * @param options.columns - (Optional) Only these columns, in this order. Defaults to every column.\n\t * @param options.parse - (Optional) Typed values for some columns: `\"number\"`, `\"date\"` or a function.\n\t * @param options.decimal - (Optional) The decimal separator of `\"number\"` columns. Defaults to `\".\"`.\n\t * @param options.minRows - (Optional) Wait for at least this many body rows with content. Defaults to `0` (no waiting).\n\t * @param options.stable - (Optional) Wait until the table stops changing before reading it. Defaults to `false`.\n\t * @param options.timeout - (Optional) With `minRows` or `stable`, the time to wait in milliseconds (default 5000).\n\t * Without them, the time to wait for the table element to be attached.\n\t * @param options.raw - (Optional) Return the cell texts without normalization. Defaults to `false`.\n\t * @returns A promise that resolves to one object per body row, or an empty array if there are no body rows.\n\t * @throws Error if the table has no header row (without `minRows`).\n\t * @throws Error if a key of `columns` or `parse` is not a header key of the table, with the available headers.\n\t * @throws Error if a cell of a `parse` column cannot be parsed, with the row, the column and the text.\n\t * @throws Error if `minRows` is not reached, or the table doesn't become stable, within the timeout.\n\t * @throws Error if `minRows` is not a non-negative integer.\n\t *\n\t * @example\n\t * expect(await users.toJson()).toEqual([\n\t * { Name: \"John\", Status: \"Active\" },\n\t * { Name: \"Jane\", Status: \"Inactive\" },\n\t * ]);\n\t *\n\t * @example\n\t * // Wait until at least one row is loaded\n\t * const data = await users.toJson({ minRows: 1 });\n\t *\n\t * @example\n\t * // Some columns, with typed values: { Id: string; Total: number | null }[]\n\t * const totals = await orders.toJson({ columns: [\"Id\", \"Total\"], parse: { Total: \"number\" } });\n\t */\n\tasync toJson<const C extends HeaderKey<H> = HeaderKey<H>, const P extends ColumnParsers<C> = Record<never, never>>(\n\t\toptions?: TableJsonOptions<C, P>\n\t): Promise<TableJsonRow<C, P>[]> {\n\t\tconst columns: readonly string[] | undefined = options?.columns;\n\t\tconst { keys, rows } = await this.readJsonTexts(options ?? {}, columns);\n\t\tconst outputKeys = columns ?? keys;\n\t\t// A `parse` key is normalized like a header name, as `columns` keys are: it parses the column it names.\n\t\tconst parsers = Object.entries<ColumnParser | undefined>(options?.parse ?? {}).map(\n\t\t\t([key, parser]): [string, ColumnParser | undefined] => [\n\t\t\t\toutputKeys.find(output => output === key) ??\n\t\t\t\t\toutputKeys.find(output => normalizeLine(output) === normalizeLine(key)) ??\n\t\t\t\t\tkey,\n\t\t\t\tparser,\n\t\t\t]\n\t\t);\n\t\tthis.checkJsonColumns(keys, outputKeys, columns ?? [], parsers);\n\n\t\tconst decimal = options?.decimal ?? \".\";\n\t\tconst result = rows.map((cells, r) => {\n\t\t\tconst row: Record<string, unknown> = {};\n\t\t\toutputKeys.forEach((key, index) => {\n\t\t\t\trow[key] = cells[index] ?? \"\";\n\t\t\t});\n\t\t\tfor (const [key, parser] of parsers) {\n\t\t\t\tif (parser !== undefined) row[key] = parseCell(parser, String(row[key]), decimal, r, key);\n\t\t\t}\n\t\t\treturn row;\n\t\t});\n\t\t// The values are built from `columns` and `parse`, exactly as `TableJsonRow` describes them.\n\t\treturn result as TableJsonRow<C, P>[];\n\t}\n\n\t/**\n\t * Reads the text of every body cell under `column`, one per body row. A cell that spans rows is\n\t * repeated in every row it covers; a row without a cell there reads as `\"\"`. Text is normalized as in\n\t * row conditions.\n\t *\n\t * This is a snapshot, not a locator: it reads the table once. To wait for content, assert first, or\n\t * use `toHaveColumnValues`.\n\t *\n\t * @param column - The header key of the column, or its 0-based index (also works without header rows).\n\t * @param options - Optional timeout for waiting until the table element is attached.\n\t * @returns A promise that resolves to the cell texts, or an empty array if there are no body rows.\n\t * @throws Error if the table has no such column, with the available headers.\n\t *\n\t * @example\n\t * expect(await users.columnValues(\"Status\")).toEqual([\"Active\", \"Inactive\", \"Active\"]);\n\t *\n\t * @example\n\t * // The distinct values of a column\n\t * const statuses = new Set(await users.columnValues(\"Status\"));\n\t */\n\tasync columnValues(column: ColumnKey<H>, options?: { timeout?: number }): Promise<string[]> {\n\t\tconst request: EngineValuesRequest = { op: \"values\", cfg: this._config, column: resolveColumn(column) };\n\t\tconst { keys, values } = await this.root.evaluate(readColumnValues, request, options);\n\t\tif (values === null) {\n\t\t\tthrow new Error(\n\t\t\t\t`TableLocator.columnValues(): ` +\n\t\t\t\t\t(typeof column === \"number\" ? `column ${column} does not exist.` : `Header \"${column}\" not found.`) +\n\t\t\t\t\t`\\nAvailable headers: [${keys.join(\", \")}]\\n` +\n\t\t\t\t\t`Table locator: ${this.root.toString()}`\n\t\t\t);\n\t\t}\n\t\treturn values;\n\t}\n\n\t/**\n\t * Waits until the table stops changing: the header keys and the text of every body cell stay the same\n\t * for `quiet` milliseconds, and the `loading` indicator (if any) is hidden. Use it after an action that\n\t * refreshes the table (searching, filtering, paging, sorting) before you read it with a snapshot method\n\t * such as {@link toJson}.\n\t *\n\t * Locators and the table matchers retry by themselves and don't need it. A table that has not started\n\t * to refresh yet looks stable, so pass `loading` when the table shows an indicator while it loads.\n\t *\n\t * @param options - Optional settings. See {@link StableOptions}.\n\t * @param options.quiet - (Optional) How long nothing may change, in milliseconds. Defaults to 500.\n\t * @param options.timeout - (Optional) The time to wait in milliseconds. Defaults to 5000.\n\t * @param options.loading - (Optional) A loading indicator that must be hidden. Defaults to the `loading` option of the table.\n\t * @returns A promise that resolves once the table is stable.\n\t * @throws Error if the table is not stable within the timeout: it kept changing, the loading indicator\n\t * stayed visible, or the table could not be read.\n\t *\n\t * @example\n\t * await page.getByLabel(\"Search\").fill(\"Jo\");\n\t * await users.waitForStable({ loading: page.locator(\".spinner\") });\n\t * const rows = await users.toJson();\n\t */\n\tasync waitForStable(options?: StableOptions): Promise<void> {\n\t\tconst quiet = options?.quiet ?? 500;\n\t\tconst timeout = checkTimeout(options?.timeout ?? 5_000);\n\t\tif (!(quiet >= 0) || !Number.isFinite(quiet)) {\n\t\t\tthrow new Error(`quiet must be a non-negative number, got: ${quiet}`);\n\t\t}\n\t\tconst loading = this.resolveLoading(options?.loading);\n\t\tconst request: EngineFingerprintRequest = { op: \"fingerprint\", cfg: this._config };\n\t\tconst deadline = Date.now() + timeout;\n\t\tconst state: StableState = { last: undefined, since: Date.now(), changes: 0, rows: undefined, busy: false };\n\t\tlet error: unknown;\n\t\t// Sample often enough that a change within the quiet period is seen.\n\t\tconst interval = Math.max(20, Math.min(100, quiet / 4));\n\t\tfor (;;) {\n\t\t\ttry {\n\t\t\t\tconst readTimeout = Math.max(MIN_READ_TIMEOUT, deadline - Date.now());\n\t\t\t\tconst print = await this.root.evaluate(readTableFingerprint, request, { timeout: readTimeout });\n\t\t\t\tconst busy = loading !== undefined && (await isShown(loading));\n\t\t\t\terror = undefined;\n\t\t\t\tif (observe(state, print, busy, quiet)) return;\n\t\t\t} catch (readError) {\n\t\t\t\terror = readError;\n\t\t\t\tstate.last = undefined;\n\t\t\t}\n\t\t\tconst left = deadline - Date.now();\n\t\t\tif (left <= 0) break;\n\t\t\tawait new Promise(resolve => setTimeout(resolve, Math.min(interval, left)));\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`TableLocator.waitForStable() timed out after ${timeout}ms: ${describeUnstable(state, quiet)}.\\n` +\n\t\t\t\t(state.rows === undefined ? \"\" : `Body rows: ${state.rows}\\n`) +\n\t\t\t\t(loading === undefined ? \"\" : `Loading locator: ${loading.toString()}\\n`) +\n\t\t\t\tdescribeLastError(error) +\n\t\t\t\t`Table locator: ${this.root.toString()}`\n\t\t);\n\t}\n\n\t/**\n\t * Finds a body row on any page or scroll position: it searches the rows in view, then (with the\n\t * `paginate` and `scroll` options) goes through the pages from the first one (with `paginate.first`)\n\t * and scrolls each page from the top, until a row matches. The table is left showing that row, and the\n\t * returned row locator resolves to it.\n\t *\n\t * Without `paginate` and `scroll`, it waits until a row in view matches, like a locator.\n\t *\n\t * @param where - At least one condition, as for {@link row}.\n\t * @param options - Optional timeout for the whole search, in milliseconds. Defaults to 30000.\n\t * @returns A promise that resolves to the {@link TableRow} for `row(where)`.\n\t * @throws Error if no row matches on any page (or within `paginate.maxPages` and `scroll.maxSteps`), with\n\t * the number of pages and scroll steps searched, and whether the search stopped early at the timeout.\n\t *\n\t * @example\n\t * const orders = defineTable(page.getByRole(\"grid\"), {\n\t * aria: true,\n\t * paginate: { next: page.getByRole(\"button\", { name: \"Next page\" }) },\n\t * });\n\t * const row = await orders.findRow({ Id: \"1042\" });\n\t * await row.cell(\"Status\").click();\n\t */\n\tasync findRow<W extends RowWhere<H>>(\n\t\twhere: W & ValidRowWhere<H, W>,\n\t\toptions?: NavigationOptions\n\t): Promise<TableRow<H>> {\n\t\tconst row = this.matchingRows(where);\n\t\tconst request: EngineFindRequest = { op: \"find\", cfg: this._config, where: serializeWhere(where) };\n\t\tconst timeout = checkTimeout(options?.timeout ?? 30_000);\n\t\tconst deadline = Date.now() + timeout;\n\t\t// A condition on an unknown header never matches: say so, instead of searching every page for it.\n\t\tconst unknown = await waitForHeaders(this, conditionHeaders(where), deadline);\n\t\tif (unknown !== \"\") {\n\t\t\tthrow new Error(\n\t\t\t\t`TableLocator.findRow() cannot match ${describeWhere(where)}.\\n` +\n\t\t\t\t\tunknown +\n\t\t\t\t\t`Table locator: ${this.root.toString()}`\n\t\t\t);\n\t\t}\n\t\t// The problems of the last read with a `predicate` condition, such as one that throws\n\t\tlet predicateErrors: string[] = [];\n\t\tconst matches = async (readTimeout: number): Promise<boolean> => {\n\t\t\tconst found = await this.root.evaluate(findTableRows, request, { timeout: readTimeout });\n\t\t\tpredicateErrors = found.errors;\n\t\t\treturn found.matches > 0;\n\t\t};\n\n\t\tconst now = await pollUntil(\n\t\t\tmatches,\n\t\t\tfound => found || this._navigator.active,\n\t\t\tfalse,\n\t\t\tthis._navigator.active ? Date.now() : deadline\n\t\t);\n\t\tif (now.value) return row;\n\t\tlet last: NavigationPosition = { page: 0, step: 0 };\n\t\t// Why the search ended before the end of the table, if it did\n\t\tlet stopped = \"\";\n\t\tlet lastError = now.error;\n\t\tconst timedOut = \", and timed out before the end of the table. Pass a larger timeout to search further\";\n\t\tif (this._navigator.active) {\n\t\t\ttry {\n\t\t\t\tfor await (const position of this._navigator.positions(deadline)) {\n\t\t\t\t\tlast = position;\n\t\t\t\t\tif (await matches(Math.max(MIN_READ_TIMEOUT, deadline - Date.now()))) return row;\n\t\t\t\t\tif (Date.now() >= deadline) {\n\t\t\t\t\t\tstopped = timedOut;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// A wait inside the navigation that ran out of time: report the timeout, with that error\n\t\t\t\tif (Date.now() < deadline) throw error;\n\t\t\t\tstopped = timedOut;\n\t\t\t\tlastError = error;\n\t\t\t}\n\t\t}\n\t\tthrow new Error(\n\t\t\t`TableLocator.findRow() found no row matching ${describeWhere(where)}` +\n\t\t\t\tthis._navigator.describeSearch(last) +\n\t\t\t\t`${stopped}.\\n` +\n\t\t\t\tpredicateErrors.map(error => `${error}\\n`).join(\"\") +\n\t\t\t\tdescribeLastError(lastError) +\n\t\t\t\t`Table locator: ${this.root.toString()}\\n` +\n\t\t\t\t`Timeout: ${timeout}ms`\n\t\t);\n\t}\n\n\t/**\n\t * The number of body rows in the whole table, also the rows that are not rendered or are on other pages.\n\t *\n\t * - A grid with `aria-rowcount` (on the root, inside it or around it) declares it: `aria-rowcount` minus\n\t * the rows it counts that are not body rows, such as header rows.\n\t * - Otherwise, with the `paginate` or `scroll` option, every row is read, as `toJson({ allRows: true })` does.\n\t * That leaves the table on its last page, scrolled down.\n\t * - Otherwise, the number of body rows.\n\t *\n\t * @param options - Optional timeout, in milliseconds. Defaults to 30000.\n\t * @returns A promise that resolves to the number of body rows.\n\t * @throws Error if it reads every row and the timeout passes before the end of the table.\n\t *\n\t * @example\n\t * expect(await grid.totalRowCount()).toBe(200);\n\t */\n\tasync totalRowCount(options?: NavigationOptions): Promise<number> {\n\t\tconst timeout = checkTimeout(options?.timeout ?? 30_000);\n\t\tconst deadline = Date.now() + timeout;\n\t\tconst request: EngineTotalRequest = { op: \"total\", cfg: this._config };\n\t\tconst total = await this.root.evaluate(readTableTotal, request, { timeout });\n\t\tif (total.ariaRowCount !== null) return Math.max(0, total.ariaRowCount - total.otherRows);\n\t\tif (!this._navigator.active) return total.bodyRows;\n\t\treturn (await this.readAllTexts(false, undefined, { caller: \"totalRowCount()\", timeout, deadline })).rows.length;\n\t}\n\n\t/**\n\t * The body rows in view as an aligned text table, with the row index in front, for logs and debugging.\n\t * Cells longer than 30 characters are cut off, and line breaks show as `↵`.\n\t *\n\t * @param options - Optional settings.\n\t * @param options.columns - (Optional) Only these columns. Unknown columns are skipped; if none is known,\n\t * every column is shown. Defaults to every column.\n\t * @param options.maxRows - (Optional) The most rows to show. Defaults to 50.\n\t * @param options.timeout - (Optional) The time to wait for the table, in milliseconds.\n\t * @returns A promise that resolves to the table as text.\n\t *\n\t * @example\n\t * console.log(await users.format());\n\t * // # | Name | Status\n\t * // 0 | John | Active\n\t * // 1 | Jane | Inactive\n\t */\n\tasync format(options?: { columns?: readonly ColumnKey<H>[]; maxRows?: number; timeout?: number }): Promise<string> {\n\t\tconst maxRows = options?.maxRows ?? 50;\n\t\tif (maxRows < 0 || !Number.isInteger(maxRows)) {\n\t\t\tthrow new Error(`maxRows must be a non-negative integer, got: ${maxRows}`);\n\t\t}\n\t\tconst texts = await this.readTexts(false, undefined, { timeout: options?.timeout });\n\t\treturn formatRows(texts, { columns: options?.columns, maxRows });\n\t}\n\n\t/**\n\t * Waits until every expected header exists, and fails fast with the available headers if they don't.\n\t *\n\t * @param expected - The headers to check. Defaults to the `headers` option of this table.\n\t * @param options - Optional timeout in milliseconds. Defaults to 5000.\n\t * @returns A promise that resolves once all headers exist.\n\t * @throws Error listing the missing and available headers when the timeout is reached.\n\t * @throws Error if there are no headers to check.\n\t *\n\t * @example\n\t * const users = new TableLocator(page.locator(\"table\"), { headers: [\"Name\", \"Status\"] });\n\t * await users.validateHeaders();\n\t * // Error: Missing headers: [Status]\n\t * // Available headers: [Name, State]\n\t */\n\tasync validateHeaders(expected?: readonly HeaderKey<H>[], options?: { timeout?: number }): Promise<void> {\n\t\tconst required: readonly string[] = expected ?? this._headers ?? [];\n\t\tif (required.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t\"TableLocator.validateHeaders() needs headers: pass them as an argument or set `headers` in the options.\"\n\t\t\t);\n\t\t}\n\n\t\tconst timeout = checkTimeout(options?.timeout ?? 5_000);\n\t\tconst missingFrom = (keys: readonly string[]): string[] =>\n\t\t\trequired.filter(header => !keys.includes(normalizeLine(header)));\n\t\tconst poll = await pollUntil(\n\t\t\treadTimeout => this.headerKeys({ timeout: readTimeout }),\n\t\t\tkeys => missingFrom(keys).length === 0,\n\t\t\t[] as string[],\n\t\t\tDate.now() + timeout\n\t\t);\n\t\tconst missing = missingFrom(poll.value);\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`Missing headers: [${missing.join(\", \")}]\\n` +\n\t\t\t\t\t`Available headers: [${poll.value.join(\", \")}]\\n` +\n\t\t\t\t\tdescribeLastError(poll.error) +\n\t\t\t\t\t`Table locator: ${this.root.toString()}`\n\t\t\t);\n\t\t}\n\t}\n\n\t/** The texts for `toJson()`: read once, or after waiting for `minRows` and `stable`. */\n\tprivate async readJsonTexts(\n\t\toptions: TableJsonOptions<string, unknown>,\n\t\tcolumns: readonly string[] | undefined\n\t): Promise<EngineTexts> {\n\t\tconst raw = options.raw === true;\n\t\tconst allRows = options.allRows === true;\n\t\t// One timeout for the whole read, waits included; reading all rows has a longer default.\n\t\tconst timeout = checkTimeout(options.timeout ?? (allRows ? 30_000 : 5_000));\n\t\tconst deadline = Date.now() + timeout;\n\t\tconst left = (): number => Math.max(MIN_READ_TIMEOUT, deadline - Date.now());\n\t\tconst waited = await this.waitForJson(options, columns, left);\n\t\tif (allRows) {\n\t\t\t// Only the header keys: the rows are read at every position next.\n\t\t\tthis.checkJsonHeader(waited.texts?.keys ?? (await this.headerKeys({ timeout: left() })));\n\t\t\treturn this.readAllTexts(raw, columns, { caller: \"toJson({ allRows: true })\", timeout, deadline });\n\t\t}\n\t\tlet texts = waited.texts;\n\t\tif (texts === undefined || waited.stable) {\n\t\t\t// Without waiting, the timeout is only for the table element to be attached.\n\t\t\ttexts = await this.readTexts(raw, columns, { timeout: waited.waits ? left() : options.timeout });\n\t\t}\n\t\tthis.checkJsonHeader(texts.keys);\n\t\treturn texts;\n\t}\n\n\t/**\n\t * The waits of `toJson()`: for `minRows` (with the texts it read), then until the table is `stable`,\n\t * each within the time `left`.\n\t */\n\tprivate async waitForJson(\n\t\toptions: TableJsonOptions<string, unknown>,\n\t\tcolumns: readonly string[] | undefined,\n\t\tleft: () => number\n\t): Promise<{ texts: EngineTexts | undefined; stable: boolean; waits: boolean }> {\n\t\tconst minRows = checkMinRows(options.minRows);\n\t\tconst stable = options.stable === false ? undefined : options.stable;\n\t\tconst texts =\n\t\t\tminRows > 0 ? await this.readTextsWithRows(minRows, left(), options.raw === true, columns) : undefined;\n\t\tif (stable !== undefined) {\n\t\t\tconst settings = stable === true ? {} : stable;\n\t\t\tawait this.waitForStable({ ...settings, timeout: Math.min(settings.timeout ?? Infinity, left()) });\n\t\t}\n\t\treturn { texts, stable: stable !== undefined, waits: minRows > 0 || stable !== undefined };\n\t}\n\n\t/** @throws Error if the table has no header row, which `toJson()` needs for its keys. */\n\tprivate checkJsonHeader(keys: readonly string[]): void {\n\t\tif (keys.length > 0) return;\n\t\tconst selector = this._config.headerRow;\n\t\tthrow new Error(\n\t\t\t`TableLocator.toJson() needs a header row, but the table has none.\\n` +\n\t\t\t\t(selector === undefined ? \"\" : `Header row selector: ${JSON.stringify(selector)}\\n`) +\n\t\t\t\t`Table locator: ${this.root.toString()}`\n\t\t);\n\t}\n\n\t/**\n\t * Checks the `columns` and `parse` options of `toJson()` against the header keys of the table.\n\t * @throws Error with the available headers if a key is not a header key, or a `parse` key is not in `columns`.\n\t */\n\tprivate checkJsonColumns(\n\t\tkeys: readonly string[],\n\t\toutputKeys: readonly string[],\n\t\tcolumns: readonly string[],\n\t\tparsers: readonly [string, unknown][]\n\t): void {\n\t\tconst parseKeys = parsers.map(([key]) => key);\n\t\tconst unknown = [\n\t\t\t...columns.filter(key => !keys.includes(normalizeLine(key))),\n\t\t\t...parseKeys.filter(key => !outputKeys.includes(key) && !keys.includes(key)),\n\t\t];\n\t\tif (unknown.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`TableLocator.toJson(): ${unknown.map(key => `Header \"${key}\" not found.`).join(\" \")}\\n` +\n\t\t\t\t\t`Available headers: [${keys.join(\", \")}]\\n` +\n\t\t\t\t\t`Table locator: ${this.root.toString()}`\n\t\t\t);\n\t\t}\n\t\tconst notSelected = parseKeys.filter(key => !outputKeys.includes(key));\n\t\tif (notSelected.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`TableLocator.toJson(): parse has headers that are not in columns: [${notSelected.join(\", \")}]\\n` +\n\t\t\t\t\t`Columns: [${outputKeys.join(\", \")}]\\n` +\n\t\t\t\t\t`Table locator: ${this.root.toString()}`\n\t\t\t);\n\t\t}\n\t}\n\n\t/** The loading indicator for `loading`, or else the `loading` option of the table. */\n\tprivate resolveLoading(loading: LocatorRef | undefined): Locator | undefined {\n\t\treturn loading === undefined ? this._loading : resolveRef(loading, this.root);\n\t}\n\n\t/** A fingerprint of the header keys and body cell texts, and the number of body rows. */\n\tprivate async fingerprint(timeout: number): Promise<{ rows: number; print: string }> {\n\t\tconst request: EngineFingerprintRequest = { op: \"fingerprint\", cfg: this._config };\n\t\tconst print = await this.root.evaluate(readTableFingerprint, request, { timeout });\n\t\treturn { rows: print.rows, print: `${print.rows}|${print.hash}` };\n\t}\n\n\t/**\n\t * Reads every row on every page and scroll position. Rows are told apart by their key per page, and\n\t * ordered by their index when every row has one. Header keys are merged across positions, so a grid\n\t * that renders only some columns at a time still gets every column it showed.\n\t *\n\t * @throws Error if the deadline passes before every row is read (up to `paginate.maxPages` and\n\t * `scroll.maxSteps`), so part of the rows is never returned as all of them.\n\t */\n\tprivate async readAllTexts(\n\t\traw: boolean,\n\t\tcolumns: readonly string[] | undefined,\n\t\tread: { caller: string; timeout: number; deadline: number }\n\t): Promise<EngineTexts> {\n\t\tconst { caller, timeout, deadline } = read;\n\t\tconst request: EngineWindowRequest = { op: \"window\", cfg: this._config };\n\t\tif (raw) request.raw = true;\n\t\tif (columns !== undefined) request.columns = [...columns];\n\t\tif (this._rowKey !== undefined) request.rowKey = this._rowKey;\n\n\t\tconst keys: string[] = [];\n\t\tconst rows: Record<string, string>[] = [];\n\t\tlet page: Map<string, { index: number | null; cells: Record<string, string> }> = new Map();\n\t\tlet pageNumber = 0;\n\t\tconst flush = (): void => {\n\t\t\tconst entries = [...page.values()];\n\t\t\tif (entries.every(entry => entry.index !== null)) {\n\t\t\t\tentries.sort((a, b) => (a.index ?? 0) - (b.index ?? 0));\n\t\t\t}\n\t\t\trows.push(...entries.map(entry => entry.cells));\n\t\t\tpage = new Map();\n\t\t};\n\t\tconst progress = (): string =>\n\t\t\t`${rows.length + page.size} rows were read, on ${pageNumber + 1} page${pageNumber === 0 ? \"\" : \"s\"}`;\n\t\tlet timedOut = false;\n\t\tlet lastError: unknown;\n\t\ttry {\n\t\t\tfor await (const position of this._navigator.positions(deadline)) {\n\t\t\t\t// The navigation moved on, so there are rows left to read\n\t\t\t\tif (Date.now() >= deadline) {\n\t\t\t\t\ttimedOut = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (position.page !== pageNumber) {\n\t\t\t\t\tflush();\n\t\t\t\t\tpageNumber = position.page;\n\t\t\t\t}\n\t\t\t\tconst window = await this.root.evaluate(readTableWindow, request, {\n\t\t\t\t\ttimeout: Math.max(MIN_READ_TIMEOUT, deadline - Date.now()),\n\t\t\t\t});\n\t\t\t\tmergeWindow(window, columns, keys, page);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// A wait inside the navigation that ran out of time: report the timeout, with that error\n\t\t\tif (Date.now() < deadline) throw error;\n\t\t\ttimedOut = true;\n\t\t\tlastError = error;\n\t\t}\n\t\tif (timedOut) {\n\t\t\tthrow new Error(\n\t\t\t\t`TableLocator.${caller} timed out after ${timeout}ms before reading every row; ${progress()}. ` +\n\t\t\t\t\t`Pass a larger timeout.\\n` +\n\t\t\t\t\tdescribeLastError(lastError) +\n\t\t\t\t\t`Table locator: ${this.root.toString()}`\n\t\t\t);\n\t\t}\n\t\tflush();\n\t\tconst names = columns ?? keys;\n\t\treturn { keys, rows: rows.map(cells => names.map(name => cells[name] ?? \"\")) };\n\t}\n\n\tprivate readTexts(\n\t\traw: boolean,\n\t\tcolumns: readonly string[] | undefined,\n\t\toptions?: { timeout?: number }\n\t): Promise<EngineTexts> {\n\t\tconst request: EngineTextsRequest = { op: \"texts\", cfg: this._config };\n\t\tif (raw) request.raw = true;\n\t\tif (columns !== undefined) request.columns = [...columns];\n\t\treturn this.root.evaluate(readTableTexts, request, options);\n\t}\n\n\t/** Reads the table once it has a header row and at least `minRows` body rows with content. */\n\tprivate async readTextsWithRows(\n\t\tminRows: number,\n\t\ttimeout: number,\n\t\traw: boolean,\n\t\tcolumns: readonly string[] | undefined\n\t): Promise<EngineTexts> {\n\t\t// Raw texts are normalized to decide, so a cell with only a non-breaking space or a glyph is empty.\n\t\tconst withContent = (texts: EngineTexts): number =>\n\t\t\ttexts.rows.filter(row => row.some(text => normalizeCell(text) !== \"\")).length;\n\t\tconst poll = await pollUntil(\n\t\t\treadTimeout => this.readTexts(raw, columns, { timeout: readTimeout }),\n\t\t\ttexts => texts.keys.length > 0 && withContent(texts) >= minRows,\n\t\t\t{ keys: [], rows: [] },\n\t\t\tDate.now() + timeout\n\t\t);\n\t\tconst texts = poll.value;\n\t\tif (texts.keys.length > 0 && withContent(texts) >= minRows) return texts;\n\n\t\tconst found =\n\t\t\ttexts.keys.length === 0\n\t\t\t\t? \"the table has no header row\"\n\t\t\t\t: `found ${withContent(texts)} (${texts.rows.length} body rows in total)`;\n\t\tthrow new Error(\n\t\t\t`TableLocator.toJson() expected at least ${minRows} body rows with content, ${found}.\\n` +\n\t\t\t\t`Header keys: [${texts.keys.join(\", \")}]\\n` +\n\t\t\t\tdescribeLastError(poll.error) +\n\t\t\t\t`Table locator: ${this.root.toString()}\\n` +\n\t\t\t\t`Timeout: ${timeout}ms`\n\t\t);\n\t}\n\n\tprivate selector(query: EngineQuery): string {\n\t\treturn `${TABLE_SELECTOR_ENGINE_NAME}=${JSON.stringify(query)}`;\n\t}\n}\n\n/**\n * Creates a {@link TableLocator}. Header names passed in `options.headers` are inferred as literal\n * types, so header arguments are checked and autocompleted.\n *\n * @param root - The Playwright `Locator` pointing to the root table element.\n * @param options - Optional configuration. See {@link TableLocatorOptions}.\n * @returns A new {@link TableLocator}.\n *\n * @example\n * const users = defineTable(page.locator(\"#users\"), { headers: [\"Name\", \"Status\", \"Email\"] });\n * await expect(users.row({ Name: \"John\" }).cell(\"Email\")).toHaveText(\"john@example.com\");\n * // @ts-expect-error \"Nme\" is not a header of this table\n * users.row({ Nme: \"John\" });\n */\nexport function defineTable<const H extends string = string>(\n\troot: Locator,\n\toptions?: TableLocatorOptions<H>\n): TableLocator<H> {\n\treturn new TableLocator<H>(root, options);\n}\n\n/**\n * The engine configuration for `options`. Only what differs from the defaults is set, so selectors stay\n * short; the engine fills in the default selectors.\n */\nfunction resolveEngineConfig(options: TableLocatorOptions<string> = {}): EngineConfig {\n\tconst { header = {}, row = {} } = options;\n\tconst cfg: EngineConfig = {};\n\tif (options.aria === true) cfg.aria = 1;\n\tif (header.rowSelector !== undefined) cfg.headerRow = serializeSelector(\"header.rowSelector\", header.rowSelector);\n\tif (header.columnSelector !== undefined) {\n\t\tcfg.headerCell = serializeSelector(\"header.columnSelector\", header.columnSelector);\n\t}\n\tif (row.rowSelector !== undefined) cfg.bodyRow = serializeSelector(\"row.rowSelector\", row.rowSelector);\n\tif (row.columnSelector !== undefined) cfg.bodyCell = serializeSelector(\"row.columnSelector\", row.columnSelector);\n\tif (header.setMainHeaderRow !== undefined) cfg.mainHeaderRow = header.setMainHeaderRow;\n\tif (options.emptyRow !== undefined) cfg.emptyRow = serializeSelector(\"emptyRow\", options.emptyRow);\n\tif (options.footer?.rowSelector !== undefined) {\n\t\tcfg.footerRow = serializeSelector(\"footer.rowSelector\", options.footer.rowSelector);\n\t}\n\tTableUtils.warnOnIdenticalRowSelectors(\"TableLocator\", cfg.headerRow, cfg.bodyRow);\n\treturn { ...cfg, ...resolveTextConfig(options) };\n}\n\n/** The engine configuration for how `options` reads cell text. Only what differs from the defaults is set. */\nfunction resolveTextConfig(options: TableLocatorOptions<string>): EngineConfig {\n\tconst cfg: EngineConfig = {};\n\tif (options.cellContentType === CellContentType.TextContent) cfg.textContent = 1;\n\tif (options.ignore !== undefined) {\n\t\tcfg.ignore = options.ignore.map((selector, i) => serializeSelector(`ignore[${i}]`, selector));\n\t}\n\tif (options.readInputValues === true) cfg.inputs = 1;\n\treturn cfg;\n}\n\n/** What `waitForStable()` has seen so far. */\ntype StableState = {\n\t/** The last fingerprint, or `undefined` while the table is loading or could not be read. */\n\tlast: string | undefined;\n\t/** When the last fingerprint was first seen. */\n\tsince: number;\n\t/** How often the fingerprint changed. */\n\tchanges: number;\n\t/** The number of body rows of the last read, or `undefined` if no read succeeded. */\n\trows: number | undefined;\n\t/** Whether the loading indicator was visible at the last read. */\n\tbusy: boolean;\n};\n\n/** Records a read in `state`. Returns whether the table has stayed the same for `quiet` milliseconds. */\nfunction observe(state: StableState, print: EngineFingerprint, busy: boolean, quiet: number): boolean {\n\tstate.rows = print.rows;\n\tstate.busy = busy;\n\tconst current = busy ? undefined : `${print.rows}|${print.hash}`;\n\tif (current !== undefined && current === state.last) return Date.now() - state.since >= quiet;\n\tif (state.last !== undefined) state.changes++;\n\tstate.last = current;\n\tstate.since = Date.now();\n\treturn false;\n}\n\n/** Why `waitForStable()` timed out. */\nfunction describeUnstable(state: StableState, quiet: number): string {\n\tif (state.rows === undefined) return \"the table could not be read\";\n\tif (state.busy) return \"the loading indicator is still visible\";\n\tif (state.changes > 0) return `the table kept changing (${state.changes} changes seen)`;\n\treturn `it did not stay the same for ${quiet}ms`;\n}\n\n/** `minRows` of `toJson()`, checked. */\nfunction checkMinRows(minRows: number | undefined): number {\n\tconst value = minRows ?? 0;\n\tif (value < 0 || !Number.isInteger(value)) {\n\t\tthrow new Error(`minRows must be a non-negative integer, got: ${value}`);\n\t}\n\treturn value;\n}\n\n/**\n * Whether any element of `locator` is visible, in one round trip. Doesn't wait, and works when it matches\n * several elements (or none). Visible means what Playwright means: a non-empty box, and not\n * `visibility: hidden`.\n */\nasync function isShown(locator: Locator): Promise<boolean> {\n\treturn locator.evaluateAll(elements =>\n\t\telements.some(element => {\n\t\t\tconst box = element.getBoundingClientRect();\n\t\t\treturn box.width > 0 && box.height > 0 && getComputedStyle(element).visibility !== \"hidden\";\n\t\t})\n\t);\n}\n\n/**\n * The value of a cell of a `parse` column of `toJson()`.\n * @throws Error with the row, the column and the text if the cell cannot be parsed.\n */\nfunction parseCell(parser: ColumnParser, text: string, decimal: DecimalSeparator, row: number, key: string): unknown {\n\tconst fail = (problem: string): Error =>\n\t\tnew Error(`TableLocator.toJson(): row ${row} \"${key}\" (${JSON.stringify(text)}) ${problem}`);\n\tif (typeof parser === \"function\") {\n\t\ttry {\n\t\t\treturn parser(text);\n\t\t} catch (error) {\n\t\t\tthrow fail(`could not be parsed: ${error instanceof Error ? error.message : String(error)}`);\n\t\t}\n\t}\n\tif (text.trim() === \"\") return null;\n\tif (parser === \"number\") {\n\t\tconst value = parseNumber(text, decimal);\n\t\tif (isNaN(value)) throw fail(`is not a number (decimal separator \"${decimal}\")`);\n\t\treturn value;\n\t}\n\tconst time = Date.parse(text);\n\tif (isNaN(time)) throw fail(\"is not a date (parsed with Date.parse)\");\n\treturn new Date(time);\n}\n\n/** A column for the engine: a header name normalized like header text, or a checked column index. */\nfunction resolveColumn(column: string | number): string | number {\n\tif (typeof column === \"string\") return normalizeLine(column);\n\tif (column < 0 || !Number.isInteger(column)) {\n\t\tthrow new Error(`Column index must be a non-negative integer, got: ${column}`);\n\t}\n\treturn column;\n}\n\n/**\n * `locator`, described as `description` in error messages, the call log and traces. `describe()` exists\n * since Playwright 1.53; on older versions the locator is returned as it is.\n */\nfunction described(locator: Locator, description: string): Locator {\n\t// Through `unknown`, so this also compiles against the types of Playwright versions without `describe()`\n\tconst describe = (locator as unknown as { describe?: (description: string) => Locator }).describe;\n\treturn typeof describe === \"function\" ? describe.call(locator, description) : locator;\n}\n\n/**\n * Adds the rows of one screen of a table to the rows of its page, by row key, so a row seen at several\n * scroll positions is one row. New header keys are added to `keys`.\n */\nfunction mergeWindow(\n\twindow: EngineWindow,\n\tcolumns: readonly string[] | undefined,\n\tkeys: string[],\n\tpage: Map<string, { index: number | null; cells: Record<string, string> }>\n): void {\n\tconst names = columns ?? window.keys;\n\tfor (const key of window.keys) if (!keys.includes(key)) keys.push(key);\n\tfor (const row of window.rows) {\n\t\tconst cells = page.get(row.key)?.cells ?? {};\n\t\tnames.forEach((name, index) => {\n\t\t\tcells[name] = row.texts[index] ?? \"\";\n\t\t});\n\t\tpage.set(row.key, { index: row.index, cells });\n\t}\n}\n\n/** Describes `Locator.filter()` options, such as `{ hasText: \"Jane\" }`. Locators show their own description. */\nfunction describeFilter(options?: RowFilterOptions): string {\n\tconst entries: [string, unknown][] = Object.entries(options ?? {});\n\tconst parts = entries\n\t\t.filter(entry => entry[1] !== undefined)\n\t\t.map(([key, value]) => `${key}: ${typeof value === \"string\" ? JSON.stringify(value) : String(value)}`);\n\treturn parts.length === 0 ? \"\" : `{ ${parts.join(\", \")} }`;\n}\n","import type { Locator } from \"@playwright/test\";\n\nimport type { LocatorRef, TableLocatorOptions } from \"./table-locator.types\";\nimport { resolveRef } from \"./table-navigation\";\nimport { DEFAULT_IGNORE } from \"./table-selector-engine\";\n\n/**\n * {@link TableLocatorOptions} without `headers`, so a preset can be spread into options with your own\n * typed headers.\n */\nexport type TablePreset = Omit<TableLocatorOptions<string>, \"headers\">;\n\n/** The button inside `root` with exactly this accessible name. */\nfunction button(root: Locator, name: string): Locator {\n\treturn root.getByRole(\"button\", { name, exact: true });\n}\n\n/**\n * The rows AG Grid pins to the top or bottom of the grid (pinnedTopRowData, pinnedBottomRowData), with the\n * class names of AG Grid 33 and later, and of older versions.\n */\nconst PINNED_ROWS =\n\t\".ag-grid-pinned-top-rows .ag-row, .ag-floating-top .ag-row, .ag-grid-pinned-bottom-rows .ag-row, .ag-floating-bottom .ag-row\";\n\n/**\n * Options for AG Grid (tested with AG Grid Community 36): ARIA roles, the header rows without the\n * floating filter row, the pinned top and bottom rows (such as totals) as footer rows, the body viewport to scroll, the\n * pagination panel, and the loading overlay. The table root is the element you created the grid in, or\n * any element inside it that holds the whole grid.\n *\n * AG Grid also renders only the columns in view (column virtualization). Rows are read with every\n * column AG Grid has rendered; to read columns outside the view, turn it off with\n * `suppressColumnVirtualisation: true`, or make the grid wide enough in your tests.\n *\n * @example\n * const cars = defineTable(page.locator(\"#myGrid\"), { ...presets.agGrid(), headers: [\"Make\", \"Model\", \"Price\"] });\n * const row = await cars.findRow({ Model: \"Model 150\" });\n * await expect(cars).toHaveTotalRowCount(200);\n */\nfunction agGrid(): TablePreset {\n\treturn {\n\t\taria: true,\n\t\theader: {\n\t\t\t// Column group rows and the column row; the floating filter row is not a header row of keys.\n\t\t\trowSelector: \".ag-header-row-column-group, .ag-header-row-column\",\n\t\t\tcolumnSelector: \"[role=columnheader]\",\n\t\t},\n\t\trow: { rowSelector: `.ag-row:not(${PINNED_ROWS})` },\n\t\tfooter: { rowSelector: PINNED_ROWS },\n\t\tscroll: { container: root => root.locator(\".ag-grid-viewport, .ag-body-viewport\").first() },\n\t\tpaginate: {\n\t\t\tnext: root => button(root, \"Next Page\"),\n\t\t\tfirst: root => button(root, \"First Page\"),\n\t\t},\n\t\tloading: root => root.locator(\".ag-overlay-loading-wrapper, .ag-overlay-loading-center\"),\n\t\tignore: [...DEFAULT_IGNORE, \".ag-hidden\"],\n\t};\n}\n\n/**\n * Options for MUI X Data Grid (based on the markup of version 7 and 8): ARIA roles, the row and cell\n * classes (without filler and skeleton cells), the virtual scroller, the pagination buttons, and the\n * loading indicator. The table root is the `.MuiDataGrid-root` element, such as `page.getByRole(\"grid\")`.\n *\n * @example\n * const users = defineTable(page.getByRole(\"grid\"), presets.muiDataGrid());\n * await expect(users).toHaveTotalRowCount(100);\n */\nfunction muiDataGrid(): TablePreset {\n\treturn {\n\t\taria: true,\n\t\theader: {\n\t\t\trowSelector: \".MuiDataGrid-columnHeaders [role=row], .MuiDataGrid-columnHeaderRow\",\n\t\t\tcolumnSelector: \"[role=columnheader]\",\n\t\t},\n\t\trow: {\n\t\t\trowSelector: \".MuiDataGrid-row\",\n\t\t\tcolumnSelector: \"[role=gridcell]:not(.MuiDataGrid-cellEmpty):not(.MuiDataGrid-cellSkeleton)\",\n\t\t},\n\t\tscroll: { container: root => root.locator(\".MuiDataGrid-virtualScroller\").first() },\n\t\tpaginate: { next: root => button(root, \"Go to next page\") },\n\t\tloading: root => root.locator(\".MuiDataGrid-overlay [role=progressbar], .MuiDataGrid-loadingOverlay\"),\n\t};\n}\n\n/**\n * Options for an Angular Material table (`mat-table`, as a native `<table>` or with the `<mat-table>`\n * elements), in both the MDC (`mat-mdc-*`) and the legacy class names. The \"no data\" row is not a body\n * row, and footer rows are footer rows. With `paginator`, the `mat-paginator` that pages the table: a\n * `Locator`, or a function that finds it from the table root.\n *\n * @example\n * const orders = defineTable(page.locator(\"table[mat-table]\"), presets.angularMaterial({ paginator: page.locator(\"mat-paginator\") }));\n * const row = await orders.findRow({ Id: \"42\" });\n */\nfunction angularMaterial(options?: { paginator?: LocatorRef }): TablePreset {\n\tconst paginator = options?.paginator;\n\treturn {\n\t\theader: {\n\t\t\trowSelector: \".mat-mdc-header-row, .mat-header-row\",\n\t\t\tcolumnSelector: \".mat-mdc-header-cell, .mat-header-cell\",\n\t\t},\n\t\trow: {\n\t\t\trowSelector: \".mat-mdc-row, .mat-row\",\n\t\t\tcolumnSelector: \".mat-mdc-cell, .mat-cell, .mat-mdc-footer-cell, .mat-footer-cell\",\n\t\t},\n\t\tfooter: { rowSelector: \".mat-mdc-footer-row, .mat-footer-row\" },\n\t\t// The \"no data\" row gets `mat-mdc-no-data-row`, and the Angular docs give it `mat-row` as well\n\t\temptyRow: \".mat-mdc-no-data-row, .mat-no-data-row\",\n\t\t...(paginator === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\tpaginate: {\n\t\t\t\t\t\tnext: (root: Locator) => button(resolveRef(paginator, root), \"Next page\"),\n\t\t\t\t\t\tfirst: (root: Locator) => button(resolveRef(paginator, root), \"First page\"),\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t// The sort header arrow is drawn, but some versions put text in it.\n\t\tignore: [...DEFAULT_IGNORE, \".mat-sort-header-arrow\"],\n\t};\n}\n\n/**\n * Options for a table virtualized with TanStack Virtual (`@tanstack/react-virtual` and friends), which\n * renders only the rows in view and marks each with `data-index`. TanStack Table itself renders plain\n * HTML tables, which work without a preset.\n *\n * @param options.container - The element that scrolls, usually a `div` around the table.\n *\n * @example\n * const rows = defineTable(page.locator(\"table\"), presets.tanstackVirtual({ container: page.locator(\".scroll-container\") }));\n * const all = await rows.toJson({ allRows: true });\n */\nfunction tanstackVirtual(options: { container: Locator }): TablePreset {\n\treturn { scroll: { container: options.container, rowKey: \"data-index\" } };\n}\n\n/**\n * Ready-made {@link TableLocatorOptions} for popular data grids. Spread a preset into your own options to\n * add typed headers or change a setting.\n *\n * @example\n * const grid = defineTable(page.locator(\"#grid\"), { ...presets.agGrid(), headers: [\"Id\", \"Name\"] });\n */\nexport const presets: {\n\tagGrid: typeof agGrid;\n\tmuiDataGrid: typeof muiDataGrid;\n\tangularMaterial: typeof angularMaterial;\n\ttanstackVirtual: typeof tanstackVirtual;\n} = { agGrid, muiDataGrid, angularMaterial, tanstackVirtual };\n","import {\n\ttest as base,\n\tselectors as defaultSelectors,\n\tPlaywrightTestArgs,\n\tPlaywrightTestOptions,\n\tPlaywrightWorkerArgs,\n\tPlaywrightWorkerOptions,\n\tSelectors,\n\tTestType,\n} from \"@playwright/test\";\n\nimport { TABLE_SELECTOR_ENGINE_NAME, tableSelectorEngine } from \"./table-selector-engine\";\n\nconst registrations = new WeakMap<Selectors, Promise<void>>();\n\n/**\n * Registers the `pw-table-v1` selector engine used by {@link TableLocator}.\n *\n * Safe to call more than once: later calls reuse the first registration, and an\n * \"already registered\" error (for example from another copy of this package) is ignored.\n *\n * Registration must happen **before the page is created**. You don't need this function if you\n * import `test` from this package, which registers the engine with a worker-scoped auto fixture.\n *\n * @param target - The Playwright `selectors` object to register on. Defaults to `selectors` from `@playwright/test`.\n * @returns A promise that resolves once the engine is registered.\n *\n * @example\n * // With your own test fixtures\n * import { test as base } from \"@playwright/test\";\n * import { registerTableSelectors } from \"@cerios/playwright-table\";\n *\n * export const test = base.extend<{}, { tableSelectors: void }>({\n * tableSelectors: [async ({ playwright }, use) => {\n * await registerTableSelectors(playwright.selectors);\n * await use();\n * }, { scope: \"worker\", auto: true }],\n * });\n *\n * @example\n * // Without fixtures\n * test.beforeAll(async () => {\n * await registerTableSelectors();\n * });\n */\nexport function registerTableSelectors(target: Selectors = defaultSelectors): Promise<void> {\n\tlet registration = registrations.get(target);\n\tif (registration === undefined) {\n\t\t// Run in an isolated world: Firefox evaluates custom engines with eval(), which a strict page CSP\n\t\t// blocks in the main world. The isolated world shares the DOM, which is all the engine needs.\n\t\tconst options = { contentScript: true };\n\t\tregistration = target.register(TABLE_SELECTOR_ENGINE_NAME, tableSelectorEngine, options).catch((error: unknown) => {\n\t\t\tif (error instanceof Error && /already registered/.test(error.message)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tregistrations.delete(target);\n\t\t\tthrow error;\n\t\t});\n\t\tregistrations.set(target, registration);\n\t}\n\treturn registration;\n}\n\n/**\n * Playwright `test` with the `pw-table-v1` selector engine registered for every worker, so\n * {@link TableLocator} works without any setup. Use it instead of `test` from `@playwright/test`.\n *\n * The engine is registered by a worker-scoped auto fixture, so it is always registered before\n * any page is created.\n *\n * @example\n * import { test, expect, defineTable } from \"@cerios/playwright-table\";\n *\n * test(\"shows the user\", async ({ page }) => {\n * const users = defineTable(page.locator(\"table\"), { headers: [\"Name\", \"Status\"] });\n * await expect(users.row({ Name: \"John\" }).cell(\"Status\")).toHaveText(\"Active\");\n * });\n */\nexport const test: TestType<\n\tPlaywrightTestArgs & PlaywrightTestOptions,\n\tPlaywrightWorkerArgs & PlaywrightWorkerOptions & { _pwTableSelectors: void }\n> = base.extend<{}, { _pwTableSelectors: void }>({\n\t_pwTableSelectors: [\n\t\tasync ({ playwright }, use) => {\n\t\t\tawait registerTableSelectors(playwright.selectors);\n\t\t\tawait use();\n\t\t},\n\t\t{ scope: \"worker\", auto: true },\n\t],\n});\n","import { expect as baseExpect, Expect, ExpectMatcherState, Locator, test, TestInfo } from \"@playwright/test\";\n\nimport { describeMatcher, describeWhere, serializeMatcher, serializeWhere } from \"./cell-matcher-serializer\";\nimport { checkTimeout, describeLastError, MIN_READ_TIMEOUT, PollOutcome, pollUntil } from \"./polling\";\nimport { conditionHeaders, describeUnknown, waitForHeaders } from \"./table-diagnostics\";\nimport { formatMarkdown, formatRows } from \"./table-format\";\nimport { TableLocator, TableRow } from \"./table-locator\";\nimport {\n\tCellMatcher,\n\tColumnKey,\n\tDecimalSeparator,\n\tEngineFindRequest,\n\tEngineMatchRequest,\n\tEngineMatchResult,\n\tEngineMatrixRequest,\n\tEngineMatrixResult,\n\tEngineTextRequest,\n\tEngineTexts,\n\tEngineTextsRequest,\n\tEngineTotalRequest,\n\tEngineValues,\n\tEngineValuesRequest,\n\tRowWhere,\n\tSerializedMatcher,\n\tSerializedWhere,\n\tValidRowWhere,\n} from \"./table-locator.types\";\nimport {\n\tfindTableRows,\n\tmatchTableMatrix,\n\tmatchTableRows,\n\tnormalizeLine,\n\tparseNumber,\n\treadCellText,\n\treadColumnValues,\n\treadTableTexts,\n\treadTableTotal,\n} from \"./table-selector-engine\";\n\n/** Maximum number of mismatching rows listed in a `toHaveRows` failure message. */\nconst MAX_REPORTED_ROWS = 10;\n\n/**\n * Time for the extra reads that describe a failure, in milliseconds. The table was read during the\n * assertion, so a read that takes longer won't succeed; keep it short, so a failure is reported soon after\n * the timeout, and before the test timeout.\n */\nconst FAILURE_READ_TIMEOUT = 2_000;\n\n/** Time for a read that checks the headers or the predicates after the assertion, in milliseconds. */\nconst DIAGNOSTICS_TIMEOUT = 1_000;\n\n/** Maximum number of column values listed in a `toBeSortedBy` failure message. */\nconst MAX_REPORTED_VALUES = 20;\n\n/**\n * What a matcher returns to `expect.extend`. Declared here instead of importing `MatcherReturnType`,\n * which older versions of `@playwright/test` within the peer range don't export.\n */\ntype MatcherResult = {\n\tname: string;\n\tpass: boolean;\n\tmessage: () => string;\n\texpected?: unknown;\n\tactual?: unknown;\n\ttimeout?: number;\n};\n\n/** Options shared by the table matchers. */\nexport type TableMatcherOptions = {\n\t/** Time to retry the assertion for, in milliseconds. Defaults to the `expect` timeout. */\n\ttimeout?: number;\n};\n\n/** Options for the `toBeSortedBy` matcher. */\nexport type TableSortOptions = TableMatcherOptions & {\n\t/** The expected order. Defaults to `\"asc\"`. */\n\torder?: \"asc\" | \"desc\";\n\t/**\n\t * How cell texts are compared. Defaults to `\"text\"`.\n\t * - `\"text\"`: case- and accent-insensitive, with digit runs compared as numbers (`\"item 9\"` before\n\t * `\"item 10\"`).\n\t * - `\"number\"`: the one number in the text, read with the `decimal` separator (`\"€ 1,200\"` is 1200).\n\t * See {@link DecimalSeparator} for the rules.\n\t * - `\"date\"`: parsed with `Date.parse`.\n\t */\n\ttype?: \"text\" | \"number\" | \"date\";\n\t/** The decimal separator for `type: \"number\"`. Defaults to `\".\"`. */\n\tdecimal?: DecimalSeparator;\n\t/**\n\t * Custom comparison of two cell texts, like `Array.sort`. Runs in Node, so it can use test variables.\n\t * Overrides `type`.\n\t */\n\tcompare?: (a: string, b: string) => number;\n\t/** Also require `aria-sort=\"ascending\"` or `\"descending\"` on the header cell. Defaults to `false`. */\n\tariaSort?: boolean;\n};\n\n/** Options for the `toHaveRows` and `toHaveColumnValues` matchers. */\nexport type TableRowsOptions = TableMatcherOptions & {\n\t/**\n\t * Accept the rows (or values) in any order: each expected entry must match a different body row.\n\t * Defaults to `false`: body row `i` must match entry `i`.\n\t */\n\tanyOrder?: boolean;\n};\n\n/**\n * Asserts that the table has at least one body row matching every condition (or none, with `.not`).\n * Retries until the timeout. On failure, unknown headers are reported with the available headers.\n *\n * Conditions are checked against header names at runtime. With the `expect` of this package, they are\n * also checked at compile time against the `headers` of the table.\n */\nasync function toHaveRow(\n\tthis: ExpectMatcherState,\n\ttable: TableLocator,\n\twhere: RowWhere<string>,\n\toptions?: TableMatcherOptions\n): Promise<MatcherResult> {\n\tconst matcherName = \"toHaveRow\";\n\tconst timeout = options?.timeout ?? this.timeout;\n\tconst deadline = Date.now() + timeout;\n\tconst rows = table.row(where).locator;\n\n\t// A condition on an unknown header never matches, so `.not` would pass on a typo.\n\tconst unknown = this.isNot ? await waitForHeaders(table, conditionHeaders(where), deadline) : \"\";\n\tif (unknown !== \"\") {\n\t\treturn uncheckable(this, {\n\t\t\tmatcherName,\n\t\t\treceiver: \"table\",\n\t\t\targument: \"where\",\n\t\t\texpected: where,\n\t\t\tdescription: `no row matching ${describeWhere(where)}`,\n\t\t\tdiagnostics: unknown,\n\t\t\tlocator: `Table locator: ${table.root.toString()}`,\n\t\t\ttimeout,\n\t\t});\n\t}\n\n\tlet found: boolean;\n\ttry {\n\t\tconst remaining = Math.max(MIN_READ_TIMEOUT, deadline - Date.now());\n\t\tif (this.isNot) {\n\t\t\tawait baseExpect(rows).toHaveCount(0, { timeout: remaining });\n\t\t} else {\n\t\t\tawait baseExpect(rows).not.toHaveCount(0, { timeout: remaining });\n\t\t}\n\t\tfound = !this.isNot;\n\t} catch {\n\t\tfound = this.isNot;\n\t}\n\n\t// A predicate that throws never matches, so `.not` would pass on a broken predicate.\n\tconst errors = this.isNot && !found ? await readPredicateErrors(table, where) : [];\n\tif (errors.length > 0) {\n\t\treturn uncheckable(this, {\n\t\t\tmatcherName,\n\t\t\treceiver: \"table\",\n\t\t\targument: \"where\",\n\t\t\texpected: where,\n\t\t\tdescription: `no row matching ${describeWhere(where)}`,\n\t\t\tdiagnostics: describePredicateErrors(errors),\n\t\t\tlocator: `Table locator: ${table.root.toString()}`,\n\t\t\ttimeout,\n\t\t});\n\t}\n\n\tconst failed = found === this.isNot;\n\tconst diagnostics = failed\n\t\t? (await headerDiagnostics(table, Object.keys(where))) + (await predicateDiagnostics(table, where))\n\t\t: \"\";\n\n\treturn {\n\t\tname: matcherName,\n\t\tpass: found,\n\t\texpected: where,\n\t\tactual: found,\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tthis.utils.matcherHint(matcherName, \"table\", \"where\", { isNot: this.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${this.isNot ? \"no row\" : \"a row\"} matching ${describeWhere(where)}\\n` +\n\t\t\t`Received: ${found ? \"a matching row\" : \"no matching row\"}\\n` +\n\t\t\tdiagnostics +\n\t\t\t`Table locator: ${table.root.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/**\n * Asserts that the table has exactly `count` body rows. Retries until the timeout.\n */\nasync function toHaveRowCount(\n\tthis: ExpectMatcherState,\n\ttable: TableLocator,\n\tcount: number,\n\toptions?: TableMatcherOptions\n): Promise<MatcherResult> {\n\tconst matcherName = \"toHaveRowCount\";\n\tconst timeout = checkTimeout(options?.timeout ?? this.timeout);\n\tif (count < 0 || !Number.isInteger(count)) {\n\t\tthrow new Error(`${matcherName}() expects a non-negative integer count, got: ${count}`);\n\t}\n\tconst deadline = Date.now() + timeout;\n\tconst rows = table.rows.locator;\n\n\t// With `.not`, a table that is not there has no rows, so it would pass: wait until it is attached.\n\tconst attached = this.isNot\n\t\t? await table.root\n\t\t\t\t.first()\n\t\t\t\t.waitFor({ state: \"attached\", timeout: Math.max(MIN_READ_TIMEOUT, timeout) })\n\t\t\t\t.then(\n\t\t\t\t\t() => true,\n\t\t\t\t\t() => false\n\t\t\t\t)\n\t\t: true;\n\n\tlet reached = false;\n\tif (attached) {\n\t\ttry {\n\t\t\tconst expectation = this.isNot ? baseExpect(rows).not : baseExpect(rows);\n\t\t\t// A timeout of 0 means no timeout to `toHaveCount`; here, like the other matchers, it is one read.\n\t\t\tawait expectation.toHaveCount(count, { timeout: Math.max(MIN_READ_TIMEOUT, deadline - Date.now()) });\n\t\t\treached = true;\n\t\t} catch {\n\t\t\treached = false;\n\t\t}\n\t}\n\n\t// A table that is not there fails both the assertion and its negation.\n\tconst pass = !attached ? this.isNot : this.isNot ? !reached : reached;\n\tconst actual = reached ? count : await rows.count().catch(() => undefined);\n\t// A broken selector matches no rows; reading the table directly shows why.\n\tconst diagnostics = pass === this.isNot ? await headerDiagnostics(table, []) : \"\";\n\n\treturn {\n\t\tname: matcherName,\n\t\tpass,\n\t\texpected: count,\n\t\tactual,\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tthis.utils.matcherHint(matcherName, \"table\", \"count\", { isNot: this.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${this.isNot ? \"not \" : \"\"}${this.utils.printExpected(count)} body rows\\n` +\n\t\t\t(attached ? `Received: ${this.utils.printReceived(actual)}\\n` : \"Received: the table is not attached\\n\") +\n\t\t\tdiagnostics +\n\t\t\t`Table locator: ${table.root.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/**\n * Asserts that the main header row contains every given header key, or with `exact: true`, that it\n * equals the given keys in order. Retries until the timeout.\n */\nasync function toHaveHeaders(\n\tthis: ExpectMatcherState,\n\ttable: TableLocator,\n\theaders: readonly string[],\n\toptions?: TableMatcherOptions & {\n\t\t/** Require exactly these header keys, in this order. Defaults to `false`. */\n\t\texact?: boolean;\n\t}\n): Promise<MatcherResult> {\n\tconst matcherName = \"toHaveHeaders\";\n\tconst timeout = options?.timeout ?? this.timeout;\n\tconst exact = options?.exact === true;\n\tconst deadline = Date.now() + timeout;\n\n\t// Header names are normalized like header text, so \"First\\nname\" finds the header \"First name\".\n\tconst expected = headers.map(normalizeLine);\n\tconst matches = (keys: string[]): boolean =>\n\t\texact\n\t\t\t? keys.length === expected.length && expected.every((header, index) => keys[index] === header)\n\t\t\t: expected.every(header => keys.includes(header));\n\n\tconst poll = await pollUntil(\n\t\treadTimeout => table.headerKeys({ timeout: readTimeout }),\n\t\tread => matches(read) !== this.isNot,\n\t\t[] as string[],\n\t\tdeadline\n\t);\n\tconst keys = poll.value;\n\tconst matched = matches(keys);\n\tconst missing = headers.filter(header => !keys.includes(normalizeLine(header)));\n\n\treturn {\n\t\tname: matcherName,\n\t\t// A table that was never read fails both the assertion and its negation.\n\t\tpass: poll.read ? matched : this.isNot,\n\t\texpected: headers,\n\t\tactual: keys,\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tthis.utils.matcherHint(matcherName, \"table\", \"headers\", { isNot: this.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${this.isNot ? \"not \" : \"\"}${exact ? \"exactly \" : \"\"}${this.utils.printExpected(headers)}\\n` +\n\t\t\t(poll.read ? `Received: ${this.utils.printReceived(keys)}\\n` : \"Received: the table could not be read\\n\") +\n\t\t\t(missing.length > 0 && !this.isNot ? `Missing headers: [${missing.join(\", \")}]\\n` : \"\") +\n\t\t\tdescribeLastError(poll.error) +\n\t\t\t`Table locator: ${table.root.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/**\n * Asserts that a {@link TableRow} resolves to exactly one row whose cells match every condition.\n * With `.not`, the row must exist and not match. Retries until the timeout.\n *\n * @example\n * await expect(users.row({ Name: \"John\" })).toHaveCells({ Status: \"Active\", Email: /@example\\.com$/ });\n * await expect(users.rowAt(0)).not.toHaveCells({ Status: \"Deleted\" });\n */\nasync function toHaveCells(\n\tthis: ExpectMatcherState,\n\trow: TableRow,\n\tcells: RowWhere<string>,\n\toptions?: TableMatcherOptions\n): Promise<MatcherResult> {\n\tconst matcherName = \"toHaveCells\";\n\tconst timeout = options?.timeout ?? this.timeout;\n\tconst deadline = Date.now() + timeout;\n\tconst matching = row.locator.and(row.table.row(cells).locator);\n\n\t// A condition on an unknown header never matches, so `.not` would pass on a typo.\n\tconst unknown = this.isNot ? await waitForHeaders(row.table, conditionHeaders(cells), deadline) : \"\";\n\tif (unknown !== \"\") {\n\t\treturn uncheckable(this, {\n\t\t\tmatcherName,\n\t\t\treceiver: \"row\",\n\t\t\targument: \"cells\",\n\t\t\texpected: cells,\n\t\t\tdescription: `a row not matching ${describeWhere(cells)}`,\n\t\t\tdiagnostics: unknown,\n\t\t\tlocator: `Row locator: ${row.locator.toString()}`,\n\t\t\ttimeout,\n\t\t});\n\t}\n\n\tconst { rowCount, reached } = await pollRowMatch(row, matching, this.isNot ? 0 : 1, deadline);\n\t// A predicate that throws never matches, so `.not` would pass on a broken predicate.\n\tconst errors = this.isNot && reached ? await readPredicateErrors(row.table, cells) : [];\n\tif (errors.length > 0) {\n\t\treturn uncheckable(this, {\n\t\t\tmatcherName,\n\t\t\treceiver: \"row\",\n\t\t\targument: \"cells\",\n\t\t\texpected: cells,\n\t\t\tdescription: `a row not matching ${describeWhere(cells)}`,\n\t\t\tdiagnostics: describePredicateErrors(errors),\n\t\t\tlocator: `Row locator: ${row.locator.toString()}`,\n\t\t\ttimeout,\n\t\t});\n\t}\n\tconst pass = this.isNot ? !reached : reached;\n\tconst failed = pass === this.isNot;\n\tconst headers = Object.keys(cells);\n\tconst diagnostics = failed ? await headerDiagnostics(row.table, headers) : \"\";\n\tconst received = failed && rowCount === 1 && diagnostics === \"\" ? await readCells(row, headers) : undefined;\n\tconst predicates = failed ? await predicateDiagnostics(row.table, cells) : \"\";\n\n\treturn {\n\t\tname: matcherName,\n\t\tpass,\n\t\texpected: cells,\n\t\tactual: received,\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tthis.utils.matcherHint(matcherName, \"row\", \"cells\", { isNot: this.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${this.isNot ? \"a row not matching\" : \"a row matching\"} ${describeWhere(cells)}\\n` +\n\t\t\tdescribeReceivedRow(rowCount, received) +\n\t\t\tdiagnostics +\n\t\t\tpredicates +\n\t\t\t`Row locator: ${row.locator.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/**\n * Asserts that the table has exactly as many body rows as `rows`, and that body row `i` matches every\n * condition of `rows[i]`. Headers that a row does not mention are not checked, so `{}` matches any row.\n * With `anyOrder: true`, the rows may come in any order: each entry must match a different body row.\n * With `.not`, the table must not match. Retries until the timeout.\n *\n * @example\n * await expect(users).toHaveRows([\n * { Name: \"John\", Status: \"Active\" },\n * { Name: \"Jane\", Status: /inactive/i },\n * ]);\n */\nasync function toHaveRows(\n\tthis: ExpectMatcherState,\n\ttable: TableLocator,\n\trows: readonly RowWhere<string>[],\n\toptions?: TableRowsOptions\n): Promise<MatcherResult> {\n\tconst matcherName = \"toHaveRows\";\n\tconst timeout = options?.timeout ?? this.timeout;\n\tif (options?.anyOrder === true) {\n\t\treturn matchUnordered(this, { matcherName, table, rows, exact: true, timeout });\n\t}\n\tconst deadline = Date.now() + timeout;\n\t// `_config` is private to TableLocator; the matchers of this package read it to query the engine.\n\tconst request: EngineMatchRequest = { op: \"match\", cfg: table[\"_config\"], rows: rows.map(serializeWhere) };\n\tconst matches = (result: EngineMatchResult): boolean =>\n\t\tresult.unknown.length === 0 && result.count === rows.length && result.matched.every(Boolean);\n\n\tconst poll = await pollUntil(\n\t\treadTimeout => table.root.evaluate(matchTableRows, request, { timeout: readTimeout }),\n\t\t// With `.not`, an unknown header or a broken predicate is not a pass: keep waiting for it to go away.\n\t\tread => matches(read) !== this.isNot && (!this.isNot || checkableNot(read)),\n\t\t{ keys: [], rows: [], count: 0, matched: [], unknown: [], errors: [] },\n\t\tdeadline\n\t);\n\tlet result = poll.value;\n\tconst matched = matches(result);\n\t// A table that was never read, or has an unknown header, cannot be checked: it fails both the\n\t// assertion and its negation. With `.not`, so does a broken predicate, which never matches.\n\tconst uncheckable = !poll.read || result.unknown.length > 0 || (this.isNot && !checkableNot(result));\n\tif (!this.isNot && !uncheckable && !matched) {\n\t\t// The reads above leave out the cell texts; read them once, to describe the mismatch.\n\t\tconst describe: EngineMatchRequest = { ...request, texts: 1 };\n\t\tresult = await table.root.evaluate(matchTableRows, describe, { timeout: FAILURE_READ_TIMEOUT }).catch(() => result);\n\t}\n\tconst received = result.rows.map(texts => toRecord(result.keys, texts));\n\n\treturn {\n\t\tname: matcherName,\n\t\tpass: uncheckable ? this.isNot : matched,\n\t\texpected: rows,\n\t\tactual: received,\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tthis.utils.matcherHint(matcherName, \"table\", \"rows\", { isNot: this.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${this.isNot ? \"not \" : \"\"}${rows.length} body rows matching\\n` +\n\t\t\trows.map((where, index) => ` [${index}] ${describeWhere(where)}\\n`).join(\"\") +\n\t\t\t(!poll.read\n\t\t\t\t? \"Received: the table could not be read\\n\"\n\t\t\t\t: uncheckable\n\t\t\t\t\t? \"Received: a table that cannot be checked\\n\"\n\t\t\t\t\t: this.isNot\n\t\t\t\t\t\t? `Received: ${result.count} body rows that match\\n`\n\t\t\t\t\t\t: describeRowMismatches(rows, result, received)) +\n\t\t\t(result.unknown.length > 0 ? describeUnknown(result.unknown, result.keys) : \"\") +\n\t\t\tdescribePredicateErrors(result.errors) +\n\t\t\tdescribeLastError(poll.error) +\n\t\t\t`Table locator: ${table.root.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/**\n * Asserts that every entry of `rows` matches a different body row, in any order; other body rows are\n * allowed. With `.not`, at least one entry has no body row of its own. Retries until the timeout.\n *\n * @example\n * await expect(users).toContainRows([\n * { Name: \"Joe\", Status: \"Active\" },\n * { Name: \"John\" },\n * ]);\n */\nasync function toContainRows(\n\tthis: ExpectMatcherState,\n\ttable: TableLocator,\n\trows: readonly RowWhere<string>[],\n\toptions?: TableMatcherOptions\n): Promise<MatcherResult> {\n\tconst timeout = options?.timeout ?? this.timeout;\n\treturn matchUnordered(this, { matcherName: \"toContainRows\", table, rows, exact: false, timeout });\n}\n\n/**\n * Asserts that the table has body rows and that every one of them matches `where`, for example after\n * filtering. With `.not`, at least one body row doesn't match. A table without body rows fails both,\n * so a filter that leaves nothing never passes. Retries until the timeout.\n *\n * @example\n * await page.getByLabel(\"Status\").selectOption(\"Active\");\n * await expect(users).toHaveEveryRow({ Status: \"Active\" });\n */\nasync function toHaveEveryRow(\n\tthis: ExpectMatcherState,\n\ttable: TableLocator,\n\twhere: RowWhere<string>,\n\toptions?: TableMatcherOptions\n): Promise<MatcherResult> {\n\tconst matcherName = \"toHaveEveryRow\";\n\tconst timeout = options?.timeout ?? this.timeout;\n\tconst conditions = serializeWhere(where);\n\tif (conditions.length === 0) {\n\t\tthrow new Error(`${matcherName}() requires at least one condition.`);\n\t}\n\t// With `.not`, a broken predicate never matches, so it would pass: it cannot be checked.\n\tconst checkable = (result: EngineMatrixResult): boolean =>\n\t\tresult.unknown.length === 0 && result.count > 0 && (!this.isNot || checkableNot(result));\n\tconst every = (result: EngineMatrixResult): boolean => (result.matches[0]?.length ?? 0) === result.count;\n\n\tconst poll = await pollMatrix(\n\t\ttable,\n\t\t[conditions],\n\t\tDate.now() + timeout,\n\t\tread => checkable(read) && every(read) !== this.isNot\n\t);\n\tconst result = poll.value;\n\tconst canCheck = poll.read && checkable(result);\n\tconst pass = canCheck ? every(result) : this.isNot;\n\tconst failed = pass === this.isNot;\n\tconst matching = new Set(result.matches[0] ?? []);\n\tconst mismatches = range(result.count).filter(index => !matching.has(index));\n\tconst body = failed && canCheck && !this.isNot ? await readBody(table) : undefined;\n\n\treturn {\n\t\tname: matcherName,\n\t\tpass,\n\t\texpected: where,\n\t\tactual: result.count - mismatches.length,\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tthis.utils.matcherHint(matcherName, \"table\", \"where\", { isNot: this.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${this.isNot ? \"not every\" : \"every\"} body row matching ${describeWhere(where)}\\n` +\n\t\t\t(!poll.read\n\t\t\t\t? \"Received: the table could not be read\\n\"\n\t\t\t\t: result.unknown.length > 0\n\t\t\t\t\t? \"Received: a table that cannot be checked\\n\" + describeUnknown(result.unknown, result.keys)\n\t\t\t\t\t: result.count === 0\n\t\t\t\t\t\t? \"Received: the table has no body rows\\n\"\n\t\t\t\t\t\t: !canCheck\n\t\t\t\t\t\t\t? \"Received: a table that cannot be checked\\n\"\n\t\t\t\t\t\t\t: `Received: ${result.count - mismatches.length} of ${result.count} body rows match\\n`) +\n\t\t\t(body === undefined\n\t\t\t\t? \"\"\n\t\t\t\t: \"Body rows that do not match:\\n\" +\n\t\t\t\t\tformatRows(body, { indexes: mismatches, columns: conditionHeaders(where), maxRows: MAX_REPORTED_ROWS })) +\n\t\t\tdescribePredicateErrors(result.errors) +\n\t\t\tdescribeLastError(poll.error) +\n\t\t\t`Table locator: ${table.root.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/**\n * Asserts that `column` has exactly these cell values, one per body row: body row `i` matches `values[i]`,\n * or with `anyOrder: true`, each value matches a different body row. Values are an exact string, a RegExp\n * or a {@link CellCondition}, compared as in row conditions. With `.not`, the column must not match.\n * Retries until the timeout.\n *\n * @example\n * await expect(users).toHaveColumnValues(\"Status\", [\"Active\", \"Inactive\", \"Active\"]);\n * await expect(orders).toHaveColumnValues(\"Total\", [{ gt: 0 }, { gt: 0 }], { anyOrder: true });\n */\nasync function toHaveColumnValues(\n\tthis: ExpectMatcherState,\n\ttable: TableLocator,\n\tcolumn: string | number,\n\tvalues: readonly CellMatcher[],\n\toptions?: TableRowsOptions\n): Promise<MatcherResult> {\n\tconst matcherName = \"toHaveColumnValues\";\n\tconst timeout = options?.timeout ?? this.timeout;\n\tconst anyOrder = options?.anyOrder === true;\n\tif (typeof column === \"number\" && (column < 0 || !Number.isInteger(column))) {\n\t\tthrow new Error(`Column index must be a non-negative integer, got: ${column}`);\n\t}\n\tconst header = typeof column === \"string\" ? normalizeLine(column) : column;\n\tconst label = String(column);\n\tconst rows: SerializedWhere[] = values.map(value => [{ h: header, m: serializeMatcher(label, value) }]);\n\t// `_config` is private to TableLocator; the matchers of this package read it to query the engine.\n\tconst request: EngineMatchRequest = { op: \"match\", cfg: table[\"_config\"], rows };\n\tconst matches = (result: EngineMatchResult): boolean =>\n\t\tresult.unknown.length === 0 && result.count === values.length && result.matched.every(Boolean);\n\tconst accept = (result: EngineMatchResult): boolean =>\n\t\tmatches(result) !== this.isNot && (!this.isNot || checkableNot(result));\n\n\tlet poll: PollOutcome<EngineMatchResult>;\n\tif (anyOrder) {\n\t\t// The matrix lists every body row a value matches; the values match when each gets a row of its own.\n\t\tconst matrix = await pollMatrix(table, rows, Date.now() + timeout, read => accept(fromMatrix(read)), true);\n\t\tpoll = { ...matrix, value: fromMatrix(matrix.value) };\n\t} else {\n\t\tpoll = await pollUntil(\n\t\t\treadTimeout => table.root.evaluate(matchTableRows, request, { timeout: readTimeout }),\n\t\t\taccept,\n\t\t\t{ keys: [], rows: [], count: 0, matched: [], unknown: [], errors: [] },\n\t\t\tDate.now() + timeout\n\t\t);\n\t}\n\tconst result = poll.value;\n\tconst uncheckable = !poll.read || result.unknown.length > 0 || (this.isNot && !checkableNot(result));\n\tconst pass = uncheckable ? this.isNot : matches(result);\n\tconst received =\n\t\tpass === this.isNot && !uncheckable ? await readValues(table, header).catch(() => undefined) : undefined;\n\n\treturn {\n\t\tname: matcherName,\n\t\tpass,\n\t\texpected: values,\n\t\tactual: received,\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tthis.utils.matcherHint(matcherName, \"table\", \"values\", { isNot: this.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${typeof column === \"number\" ? `column ${column}` : `column ${JSON.stringify(column)}`} ` +\n\t\t\t`${this.isNot ? \"not \" : \"\"}with ${values.length} values${anyOrder ? \" in any order\" : \"\"}: ` +\n\t\t\t`[${values.map(describeMatcher).join(\", \")}]\\n` +\n\t\t\t(!poll.read\n\t\t\t\t? \"Received: the table could not be read\\n\"\n\t\t\t\t: uncheckable\n\t\t\t\t\t? \"Received: a table that cannot be checked\\n\" +\n\t\t\t\t\t\t(result.unknown.length > 0 ? describeUnknown(result.unknown, result.keys) : \"\")\n\t\t\t\t\t: describeReceivedValues(values, result, received, anyOrder, this.isNot)) +\n\t\t\tdescribePredicateErrors(result.errors) +\n\t\t\tdescribeLastError(poll.error) +\n\t\t\t`Table locator: ${table.root.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/**\n * Asserts that the body rows are sorted by `column`. Values are compared in Node, so `compare` can use\n * variables from the test. An empty body, an unknown column or a value that cannot be parsed fails the\n * assertion, also with `.not`. Retries until the timeout.\n *\n * @example\n * await users.header(\"Age\").click();\n * await expect(users).toBeSortedBy(\"Age\", { type: \"number\" });\n * await expect(users).toBeSortedBy(\"Name\", { order: \"desc\", ariaSort: true });\n */\nasync function toBeSortedBy(\n\tthis: ExpectMatcherState,\n\ttable: TableLocator,\n\tcolumn: string | number,\n\toptions?: TableSortOptions\n): Promise<MatcherResult> {\n\tconst matcherName = \"toBeSortedBy\";\n\tconst timeout = options?.timeout ?? this.timeout;\n\tconst sort: SortSettings = {\n\t\torder: options?.order ?? \"asc\",\n\t\ttype: options?.type ?? \"text\",\n\t\tdecimal: options?.decimal ?? \".\",\n\t\tcompare: options?.compare,\n\t\tariaSort: options?.ariaSort === true,\n\t};\n\n\tconst { read, check, sorted, error } = await pollSorted(table, column, sort, Date.now() + timeout, this.isNot);\n\tconst values = check.values ?? [];\n\n\treturn {\n\t\tname: matcherName,\n\t\t// A table that cannot be checked fails both the assertion and its negation.\n\t\tpass: check.error === undefined ? sorted : this.isNot,\n\t\texpected: `${sort.order} (${sort.type})`,\n\t\tactual: values,\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tthis.utils.matcherHint(matcherName, \"table\", \"column\", { isNot: this.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\tdescribeExpectedSort(column, sort, this.isNot) +\n\t\t\tdescribeReceivedSort(check, values, sort.ariaSort ? read.ariaSort : undefined) +\n\t\t\t(check.unknown === true ? `Available headers: [${read.column.keys.join(\", \")}]\\n` : \"\") +\n\t\t\tdescribeLastError(error) +\n\t\t\t`Table locator: ${table.root.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/** The resolved {@link TableSortOptions} of a `toBeSortedBy` assertion. */\ntype SortSettings = {\n\torder: \"asc\" | \"desc\";\n\ttype: \"text\" | \"number\" | \"date\";\n\tdecimal: DecimalSeparator;\n\tcompare: ((a: string, b: string) => number) | undefined;\n\tariaSort: boolean;\n};\n\n/** One read of a `toBeSortedBy` assertion. */\ntype SortRead = {\n\tcolumn: EngineValues;\n\t/** The `aria-sort` attribute of the header cell, if it was read. */\n\tariaSort: string | null;\n};\n\n/** The outcome of a `toBeSortedBy` assertion. */\ntype SortPoll = {\n\tread: SortRead;\n\tcheck: SortCheck;\n\tsorted: boolean;\n\t/** The error of the last read, if it failed. */\n\terror: unknown;\n};\n\n/**\n * Reads the column until it is sorted (or, with `isNot`, until it is not), or until `deadline`.\n * A table that cannot be checked keeps being read until the deadline.\n */\nasync function pollSorted(\n\ttable: TableLocator,\n\tcolumn: string | number,\n\tsort: SortSettings,\n\tdeadline: number,\n\tisNot: boolean\n): Promise<SortPoll> {\n\tconst expectedAriaSort = sort.order === \"asc\" ? \"ascending\" : \"descending\";\n\t// `_config` is private to TableLocator; the matchers of this package read it to query the engine.\n\tconst request: EngineValuesRequest = {\n\t\top: \"values\",\n\t\tcfg: table[\"_config\"],\n\t\tcolumn: typeof column === \"string\" ? normalizeLine(column) : column,\n\t};\n\tconst evaluate = (read: SortRead): { check: SortCheck; sorted: boolean } => {\n\t\tconst check = checkSorted(read.column, column, sort);\n\t\tconst sorted =\n\t\t\tcheck.error === undefined &&\n\t\t\tcheck.outOfOrder === undefined &&\n\t\t\t(!sort.ariaSort || read.ariaSort === expectedAriaSort);\n\t\treturn { check, sorted };\n\t};\n\n\tconst poll = await pollUntil(\n\t\tasync (readTimeout): Promise<SortRead> => {\n\t\t\tconst values = await table.root.evaluate(readColumnValues, request, { timeout: readTimeout });\n\t\t\tconst ariaSort =\n\t\t\t\tsort.ariaSort && values.values !== null\n\t\t\t\t\t? await table\n\t\t\t\t\t\t\t.header(column)\n\t\t\t\t\t\t\t.getAttribute(\"aria-sort\", { timeout: MIN_READ_TIMEOUT })\n\t\t\t\t\t\t\t.catch(() => null)\n\t\t\t\t\t: null;\n\t\t\treturn { column: values, ariaSort };\n\t\t},\n\t\tread => {\n\t\t\tconst { check, sorted } = evaluate(read);\n\t\t\t// A `compare` that throws won't stop throwing: fail at once.\n\t\t\treturn check.fatal === true || (check.error === undefined && sorted !== isNot);\n\t\t},\n\t\t{ column: { keys: [], values: null }, ariaSort: null },\n\t\tdeadline\n\t);\n\tif (!poll.read) {\n\t\treturn { read: poll.value, check: { error: \"the table could not be read\" }, sorted: false, error: poll.error };\n\t}\n\treturn { read: poll.value, ...evaluate(poll.value), error: poll.error };\n}\n\n/** The \"Expected:\" line of a `toBeSortedBy` failure. */\nfunction describeExpectedSort(column: string | number, sort: SortSettings, isNot: boolean): string {\n\tconst name = typeof column === \"number\" ? `column ${column}` : `column ${JSON.stringify(column)}`;\n\tconst direction = sort.order === \"asc\" ? \"ascending\" : \"descending\";\n\tconst comparison = sort.compare === undefined ? ` as ${sort.type}` : \" (custom compare)\";\n\tconst aria = sort.ariaSort ? ` with aria-sort=\"${direction}\"` : \"\";\n\treturn `Expected: ${name} ${isNot ? \"not \" : \"\"}sorted ${direction}${comparison}${aria}\\n`;\n}\n\n/**\n * The \"Received:\" lines of a `toBeSortedBy` failure. `ariaSort` is `undefined` when the `aria-sort`\n * attribute is not checked.\n */\nfunction describeReceivedSort(\n\tcheck: SortCheck,\n\tvalues: readonly string[],\n\tariaSort: string | null | undefined\n): string {\n\tif (check.error !== undefined) return `Received: ${check.error}\\n`;\n\tconst shown = values.slice(0, MAX_REPORTED_VALUES).map(value => JSON.stringify(value));\n\tif (values.length > MAX_REPORTED_VALUES) shown.push(`... ${values.length - MAX_REPORTED_VALUES} more`);\n\tlet message = `Received: [${shown.join(\", \")}]\\n`;\n\tif (check.outOfOrder !== undefined) {\n\t\tmessage +=\n\t\t\t`Row ${check.outOfOrder} (${JSON.stringify(values[check.outOfOrder])}) comes before ` +\n\t\t\t`row ${check.outOfOrder + 1} (${JSON.stringify(values[check.outOfOrder + 1])})\\n`;\n\t}\n\tif (ariaSort !== undefined) {\n\t\tmessage += `aria-sort: ${ariaSort === null ? \"<none>\" : JSON.stringify(ariaSort)}\\n`;\n\t}\n\treturn message;\n}\n\n/**\n * Asserts the number of body rows in the whole table, also the rows that are not rendered or are on\n * other pages (see {@link TableLocator.totalRowCount}). Retries until the timeout.\n *\n * @example\n * await expect(grid).toHaveTotalRowCount(200);\n */\nasync function toHaveTotalRowCount(\n\tthis: ExpectMatcherState,\n\ttable: TableLocator,\n\tcount: number,\n\toptions?: TableMatcherOptions\n): Promise<MatcherResult> {\n\tconst matcherName = \"toHaveTotalRowCount\";\n\tconst timeout = options?.timeout ?? this.timeout;\n\tconst poll = await pollUntil(\n\t\treadTimeout => table.totalRowCount({ timeout: readTimeout }),\n\t\ttotal => (total === count) !== this.isNot,\n\t\t-1,\n\t\tDate.now() + timeout\n\t);\n\t// A table that was never read fails both the assertion and its negation.\n\tconst pass = poll.read ? poll.value === count : this.isNot;\n\tconst source = pass === this.isNot && poll.read ? await describeTotal(table) : \"\";\n\n\treturn {\n\t\tname: matcherName,\n\t\tpass,\n\t\texpected: count,\n\t\tactual: poll.read ? poll.value : undefined,\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tthis.utils.matcherHint(matcherName, \"table\", \"count\", { isNot: this.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${this.isNot ? \"not \" : \"\"}${this.utils.printExpected(count)} body rows in total\\n` +\n\t\t\t(poll.read\n\t\t\t\t? `Received: ${this.utils.printReceived(poll.value)}${source}\\n`\n\t\t\t\t: \"Received: the table could not be read\\n\") +\n\t\t\tdescribeLastError(poll.error) +\n\t\t\t`Table locator: ${table.root.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/** Where the total of `toHaveTotalRowCount` comes from, such as ` (aria-rowcount 201, minus 1 other row)`. */\nasync function describeTotal(table: TableLocator): Promise<string> {\n\t// `_config` is private to TableLocator; the matchers of this package read it to query the engine.\n\tconst request: EngineTotalRequest = { op: \"total\", cfg: table[\"_config\"] };\n\ttry {\n\t\tconst total = await table.root.evaluate(readTableTotal, request, { timeout: 1_000 });\n\t\tif (total.ariaRowCount === null) return \"\";\n\t\tconst others = total.otherRows === 1 ? \"1 other row\" : `${total.otherRows} other rows`;\n\t\treturn ` (aria-rowcount ${total.ariaRowCount}, minus ${others})`;\n\t} catch {\n\t\treturn \"\";\n\t}\n}\n\n/**\n * Asserts that a {@link TableRow} is selected: it has `aria-selected=\"true\"`, or the first checkbox in it\n * is checked. Retries until the timeout.\n *\n * @example\n * await users.row({ Name: \"John\" }).select();\n * await expect(users.row({ Name: \"John\" })).toBeSelected();\n */\nasync function toBeSelected(\n\tthis: ExpectMatcherState,\n\trow: TableRow,\n\toptions?: TableMatcherOptions\n): Promise<MatcherResult> {\n\treturn checkRowState(this, {\n\t\tmatcherName: \"toBeSelected\",\n\t\trow,\n\t\tstate: \"selected\",\n\t\tread: readTimeout => row.isSelected({ timeout: readTimeout }),\n\t\ttimeout: options?.timeout ?? this.timeout,\n\t});\n}\n\n/**\n * Asserts that a {@link TableRow} of a tree grid is expanded (see {@link TableRow.isExpanded}). A row that\n * cannot expand fails both the assertion and its negation. Retries until the timeout.\n *\n * @example\n * await expect(files.row({ Name: \"src\" })).not.toBeExpanded();\n */\nasync function toBeExpanded(\n\tthis: ExpectMatcherState,\n\trow: TableRow,\n\toptions?: TableMatcherOptions\n): Promise<MatcherResult> {\n\treturn checkRowState(this, {\n\t\tmatcherName: \"toBeExpanded\",\n\t\trow,\n\t\tstate: \"expanded\",\n\t\tread: readTimeout => row.isExpanded({ timeout: readTimeout }),\n\t\ttimeout: options?.timeout ?? this.timeout,\n\t});\n}\n\n/** `toBeSelected` and `toBeExpanded`: reads a state of the row until it is (or with `.not`, isn't) set. */\nasync function checkRowState(\n\tstate: ExpectMatcherState,\n\tdetails: {\n\t\tmatcherName: string;\n\t\trow: TableRow;\n\t\tstate: string;\n\t\tread: (timeout: number) => Promise<boolean | null>;\n\t\ttimeout: number;\n\t}\n): Promise<MatcherResult> {\n\tconst { matcherName, row, timeout } = details;\n\tconst poll = await pollUntil(\n\t\tdetails.read,\n\t\tvalue => value !== null && value !== state.isNot,\n\t\tnull as boolean | null,\n\t\tDate.now() + timeout\n\t);\n\tconst pass = poll.value ?? state.isNot;\n\tconst received = !poll.read\n\t\t? \"the row could not be read\"\n\t\t: poll.value === null\n\t\t\t? `a row that cannot be ${details.state}`\n\t\t\t: `${poll.value ? \"\" : \"not \"}${details.state}`;\n\n\treturn {\n\t\tname: matcherName,\n\t\tpass,\n\t\texpected: !state.isNot,\n\t\tactual: poll.value,\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tstate.utils.matcherHint(matcherName, \"row\", \"\", { isNot: state.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${state.isNot ? \"not \" : \"\"}${details.state}\\n` +\n\t\t\t`Received: ${received}\\n` +\n\t\t\tdescribeLastError(poll.error) +\n\t\t\t`Row locator: ${row.locator.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/**\n * The tables that already have a table attachment in the running test (and retry), so failures inside a\n * test attach each table once. Cleared when another test runs, so it doesn't grow for the life of a worker.\n */\nconst attached = { test: \"\", tables: new Set<string>() };\n\n/**\n * Attaches the body rows of `table` to the report of the running test, as a Markdown table, once per\n * test and table. Does nothing outside a test, or for a table that is not attached.\n */\nasync function attachTable(table: TableLocator): Promise<void> {\n\tlet info: TestInfo;\n\ttry {\n\t\tinfo = test.info();\n\t} catch {\n\t\treturn;\n\t}\n\tconst current = `${info.testId}|${info.retry}`;\n\tif (attached.test !== current) {\n\t\tattached.test = current;\n\t\tattached.tables.clear();\n\t}\n\tconst key = table.root.toString();\n\tif (attached.tables.has(key)) return;\n\t// A table that is not there has nothing to attach; don't wait for it.\n\tif ((await table.root.count()) === 0) return;\n\tconst body = await readBody(table);\n\tif (body === undefined) return;\n\tattached.tables.add(key);\n\tawait info.attach(`table ${table.root.toString()}`, {\n\t\tbody: formatMarkdown(body, { maxRows: 1_000 }),\n\t\tcontentType: \"text/markdown\",\n\t});\n}\n\n/** `matcher`, also attaching the table to the test report when the assertion fails. */\nfunction attachOnFailure<R extends TableLocator | TableRow, A extends unknown[]>(\n\tmatcher: (this: ExpectMatcherState, receiver: R, ...args: A) => Promise<MatcherResult>\n): (this: ExpectMatcherState, receiver: R, ...args: A) => Promise<MatcherResult> {\n\treturn async function (this: ExpectMatcherState, receiver: R, ...args: A): Promise<MatcherResult> {\n\t\tconst result = await matcher.call(this, receiver, ...args);\n\t\tif (result.pass === this.isNot) {\n\t\t\tawait attachTable(receiver instanceof TableRow ? receiver.table : receiver).catch(() => undefined);\n\t\t}\n\t\treturn result;\n\t};\n}\n\n/**\n * Custom `expect` matchers for {@link TableLocator} and {@link TableRow}. Use them to extend your own `expect`.\n *\n * - `toHaveRow(where, options?)`: at least one body row matches every condition.\n * - `toHaveRowCount(count, options?)`: exactly `count` body rows.\n * - `toHaveRows(rows, options?)`: exactly these body rows, in order (or `anyOrder`), each matching its conditions.\n * - `toContainRows(rows, options?)`: each entry matches a different body row, in any order; other rows are allowed.\n * - `toHaveEveryRow(where, options?)`: there are body rows, and every one matches the conditions.\n * - `toHaveColumnValues(column, values, options?)`: one value per body row, in order (or `anyOrder`).\n * - `toHaveHeaders(headers, options?)`: the main header row contains these header keys (`exact` for an ordered match).\n * - `toBeSortedBy(column, options?)`: the body rows are sorted by a column (see {@link TableSortOptions}).\n * - `toHaveTotalRowCount(count, options?)`: the number of body rows in the whole table, on every page.\n * - `toHaveCells(cells, options?)` on a {@link TableRow}: exactly one row, whose cells match every condition.\n * - `toBeSelected(options?)` on a {@link TableRow}: the row is selected.\n * - `toBeExpanded(options?)` on a {@link TableRow}: the row of a tree grid is expanded.\n *\n * When a table matcher fails inside a test, the body rows are attached to the test report as a Markdown\n * table, once per test and table.\n *\n * @example\n * // Combine with your own matchers\n * import { expect as base } from \"@playwright/test\";\n * import { tableMatchers } from \"@cerios/playwright-table\";\n *\n * export const expect = base.extend({\n * ...tableMatchers,\n * async toHaveEmailFor(table: TableLocator, name: string) { ... },\n * });\n *\n * @example\n * // Or merge with another extended expect\n * import { mergeExpects } from \"@playwright/test\";\n * import { expect as tableExpect } from \"@cerios/playwright-table\";\n *\n * export const expect = mergeExpects(tableExpect, myExpect);\n */\nexport const tableMatchers: {\n\ttoHaveRow: typeof toHaveRow;\n\ttoHaveRowCount: typeof toHaveRowCount;\n\ttoHaveRows: typeof toHaveRows;\n\ttoContainRows: typeof toContainRows;\n\ttoHaveEveryRow: typeof toHaveEveryRow;\n\ttoHaveColumnValues: typeof toHaveColumnValues;\n\ttoHaveHeaders: typeof toHaveHeaders;\n\ttoHaveCells: typeof toHaveCells;\n\ttoBeSortedBy: typeof toBeSortedBy;\n\ttoHaveTotalRowCount: typeof toHaveTotalRowCount;\n\ttoBeSelected: typeof toBeSelected;\n\ttoBeExpanded: typeof toBeExpanded;\n} = {\n\ttoHaveRow: attachOnFailure(toHaveRow),\n\ttoHaveRowCount: attachOnFailure(toHaveRowCount),\n\ttoHaveRows: attachOnFailure(toHaveRows),\n\ttoContainRows: attachOnFailure(toContainRows),\n\ttoHaveEveryRow: attachOnFailure(toHaveEveryRow),\n\ttoHaveColumnValues: attachOnFailure(toHaveColumnValues),\n\ttoHaveHeaders: attachOnFailure(toHaveHeaders),\n\ttoHaveCells: attachOnFailure(toHaveCells),\n\ttoBeSortedBy: attachOnFailure(toBeSortedBy),\n\ttoHaveTotalRowCount: attachOnFailure(toHaveTotalRowCount),\n\ttoBeSelected,\n\ttoBeExpanded,\n};\n\n/**\n * Playwright `expect` extended with {@link tableMatchers}.\n *\n * @example\n * import { test, expect, defineTable } from \"@cerios/playwright-table\";\n *\n * test(\"users\", async ({ page }) => {\n * const users = defineTable(page.locator(\"table\"), { headers: [\"Name\", \"Status\"] });\n * await expect(users).toHaveHeaders([\"Name\", \"Status\"]);\n * await expect(users).toHaveRow({ Name: \"John\", Status: /active/i });\n * await expect(users).not.toHaveRow({ Name: \"Ghost\" });\n * await expect(users).toHaveRowCount(3);\n * await expect(users).toHaveRows([{ Name: \"John\" }, { Name: \"Jane\" }, { Name: \"Joe\" }]);\n * await expect(users).toContainRows([{ Name: \"Joe\" }, { Name: \"John\" }]);\n * await expect(users).toHaveColumnValues(\"Status\", [\"Active\", \"Inactive\", \"Active\"]);\n * await users.header(\"Name\").click();\n * await expect(users).toBeSortedBy(\"Name\");\n * await expect(users.row({ Name: \"John\" })).toHaveCells({ Status: \"Active\" });\n * });\n */\nconst tableExpect: Expect<typeof tableMatchers> = baseExpect.extend(tableMatchers);\n\n/** The matchers Playwright's `expect` (extended with {@link tableMatchers}) has for a value of type `T`. */\ntype BaseAssertions<T> = ReturnType<typeof tableExpect<T>>;\n\n/** `Base` with the matchers of `Typed` replaced by their typed versions, also after `.not`. */\ntype WithTyped<Base, Typed> = Omit<Base, keyof Typed | \"not\"> &\n\tTyped & { not: Omit<Base, keyof Typed | \"not\"> & Typed };\n\n/**\n * The table matchers of {@link expect} on a {@link TableLocator} with typed headers: header keys in\n * conditions and columns are checked at compile time, like in {@link TableLocator.row}.\n */\nexport interface TableAssertions<H extends string> {\n\ttoHaveRow<W extends RowWhere<H>>(where: W & ValidRowWhere<H, W>, options?: TableMatcherOptions): Promise<void>;\n\ttoHaveRowCount(count: number, options?: TableMatcherOptions): Promise<void>;\n\ttoHaveRows(rows: readonly RowWhere<H>[], options?: TableRowsOptions): Promise<void>;\n\ttoContainRows(rows: readonly RowWhere<H>[], options?: TableMatcherOptions): Promise<void>;\n\ttoHaveEveryRow<W extends RowWhere<H>>(where: W & ValidRowWhere<H, W>, options?: TableMatcherOptions): Promise<void>;\n\ttoHaveColumnValues(column: ColumnKey<H>, values: readonly CellMatcher[], options?: TableRowsOptions): Promise<void>;\n\t/** Header keys are not checked: a header that the table doesn't declare may be asserted absent. */\n\ttoHaveHeaders(headers: readonly string[], options?: TableMatcherOptions & { exact?: boolean }): Promise<void>;\n\ttoBeSortedBy(column: ColumnKey<H>, options?: TableSortOptions): Promise<void>;\n\ttoHaveTotalRowCount(count: number, options?: TableMatcherOptions): Promise<void>;\n}\n\n/** The row matchers of {@link expect} on a {@link TableRow} with typed headers. */\nexport interface RowAssertions<H extends string> {\n\ttoHaveCells<W extends RowWhere<H>>(cells: W & ValidRowWhere<H, W>, options?: TableMatcherOptions): Promise<void>;\n\ttoBeSelected(options?: TableMatcherOptions): Promise<void>;\n\ttoBeExpanded(options?: TableMatcherOptions): Promise<void>;\n}\n\n/**\n * The type of {@link expect}: Playwright's `expect` extended with {@link tableMatchers}, whose table and\n * row matchers check header keys at compile time (also with `expect.soft`).\n */\nexport type TableExpect = {\n\t<H extends string>(\n\t\tactual: TableLocator<H>,\n\t\tmessageOrOptions?: string | { message?: string }\n\t): WithTyped<BaseAssertions<TableLocator<H>>, TableAssertions<H>>;\n\t<H extends string>(\n\t\tactual: TableRow<H>,\n\t\tmessageOrOptions?: string | { message?: string }\n\t): WithTyped<BaseAssertions<TableRow<H>>, RowAssertions<H>>;\n\tsoft: TableExpect;\n} & Expect<typeof tableMatchers>;\n\n// The typed signatures only narrow the arguments of the same matchers.\nexport const expect: TableExpect = tableExpect as TableExpect;\n\nasync function readCells(row: TableRow, headers: readonly string[]): Promise<string> {\n\t// Read the cells the way the table compares them. `_config` is private to TableLocator; the matchers\n\t// of this package read it.\n\tconst request: EngineTextRequest = { op: \"text\", cfg: row.table[\"_config\"] };\n\tconst parts = await Promise.all(\n\t\theaders.map(async header => {\n\t\t\tconst text = await row\n\t\t\t\t.cell(header)\n\t\t\t\t.evaluate(readCellText, request, { timeout: 1_000 })\n\t\t\t\t.then(\n\t\t\t\t\tvalue => JSON.stringify(value),\n\t\t\t\t\t() => \"<no cell>\"\n\t\t\t\t);\n\t\t\treturn `${JSON.stringify(header)}: ${text}`;\n\t\t})\n\t);\n\treturn `{ ${parts.join(\", \")} }`;\n}\n\n/**\n * The headers of `headers` the table does not have, with the available headers. If the table cannot be\n * read (it is not attached, or a selector is invalid), the error instead.\n */\nasync function headerDiagnostics(table: TableLocator, headers: readonly string[]): Promise<string> {\n\t// Reads the body too (unlike `headerKeys()`), so an invalid body selector shows up. Only failures\n\t// get here, so reading the whole table is fine.\n\tconst request: EngineTextsRequest = { op: \"texts\", cfg: table[\"_config\"] };\n\tlet available: string[];\n\ttry {\n\t\tavailable = (await table.root.evaluate(readTableTexts, request, { timeout: 1_000 })).keys;\n\t} catch (error) {\n\t\treturn describeLastError(error);\n\t}\n\tconst unknown = headers.filter(header => !available.includes(normalizeLine(header)));\n\treturn unknown.length === 0 ? \"\" : describeUnknown(unknown, available);\n}\n\n/**\n * Problems with the `predicate` conditions of `where` (a predicate that threw, for example because it\n * uses a variable from the test), or `\"\"` if there are none or `where` has no predicate.\n */\nasync function predicateDiagnostics(table: TableLocator, where: RowWhere<string>): Promise<string> {\n\treturn describePredicateErrors(await readPredicateErrors(table, where));\n}\n\n/** The problems with the `predicate` conditions of `where` on the body rows, or `[]` if it has no predicate. */\nasync function readPredicateErrors(table: TableLocator, where: RowWhere<string>): Promise<string[]> {\n\tconst conditions = serializeWhere(where);\n\tif (!conditions.some(condition => hasPredicate(condition.m))) return [];\n\t// `_config` is private to TableLocator; the matchers of this package read it to query the engine.\n\tconst request: EngineFindRequest = { op: \"find\", cfg: table[\"_config\"], where: conditions };\n\ttry {\n\t\treturn (await table.root.evaluate(findTableRows, request, { timeout: DIAGNOSTICS_TIMEOUT })).errors;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction hasPredicate(matcher: SerializedMatcher): boolean {\n\tif (matcher.t === \"f\") return true;\n\tif (matcher.t === \"n\") return hasPredicate(matcher.m);\n\tif (matcher.t === \"a\" || matcher.t === \"l\") return matcher.m.some(hasPredicate);\n\treturn false;\n}\n\nfunction describePredicateErrors(errors: readonly string[]): string {\n\treturn errors.map(error => `${error}\\n`).join(\"\");\n}\n\n/**\n * Reads the matrix of `rows` until `done` accepts it, or until `deadline`. With `assign`, the engine gives\n * each entry a body row of its own (see {@link fromMatrix}) instead of listing every row it matches.\n */\nfunction pollMatrix(\n\ttable: TableLocator,\n\trows: SerializedWhere[],\n\tdeadline: number,\n\tdone: (result: EngineMatrixResult) => boolean,\n\tassign = false\n): Promise<PollOutcome<EngineMatrixResult>> {\n\t// `_config` is private to TableLocator; the matchers of this package read it to query the engine.\n\tconst request: EngineMatrixRequest = { op: \"matrix\", cfg: table[\"_config\"], rows };\n\tif (assign) request.assign = 1;\n\treturn pollUntil(\n\t\treadTimeout => table.root.evaluate(matchTableMatrix, request, { timeout: readTimeout }),\n\t\tdone,\n\t\t{ keys: [], count: 0, matches: [], unknown: [], errors: [] },\n\t\tdeadline\n\t);\n}\n\n/**\n * A matrix result read with `assign` as a match result: entry `i` matches when the engine gave it a body\n * row of its own (a maximum bipartite matching, so overlapping entries don't take each other's rows).\n */\nfunction fromMatrix(result: EngineMatrixResult): EngineMatchResult {\n\treturn {\n\t\tkeys: result.keys,\n\t\trows: [],\n\t\tcount: result.count,\n\t\tmatched: (result.assigned ?? []).map(row => row !== -1),\n\t\tunknown: result.unknown,\n\t\terrors: result.errors,\n\t};\n}\n\n/** `toContainRows`, and `toHaveRows` with `anyOrder`: each entry of `rows` matches a different body row. */\nasync function matchUnordered(\n\tstate: ExpectMatcherState,\n\tdetails: {\n\t\tmatcherName: string;\n\t\ttable: TableLocator;\n\t\trows: readonly RowWhere<string>[];\n\t\t/** Whether the table must have exactly as many body rows as `rows`. */\n\t\texact: boolean;\n\t\ttimeout: number;\n\t}\n): Promise<MatcherResult> {\n\tconst { matcherName, table, rows, exact, timeout } = details;\n\tconst matches = (result: EngineMatchResult): boolean =>\n\t\tresult.unknown.length === 0 && result.matched.every(Boolean) && (!exact || result.count === rows.length);\n\n\tconst poll = await pollMatrix(\n\t\ttable,\n\t\trows.map(serializeWhere),\n\t\tDate.now() + timeout,\n\t\t// With `.not`, an unknown header or a broken predicate is not a pass: keep waiting for it to go away.\n\t\tread => {\n\t\t\tconst result = fromMatrix(read);\n\t\t\treturn matches(result) !== state.isNot && (!state.isNot || checkableNot(result));\n\t\t},\n\t\ttrue\n\t);\n\tconst result = fromMatrix(poll.value);\n\tconst uncheckable = !poll.read || result.unknown.length > 0 || (state.isNot && !checkableNot(result));\n\tconst pass = uncheckable ? state.isNot : matches(result);\n\tconst failed = pass === state.isNot;\n\tconst body = failed && !uncheckable ? await readBody(table) : undefined;\n\tconst missing = range(rows.length).filter(index => result.matched[index] !== true);\n\tconst headers = rows.flatMap(conditionHeaders);\n\n\treturn {\n\t\tname: matcherName,\n\t\tpass,\n\t\texpected: rows,\n\t\tactual: body?.rows.map(texts => toRecord(body.keys, texts)),\n\t\ttimeout,\n\t\tmessage: () =>\n\t\t\tstate.utils.matcherHint(matcherName, \"table\", \"rows\", { isNot: state.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${state.isNot ? \"not \" : \"\"}${exact ? `${rows.length} body rows` : \"body rows\"} ` +\n\t\t\t`matching, in any order${exact ? \"\" : \" (other rows allowed)\"}\\n` +\n\t\t\trows.map((where, index) => ` [${index}] ${describeWhere(where)}\\n`).join(\"\") +\n\t\t\t(!poll.read\n\t\t\t\t? \"Received: the table could not be read\\n\"\n\t\t\t\t: uncheckable\n\t\t\t\t\t? \"Received: a table that cannot be checked\\n\"\n\t\t\t\t\t: `Received: ${result.count} body rows${state.isNot ? `, and every entry matches a different one` : \"\"}\\n`) +\n\t\t\t(state.isNot || uncheckable\n\t\t\t\t? \"\"\n\t\t\t\t: missing\n\t\t\t\t\t\t.slice(0, MAX_REPORTED_ROWS)\n\t\t\t\t\t\t.map(index => `No body row left for [${index}] ${describeWhere(rows[index] ?? {})}\\n`)\n\t\t\t\t\t\t.join(\"\") +\n\t\t\t\t\t(missing.length > MAX_REPORTED_ROWS ? `... and ${missing.length - MAX_REPORTED_ROWS} more\\n` : \"\")) +\n\t\t\t(body === undefined ? \"\" : \"Body rows:\\n\" + formatRows(body, { columns: headers, maxRows: MAX_REPORTED_ROWS })) +\n\t\t\t(result.unknown.length > 0 ? describeUnknown(result.unknown, result.keys) : \"\") +\n\t\t\tdescribePredicateErrors(result.errors) +\n\t\t\tdescribeLastError(poll.error) +\n\t\t\t`Table locator: ${table.root.toString()}\\n` +\n\t\t\t`Timeout: ${timeout}ms`,\n\t};\n}\n\n/** Reads the header keys and body cell texts for a failure message, or `undefined` if that fails. */\nasync function readBody(table: TableLocator): Promise<EngineTexts | undefined> {\n\t// `_config` is private to TableLocator; the matchers of this package read it to query the engine.\n\tconst request: EngineTextsRequest = { op: \"texts\", cfg: table[\"_config\"] };\n\treturn table.root.evaluate(readTableTexts, request, { timeout: FAILURE_READ_TIMEOUT }).catch(() => undefined);\n}\n\n/** Reads the body cell texts of `column` for a failure message. */\nasync function readValues(table: TableLocator, column: string | number): Promise<string[] | undefined> {\n\t// `_config` is private to TableLocator; the matchers of this package read it to query the engine.\n\tconst request: EngineValuesRequest = { op: \"values\", cfg: table[\"_config\"], column };\n\tconst read = await table.root.evaluate(readColumnValues, request, { timeout: FAILURE_READ_TIMEOUT });\n\treturn read.values ?? undefined;\n}\n\n/** The \"Received:\" lines of a `toHaveColumnValues` failure. */\nfunction describeReceivedValues(\n\tvalues: readonly CellMatcher[],\n\tresult: EngineMatchResult,\n\treceived: readonly string[] | undefined,\n\tanyOrder: boolean,\n\tisNot: boolean\n): string {\n\tconst shown = (received ?? []).slice(0, MAX_REPORTED_VALUES).map(value => JSON.stringify(value));\n\tif (received !== undefined && received.length > MAX_REPORTED_VALUES) {\n\t\tshown.push(`... ${received.length - MAX_REPORTED_VALUES} more`);\n\t}\n\tlet message = received === undefined ? `Received: ${result.count} body rows\\n` : `Received: [${shown.join(\", \")}]\\n`;\n\tif (isNot) return message;\n\tif (result.count !== values.length) message += `Expected ${values.length} values, received ${result.count}\\n`;\n\tconst mismatches = range(Math.min(values.length, result.matched.length)).filter(i => result.matched[i] !== true);\n\tfor (const index of mismatches.slice(0, MAX_REPORTED_ROWS)) {\n\t\tconst value = values[index];\n\t\tconst description = value === undefined ? \"\" : describeMatcher(value);\n\t\tmessage += anyOrder\n\t\t\t? `No body row left for value [${index}] ${description}\\n`\n\t\t\t: `Row ${index} does not match ${description}, received ${JSON.stringify(received?.[index])}\\n`;\n\t}\n\tif (mismatches.length > MAX_REPORTED_ROWS) {\n\t\tmessage += `... and ${mismatches.length - MAX_REPORTED_ROWS} more that do not match\\n`;\n\t}\n\treturn message;\n}\n\n/** The numbers `0` to `count - 1`. */\nfunction range(count: number): number[] {\n\treturn Array.from({ length: count }, (_value, index) => index);\n}\n\n/**\n * Whether a `.not` assertion can trust this read: no unknown header and no broken predicate. Both never\n * match, so the negation would pass on them.\n */\nfunction checkableNot(result: { unknown: readonly unknown[]; errors: readonly string[] }): boolean {\n\treturn result.unknown.length === 0 && result.errors.length === 0;\n}\n\n/**\n * The result of a `.not` assertion with a condition on an unknown header. Such a table cannot be checked,\n * so it fails both the assertion and its negation.\n */\nfunction uncheckable(\n\tstate: ExpectMatcherState,\n\tdetails: {\n\t\tmatcherName: string;\n\t\treceiver: string;\n\t\targument: string;\n\t\texpected: RowWhere<string>;\n\t\tdescription: string;\n\t\tdiagnostics: string;\n\t\tlocator: string;\n\t\ttimeout: number;\n\t}\n): MatcherResult {\n\treturn {\n\t\tname: details.matcherName,\n\t\tpass: state.isNot,\n\t\texpected: details.expected,\n\t\tactual: undefined,\n\t\ttimeout: details.timeout,\n\t\tmessage: () =>\n\t\t\tstate.utils.matcherHint(details.matcherName, details.receiver, details.argument, { isNot: state.isNot }) +\n\t\t\t\"\\n\\n\" +\n\t\t\t`Expected: ${details.description}\\n` +\n\t\t\t`Received: a table that cannot be checked\\n` +\n\t\t\tdetails.diagnostics +\n\t\t\t`${details.locator}\\n` +\n\t\t\t`Timeout: ${details.timeout}ms`,\n\t};\n}\n\n/**\n * Counts the rows of `row` and the ones of them in `matching` until `row` is exactly one row with\n * `expectedMatches` matches, or until `deadline`.\n */\nasync function pollRowMatch(\n\trow: TableRow,\n\tmatching: Locator,\n\texpectedMatches: number,\n\tdeadline: number\n): Promise<{ rowCount: number; reached: boolean }> {\n\tconst reached = ([rowCount, matchCount]: number[]): boolean => rowCount === 1 && matchCount === expectedMatches;\n\tconst poll = await pollUntil(() => Promise.all([row.locator.count(), matching.count()]), reached, [0, 0], deadline);\n\treturn { rowCount: poll.value[0] ?? 0, reached: reached(poll.value) };\n}\n\n/** The \"Received:\" line of a `toHaveCells` failure, or `\"\"` when there is nothing to report. */\nfunction describeReceivedRow(rowCount: number, received: string | undefined): string {\n\tif (rowCount !== 1) return `Received: the row locator matched ${rowCount} rows, expected exactly 1\\n`;\n\treturn received === undefined ? \"\" : `Received: ${received}\\n`;\n}\n\nfunction describeRowMismatches(\n\trows: readonly RowWhere<string>[],\n\tresult: EngineMatchResult,\n\treceived: Record<string, string>[]\n): string {\n\tlet message = `Received: ${result.count} body rows\\n`;\n\tconst mismatches: number[] = [];\n\tresult.matched.forEach((ok, index) => {\n\t\tif (!ok) mismatches.push(index);\n\t});\n\tfor (const index of mismatches.slice(0, MAX_REPORTED_ROWS)) {\n\t\tconst headers = Object.keys(rows[index] ?? {}).filter(header => result.keys.includes(normalizeLine(header)));\n\t\tconst cells = headers.map(\n\t\t\theader => `${JSON.stringify(header)}: ${JSON.stringify(received[index]?.[normalizeLine(header)])}`\n\t\t);\n\t\tmessage += `Row ${index} does not match, received { ${cells.join(\", \")} }\\n`;\n\t}\n\tif (mismatches.length > MAX_REPORTED_ROWS) {\n\t\tmessage += `... and ${mismatches.length - MAX_REPORTED_ROWS} more rows that do not match\\n`;\n\t}\n\treturn message;\n}\n\ntype SortCheck = {\n\t/** Why the column cannot be checked. */\n\terror?: string;\n\t/** Whether the error is an unknown header. */\n\tunknown?: boolean;\n\t/** Whether the error won't go away by reading again, such as a `compare` that throws. */\n\tfatal?: boolean;\n\t/** The cell texts of the column. */\n\tvalues?: string[];\n\t/** Index of the first row that should come after the next row. */\n\toutOfOrder?: number;\n};\n\nfunction checkSorted(read: EngineValues, column: string | number, sort: SortSettings): SortCheck {\n\tconst { order, type, compare, decimal } = sort;\n\tconst values = read.values;\n\tif (values === null) {\n\t\tif (typeof column === \"number\") return { error: `column ${column} does not exist`, unknown: true };\n\t\tif (read.keys.length === 0) return { error: \"the table has no header row\" };\n\t\treturn { error: `Header \"${column}\" not found.`, unknown: true };\n\t}\n\tif (values.length === 0) return { error: \"the table has no body rows\" };\n\n\tlet comparator: (a: string, b: string) => number;\n\tif (compare !== undefined) {\n\t\tcomparator = compare;\n\t} else if (type === \"text\") {\n\t\tcomparator = new Intl.Collator(undefined, { numeric: true, sensitivity: \"base\" }).compare;\n\t} else {\n\t\tconst parse = type === \"number\" ? (text: string) => parseNumber(text, decimal) : Date.parse;\n\t\tconst parsed = new Map<string, number>();\n\t\tfor (const [i, text] of values.entries()) {\n\t\t\tconst value = parse(text);\n\t\t\tif (isNaN(value)) {\n\t\t\t\treturn { error: `row ${i} (${JSON.stringify(text)}) is not a ${type}`, values };\n\t\t\t}\n\t\t\tparsed.set(text, value);\n\t\t}\n\t\tcomparator = (a, b) => (parsed.get(a) ?? 0) - (parsed.get(b) ?? 0);\n\t}\n\n\treturn findOutOfOrder(values, comparator, order === \"asc\" ? 1 : -1);\n}\n\n/** The first row of `values` that should come after the next row, if any. A `comparator` that throws is fatal. */\nfunction findOutOfOrder(values: string[], comparator: (a: string, b: string) => number, direction: number): SortCheck {\n\tlet previous: string | undefined;\n\tfor (const [i, value] of values.entries()) {\n\t\tlet comparison: number;\n\t\ttry {\n\t\t\tcomparison = previous === undefined ? 0 : comparator(previous, value);\n\t\t} catch (error) {\n\t\t\tconst problem = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n\t\t\treturn { error: `compare threw ${problem}`, values, fatal: true };\n\t\t}\n\t\tif (comparison * direction > 0) return { values, outOfOrder: i - 1 };\n\t\tprevious = value;\n\t}\n\treturn { values };\n}\n\nfunction toRecord(keys: readonly string[], texts: readonly string[]): Record<string, string> {\n\tconst record: Record<string, string> = {};\n\tkeys.forEach((key, index) => {\n\t\trecord[key] = texts[index] ?? \"\";\n\t});\n\treturn record;\n}\n"],"mappings":"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"}