Move uploadFiles onto ElementHandle (#348)

This patch:
- removes the `page.uploadFile` method
- adds `elementHandle.uploadFile` method.

Motivation: `elementHandle.uploadFile` is rarely used, so it doesn't worth it
to keep it on page.
This commit is contained in:
JoelEinbinder 2017-08-17 14:53:37 -07:00 committed by Andrey Lushnikov
parent ad1b292b6d
commit 5f0afd5547
6 changed files with 25 additions and 49 deletions

View File

@ -57,7 +57,6 @@
+ [page.title()](#pagetitle) + [page.title()](#pagetitle)
+ [page.tracing](#pagetracing) + [page.tracing](#pagetracing)
+ [page.type(text, options)](#pagetypetext-options) + [page.type(text, options)](#pagetypetext-options)
+ [page.uploadFile(selector, ...filePaths)](#pageuploadfileselector-filepaths)
+ [page.url()](#pageurl) + [page.url()](#pageurl)
+ [page.viewport()](#pageviewport) + [page.viewport()](#pageviewport)
+ [page.waitFor(selectorOrFunctionOrTimeout[, options])](#pagewaitforselectororfunctionortimeout-options) + [page.waitFor(selectorOrFunctionOrTimeout[, options])](#pagewaitforselectororfunctionortimeout-options)
@ -92,7 +91,6 @@
+ [frame.name()](#framename) + [frame.name()](#framename)
+ [frame.parentFrame()](#frameparentframe) + [frame.parentFrame()](#frameparentframe)
+ [frame.title()](#frametitle) + [frame.title()](#frametitle)
+ [frame.uploadFile(selector, ...filePaths)](#frameuploadfileselector-filepaths)
+ [frame.url()](#frameurl) + [frame.url()](#frameurl)
+ [frame.waitFor(selectorOrFunctionOrTimeout[, options])](#framewaitforselectororfunctionortimeout-options) + [frame.waitFor(selectorOrFunctionOrTimeout[, options])](#framewaitforselectororfunctionortimeout-options)
+ [frame.waitForFunction(pageFunction[, options, ...args])](#framewaitforfunctionpagefunction-options-args) + [frame.waitForFunction(pageFunction[, options, ...args])](#framewaitforfunctionpagefunction-options-args)
@ -102,6 +100,7 @@
+ [elementHandle.dispose()](#elementhandledispose) + [elementHandle.dispose()](#elementhandledispose)
+ [elementHandle.evaluate(pageFunction, ...args)](#elementhandleevaluatepagefunction-args) + [elementHandle.evaluate(pageFunction, ...args)](#elementhandleevaluatepagefunction-args)
+ [elementHandle.hover()](#elementhandlehover) + [elementHandle.hover()](#elementhandlehover)
+ [elementHandle.uploadFile(...filePaths)](#elementhandleuploadfilefilepaths)
* [class: Request](#class-request) * [class: Request](#class-request)
+ [request.abort()](#requestabort) + [request.abort()](#requestabort)
+ [request.continue([overrides])](#requestcontinueoverrides) + [request.continue([overrides])](#requestcontinueoverrides)
@ -684,13 +683,6 @@ page.type('Hello'); // Types instantly
page.type('World', {delay: 100}); // Types slower, like a user page.type('World', {delay: 100}); // Types slower, like a user
``` ```
#### page.uploadFile(selector, ...filePaths)
- `selector` <[string]> A [selector] to a file input
- `...filePaths` <[string]> Sets the value of the file input these paths. If some of the `filePaths` are relative paths, then they are resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd).
- returns: <[Promise]> Promise which resolves when the value is set.
Shortcut for [page.mainFrame().uploadFile(selector, ...filePaths)](#frameuploadfileselector-filepaths).
#### page.url() #### page.url()
- returns: <[string]> - returns: <[string]>
@ -1014,11 +1006,6 @@ If the name is empty, returns the id attribute instead.
#### frame.title() #### frame.title()
- returns: <[Promise]<[string]>> Returns page's title. - returns: <[Promise]<[string]>> Returns page's title.
#### frame.uploadFile(selector, ...filePaths)
- `selector` <[string]> A [selector] to a file input
- `...filePaths` <[string]> Sets the value of the file input these paths. If some of the `filePaths` are relative paths, then they are resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd).
- returns: <[Promise]> Promise which resolves when the value is set.
#### frame.url() #### frame.url()
- returns: <[string]> - returns: <[string]>
@ -1130,6 +1117,12 @@ The function will be passed in the element ifself as a first argument.
This method scrolls element into view if needed, and then uses [page.mouse](#pagemouse) to hover over the center of the element. This method scrolls element into view if needed, and then uses [page.mouse](#pagemouse) to hover over the center of the element.
If the element is detached from DOM, the method throws an error. If the element is detached from DOM, the method throws an error.
#### elementHandle.uploadFile(...filePaths)
- `...filePaths` <...[string]> Sets the value of the file input these paths. If some of the `filePaths` are relative paths, then they are resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd).
- returns: <[Promise]>
This method expects `elementHandle` to point to an [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).
### class: Request ### class: Request
Whenever the page sends a request, the following events are emitted by puppeteer's page: Whenever the page sends a request, the following events are emitted by puppeteer's page:

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
const path = require('path');
const helper = require('./helper'); const helper = require('./helper');
class ElementHandle { class ElementHandle {
@ -92,6 +93,16 @@ class ElementHandle {
let {x, y} = await this._visibleCenter(); let {x, y} = await this._visibleCenter();
await this._mouse.click(x, y, options); await this._mouse.click(x, y, options);
} }
/**
* @param {!Array<string>} filePaths
* @return {!Promise}
*/
async uploadFile(...filePaths) {
let files = filePaths.map(filePath => path.resolve(filePath));
const objectId = this._remoteObject.objectId;
return this._client.send('DOM.setFileInputFiles', { objectId, files });
}
} }
module.exports = ElementHandle; module.exports = ElementHandle;

View File

@ -15,7 +15,6 @@
*/ */
const fs = require('fs'); const fs = require('fs');
const path = require('path');
const EventEmitter = require('events'); const EventEmitter = require('events');
const helper = require('./helper'); const helper = require('./helper');
const ElementHandle = require('./ElementHandle'); const ElementHandle = require('./ElementHandle');
@ -325,21 +324,6 @@ class Frame {
return new WaitTask(this, predicateCode, polling, timeout).promise; return new WaitTask(this, predicateCode, polling, timeout).promise;
} }
/**
* @param {string} selector
* @param {!Array<string>} filePaths
* @return {!Promise}
*/
async uploadFile(selector, ...filePaths) {
let expression = helper.evaluationString(selector => document.querySelector(selector), selector);
const {result} = await this._client.send('Runtime.evaluate', { expression });
if (!result)
return;
const objectId = result.objectId;
filePaths = filePaths.map(filePath => path.resolve(filePath));
return this._client.send('DOM.setFileInputFiles', { objectId, files: filePaths });
}
/** /**
* @return {!Promise<string>} * @return {!Promise<string>}
*/ */

View File

@ -647,15 +647,6 @@ class Page extends EventEmitter {
waitForFunction(pageFunction, options = {}, ...args) { waitForFunction(pageFunction, options = {}, ...args) {
return this.mainFrame().waitForFunction(pageFunction, options, ...args); return this.mainFrame().waitForFunction(pageFunction, options, ...args);
} }
/**
* @param {string} selector
* @param {!Array<string>} filePaths
* @return {!Promise}
*/
async uploadFile(selector, ...filePaths) {
return this.mainFrame().uploadFile(selector, ...filePaths);
}
} }
/** @enum {string} */ /** @enum {string} */

View File

@ -420,9 +420,9 @@ class WebPage {
*/ */
uploadFile(selector, files) { uploadFile(selector, files) {
if (typeof files === 'string') if (typeof files === 'string')
await(this._page.uploadFile(selector, files)); await(await(this._page.$(selector)).uploadFile(files));
else else
await(this._page.uploadFile(selector, ...files)); await(await(this._page.$(selector)).uploadFile(...files));
} }
/** /**

View File

@ -1171,16 +1171,13 @@ describe('Page', function() {
it('should upload the file', SX(async function(){ it('should upload the file', SX(async function(){
await page.goto(PREFIX + '/input/fileupload.html'); await page.goto(PREFIX + '/input/fileupload.html');
const filePath = path.relative(process.cwd(), __dirname + '/assets/file-to-upload.txt'); const filePath = path.relative(process.cwd(), __dirname + '/assets/file-to-upload.txt');
await page.uploadFile('input', filePath); let input = await page.$('input');
expect(await page.evaluate(() => { await input.uploadFile(filePath);
let input = document.querySelector('input'); expect(await input.evaluate(e => e.files[0].name)).toBe('file-to-upload.txt');
return input.files[0].name; expect(await input.evaluate(e => {
})).toBe('file-to-upload.txt');
expect(await page.evaluate(() => {
let input = document.querySelector('input');
let reader = new FileReader(); let reader = new FileReader();
let promise = new Promise(fulfill => reader.onload = fulfill); let promise = new Promise(fulfill => reader.onload = fulfill);
reader.readAsText(input.files[0]); reader.readAsText(e.files[0]);
return promise.then(() => reader.result); return promise.then(() => reader.result);
})).toBe('contents of the file'); })).toBe('contents of the file');
})); }));