diff --git a/packages/puppeteer-core/src/common/PSelectorParser.test.ts b/packages/puppeteer-core/src/common/PSelectorParser.test.ts new file mode 100644 index 00000000000..2d150c52e67 --- /dev/null +++ b/packages/puppeteer-core/src/common/PSelectorParser.test.ts @@ -0,0 +1,50 @@ +/** + * @license + * Copyright 2024 Google Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +import {describe, it} from 'node:test'; + +import expect from 'expect'; + +import {parsePSelectors} from './PSelectorParser.js'; + +describe('PSelectorParser', () => { + describe('parsePSelectors', () => { + it('parses nested selectors', () => { + const [updatedSelector, isPureCSS, hasPseudoClasses] = + parsePSelectors('& > div'); + expect(updatedSelector).toEqual([[['&>div']]]); + expect(isPureCSS).toBeTruthy(); + expect(hasPseudoClasses).toBeFalsy(); + }); + + it('parses nested selectors with p-selector syntax', () => { + const [updatedSelector, isPureCSS, hasPseudoClasses] = + parsePSelectors('& > div >>> button'); + expect(updatedSelector).toEqual([[['&>div'], '>>>', ['button']]]); + expect(isPureCSS).toBeFalsy(); + expect(hasPseudoClasses).toBeFalsy(); + }); + + it('parses selectors with pseudo classes', () => { + const [updatedSelector, isPureCSS, hasPseudoClasses] = + parsePSelectors('div:focus'); + expect(updatedSelector).toEqual([[['div:focus']]]); + expect(isPureCSS).toBeTruthy(); + expect(hasPseudoClasses).toBeTruthy(); + }); + + it('parses nested selectors with pseudo classes and p-selector syntax', () => { + const [updatedSelector, isPureCSS, hasPseudoClasses] = parsePSelectors( + '& > div:focus >>>> button:focus' + ); + expect(updatedSelector).toEqual([ + [['&>div:focus'], '>>>>', ['button:focus']], + ]); + expect(isPureCSS).toBeFalsy(); + expect(hasPseudoClasses).toBeTruthy(); + }); + }); +}); diff --git a/packages/puppeteer-core/src/common/PSelectorParser.ts b/packages/puppeteer-core/src/common/PSelectorParser.ts index c870c8fe3ab..f62c9c1fb8f 100644 --- a/packages/puppeteer-core/src/common/PSelectorParser.ts +++ b/packages/puppeteer-core/src/common/PSelectorParser.ts @@ -17,6 +17,7 @@ import type { } from '../injected/PQuerySelector.js'; import {PCombinator} from '../injected/PQuerySelector.js'; +TOKENS['nesting'] = /&/g; TOKENS['combinator'] = /\s*(>>>>?|[\s>+~])\s*/g; const ESCAPE_REGEXP = /\\[\s\S]/g; @@ -94,7 +95,7 @@ export function parsePSelectors( continue; case 'pseudo-class': hasPseudoClasses = true; - continue; + break; case 'comma': if (storage.length) { compoundSelector.push(stringify(storage));