diff --git a/docs/helpers/Puppeteer.md b/docs/helpers/Puppeteer.md index a705782bc..518d87618 100644 --- a/docs/helpers/Puppeteer.md +++ b/docs/helpers/Puppeteer.md @@ -453,6 +453,19 @@ I.doubleClick('.btn.edit'); - `locator` clickable link or button located by text, or any element located by CSS|XPath|strict locator. - `context` (optional) element to search in CSS|XPath|Strict locator. +### downloadFile + +Performs a download file on an element matched by link|button|CSS or XPath. +File is downloaded by default to output folder + +```js +I.downloadFile('td[class="text-right file-link"] a'); +``` + +#### Parameters + +- `locator` clickable link or button located by CSS|XPath locator. + ### dragAndDrop Drag an item to a destination element. diff --git a/docs/webapi/downloadFile.mustache b/docs/webapi/downloadFile.mustache new file mode 100644 index 000000000..1744f5f9f --- /dev/null +++ b/docs/webapi/downloadFile.mustache @@ -0,0 +1,9 @@ +Performs a download file on an element matched by link|button|CSS or XPath. +File is downloaded by default to output folder + + +```js +I.downloadFile('td[class="text-right file-link"] a'); +``` + +@param locator clickable link or button located by CSS|XPath locator. \ No newline at end of file diff --git a/lib/helper/Puppeteer.js b/lib/helper/Puppeteer.js index 74f058d0f..e71c851dc 100644 --- a/lib/helper/Puppeteer.js +++ b/lib/helper/Puppeteer.js @@ -23,7 +23,8 @@ const path = require('path'); const ElementNotFound = require('./errors/ElementNotFound'); const Popup = require('./extras/Popup'); const Console = require('./extras/Console'); - +const request = require('request-promise'); +const fs = require('fs'); let puppeteer; const popupStore = new Popup(); @@ -814,6 +815,48 @@ class Puppeteer extends Helper { return proceedClick.call(this, locator, context, { waitForNavigation: true }); } + /** + * {{> ../webapi/downloadFile }} + */ + async downloadFile(locator) { + let fileName; + await this.page.setRequestInterception(true); + this.click(locator); + + const xRequest = await new Promise((resolve) => { + this.page.on('request', (request) => { + fileName = request.url().split('/')[request.url().split('/').length - 1]; + request.abort(); + resolve(request); + }); + }); + + const options = { + encoding: null, + method: xRequest._method, + uri: xRequest._url, + body: xRequest._postData, + headers: xRequest._headers, + }; + + const cookies = await this.page.cookies(); + options.headers.Cookie = cookies.map(ck => `${ck.name}=${ck.value}`).join(';'); + + const response = await request(options); + + const outputFile = path.join(`${global.output_dir}/${fileName}`); + + try { + const wstream = fs.createWriteStream(outputFile); + wstream.write(response); + wstream.end(); + this.debug(`File is downloaded in ${outputFile}`); + return outputFile; + } catch (error) { + throw new Error(`There is something wrong with downloaded file. ${error}`); + } + } + /** * {{> ../webapi/doubleClick }} */ diff --git a/package.json b/package.json index 02626dc11..35ab794df 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "mocha": "^4.1.0", "parse-function": "^5.2.10", "promise-retry": "^1.1.1", + "request-promise": "^4.2.2", "requireg": "^0.1.8", "sprintf-js": "^1.1.1" }, diff --git a/test/helper/Puppeteer_test.js b/test/helper/Puppeteer_test.js index c5d2e053b..9fc3392e1 100644 --- a/test/helper/Puppeteer_test.js +++ b/test/helper/Puppeteer_test.js @@ -21,6 +21,13 @@ describe('Puppeteer', function () { before(() => { global.codecept_dir = path.join(__dirname, '/../data'); + + // create directory /download; + fs.mkdir(path.join(`${__dirname}/download`), () => { + + }); + + global.output_dir = path.join(`${__dirname}/download`); I = new Puppeteer({ url: siteUrl, windowSize: '500x700', @@ -50,6 +57,19 @@ describe('Puppeteer', function () { return I._after(); }); + after(() => { + // Remove the test dir + fs.readdir(global.output_dir, (err, files) => { + if (err) throw err; + + for (const file of files) { + fs.unlink(path.join(global.output_dir, file), (err) => { + if (err) throw err; + }); + } + }); + }); + describe('open page : #amOnPage', () => { it('should open main page of configured site', async () => { await I.amOnPage('/'); @@ -557,4 +577,13 @@ describe('Puppeteer', function () { assert.notEqual(before, after); }); }); + + describe('#downloadFile', () => { + it('should dowload file', async () => { + await I.amOnPage('http://file-examples.com/index.php/sample-video-files/sample-mp4-files/'); + const outputFile = await I.downloadFile('td[class="text-right file-link"] a'); + + assert.equal(fs.existsSync(path.join(outputFile)), true); + }); + }); });