ya
`);
expect(await playwright.selectors._createSelector('z', await page.$('#target'))).toBe('"ya"~"hey"~"hello"');
expect(await page.$eval(`z="ya"~"hey"~"hello"`, e => e.outerHTML)).toBe('
hello
');
expect(await page.$eval(`z="ya"~"hey"~"unique"`, e => e.outerHTML).catch(e => e.message)).toBe('Error: failed to find element matching selector "z="ya"~"hey"~"unique""');
expect(await page.$$eval(`z="ya" ~ "hey" ~ "hello"`, es => es.map(e => e.outerHTML).join('\n'))).toBe('
hello
\n
hello
');
});
it('should query existing element with zs selector', async({page, server}) => {
await page.goto(server.PREFIX + '/playground.html');
await page.setContent('
');
const html = await page.$('z=html');
const second = await html.$('z=.second');
const inner = await second.$('z=.inner');
const content = await page.evaluate(e => e.textContent, inner);
expect(content).toBe('A');
});
});
describe('text selector', () => {
it('query', async ({page}) => {
await page.setContent(`
yo
ya
\nye
`);
expect(await page.$eval(`text=ya`, e => e.outerHTML)).toBe('
ya
');
expect(await page.$eval(`text="ya"`, e => e.outerHTML)).toBe('
ya
');
expect(await page.$eval(`text=/^[ay]+$/`, e => e.outerHTML)).toBe('
ya
');
expect(await page.$eval(`text=/Ya/i`, e => e.outerHTML)).toBe('
ya
');
expect(await page.$eval(`text=ye`, e => e.outerHTML)).toBe('
\nye
');
await page.setContent(`
ye
ye
`);
expect(await page.$eval(`text="ye"`, e => e.outerHTML)).toBe('
ye
');
await page.setContent(`
yo
"ya
hello world!
`);
expect(await page.$eval(`text="\\"ya"`, e => e.outerHTML)).toBe('
"ya
');
expect(await page.$eval(`text=/hello/`, e => e.outerHTML)).toBe('
hello world!
');
expect(await page.$eval(`text=/^\\s*heLLo/i`, e => e.outerHTML)).toBe('
hello world!
');
await page.setContent(`
`);
expect(await page.$eval(`text=hey`, e => e.outerHTML)).toBe('
');
await page.setContent(`
yo
yo
`);
expect(await page.$$eval(`text=yo`, es => es.map(e => e.outerHTML).join('\n'))).toBe('
yo
\n
yo
');
});
it('create', async ({page}) => {
await page.setContent(`
yo
"ya
ye ye
`);
expect(await playwright.selectors._createSelector('text', await page.$('div'))).toBe('yo');
expect(await playwright.selectors._createSelector('text', await page.$('div:nth-child(2)'))).toBe('"\\"ya"');
expect(await playwright.selectors._createSelector('text', await page.$('div:nth-child(3)'))).toBe('"ye ye"');
await page.setContent(`
yo
`);
expect(await playwright.selectors._createSelector('text', await page.$('div:nth-child(2)'))).toBe('hey');
await page.setContent(`
`);
expect(await playwright.selectors._createSelector('text', await page.$('div'))).toBe('yo');
await page.setContent(`
`);
expect(await playwright.selectors._createSelector('text', await page.$('div'))).toBe('" \\"yo "');
});
it('should be case sensitive iff quotes are specified', async({page}) => {
await page.setContent(`
yo
ya
\nye
`);
expect(await page.$eval(`text=yA`, e => e.outerHTML)).toBe('
ya
');
expect(await page.$(`text="yA"`)).toBe(null);
});
});
describe('selectors.register', () => {
it('should work', async ({page}) => {
const createTagSelector = () => ({
create(root, target) {
return target.nodeName;
},
query(root, selector) {
return root.querySelector(selector);
},
queryAll(root, selector) {
return Array.from(root.querySelectorAll(selector));
}
});
await playwright.selectors.register('tag', `(${createTagSelector.toString()})()`);
await page.setContent('
');
expect(await playwright.selectors._createSelector('tag', await page.$('div'))).toBe('DIV');
expect(await page.$eval('tag=DIV', e => e.nodeName)).toBe('DIV');
expect(await page.$eval('tag=SPAN', e => e.nodeName)).toBe('SPAN');
expect(await page.$$eval('tag=DIV', es => es.length)).toBe(2);
});
it('should work with path', async ({page}) => {
await playwright.selectors.register('foo', { path: path.join(__dirname, 'assets/sectionselectorengine.js') });
await page.setContent('
');
expect(await page.$eval('foo=whatever', e => e.nodeName)).toBe('SECTION');
});
it('should work in main and isolated world', async ({page}) => {
const createDummySelector = () => ({
create(root, target) { },
query(root, selector) {
return window.__answer;
},
queryAll(root, selector) {
return [document.body, document.documentElement, window.__answer];
}
});
await playwright.selectors.register('main', createDummySelector);
await playwright.selectors.register('isolated', createDummySelector, { contentScript: true });
await page.setContent('
');
await page.evaluate(() => window.__answer = document.querySelector('span'));
// Works in main if asked.
expect(await page.$eval('main=ignored', e => e.nodeName)).toBe('SPAN');
expect(await page.$eval('css=div >> main=ignored', e => e.nodeName)).toBe('SPAN');
expect(await page.$$eval('main=ignored', es => window.__answer !== undefined)).toBe(true);
expect(await page.$$eval('main=ignored', es => es.filter(e => e).length)).toBe(3);
// Works in isolated by default.
expect(await page.$('isolated=ignored')).toBe(null);
expect(await page.$('css=div >> isolated=ignored')).toBe(null);
// $$eval always works in main, to avoid adopting nodes one by one.
expect(await page.$$eval('isolated=ignored', es => window.__answer !== undefined)).toBe(true);
expect(await page.$$eval('isolated=ignored', es => es.filter(e => e).length)).toBe(3);
// At least one engine in main forces all to be in main.
expect(await page.$eval('main=ignored >> isolated=ignored', e => e.nodeName)).toBe('SPAN');
expect(await page.$eval('isolated=ignored >> main=ignored', e => e.nodeName)).toBe('SPAN');
// Can be chained to css.
expect(await page.$eval('main=ignored >> css=section', e => e.nodeName)).toBe('SECTION');
});
it('should update', async ({page}) => {
await page.setContent('
');
expect(await page.$eval('div', e => e.nodeName)).toBe('DIV');
let error = await page.$('dummy=ignored').catch(e => e);
expect(error.message).toContain('Unknown engine dummy while parsing selector dummy=ignored');
const createDummySelector = () => ({
create(root, target) {
return target.nodeName;
},
query(root, selector) {
return root.querySelector('dummy');
},
queryAll(root, selector) {
return Array.from(root.querySelectorAll('dummy'));
}
});
error = await playwright.selectors.register('$', createDummySelector).catch(e => e);
expect(error.message).toBe('Selector engine name may only contain [a-zA-Z0-9_] characters');
await playwright.selectors.register('dummy', createDummySelector);
expect(await page.$eval('dummy=ignored', e => e.id)).toBe('d1');
expect(await page.$eval('css=span >> dummy=ignored', e => e.id)).toBe('d2');
error = await playwright.selectors.register('dummy', createDummySelector).catch(e => e);
expect(error.message).toBe('"dummy" selector engine has been already registered');
error = await playwright.selectors.register('css', createDummySelector).catch(e => e);
expect(error.message).toBe('"css" is a predefined selector engine');
});
});
};