mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
Implement Page.uploadFile (#61)
This patch implements `Page.uploadFile` method to support file upload inputs.
This commit is contained in:
parent
739c1566a9
commit
da0cde1b45
@ -33,6 +33,7 @@
|
||||
* [page.setViewportSize(size)](#pagesetviewportsizesize)
|
||||
* [page.title()](#pagetitle)
|
||||
* [page.type()](#pagetype)
|
||||
* [page.uploadFile(selector, ...filePaths)](#pageuploadfileselector-filepaths)
|
||||
* [page.url()](#pageurl)
|
||||
* [page.userAgent()](#pageuseragent)
|
||||
* [page.viewportSize()](#pageviewportsize)
|
||||
@ -236,6 +237,11 @@ Pages could be closed by `page.close()` method.
|
||||
|
||||
#### page.type()
|
||||
|
||||
#### page.uploadFile(selector, ...filePaths)
|
||||
- `selector` <[string]> A query selector to a file input
|
||||
- `...filePaths` <[string]> Sets the value of the file input these paths
|
||||
- returns: <[Promise]> Promise which resolves when the value is set.
|
||||
|
||||
#### page.url()
|
||||
|
||||
- returns: <[Promise]<[string]>> Promise which resolves with the current page url.
|
||||
|
@ -108,7 +108,10 @@ class NetworkManager extends EventEmitter {
|
||||
* @param {!Object} event
|
||||
*/
|
||||
_onResponseReceived(event) {
|
||||
let request = this._idToRequest.get(event.requestId) || null;
|
||||
let request = this._idToRequest.get(event.requestId);
|
||||
// FileUpload sends a response without a matching request.
|
||||
if (!request)
|
||||
return;
|
||||
let response = new Response(request, event.response, this._getResponseBody.bind(this, event.requestId));
|
||||
request._response = response;
|
||||
this.emit(NetworkManager.Events.Response, response);
|
||||
|
19
lib/Page.js
19
lib/Page.js
@ -493,10 +493,13 @@ class Page extends EventEmitter {
|
||||
* @param {!Promise<number>}
|
||||
*/
|
||||
async _querySelector(selector) {
|
||||
return (await this._client.send('DOM.querySelector', {
|
||||
let {nodeId} = await this._client.send('DOM.querySelector', {
|
||||
nodeId: await this._rootNodeId(),
|
||||
selector
|
||||
})).nodeId;
|
||||
});
|
||||
if (!nodeId)
|
||||
throw new Error('No node found for selector: ' + selector);
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -569,6 +572,18 @@ class Page extends EventEmitter {
|
||||
waitFor(selector) {
|
||||
return this.mainFrame().waitFor(selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} selector
|
||||
* @param {!Array<string>} filePaths
|
||||
* @return {!Promise}
|
||||
*/
|
||||
async uploadFile(selector, ...filePaths) {
|
||||
await this._client.send('DOM.setFileInputFiles', {
|
||||
nodeId: await this._querySelector(selector),
|
||||
files: filePaths
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** @enum {string} */
|
||||
|
@ -332,6 +332,17 @@ class WebPage {
|
||||
await(this._page.setContent(html));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} selector
|
||||
* @param {(string|!Array<string>)} files
|
||||
*/
|
||||
uploadFile(selector, files) {
|
||||
if (typeof files === 'string')
|
||||
await(this._page.uploadFile(selector, files));
|
||||
else
|
||||
await(this._page.uploadFile(selector, ...files));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} html
|
||||
* @param {function()=} callback
|
||||
|
1
test/assets/file-to-upload.txt
Normal file
1
test/assets/file-to-upload.txt
Normal file
@ -0,0 +1 @@
|
||||
contents of the file
|
9
test/assets/input/fileupload.html
Normal file
9
test/assets/input/fileupload.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>File upload test</title>
|
||||
</head>
|
||||
<body>
|
||||
<input type="file">
|
||||
</body>
|
||||
</html>
|
24
test/test.js
24
test/test.js
@ -544,6 +544,15 @@ describe('Puppeteer', function() {
|
||||
await page.click('button');
|
||||
expect(await page.evaluate(() => result)).toBe('Clicked');
|
||||
}));
|
||||
it('should fail to click a missing button', SX(async function() {
|
||||
await page.navigate(STATIC_PREFIX + '/input/button.html');
|
||||
try {
|
||||
await page.click('button.does-not-exist');
|
||||
fail('Clicking the button did not throw.');
|
||||
} catch (error) {
|
||||
expect(error.message).toBe('No node found for selector: button.does-not-exist');
|
||||
}
|
||||
}));
|
||||
it('should type into the textarea', SX(async function() {
|
||||
await page.navigate(STATIC_PREFIX + '/input/textarea.html');
|
||||
await page.focus('textarea');
|
||||
@ -557,6 +566,21 @@ describe('Puppeteer', function() {
|
||||
await page.click('button');
|
||||
expect(await page.evaluate(() => result)).toBe('Clicked');
|
||||
}));
|
||||
it('should upload the file', SX(async function(){
|
||||
await page.navigate(STATIC_PREFIX + '/input/fileupload.html');
|
||||
await page.uploadFile('input', __dirname + '/assets/file-to-upload.txt');
|
||||
expect(await page.evaluate(() => {
|
||||
let input = document.querySelector('input');
|
||||
return input.files[0].name;
|
||||
})).toBe('file-to-upload.txt');
|
||||
expect(await page.evaluate(() => {
|
||||
let input = document.querySelector('input');
|
||||
let reader = new FileReader();
|
||||
let promise = new Promise(fulfill => reader.onload = fulfill);
|
||||
reader.readAsText(input.files[0]);
|
||||
return promise.then(() => reader.result);
|
||||
})).toBe('contents of the file');
|
||||
}));
|
||||
});
|
||||
describe('Page.setUserAgent', function() {
|
||||
it('should work', SX(async function() {
|
||||
|
@ -1,11 +1,9 @@
|
||||
//! unsupported
|
||||
|
||||
// Note: uses various files in module/webpage as things to be uploaded.
|
||||
// Which files they are doesn't matter.
|
||||
|
||||
var page;
|
||||
setup(function () {
|
||||
page = new WebPage();
|
||||
page = require('webpage').create();
|
||||
page.content =
|
||||
'<input type="file" id="file">\n' +
|
||||
'<input type="file" id="file2" multiple>\n' +
|
||||
@ -21,7 +19,7 @@ function test_one_elt(id, names) {
|
||||
var elt = document.getElementById(id);
|
||||
var rv = [];
|
||||
for (var i = 0; i < elt.files.length; i++) {
|
||||
rv.push(elt.files[i].fileName);
|
||||
rv.push(elt.files[i].name);
|
||||
}
|
||||
return rv;
|
||||
}, id);
|
||||
@ -32,7 +30,7 @@ generate_tests(test_one_elt, [
|
||||
["single upload single file", "file", ["file-upload.js"]],
|
||||
["multiple upload single file", "file2", ["file-upload.js"]],
|
||||
["multiple upload multiple file", "file3", ["file-upload.js", "object.js"]],
|
||||
], { expected_fail: true });
|
||||
], { expected_fail: false });
|
||||
|
||||
async_test(function () {
|
||||
page.onFilePicker = this.step_func(function (oldFile) {
|
||||
|
Loading…
Reference in New Issue
Block a user