fix(css selector): handle missing spaces between [] and > (#2612)

This commit is contained in:
Dmitry Gozman 2020-06-17 23:20:12 -07:00 коммит произвёл GitHub
Родитель 082bb3c3c4
Коммит f581e84829
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 31 добавлений и 15 удалений

Просмотреть файл

@ -221,7 +221,6 @@ function split(selector: string): string[][] {
let quote: string | undefined;
let insideAttr = false;
let start = 0;
let space: 'none' | 'before' | 'after' = 'none';
const result: string[][] = [];
let current: string[] = [];
const appendToCurrent = () => {
@ -234,24 +233,23 @@ function split(selector: string): string[][] {
result.push(current);
current = [];
};
const isCombinator = (char: string) => {
return char === '>' || char === '+' || char === '~';
};
const peekForward = () => {
return selector.substring(index).trim()[0];
};
const peekBackward = () => {
const s = selector.substring(0, index).trim();
return s[s.length - 1];
};
while (index < selector.length) {
const c = selector[index];
if (!quote && !insideAttr && c === ' ') {
if (space === 'none' || space === 'before')
space = 'before';
if (!quote && !insideAttr && c === ' ' && !isCombinator(peekForward()) && !isCombinator(peekBackward())) {
appendToCurrent();
start = index;
index++;
} else {
if (space === 'before') {
if (c === '>' || c === '+' || c === '~') {
space = 'after';
} else {
appendToCurrent();
start = index;
space = 'none';
}
} else {
space = 'none';
}
if (c === '\\' && index + 1 < selector.length) {
index += 2;
} else if (c === quote) {

Просмотреть файл

@ -662,6 +662,24 @@ describe('css selector', () => {
expect(await root3.$(`css:light=[attr*="value"]`)).toBe(null);
});
it('should work with > combinator and spaces', async({page, server}) => {
await page.setContent(`<div foo="bar" bar="baz"><span></span></div>`);
expect(await page.$eval(`div[foo="bar"] > span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"]> span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"] >span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"]>span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"] > span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"]> span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"] >span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"][bar="baz"] > span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"][bar="baz"]> span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"][bar="baz"] >span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"][bar="baz"]>span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"][bar="baz"] > span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"][bar="baz"]> span`, e => e.outerHTML)).toBe(`<span></span>`);
expect(await page.$eval(`div[foo="bar"][bar="baz"] >span`, e => e.outerHTML)).toBe(`<span></span>`);
});
it('should work with comma separated list', async({page, server}) => {
await page.goto(server.PREFIX + '/deep-shadow.html');
expect(await page.$$eval(`css=span,section #root1`, els => els.length)).toBe(5);