From fb5bf89b62306300c05c15b751009ccf4ab04c83 Mon Sep 17 00:00:00 2001 From: PeterNgTr Date: Tue, 15 Oct 2019 13:16:21 +0200 Subject: [PATCH 1/9] introduce authentication for puppeteer --- lib/helper/Puppeteer.js | 23 ++++++++++++++++ test/helper/Puppeteer_test.js | 49 ++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/lib/helper/Puppeteer.js b/lib/helper/Puppeteer.js index fc3f5fbc1..5fffc828d 100644 --- a/lib/helper/Puppeteer.js +++ b/lib/helper/Puppeteer.js @@ -50,6 +50,7 @@ const consoleLogStore = new Console(); * This helper should be configured in codecept.json or codecept.conf.js * * * `url`: base url of website to be tested + * * `basicAuth`: (optional) the basic authentication to pass to base url. Example: 'username, password' * * `show`: (optional, default: false) - show Google Chrome window for debug. * * `restart`: (optional, default: true) - restart browser between tests. * * `disableScreenshots`: (optional, default: false) - don't save screenshot on failure. @@ -127,6 +128,22 @@ const consoleLogStore = new Console(); * } * ``` * +* #### Example #5: Target URL with provided basic authentication + * + * ```js + * { + * helpers: { + * Puppeteer : { + * url: 'http://localhost', + * basicAuth: 'username, password', + * show: true + * } + * } + * } + * ``` + * + * + * * Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored. * * ## Access From Helpers @@ -513,6 +530,12 @@ class Puppeteer extends Helper { if (!(/^\w+\:\/\//.test(url))) { url = this.options.url + url; } + + if (this.config.basicAuth) { + const username = this.config.basicAuth.split(',')[0].trim(); + const pwd = this.config.basicAuth.split(',')[1].trim(); + this.page.authenticate({ username, password: pwd }); + } await this.page.goto(url, { waitUntil: this.options.waitForNavigation }); const performanceTiming = JSON.parse(await this.page.evaluate(() => JSON.stringify(window.performance.timing))); diff --git a/test/helper/Puppeteer_test.js b/test/helper/Puppeteer_test.js index b0f3dd14c..53f06cc24 100644 --- a/test/helper/Puppeteer_test.js +++ b/test/helper/Puppeteer_test.js @@ -19,6 +19,48 @@ let page; let FS; const siteUrl = TestHelper.siteUrl(); +describe('Puppeteer - BasicAuth', () => { + before(() => { + global.codecept_dir = path.join(__dirname, '/../data'); + + I = new Puppeteer({ + url: siteUrl, + windowSize: '500x700', + show: true, + waitForTimeout: 5000, + waitForAction: 500, + chrome: { + args: ['--no-sandbox', '--disable-setuid-sandbox'], + }, + defaultPopupAction: 'accept', + basicAuth: 'postman, password', + }); + I._init(); + return I._beforeSuite(); + }); + + beforeEach(() => { + webApiTests.init({ + I, siteUrl, + }); + return I._before().then(() => { + page = I.page; + browser = I.browser; + }); + }); + + afterEach(() => { + return I._after(); + }); + + describe('open page with provided basic auth', () => { + it.only('should be authenticated ', async () => { + await I.amOnPage('https://postman-echo.com/basic-auth'); + await I.see('{"authenticated":true}'); + }); + }); +}); + describe('Puppeteer', function () { this.timeout(35000); this.retries(1); @@ -29,7 +71,7 @@ describe('Puppeteer', function () { I = new Puppeteer({ url: siteUrl, windowSize: '500x700', - show: false, + show: true, waitForTimeout: 5000, waitForAction: 500, chrome: { @@ -72,6 +114,11 @@ describe('Puppeteer', function () { const url = await page.url(); return url.should.eql(`${siteUrl}/`); }); + + it.only('should be authenticated ', async () => { + await I.amOnPage('https://postman-echo.com/basic-auth'); + await I.see('Unauthorized'); + }); }); describe('grabDataFromPerformanceTiming', () => { From 5cbe9814aac8e1cf03b619662a519698954dca6f Mon Sep 17 00:00:00 2001 From: PeterNgTr Date: Tue, 15 Oct 2019 13:24:22 +0200 Subject: [PATCH 2/9] clean up tests --- test/helper/Puppeteer_test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/helper/Puppeteer_test.js b/test/helper/Puppeteer_test.js index 53f06cc24..4edc9cc3f 100644 --- a/test/helper/Puppeteer_test.js +++ b/test/helper/Puppeteer_test.js @@ -26,7 +26,7 @@ describe('Puppeteer - BasicAuth', () => { I = new Puppeteer({ url: siteUrl, windowSize: '500x700', - show: true, + show: false, waitForTimeout: 5000, waitForAction: 500, chrome: { @@ -54,7 +54,7 @@ describe('Puppeteer - BasicAuth', () => { }); describe('open page with provided basic auth', () => { - it.only('should be authenticated ', async () => { + it('should be authenticated ', async () => { await I.amOnPage('https://postman-echo.com/basic-auth'); await I.see('{"authenticated":true}'); }); @@ -71,7 +71,7 @@ describe('Puppeteer', function () { I = new Puppeteer({ url: siteUrl, windowSize: '500x700', - show: true, + show: false, waitForTimeout: 5000, waitForAction: 500, chrome: { @@ -115,7 +115,7 @@ describe('Puppeteer', function () { return url.should.eql(`${siteUrl}/`); }); - it.only('should be authenticated ', async () => { + it('should be authenticated ', async () => { await I.amOnPage('https://postman-echo.com/basic-auth'); await I.see('Unauthorized'); }); From c2a1a5301900a3814cfdd7df003b2c1c7e410676 Mon Sep 17 00:00:00 2001 From: PeterNgTr Date: Tue, 15 Oct 2019 14:31:10 +0200 Subject: [PATCH 3/9] PR fix --- lib/helper/Puppeteer.js | 9 ++++----- test/helper/Puppeteer_test.js | 9 ++------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/helper/Puppeteer.js b/lib/helper/Puppeteer.js index 5fffc828d..2c3f3bfa2 100644 --- a/lib/helper/Puppeteer.js +++ b/lib/helper/Puppeteer.js @@ -50,7 +50,7 @@ const consoleLogStore = new Console(); * This helper should be configured in codecept.json or codecept.conf.js * * * `url`: base url of website to be tested - * * `basicAuth`: (optional) the basic authentication to pass to base url. Example: 'username, password' + * * `basicAuth`: (optional) the basic authentication to pass to base url. Example: {username: 'username', password: 'password'} * * `show`: (optional, default: false) - show Google Chrome window for debug. * * `restart`: (optional, default: true) - restart browser between tests. * * `disableScreenshots`: (optional, default: false) - don't save screenshot on failure. @@ -135,7 +135,7 @@ const consoleLogStore = new Console(); * helpers: { * Puppeteer : { * url: 'http://localhost', - * basicAuth: 'username, password', + * basicAuth: {username: 'username', password: 'password'}, * show: true * } * } @@ -532,10 +532,9 @@ class Puppeteer extends Helper { } if (this.config.basicAuth) { - const username = this.config.basicAuth.split(',')[0].trim(); - const pwd = this.config.basicAuth.split(',')[1].trim(); - this.page.authenticate({ username, password: pwd }); + this.page.authenticate(this.config.basicAuth); } + await this.page.goto(url, { waitUntil: this.options.waitForNavigation }); const performanceTiming = JSON.parse(await this.page.evaluate(() => JSON.stringify(window.performance.timing))); diff --git a/test/helper/Puppeteer_test.js b/test/helper/Puppeteer_test.js index 4edc9cc3f..583c22189 100644 --- a/test/helper/Puppeteer_test.js +++ b/test/helper/Puppeteer_test.js @@ -1,15 +1,10 @@ const TestHelper = require('../support/TestHelper'); const Puppeteer = require('../../lib/helper/Puppeteer'); const puppeteer = require('puppeteer'); -const should = require('chai').should(); const expect = require('chai').expect; const assert = require('assert'); const path = require('path'); -const fs = require('fs'); -const fileExists = require('../../lib/utils').fileExists; const AssertionFailedError = require('../../lib/assert/error'); -const formContents = require('../../lib/utils').test.submittedData(path.join(__dirname, '/../data/app/db')); -const expectError = require('../../lib/utils').test.expectError; const webApiTests = require('./webapi'); const FileSystem = require('../../lib/helper/FileSystem'); @@ -33,7 +28,7 @@ describe('Puppeteer - BasicAuth', () => { args: ['--no-sandbox', '--disable-setuid-sandbox'], }, defaultPopupAction: 'accept', - basicAuth: 'postman, password', + basicAuth: { username: 'postman', password: 'password' }, }); I._init(); return I._beforeSuite(); @@ -115,7 +110,7 @@ describe('Puppeteer', function () { return url.should.eql(`${siteUrl}/`); }); - it('should be authenticated ', async () => { + it('should be unauthenticated ', async () => { await I.amOnPage('https://postman-echo.com/basic-auth'); await I.see('Unauthorized'); }); From 9cac0cb5b5a662ae4a7957e34fe348eb9d4e0dce Mon Sep 17 00:00:00 2001 From: PeterNgTr Date: Tue, 15 Oct 2019 15:17:40 +0200 Subject: [PATCH 4/9] include the basicAuth when openning the url for wdio --- lib/helper/WebDriver.js | 24 ++++++++++++++++++++++++ test/helper/WebDriver_test.js | 6 ++++++ 2 files changed, 30 insertions(+) diff --git a/lib/helper/WebDriver.js b/lib/helper/WebDriver.js index faf01e341..a52fcdae1 100644 --- a/lib/helper/WebDriver.js +++ b/lib/helper/WebDriver.js @@ -39,6 +39,7 @@ const webRoot = 'body'; * This helper should be configured in codecept.json or codecept.conf.js * * * `url`: base url of website to be tested. + * * `basicAuth`: (optional) the basic authentication to pass to base url. Example: {username: 'username', password: 'password'} * * `browser`: browser in which to perform testing. * * `host`: (optional, default: localhost) - WebDriver host to connect. * * `port`: (optional, default: 4444) - WebDriver port to connect. @@ -78,6 +79,25 @@ const webRoot = 'body'; * } * ``` * + * Example with basic authentication + * ```js + * { + * helpers: { + * WebDriver : { + * smartWait: 5000, + * browser: "chrome", + * basicAuth: {username: 'username', password: 'password'}, + * restart: false, + * windowSize: "maximize", + * timeouts: { + * "script": 60000, + * "page load": 10000 + * } + * } + * } + * } + * ``` + * * Additional configuration params can be used from [webdriverio * website](http://webdriver.io/guide/getstarted/configuration.html). * @@ -701,6 +721,10 @@ class WebDriver extends Helper { * */ amOnPage(url) { + if (this.config.basicAuth) { + const split_url = url.split('//'); + url = `${split_url[0]}//${this.config.basicAuth.username}:${this.config.basicAuth.password}@${split_url[1]}`; + } return this.browser.url(url); } diff --git a/test/helper/WebDriver_test.js b/test/helper/WebDriver_test.js index 99ca7092a..ffac228af 100644 --- a/test/helper/WebDriver_test.js +++ b/test/helper/WebDriver_test.js @@ -25,6 +25,7 @@ describe('WebDriver', function () { wd = new WebDriver({ url: siteUrl, + basicAuth: { username: 'postman', password: 'password' }, browser: 'chrome', windowSize: '500x700', smartWait: 0, // just to try @@ -67,6 +68,11 @@ describe('WebDriver', function () { const url = await wd.grabCurrentUrl(); url.should.eql(`${siteUrl}/`); }); + + it('should be authenticated', async () => { + await wd.amOnPage('https://postman-echo.com/basic-auth'); + await wd.see('{"authenticated":true}'); + }); }); describe('see text : #see', () => { From bf655e794ddf1bc4ab701e86d95069f55a408b26 Mon Sep 17 00:00:00 2001 From: PeterNgTr Date: Tue, 15 Oct 2019 15:46:46 +0200 Subject: [PATCH 5/9] fix wdio tests --- test/helper/WebDriver_test.js | 46 ++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/test/helper/WebDriver_test.js b/test/helper/WebDriver_test.js index ffac228af..cd198a849 100644 --- a/test/helper/WebDriver_test.js +++ b/test/helper/WebDriver_test.js @@ -25,7 +25,6 @@ describe('WebDriver', function () { wd = new WebDriver({ url: siteUrl, - basicAuth: { username: 'postman', password: 'password' }, browser: 'chrome', windowSize: '500x700', smartWait: 0, // just to try @@ -1060,3 +1059,48 @@ describe('WebDriver', function () { }); }); }); + +describe('WebDriver - Basic Authentication', () => { + before(() => { + global.codecept_dir = path.join(__dirname, '/../data'); + try { + fs.unlinkSync(dataFile); + } catch (err) { + // continue regardless of error + } + + wd = new WebDriver({ + url: siteUrl, + basicAuth: { username: 'postman', password: 'password' }, + browser: 'chrome', + windowSize: '500x700', + remoteFileUpload: true, + smartWait: 0, // just to try + host: TestHelper.seleniumHost(), + port: TestHelper.seleniumPort(), + waitForTimeout: 5000, + capabilities: { + chromeOptions: { + args: ['--headless', '--disable-gpu', '--window-size=1280,1024'], + }, + }, + }); + }); + + beforeEach(() => { + webApiTests.init({ I: wd, siteUrl }); + return wd._before(); + }); + + afterEach(() => wd._after()); + + // load common test suite + webApiTests.tests(); + + describe('open page : #amOnPage', () => { + it('should be authenticated', async () => { + await wd.amOnPage('https://postman-echo.com/basic-auth'); + await wd.see('{"authenticated":true}'); + }); + }); +}); From 7261158e8c44955b017b88c6c4d0bb44cfe6bc49 Mon Sep 17 00:00:00 2001 From: PeterNgTr Date: Tue, 15 Oct 2019 16:09:46 +0200 Subject: [PATCH 6/9] fix tests --- test/helper/WebDriver_test.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/helper/WebDriver_test.js b/test/helper/WebDriver_test.js index cd198a849..d1b6c3beb 100644 --- a/test/helper/WebDriver_test.js +++ b/test/helper/WebDriver_test.js @@ -67,11 +67,6 @@ describe('WebDriver', function () { const url = await wd.grabCurrentUrl(); url.should.eql(`${siteUrl}/`); }); - - it('should be authenticated', async () => { - await wd.amOnPage('https://postman-echo.com/basic-auth'); - await wd.see('{"authenticated":true}'); - }); }); describe('see text : #see', () => { From f6ddab99994aa9bfa261635572fa0ac96ff76006 Mon Sep 17 00:00:00 2001 From: PeterNgTr Date: Tue, 15 Oct 2019 16:45:41 +0200 Subject: [PATCH 7/9] remove loading more commom tests --- test/helper/WebDriver_test.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/helper/WebDriver_test.js b/test/helper/WebDriver_test.js index d1b6c3beb..b11772b1e 100644 --- a/test/helper/WebDriver_test.js +++ b/test/helper/WebDriver_test.js @@ -1089,9 +1089,6 @@ describe('WebDriver - Basic Authentication', () => { afterEach(() => wd._after()); - // load common test suite - webApiTests.tests(); - describe('open page : #amOnPage', () => { it('should be authenticated', async () => { await wd.amOnPage('https://postman-echo.com/basic-auth'); From 4bd8e85e60a5545cead219d423104d2c7a7a54b1 Mon Sep 17 00:00:00 2001 From: PeterNgTr Date: Tue, 22 Oct 2019 10:45:17 +0200 Subject: [PATCH 8/9] CR fix --- lib/helper/Puppeteer.js | 8 ++++++-- test/helper/Puppeteer_test.js | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/helper/Puppeteer.js b/lib/helper/Puppeteer.js index 2c3f3bfa2..02ac899ee 100644 --- a/lib/helper/Puppeteer.js +++ b/lib/helper/Puppeteer.js @@ -33,6 +33,7 @@ const fsExtra = require('fs-extra'); let puppeteer; let perfTiming; +let isAuthenticated = false; const popupStore = new Popup(); const consoleLogStore = new Console(); @@ -531,8 +532,11 @@ class Puppeteer extends Helper { url = this.options.url + url; } - if (this.config.basicAuth) { - this.page.authenticate(this.config.basicAuth); + if (this.config.basicAuth && (isAuthenticated !== true)) { + if (url.includes(this.options.url)) { + this.page.authenticate(this.config.basicAuth); + isAuthenticated = true; + } } await this.page.goto(url, { waitUntil: this.options.waitForNavigation }); diff --git a/test/helper/Puppeteer_test.js b/test/helper/Puppeteer_test.js index 583c22189..f13c3d343 100644 --- a/test/helper/Puppeteer_test.js +++ b/test/helper/Puppeteer_test.js @@ -19,7 +19,7 @@ describe('Puppeteer - BasicAuth', () => { global.codecept_dir = path.join(__dirname, '/../data'); I = new Puppeteer({ - url: siteUrl, + url: 'https://postman-echo.com', windowSize: '500x700', show: false, waitForTimeout: 5000, @@ -50,7 +50,7 @@ describe('Puppeteer - BasicAuth', () => { describe('open page with provided basic auth', () => { it('should be authenticated ', async () => { - await I.amOnPage('https://postman-echo.com/basic-auth'); + await I.amOnPage('/basic-auth'); await I.see('{"authenticated":true}'); }); }); From 00325c4b57e11c23ade7bc4be51a3be4c8a32e40 Mon Sep 17 00:00:00 2001 From: PeterNgTr Date: Mon, 25 Nov 2019 15:52:43 +0100 Subject: [PATCH 9/9] update tests to use localhost --- lib/helper/WebDriver.js | 6 +++++- test/data/app/controllers.php | 6 ++++++ test/data/app/index.php | 1 + test/data/app/view/basic_auth.php | 11 +++++++++++ test/helper/Puppeteer_test.js | 12 ++++++------ test/helper/WebDriver_test.js | 10 +++++----- 6 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 test/data/app/view/basic_auth.php diff --git a/lib/helper/WebDriver.js b/lib/helper/WebDriver.js index a52fcdae1..5b92dbf35 100644 --- a/lib/helper/WebDriver.js +++ b/lib/helper/WebDriver.js @@ -721,8 +721,12 @@ class WebDriver extends Helper { * */ amOnPage(url) { + let split_url; if (this.config.basicAuth) { - const split_url = url.split('//'); + if (url.startsWith('/')) { + url = this.config.url + url; + } + split_url = url.split('//'); url = `${split_url[0]}//${this.config.basicAuth.username}:${this.config.basicAuth.password}@${split_url[1]}`; } return this.browser.url(url); diff --git a/test/data/app/controllers.php b/test/data/app/controllers.php index c18337f4a..1ef696c7d 100755 --- a/test/data/app/controllers.php +++ b/test/data/app/controllers.php @@ -282,4 +282,10 @@ function GET() readfile($file_url); //Absolute URL exit(); } +} + +class basic_auth { + function GET() { + include __DIR__.'/view/basic_auth.php'; + } } \ No newline at end of file diff --git a/test/data/app/index.php b/test/data/app/index.php index 9053c46a7..f21251dab 100755 --- a/test/data/app/index.php +++ b/test/data/app/index.php @@ -42,6 +42,7 @@ '/dynamic' => 'dynamic', '/timeout' => 'timeout', '/download' => 'download', + '/basic_auth' => 'basic_auth' ); glue::stick($urls); diff --git a/test/data/app/view/basic_auth.php b/test/data/app/view/basic_auth.php new file mode 100644 index 000000000..86ba4f27b --- /dev/null +++ b/test/data/app/view/basic_auth.php @@ -0,0 +1,11 @@ +Hello {$_SERVER['PHP_AUTH_USER']}.

"; + echo "

You entered {$_SERVER['PHP_AUTH_PW']} as your password.

"; +} +?> \ No newline at end of file diff --git a/test/helper/Puppeteer_test.js b/test/helper/Puppeteer_test.js index f13c3d343..3680e5d9a 100644 --- a/test/helper/Puppeteer_test.js +++ b/test/helper/Puppeteer_test.js @@ -19,7 +19,7 @@ describe('Puppeteer - BasicAuth', () => { global.codecept_dir = path.join(__dirname, '/../data'); I = new Puppeteer({ - url: 'https://postman-echo.com', + url: 'http://localhost:8000', windowSize: '500x700', show: false, waitForTimeout: 5000, @@ -28,7 +28,7 @@ describe('Puppeteer - BasicAuth', () => { args: ['--no-sandbox', '--disable-setuid-sandbox'], }, defaultPopupAction: 'accept', - basicAuth: { username: 'postman', password: 'password' }, + basicAuth: { username: 'admin', password: 'admin' }, }); I._init(); return I._beforeSuite(); @@ -50,8 +50,8 @@ describe('Puppeteer - BasicAuth', () => { describe('open page with provided basic auth', () => { it('should be authenticated ', async () => { - await I.amOnPage('/basic-auth'); - await I.see('{"authenticated":true}'); + await I.amOnPage('/basic_auth'); + await I.see('You entered admin as your password.'); }); }); }); @@ -111,8 +111,8 @@ describe('Puppeteer', function () { }); it('should be unauthenticated ', async () => { - await I.amOnPage('https://postman-echo.com/basic-auth'); - await I.see('Unauthorized'); + await I.amOnPage('/basic_auth'); + await I.dontSee('You entered admin as your password.'); }); }); diff --git a/test/helper/WebDriver_test.js b/test/helper/WebDriver_test.js index b11772b1e..c05580a35 100644 --- a/test/helper/WebDriver_test.js +++ b/test/helper/WebDriver_test.js @@ -1066,7 +1066,7 @@ describe('WebDriver - Basic Authentication', () => { wd = new WebDriver({ url: siteUrl, - basicAuth: { username: 'postman', password: 'password' }, + basicAuth: { username: 'admin', password: 'admin' }, browser: 'chrome', windowSize: '500x700', remoteFileUpload: true, @@ -1082,17 +1082,17 @@ describe('WebDriver - Basic Authentication', () => { }); }); - beforeEach(() => { + beforeEach(async () => { webApiTests.init({ I: wd, siteUrl }); - return wd._before(); + await wd._before(); }); afterEach(() => wd._after()); describe('open page : #amOnPage', () => { it('should be authenticated', async () => { - await wd.amOnPage('https://postman-echo.com/basic-auth'); - await wd.see('{"authenticated":true}'); + await wd.amOnPage('/basic_auth'); + await wd.see('You entered admin as your password.'); }); }); });