diff --git a/docs/api.md b/docs/api.md index 227bcdc6..7528abd1 100644 --- a/docs/api.md +++ b/docs/api.md @@ -25,8 +25,6 @@ + [event: 'requestfailed'](#event-requestfailed) + [event: 'requestfinished'](#event-requestfinished) + [event: 'response'](#event-response) - + [page.$(selector, pageFunction, ...args)](#pageselector-pagefunction-args) - + [page.$$(selector, pageFunction, ...args)](#pageselector-pagefunction-args) + [page.addScriptTag(url)](#pageaddscripttagurl) + [page.click(selector[, options])](#pageclickselector-options) + [page.close()](#pageclose) @@ -81,8 +79,6 @@ + [dialog.message()](#dialogmessage) + [dialog.type](#dialogtype) * [class: Frame](#class-frame) - + [frame.$(selector, pageFunction, ...args)](#frameselector-pagefunction-args) - + [frame.$$(selector, pageFunction, ...args)](#frameselector-pagefunction-args) + [frame.addScriptTag(url)](#frameaddscripttagurl) + [frame.childFrames()](#framechildframes) + [frame.click(selector[, options])](#frameclickselector-options) @@ -316,30 +312,6 @@ Emitted when a request is successfully finished. Emitted when a [response] is received. -#### page.$(selector, pageFunction, ...args) -- `selector` <[string]> A [selector] to be matched in the page -- `pageFunction` <[function]\([Element]\)> Function to be evaluated with first element matching `selector` -- `...args` <...[string]> Arguments to pass to `pageFunction` -- returns: <[Promise]<[Object]>> Promise which resolves to function return value. -Example: -```js -const outerhtml = await page.$('#box', e => e.outerHTML); -``` -Shortcut for [page.mainFrame().$(selector, pageFunction, ...args)](#frameselector-pagefunction-args). - -#### page.$$(selector, pageFunction, ...args) -- `selector` <[string]> A [selector] to be matched in the page -- `pageFunction` <[function]\([Element]\)> Function to be evaluted for every element matching `selector`. -- `...args` <...[string]> Arguments to pass to `pageFunction` -- returns: <[Promise]<[Array]<[Object]>>> Promise which resolves to array of function return values. -Example: -```js -const headings = await page.$$('h1,h2,h3,h4', el => el.textContent); -for (const heading of headings) console.log(heading); -``` - -Shortcut for [page.mainFrame().$$(selector, pageFunction, ...args)](#frameselector-pagefunction-args-1). - #### page.addScriptTag(url) - `url` <[string]> Url of a script to be added - returns: <[Promise]> Promise which resolves as the script gets added and loads. @@ -916,28 +888,6 @@ browser.newPage().then(async page => { }); ``` -#### frame.$(selector, pageFunction, ...args) -- `selector` <[string]> A [selector] to be matched in the page -- `pageFunction` <[function]\([Element]\)> Function to be evaluated with first element matching `selector` -- `...args` <...[string]> Arguments to pass to `pageFunction` -- returns: <[Promise]<[Object]>> Promise which resolves to function return value. -Example: -```js -const outerhtml = await page.$('#box', e => e.outerHTML); -``` - - -#### frame.$$(selector, pageFunction, ...args) -- `selector` <[string]> A [selector] to be matched in the page -- `pageFunction` <[function]\([Element]\)> Function to be evaluted for every element matching `selector`. -- `...args` <...[string]> Arguments to pass to `pageFunction` -- returns: <[Promise]<[Array]<[Object]>>> Promise which resolves to array of function return values. -Example: -```js -const headings = await page.$$('h1,h2,h3,h4', el => el.textContent); -for (const heading of headings) console.log(heading); -``` - #### frame.addScriptTag(url) - `url` <[string]> Url of a script to be added diff --git a/lib/FrameManager.js b/lib/FrameManager.js index c126ba56..29325e3c 100644 --- a/lib/FrameManager.js +++ b/lib/FrameManager.js @@ -317,40 +317,6 @@ class Frame { return this._client.send('DOM.setFileInputFiles', { objectId, files: filePaths }); } - /** - * @template T - * @param {string} selector - * @param {function(!Element):T} pageFunction - * @param {!Array<*>} args - * @return {!Promise} - */ - async $(selector, pageFunction, ...args) { - let argsString = ['node'].concat(args.map(x => JSON.stringify(x))).join(','); - let expression = `(()=>{ - let node = document.querySelector(${JSON.stringify(selector)}); - if (!node) - return null; - return (${pageFunction})(${argsString}); - })()`; - return this.evaluate(expression); - } - - /** - * @template T - * @param {string} selector - * @param {function(!Element):T} pageFunction - * @param {!Array<*>} args - * @return {!Promise>} - */ - async $$(selector, pageFunction, ...args) { - let argsString = ['node, index'].concat(args.map(x => JSON.stringify(x))).join(','); - let expression = `(()=>{ - let nodes = document.querySelectorAll(${JSON.stringify(selector)}); - return Array.prototype.map.call(nodes, (node, index) => (${pageFunction})(${argsString})); - })()`; - return this.evaluate(expression); - } - /** * @return {!Promise} */ diff --git a/lib/Page.js b/lib/Page.js index 89233f62..3a2dc609 100644 --- a/lib/Page.js +++ b/lib/Page.js @@ -623,28 +623,6 @@ class Page extends EventEmitter { async uploadFile(selector, ...filePaths) { return this.mainFrame().uploadFile(selector, ...filePaths); } - - /** - * @template T - * @param {string} selector - * @param {function(!Element):T} pageFunction - * @param {!Array<*>} args - * @return {!Promise} - */ - async $(selector, pageFunction, ...args) { - return this.mainFrame().$(selector, pageFunction, ...args); - } - - /** - * @template T - * @param {string} selector - * @param {function(!Element):T} pageFunction - * @param {!Array<*>} args - * @return {!Promise>} - */ - async $$(selector, pageFunction, ...args) { - return this.mainFrame().$$(selector, pageFunction, ...args); - } } /** @enum {string} */ diff --git a/test/test.js b/test/test.js index 291a9fa1..a45cd0f6 100644 --- a/test/test.js +++ b/test/test.js @@ -311,13 +311,10 @@ describe('Page', function() { it('should work when node is added through innerHTML', SX(async function() { await page.navigate(EMPTY_PAGE); - let frame = page.mainFrame(); - let added = false; - frame.waitForSelector('h3 div').then(() => added = true); - expect(added).toBe(false); - await frame.evaluate(addElement, 'span'); - await page.$('span', span => span.innerHTML = '

'); - expect(added).toBe(true); + let watchdog = page.waitForSelector('h3 div'); + await page.evaluate(addElement, 'span'); + await page.evaluate(() => document.querySelector('span').innerHTML = '

'); + await watchdog; })); it('Page.waitForSelector is shortcut for main frame', SX(async function() { @@ -956,21 +953,21 @@ describe('Page', function() { await page.navigate(PREFIX + '/input/textarea.html'); await page.focus('textarea'); await page.press('a', {text: 'f'}); - expect(await page.$('textarea', t => t.value)).toBe('f'); + expect(await page.evaluate(() => document.querySelector('textarea').value)).toBe('f'); await page.evaluate(() => window.addEventListener('keydown', e => e.preventDefault(), true)); await page.press('a', {text: 'y'}); - expect(await page.$('textarea', t => t.value)).toBe('f'); + expect(await page.evaluate(() => document.querySelector('textarea').value)).toBe('f'); })); it('should send a character with sendCharacter', SX(async function() { await page.navigate(PREFIX + '/input/textarea.html'); await page.focus('textarea'); await page.keyboard.sendCharacter('嗨'); - expect(await page.$('textarea', t => t.value)).toBe('嗨'); + expect(await page.evaluate(() => document.querySelector('textarea').value)).toBe('嗨'); await page.evaluate(() => window.addEventListener('keydown', e => e.preventDefault(), true)); await page.keyboard.sendCharacter('a'); - expect(await page.$('textarea', t => t.value)).toBe('嗨a'); + expect(await page.evaluate(() => document.querySelector('textarea').value)).toBe('嗨a'); })); it('should report shiftKey', SX(async function(){ await page.navigate(PREFIX + '/input/keyboard.html'); @@ -1070,13 +1067,14 @@ describe('Page', function() { it('should scroll and click the button', SX(async function(){ await page.navigate(PREFIX + '/input/scrollable.html'); await page.click('#button-5'); - expect(await page.$('#button-5', button => button.textContent)).toBe('clicked'); + expect(await page.evaluate(() => document.querySelector('#button-5').textContent)).toBe('clicked'); await page.click('#button-80'); - expect(await page.$('#button-80', button => button.textContent)).toBe('clicked'); + expect(await page.evaluate(() => document.querySelector('#button-80').textContent)).toBe('clicked'); })); it('should click a partially obscured button', SX(async function() { await page.navigate(PREFIX + '/input/button.html'); - await page.$('button', button => { + await page.evaluate(() => { + let button = document.querySelector('button'); button.textContent = 'Some really long text that will go offscreen'; button.style.position = 'absolute'; button.style.left = '368px'; @@ -1089,7 +1087,7 @@ describe('Page', function() { await page.focus('textarea'); let text = 'This is the text that we are going to try to select. Let\'s see how it goes.'; await page.type(text); - await page.$('textarea', textarea => textarea.scrollTop = 0); + await page.evaluate(() => document.querySelector('textarea').scrollTop = 0); let {x, y} = await page.evaluate(dimensions); await page.mouse.move(x + 2,y + 2); await page.mouse.down(); @@ -1110,20 +1108,20 @@ describe('Page', function() { it('should trigger hover state', SX(async function(){ await page.navigate(PREFIX + '/input/scrollable.html'); await page.hover('#button-6'); - expect(await page.$('button:hover', button => button.id)).toBe('button-6'); + expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-6'); await page.hover('#button-2'); - expect(await page.$('button:hover', button => button.id)).toBe('button-2'); + expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-2'); await page.hover('#button-91'); - expect(await page.$('button:hover', button => button.id)).toBe('button-91'); + expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-91'); })); it('should fire contextmenu event on right click', SX(async function(){ await page.navigate(PREFIX + '/input/scrollable.html'); await page.click('#button-8', {button: 'right'}); - expect(await page.$('#button-8', button => button.textContent)).toBe('context menu'); + expect(await page.evaluate(() => document.querySelector('#button-8').textContent)).toBe('context menu'); })); it('should set modifier keys on click', SX(async function(){ await page.navigate(PREFIX + '/input/scrollable.html'); - await page.$('#button-3', button => button.addEventListener('mousedown', e => window.lastEvent = e, true)); + await page.evaluate(() => document.querySelector('#button-3').addEventListener('mousedown', e => window.lastEvent = e, true)); let modifiers = {'Shift': 'shiftKey', 'Control': 'ctrlKey', 'Alt': 'altKey', 'Meta': 'metaKey'}; for (let modifier in modifiers) { await page.keyboard.down(modifier); @@ -1141,7 +1139,7 @@ describe('Page', function() { it('should specify repeat property', SX(async function(){ await page.navigate(PREFIX + '/input/textarea.html'); await page.focus('textarea'); - await page.$('textarea', textarea => textarea.addEventListener('keydown', e => window.lastEvent = e, true)); + await page.evaluate(() => document.querySelector('textarea').addEventListener('keydown', e => window.lastEvent = e, true)); await page.keyboard.down('a', {text: 'a'}); expect(await page.evaluate(() => window.lastEvent.repeat)).toBe(false); await page.press('a'); @@ -1394,34 +1392,6 @@ describe('Page', function() { })); }); - describe('Query selector', function() { - it('Page.$', SX(async function() { - await page.navigate(PREFIX + '/playground.html'); - expect(await page.$('#first', element => element.textContent)).toBe('First div'); - expect(await page.$('#second span', element => element.textContent)).toBe('Inner span'); - expect(await page.$('#first', (element, arg1) => arg1, 'value1')).toBe('value1'); - expect(await page.$('#first', (element, arg1, arg2) => arg2, 'value1', 'value2')).toBe('value2'); - expect(await page.$('doesnot-exist', element => 5)).toBe(null); - expect(await page.$('button', function(element, arg1) { - element.textContent = arg1; - return true; - }, 'new button text')).toBe(true); - expect(await page.$('button', function(element) { - return element.textContent; - })).toBe('new button text'); - })); - - it('Page.$$', SX(async function() { - await page.navigate(PREFIX + '/playground.html'); - expect((await page.$$('div', element => element.textContent)).length).toBe(2); - expect((await page.$$('div', (element, index) => index))[0]).toBe(0); - expect((await page.$$('div', (element, index) => index))[1]).toBe(1); - expect((await page.$$('doesnotexist', function(){})).length).toBe(0); - expect((await page.$$('div', element => element.textContent))[0]).toBe('First div'); - expect((await page.$$('span', (element, index, arg1) => arg1, 'value1'))[0]).toBe('value1'); - })); - }); - describe('Page.screenshot', function() { it('should work', SX(async function() { await page.setViewport({width: 500, height: 500});