From f00f8595ab7ef9e2d3b2fbe936b1d233d863736a Mon Sep 17 00:00:00 2001 From: Craig de Gouveia Date: Mon, 15 May 2017 13:23:40 +0100 Subject: [PATCH 1/6] Expanded saveScreenshot fucntion for nightmare and updated docs --- docs/webapi/saveScreenshot.mustache | 7 +++-- lib/helper/Nightmare.js | 42 ++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/docs/webapi/saveScreenshot.mustache b/docs/webapi/saveScreenshot.mustache index 3014ee9df..7bdf16329 100644 --- a/docs/webapi/saveScreenshot.mustache +++ b/docs/webapi/saveScreenshot.mustache @@ -1,7 +1,10 @@ Saves a screenshot to ouput folder (set in codecept.json). -Filename is relative to output folder. +Filename is relative to output folder. +Optionally resize the window to the full availible page height and width to capture the entire page by passing `true` in as the second argument. ```js I.saveScreenshot('debug.png'); +I.saveScreenshot('debug.png',ture) \\resizes to availible scrollHeight and scrollWidth before taking screenshot ``` -@param fileName \ No newline at end of file +@param fileName +@param fullPage (optional) \ No newline at end of file diff --git a/lib/helper/Nightmare.js b/lib/helper/Nightmare.js index dd3c5bb05..b8250097c 100644 --- a/lib/helper/Nightmare.js +++ b/lib/helper/Nightmare.js @@ -797,20 +797,36 @@ class Nightmare extends Helper { }, lctype(locator), lcval(locator)); } - /** - * {{> ../webapi/saveScreenshot }} - */ - saveScreenshot(fileName) { - let outputFile = path.join(global.output_dir, fileName); - this.debug('Screenshot is saving to ' + outputFile); - let recorder = require('../recorder'); - return this.browser.screenshot(outputFile); - } + /** + * {{> ../webapi/saveScreenshot }} + */ + saveScreenshot(fileName, fullPage) { + fullPage = fullPage || false + let outputFile = path.join(global.output_dir, fileName); + this.debug('Screenshot is saving to ' + outputFile); + let recorder = require('../recorder'); + + if (full === true) { + this.browser.evaluate(function () { + o = { + height: document.body.scrollHeight, + width: document.body.scrollWidth + } + return o + }).then(doc => { + console.log(doc.width, doc.height) + this.browser.viewport(doc.width, doc.width); + return this.browser.screenshot(outputFile) + }) + } - _failed(test) { - let fileName = test.title.replace(/\W/g, '_') + '.failed.png'; - return this.saveScreenshot(fileName); - } + return this.browser.screenshot(outputFile); + } + + _failed(test) { + let fileName = test.title.replace(/\W/g, '_') + '.failed.png'; + return this.saveScreenshot(fileName, true); + } /** * Scrolls to element matched by locator. From fb3aa01b7df5d860681b9fb50f3d5153b37a68b3 Mon Sep 17 00:00:00 2001 From: Craig de Gouveia Date: Tue, 16 May 2017 12:21:05 +0100 Subject: [PATCH 2/6] Webdriver and WDIO work to bring inline with Nightmare. --- lib/helper/Nightmare.js | 35 +++++++++++++++------------------ lib/helper/SeleniumWebdriver.js | 29 ++++++++++++++++++++++----- lib/helper/WebDriverIO.js | 23 ++++++++++++++++++---- 3 files changed, 59 insertions(+), 28 deletions(-) diff --git a/lib/helper/Nightmare.js b/lib/helper/Nightmare.js index b8250097c..80f56470d 100644 --- a/lib/helper/Nightmare.js +++ b/lib/helper/Nightmare.js @@ -800,27 +800,24 @@ class Nightmare extends Helper { /** * {{> ../webapi/saveScreenshot }} */ - saveScreenshot(fileName, fullPage) { - fullPage = fullPage || false - let outputFile = path.join(global.output_dir, fileName); - this.debug('Screenshot is saving to ' + outputFile); - let recorder = require('../recorder'); - - if (full === true) { - this.browser.evaluate(function () { - o = { - height: document.body.scrollHeight, - width: document.body.scrollWidth - } - return o - }).then(doc => { - console.log(doc.width, doc.height) - this.browser.viewport(doc.width, doc.width); - return this.browser.screenshot(outputFile) - }) - } + saveScreenshot(fileName, fullPage = false) { + let outputFile = path.join(global.output_dir, fileName); + this.debug('Screenshot is saving to ' + outputFile); + let recorder = require('../recorder'); + if (!fullPage) { return this.browser.screenshot(outputFile); + } + return this.browser.evaluate(() => ({ + height: document.body.scrollHeight, + width: document.body.scrollWidth + })).then(({ + width, + height + }) => { + this.browser.viewport(width, height); + return this.browser.screenshot(outputFile) + }) } _failed(test) { diff --git a/lib/helper/SeleniumWebdriver.js b/lib/helper/SeleniumWebdriver.js index 6c799702b..ac8889e9e 100644 --- a/lib/helper/SeleniumWebdriver.js +++ b/lib/helper/SeleniumWebdriver.js @@ -159,7 +159,7 @@ class SeleniumWebdriver extends Helper { _failed(test) { let fileName = test.title.replace(/ /g, '_') + '.failed.png'; - return this.saveScreenshot(fileName); + return this.saveScreenshot(fileName,true); } _withinBegin(locator) { @@ -571,20 +571,39 @@ class SeleniumWebdriver extends Helper { /** * {{> ../webapi/saveScreenshot }} */ - saveScreenshot(fileName) { + saveScreenshot(fileName, fullPage = false) { let outputFile = path.join(global.output_dir, fileName); this.debug('Screenshot has been saved to ' + outputFile); - return this.browser.takeScreenshot().then(function (png) { + + const writeFile = (png,outputFile) => { let fs = require('fs'); - var stream = fs.createWriteStream(outputFile); + let stream = fs.createWriteStream(outputFile); stream.write(new Buffer(png, 'base64')); stream.end(); return new Promise(function (resolve) { return stream.on('finish', resolve); }); - }); + } + + if (!fullPage) { + return this.browser.takeScreenshot() + .then(png => writeFile(png,outputFile)); + } + return this.browser.executeScript(() => ({ + height: document.body.scrollHeight, + width: document.body.scrollWidth + })).then(({ + width, + height + }) => { + this.browser.manage().window().setSize(width, height) + return this.browser.takeScreenshot() + .then(png => writeFile(png,outputFile)); + }) } + + /** * {{> ../webapi/setCookie}} * diff --git a/lib/helper/WebDriverIO.js b/lib/helper/WebDriverIO.js index 0a7b5cd40..e1f56601b 100644 --- a/lib/helper/WebDriverIO.js +++ b/lib/helper/WebDriverIO.js @@ -304,7 +304,7 @@ class WebDriverIO extends Helper { } else { fileName = test.title.replace(/ /g, '_') + '.failed.png'; } - return this.saveScreenshot(fileName); + return this.saveScreenshot(fileName,true); } _withinBegin(locator) { @@ -859,12 +859,27 @@ class WebDriverIO extends Helper { /** * {{> ../webapi/saveScreenshot}} */ - saveScreenshot(fileName) { + saveScreenshot(fileName,fullPage = false) { let outputFile = path.join(global.output_dir, fileName); - this.debug('Screenshot has been saved to ' + outputFile); - return this.browser.saveScreenshot(outputFile); + + if (!fullPage) { + this.debug('Screenshot has been saved to ' + outputFile); + return this.browser.saveScreenshot(outputFile); + } + return this.browser.execute(() => ({ + height: document.body.scrollHeight, + width: document.body.scrollWidth + })).then(({ + width, + height + }) => { + this.browser.windowHandleSize(width, height); + this.debug('Screenshot has been saved to ' + outputFile); + return this.browser.saveScreenshot(outputFile) + }) } + /** * {{> ../webapi/setCookie}} * From a207d659bd3332485fdf21b8bd8a6dd25591f565 Mon Sep 17 00:00:00 2001 From: Craig de Gouveia Date: Tue, 16 May 2017 12:56:47 +0100 Subject: [PATCH 3/6] Updated docs and added tests --- docs/webapi/saveScreenshot.mustache | 2 +- test/helper/Protractor_test.js | 6 ++++++ test/helper/webapi.js | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/webapi/saveScreenshot.mustache b/docs/webapi/saveScreenshot.mustache index 7bdf16329..902420adf 100644 --- a/docs/webapi/saveScreenshot.mustache +++ b/docs/webapi/saveScreenshot.mustache @@ -1,6 +1,6 @@ Saves a screenshot to ouput folder (set in codecept.json). Filename is relative to output folder. -Optionally resize the window to the full availible page height and width to capture the entire page by passing `true` in as the second argument. +Optionally resize the window to the full availible page `scrollHeight` and `scrollWidth` to capture the entire page by passing `true` in as the second argument. ```js I.saveScreenshot('debug.png'); diff --git a/test/helper/Protractor_test.js b/test/helper/Protractor_test.js index 4cec20691..ab39964f5 100644 --- a/test/helper/Protractor_test.js +++ b/test/helper/Protractor_test.js @@ -372,6 +372,12 @@ describe('Protractor', function() { return assert.ok(fileExists(path.join(output_dir, 'protractor_user.png')), null, 'file does not exists'); }); + it('should create full page a screenshot file in output dir', function*() { + yield I.amOnPage('/'); + yield I.saveScreenshot('protractor_user_full.png',true); + return assert.ok(fileExists(path.join(output_dir, 'protractor_user_full.png')), null, 'file does not exists'); + }); + it('should create a screenshot on fail', function*() { let test = { title: 'protractor should do smth' }; yield I.amOnPage('/') diff --git a/test/helper/webapi.js b/test/helper/webapi.js index 781c51256..79f67e93a 100644 --- a/test/helper/webapi.js +++ b/test/helper/webapi.js @@ -472,6 +472,13 @@ module.exports.tests = function() { .then(() => assert.ok(fileExists(path.join(output_dir, 'screenshot_'+sec)), null, 'file does not exists')); }); + it('should create a full page screenshot file in output dir', () => { + let sec = (new Date()).getUTCMilliseconds(); + return I.amOnPage('/') + .then(() => I.saveScreenshot(`screenshot_full_${+sec}`,true)) + .then(() => assert.ok(fileExists(path.join(output_dir, `screenshot_full_${+sec}`)), null, 'file does not exists')); + }); + it('should create a screenshot on fail', () => { let sec = (new Date()).getUTCMilliseconds().toString(); let test = { title: 'sw should do smth '+sec }; From 793eeefae0a3e38f29f8e67bdc9b6b01c5e3cd05 Mon Sep 17 00:00:00 2001 From: Craig de Gouveia Date: Tue, 16 May 2017 13:22:00 +0100 Subject: [PATCH 4/6] typos and spelling mistakes in docs --- docs/webapi/saveScreenshot.mustache | 4 +-- lib/helper/Nightmare.js | 38 ++++++++++++++--------------- lib/helper/SeleniumWebdriver.js | 15 ++++++------ lib/helper/WebDriverIO.js | 8 +++--- 4 files changed, 32 insertions(+), 33 deletions(-) diff --git a/docs/webapi/saveScreenshot.mustache b/docs/webapi/saveScreenshot.mustache index 902420adf..cc9305659 100644 --- a/docs/webapi/saveScreenshot.mustache +++ b/docs/webapi/saveScreenshot.mustache @@ -1,10 +1,10 @@ Saves a screenshot to ouput folder (set in codecept.json). Filename is relative to output folder. -Optionally resize the window to the full availible page `scrollHeight` and `scrollWidth` to capture the entire page by passing `true` in as the second argument. +Optionally resize the window to the full available page `scrollHeight` and `scrollWidth` to capture the entire page by passing `true` in as the second argument. ```js I.saveScreenshot('debug.png'); -I.saveScreenshot('debug.png',ture) \\resizes to availible scrollHeight and scrollWidth before taking screenshot +I.saveScreenshot('debug.png',true) \\resizes to available scrollHeight and scrollWidth before taking screenshot ``` @param fileName @param fullPage (optional) \ No newline at end of file diff --git a/lib/helper/Nightmare.js b/lib/helper/Nightmare.js index 80f56470d..01db4085d 100644 --- a/lib/helper/Nightmare.js +++ b/lib/helper/Nightmare.js @@ -800,30 +800,30 @@ class Nightmare extends Helper { /** * {{> ../webapi/saveScreenshot }} */ - saveScreenshot(fileName, fullPage = false) { - let outputFile = path.join(global.output_dir, fileName); - this.debug('Screenshot is saving to ' + outputFile); - let recorder = require('../recorder'); + saveScreenshot(fileName, fullPage = false) { + let outputFile = path.join(global.output_dir, fileName); + this.debug('Screenshot is saving to ' + outputFile); + let recorder = require('../recorder'); - if (!fullPage) { - return this.browser.screenshot(outputFile); - } - return this.browser.evaluate(() => ({ - height: document.body.scrollHeight, - width: document.body.scrollWidth - })).then(({ + if (!fullPage) { + return this.browser.screenshot(outputFile); + } + return this.browser.evaluate(() => ({ + height: document.body.scrollHeight, + width: document.body.scrollWidth + })).then(({ width, height }) => { - this.browser.viewport(width, height); - return this.browser.screenshot(outputFile) - }) - } + this.browser.viewport(width, height); + return this.browser.screenshot(outputFile); + }); + } - _failed(test) { - let fileName = test.title.replace(/\W/g, '_') + '.failed.png'; - return this.saveScreenshot(fileName, true); - } + _failed(test) { + let fileName = test.title.replace(/\W/g, '_') + '.failed.png'; + return this.saveScreenshot(fileName, true); + } /** * Scrolls to element matched by locator. diff --git a/lib/helper/SeleniumWebdriver.js b/lib/helper/SeleniumWebdriver.js index ac8889e9e..e2218fb6a 100644 --- a/lib/helper/SeleniumWebdriver.js +++ b/lib/helper/SeleniumWebdriver.js @@ -159,7 +159,7 @@ class SeleniumWebdriver extends Helper { _failed(test) { let fileName = test.title.replace(/ /g, '_') + '.failed.png'; - return this.saveScreenshot(fileName,true); + return this.saveScreenshot(fileName, true); } _withinBegin(locator) { @@ -575,7 +575,7 @@ class SeleniumWebdriver extends Helper { let outputFile = path.join(global.output_dir, fileName); this.debug('Screenshot has been saved to ' + outputFile); - const writeFile = (png,outputFile) => { + const writeFile = (png, outputFile) => { let fs = require('fs'); let stream = fs.createWriteStream(outputFile); stream.write(new Buffer(png, 'base64')); @@ -583,11 +583,11 @@ class SeleniumWebdriver extends Helper { return new Promise(function (resolve) { return stream.on('finish', resolve); }); - } + }; if (!fullPage) { return this.browser.takeScreenshot() - .then(png => writeFile(png,outputFile)); + .then(png => writeFile(png, outputFile)); } return this.browser.executeScript(() => ({ height: document.body.scrollHeight, @@ -596,14 +596,13 @@ class SeleniumWebdriver extends Helper { width, height }) => { - this.browser.manage().window().setSize(width, height) + this.browser.manage().window().setSize(width, height); return this.browser.takeScreenshot() - .then(png => writeFile(png,outputFile)); - }) + .then(png => writeFile(png, outputFile)); + }); } - /** * {{> ../webapi/setCookie}} * diff --git a/lib/helper/WebDriverIO.js b/lib/helper/WebDriverIO.js index e1f56601b..070d8b2af 100644 --- a/lib/helper/WebDriverIO.js +++ b/lib/helper/WebDriverIO.js @@ -304,7 +304,7 @@ class WebDriverIO extends Helper { } else { fileName = test.title.replace(/ /g, '_') + '.failed.png'; } - return this.saveScreenshot(fileName,true); + return this.saveScreenshot(fileName, true); } _withinBegin(locator) { @@ -859,7 +859,7 @@ class WebDriverIO extends Helper { /** * {{> ../webapi/saveScreenshot}} */ - saveScreenshot(fileName,fullPage = false) { + saveScreenshot(fileName, fullPage = false) { let outputFile = path.join(global.output_dir, fileName); if (!fullPage) { @@ -875,8 +875,8 @@ class WebDriverIO extends Helper { }) => { this.browser.windowHandleSize(width, height); this.debug('Screenshot has been saved to ' + outputFile); - return this.browser.saveScreenshot(outputFile) - }) + return this.browser.saveScreenshot(outputFile); + }); } From 551d79ea59da415a2b0659b6badc6aa3bed41ec7 Mon Sep 17 00:00:00 2001 From: Craig de Gouveia Date: Tue, 16 May 2017 14:52:58 +0100 Subject: [PATCH 5/6] Moved test for resizeWindow This was causing the SeleniumWebdriver tests to fail as the window size isn't reset after prior tests. --- test/helper/webapi.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/test/helper/webapi.js b/test/helper/webapi.js index 79f67e93a..c24fb721a 100644 --- a/test/helper/webapi.js +++ b/test/helper/webapi.js @@ -460,6 +460,23 @@ module.exports.tests = function() { }); }); + describe('window size #resizeWindow', () => { + it('should set initial window size', () => { + return I.amOnPage('/form/resize') + .then(() => I.click('Window Size')) + .then(() => I.see('Height 400', '#height')) + .then(() => I.see('Width 500', '#width')) + }); + + it('should resize window to specific dimensions', () => { + return I.amOnPage('/form/resize') + .then(() => I.resizeWindow(800, 600)) + .then(() => I.click('Window Size')) + .then(() => I.see('Height 600', '#height')) + .then(() => I.see('Width 800', '#width')) + }); + }); + describe('#saveScreenshot', () => { beforeEach(() => { global.output_dir = path.join(global.codecept_dir, 'output'); @@ -531,23 +548,6 @@ module.exports.tests = function() { }); }); - describe('window size #resizeWindow', () => { - it('should set initial window size', () => { - return I.amOnPage('/form/resize') - .then(() => I.click('Window Size')) - .then(() => I.see('Height 400', '#height')) - .then(() => I.see('Width 500', '#width')) - }); - - it('should resize window to specific dimensions', () => { - return I.amOnPage('/form/resize') - .then(() => I.resizeWindow(800, 600)) - .then(() => I.click('Window Size')) - .then(() => I.see('Height 600', '#height')) - .then(() => I.see('Width 800', '#width')) - }); - }); - describe('#waitForElement', () => { it('should wait for visibile element', () => { return I.amOnPage('/form/wait_visible') From defb80b0dd7628c4b4bf724759f85c9c003c8da8 Mon Sep 17 00:00:00 2001 From: Craig de Gouveia Date: Wed, 7 Jun 2017 17:04:13 +0100 Subject: [PATCH 6/6] Resolves #540. Added config option to helpers for saveScreenshot() --- lib/helper/Nightmare.js | 3 ++- lib/helper/Protractor.js | 1 + lib/helper/SeleniumWebdriver.js | 1 + lib/helper/WebDriverIO.js | 48 +++++++++++++++++---------------- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/lib/helper/Nightmare.js b/lib/helper/Nightmare.js index 01db4085d..27cadd354 100644 --- a/lib/helper/Nightmare.js +++ b/lib/helper/Nightmare.js @@ -48,6 +48,7 @@ class Nightmare extends Helper { this.options = { waitForAction: 500, waitForTimeout: 1000, + fullPageScreenshots: true, rootElement: 'body', restart: true, keepCookies: false, @@ -800,7 +801,7 @@ class Nightmare extends Helper { /** * {{> ../webapi/saveScreenshot }} */ - saveScreenshot(fileName, fullPage = false) { + saveScreenshot(fileName, fullPage = this.options.fullPageScreenshots) { let outputFile = path.join(global.output_dir, fileName); this.debug('Screenshot is saving to ' + outputFile); let recorder = require('../recorder'); diff --git a/lib/helper/Protractor.js b/lib/helper/Protractor.js index 02ec07d98..de1532568 100644 --- a/lib/helper/Protractor.js +++ b/lib/helper/Protractor.js @@ -68,6 +68,7 @@ class Protractor extends SeleniumWebdriver { browser: 'chrome', url: 'http://localhost', seleniumAddress: 'http://localhost:4444/wd/hub', + fullPageScreenshots: true, rootElement: 'body', scriptsTimeout: 10000, waitForTimeout: 1000, // ms diff --git a/lib/helper/SeleniumWebdriver.js b/lib/helper/SeleniumWebdriver.js index 5813a6725..cdacf5d07 100644 --- a/lib/helper/SeleniumWebdriver.js +++ b/lib/helper/SeleniumWebdriver.js @@ -72,6 +72,7 @@ class SeleniumWebdriver extends Helper { restart: true, keepCookies: false, windowSize: null, + fullPageScreenshots: true, waitForTimeout: 1000, // ms scriptTimeout: 1000, // ms manualStart: false, diff --git a/lib/helper/WebDriverIO.js b/lib/helper/WebDriverIO.js index 9aa0d92a1..26ef1f815 100644 --- a/lib/helper/WebDriverIO.js +++ b/lib/helper/WebDriverIO.js @@ -921,13 +921,15 @@ class WebDriverIO extends Helper { this.debug('Screenshot has been saved to ' + outputFile); return this.browser.saveScreenshot(outputFile); } - return this.browser.execute(() => ({ - height: document.body.scrollHeight, - width: document.body.scrollWidth - })).then(({ - width, - height - }) => { + return this.browser.execute(function () { + return ({ + height: document.body.scrollHeight, + width: document.body.scrollWidth + }) + }).then(({ + width, + height + }) => { this.browser.windowHandleSize(width, height); this.debug('Screenshot has been saved to ' + outputFile); return this.browser.saveScreenshot(outputFile); @@ -1120,13 +1122,13 @@ class WebDriverIO extends Helper { sec = sec || this.options.waitForTimeout; context = context || 'body'; return this.browser.waitUntil(function () { - return this.getText(withStrictLocator(context)).then(function (source) { - if (Array.isArray(source)) { - return source.filter(part => part.indexOf(text) >= 0).length > 0; - } - return source.indexOf(text) >= 0; - }); - }, sec * 1000) + return this.getText(withStrictLocator(context)).then(function (source) { + if (Array.isArray(source)) { + return source.filter(part => part.indexOf(text) >= 0).length > 0; + } + return source.indexOf(text) >= 0; + }); + }, sec * 1000) .catch((e) => { if (e.type === 'WaitUntilTimeoutError') { return proceedSee.call(this, 'assert', text, withStrictLocator(context)); @@ -1361,15 +1363,15 @@ function withStrictLocator(locator) { locator.toString = () => `{${key}: '${value}'}`; switch (key) { - case 'by': - case 'xpath': - return value; - case 'css': - return value; - case 'id': - return '#' + value; - case 'name': - return `[name="${value}"]`; + case 'by': + case 'xpath': + return value; + case 'css': + return value; + case 'id': + return '#' + value; + case 'name': + return `[name="${value}"]`; } }