diff --git a/lib/helper/Puppeteer.js b/lib/helper/Puppeteer.js index ecd70cf69..1630d8ed5 100644 --- a/lib/helper/Puppeteer.js +++ b/lib/helper/Puppeteer.js @@ -36,6 +36,7 @@ const findReact = require('./extras/React'); let puppeteer; let perfTiming; +let isAuthenticated = false; const popupStore = new Popup(); const consoleLogStore = new Console(); @@ -53,6 +54,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: '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. @@ -130,6 +132,22 @@ const consoleLogStore = new Console(); * } * ``` * +* #### Example #5: Target URL with provided basic authentication + * + * ```js + * { + * helpers: { + * Puppeteer : { + * url: 'http://localhost', + * basicAuth: {username: 'username', password: 'password'}, + * show: true + * } + * } + * } + * ``` + * + * + * * Note: When connecting to remote browser `show` and specific `chrome` options (e.g. `headless` or `devtools`) are ignored. * * ## Access From Helpers @@ -524,6 +542,14 @@ class Puppeteer extends Helper { if (!(/^\w+\:\/\//.test(url))) { url = this.options.url + url; } + + 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 }); const performanceTiming = JSON.parse(await this.page.evaluate(() => JSON.stringify(window.performance.timing))); diff --git a/lib/helper/WebDriver.js b/lib/helper/WebDriver.js index cf2b7ef31..edaf49fb5 100644 --- a/lib/helper/WebDriver.js +++ b/lib/helper/WebDriver.js @@ -41,6 +41,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. @@ -80,6 +81,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). * @@ -703,6 +723,14 @@ class WebDriver extends Helper { * */ amOnPage(url) { + let split_url; + if (this.config.basicAuth) { + 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 1cb40304c..1d6773023 100644 --- a/test/helper/Puppeteer_test.js +++ b/test/helper/Puppeteer_test.js @@ -1,10 +1,12 @@ const assert = require('assert'); const expect = require('chai').expect; const path = require('path'); + const puppeteer = require('puppeteer'); const TestHelper = require('../support/TestHelper'); const Puppeteer = require('../../lib/helper/Puppeteer'); + const AssertionFailedError = require('../../lib/assert/error'); const webApiTests = require('./webapi'); const FileSystem = require('../../lib/helper/FileSystem'); @@ -15,6 +17,48 @@ let page; let FS; const siteUrl = TestHelper.siteUrl(); +describe('Puppeteer - BasicAuth', () => { + before(() => { + global.codecept_dir = path.join(__dirname, '/../data'); + + I = new Puppeteer({ + url: 'http://localhost:8000', + windowSize: '500x700', + show: false, + waitForTimeout: 5000, + waitForAction: 500, + chrome: { + args: ['--no-sandbox', '--disable-setuid-sandbox'], + }, + defaultPopupAction: 'accept', + basicAuth: { username: 'admin', password: 'admin' }, + }); + 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('should be authenticated ', async () => { + await I.amOnPage('/basic_auth'); + await I.see('You entered admin as your password.'); + }); + }); +}); + describe('Puppeteer', function () { this.timeout(35000); this.retries(1); @@ -81,6 +125,11 @@ describe('Puppeteer', function () { const url = await page.url(); return url.should.eql(`${siteUrl}/`); }); + + it('should be unauthenticated ', async () => { + await I.amOnPage('/basic_auth'); + await I.dontSee('You entered admin as your password.'); + }); }); describe('grabDataFromPerformanceTiming', () => { diff --git a/test/helper/WebDriver_test.js b/test/helper/WebDriver_test.js index 69caee85a..80981de3a 100644 --- a/test/helper/WebDriver_test.js +++ b/test/helper/WebDriver_test.js @@ -1140,3 +1140,45 @@ 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: 'admin', password: 'admin' }, + 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(async () => { + webApiTests.init({ I: wd, siteUrl }); + await wd._before(); + }); + + afterEach(() => wd._after()); + + describe('open page : #amOnPage', () => { + it('should be authenticated', async () => { + await wd.amOnPage('/basic_auth'); + await wd.see('You entered admin as your password.'); + }); + }); +});