From 38b6b6caa0de98e99b6db84142a6595771de3539 Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Wed, 7 Oct 2015 16:20:35 -0700 Subject: [PATCH 01/11] First working version --- examples/hello/.babelrc | 3 ++ examples/hello/package.json | 4 +++ examples/hello/server.js | 8 ++++++ examples/hello/test/hello-world.js | 13 +++++++++ lib/browser.js | 28 +++++++++++++++++++ lib/testium-driver-sync.js | 45 ++++++++++++++++++++++++++++++ package.json | 13 +++++++-- 7 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 examples/hello/.babelrc create mode 100644 examples/hello/package.json create mode 100644 examples/hello/server.js create mode 100644 examples/hello/test/hello-world.js create mode 100644 lib/browser.js diff --git a/examples/hello/.babelrc b/examples/hello/.babelrc new file mode 100644 index 0000000..b25ec8f --- /dev/null +++ b/examples/hello/.babelrc @@ -0,0 +1,3 @@ +{ + "only": "test/*.js" +} diff --git a/examples/hello/package.json b/examples/hello/package.json new file mode 100644 index 0000000..b4625d1 --- /dev/null +++ b/examples/hello/package.json @@ -0,0 +1,4 @@ +{ + "name": "testium-driver-sync.example", + "version": "0.0.0" +} diff --git a/examples/hello/server.js b/examples/hello/server.js new file mode 100644 index 0000000..10ac113 --- /dev/null +++ b/examples/hello/server.js @@ -0,0 +1,8 @@ +'use strict'; + +var http = require('http'); + +http.createServer(function(req, res) { + console.log('GET ', req.url); + res.end('ok'); +}).listen(process.env.PORT || 3000); diff --git a/examples/hello/test/hello-world.js b/examples/hello/test/hello-world.js new file mode 100644 index 0000000..119a8da --- /dev/null +++ b/examples/hello/test/hello-world.js @@ -0,0 +1,13 @@ +'use strict'; + +import {test} from 'babel-tap'; +import initTestium from 'testium-core'; + +import createDriver from '../../..'; + +test('Load example page', async t => { + const { browser } = await initTestium().then(createDriver); + + browser.navigateTo('/ok'); + t.equal(browser.getPageTitle(), 'ok', 'has the correct title'); +}); diff --git a/lib/browser.js b/lib/browser.js new file mode 100644 index 0000000..d3e0f56 --- /dev/null +++ b/lib/browser.js @@ -0,0 +1,28 @@ +'use strict'; + +var debug = require('debug')('testium-driver-sync:browser'); +var _ = require('lodash'); + +function Browser(driver, options) { + this.driver = driver; + + options = options || {}; + this.appUrl = options.appUrl; + this._getNewPageUrl = options.getNewPageUrl; +} +module.exports = Browser; + +Browser.prototype._forwardToDriver = function _forwardToDriver(method) { + this[method] = function _forwarded() { + return this.driver[method].apply(this.driver, arguments); + } +} + +Browser.prototype._forwardToDriver('clearCookies'); +Browser.prototype._forwardToDriver('getPageTitle'); +Browser.prototype._forwardToDriver('setPageSize'); +Browser.prototype._forwardToDriver('getPageSize'); + +Browser.prototype.navigateTo = function(url, options) { + this.driver.navigateTo(this._getNewPageUrl(url, options)); +}; diff --git a/lib/testium-driver-sync.js b/lib/testium-driver-sync.js index ad9a93a..df28e37 100644 --- a/lib/testium-driver-sync.js +++ b/lib/testium-driver-sync.js @@ -1 +1,46 @@ 'use strict'; + +var WebDriver = require('webdriver-http-sync'); +var debug = require('debug')('testium-driver-sync:browser'); + +var Browser = require('./browser'); + +function createDriver(testium) { + var config = testium.config; + + var seleniumUrl = testium.config.get('selenium.serverUrl'); + var requestOptions = config.get('webdriver.requestOptions', {}); + var desiredCapabilities = config.get('desiredCapabilities'); + + var driver = new WebDriver(seleniumUrl, desiredCapabilities, requestOptions); + + var browser = testium.browser = new Browser(driver, { + appUrl: 'http://127.0.0.1:' + config.get('app.port'), + getNewPageUrl: testium.getNewPageUrl + }); + + // Default to reasonable size. + // This fixes some phantomjs element size/position reporting. + browser.setPageSize({ height: 768, width: 1024 }); + + var skipPriming = false; + var keepCookies = false; + + if (skipPriming) { + debug('Skipping priming load'); + } else { + driver.navigateTo(testium.getInitialUrl()); + debug('Browser was primed'); + } + + if (keepCookies) { + debug('Keeping cookies around'); + } else { + debug('Clearing cookies for clean state'); + browser.clearCookies(); + } + + return testium; +} + +module.exports = createDriver; diff --git a/package.json b/package.json index 16a58b4..aba28a4 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Sync interface for testium", "main": "lib/testium-driver-sync.js", "scripts": { - "test": "tap 'test/**/*.js'" + "test": "cd examples/hello && babel-tap 'test/**/*.js'" }, "repository": { "type": "git", @@ -21,5 +21,14 @@ "bugs": { "url": "https://github.com/testiumjs/testium-driver-sync/issues" }, - "homepage": "https://github.com/testiumjs/testium-driver-sync#readme" + "homepage": "https://github.com/testiumjs/testium-driver-sync#readme", + "devDependencies": { + "babel-tap": "^3.0.1", + "testium-core": "^1.1.0" + }, + "dependencies": { + "debug": "^2.2.0", + "lodash": "^3.10.1", + "webdriver-http-sync": "^1.2.1" + } } From bcd56285b9d7e89bba5c2bc42f5004a13267a9e4 Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Mon, 12 Oct 2015 14:59:01 -0700 Subject: [PATCH 02/11] WIP - Porting testium test suite --- .babelrc | 3 + .testiumrc | 6 + examples/hello/.babelrc | 3 - examples/hello/package.json | 4 - examples/hello/server.js | 8 - examples/hello/test/hello-world.js | 13 - .../public/blackholed-resource.html | 28 ++ .../testium-example-app/public/dynamic.html | 27 ++ .../testium-example-app/public/frame.html | 20 ++ .../public/index-diff.html | 43 +++ .../testium-example-app/public/index.html | 79 ++++++ .../public/other-page.html | 7 + .../testium-example-app/public/popup.html | 19 ++ .../public/redirect-after.html | 5 + .../public/redirect-to-query.html | 5 + .../testium-example-app/public/windows.html | 18 ++ examples/testium-example-app/server.js | 83 ++++++ lib/assert/element.js | 176 ++++++++++++ lib/assert/index.js | 18 ++ lib/assert/navigation.js | 9 + lib/browser.js | 28 -- lib/browser/cookie.js | 59 ++++ lib/browser/element.js | 125 +++++++++ lib/browser/index.js | 56 ++++ lib/browser/makeUrlRegExp.js | 49 ++++ lib/browser/navigation.js | 41 +++ lib/browser/page.js | 9 + lib/browser/wait.js | 41 +++ lib/testium-driver-sync.js | 2 + package.json | 10 +- test/integration/assert/imgLoaded.test.coffee | 37 +++ test/integration/element.test.js | 262 ++++++++++++++++++ test/integration/evaluate.test.js | 24 ++ test/integration/navigation.test.js | 121 ++++++++ test/integration/proxy.test.js | 50 ++++ test/log/application.log | 1 + test/log/phantomjs.log | 129 +++++++++ test/log/proxy.log | 60 ++++ test/mini-testium-mocha.js | 14 + test/mocha.opts | 2 + 40 files changed, 1635 insertions(+), 59 deletions(-) create mode 100644 .babelrc create mode 100644 .testiumrc delete mode 100644 examples/hello/.babelrc delete mode 100644 examples/hello/package.json delete mode 100644 examples/hello/server.js delete mode 100644 examples/hello/test/hello-world.js create mode 100644 examples/testium-example-app/public/blackholed-resource.html create mode 100644 examples/testium-example-app/public/dynamic.html create mode 100644 examples/testium-example-app/public/frame.html create mode 100644 examples/testium-example-app/public/index-diff.html create mode 100644 examples/testium-example-app/public/index.html create mode 100644 examples/testium-example-app/public/other-page.html create mode 100644 examples/testium-example-app/public/popup.html create mode 100644 examples/testium-example-app/public/redirect-after.html create mode 100644 examples/testium-example-app/public/redirect-to-query.html create mode 100644 examples/testium-example-app/public/windows.html create mode 100644 examples/testium-example-app/server.js create mode 100644 lib/assert/element.js create mode 100644 lib/assert/index.js create mode 100644 lib/assert/navigation.js delete mode 100644 lib/browser.js create mode 100644 lib/browser/cookie.js create mode 100644 lib/browser/element.js create mode 100644 lib/browser/index.js create mode 100644 lib/browser/makeUrlRegExp.js create mode 100644 lib/browser/navigation.js create mode 100644 lib/browser/page.js create mode 100644 lib/browser/wait.js create mode 100644 test/integration/assert/imgLoaded.test.coffee create mode 100644 test/integration/element.test.js create mode 100644 test/integration/evaluate.test.js create mode 100644 test/integration/navigation.test.js create mode 100644 test/integration/proxy.test.js create mode 100644 test/log/application.log create mode 100644 test/log/phantomjs.log create mode 100644 test/log/proxy.log create mode 100644 test/mini-testium-mocha.js create mode 100644 test/mocha.opts diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..50f2ab3 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "only": "test" +} diff --git a/.testiumrc b/.testiumrc new file mode 100644 index 0000000..ce5a357 --- /dev/null +++ b/.testiumrc @@ -0,0 +1,6 @@ +{ + "launch": true, + "app": { + "command": "node examples/testium-example-app/server.js" + } +} diff --git a/examples/hello/.babelrc b/examples/hello/.babelrc deleted file mode 100644 index b25ec8f..0000000 --- a/examples/hello/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "only": "test/*.js" -} diff --git a/examples/hello/package.json b/examples/hello/package.json deleted file mode 100644 index b4625d1..0000000 --- a/examples/hello/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "testium-driver-sync.example", - "version": "0.0.0" -} diff --git a/examples/hello/server.js b/examples/hello/server.js deleted file mode 100644 index 10ac113..0000000 --- a/examples/hello/server.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -var http = require('http'); - -http.createServer(function(req, res) { - console.log('GET ', req.url); - res.end('ok'); -}).listen(process.env.PORT || 3000); diff --git a/examples/hello/test/hello-world.js b/examples/hello/test/hello-world.js deleted file mode 100644 index 119a8da..0000000 --- a/examples/hello/test/hello-world.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -import {test} from 'babel-tap'; -import initTestium from 'testium-core'; - -import createDriver from '../../..'; - -test('Load example page', async t => { - const { browser } = await initTestium().then(createDriver); - - browser.navigateTo('/ok'); - t.equal(browser.getPageTitle(), 'ok', 'has the correct title'); -}); diff --git a/examples/testium-example-app/public/blackholed-resource.html b/examples/testium-example-app/public/blackholed-resource.html new file mode 100644 index 0000000..400fb75 --- /dev/null +++ b/examples/testium-example-app/public/blackholed-resource.html @@ -0,0 +1,28 @@ + + + + Test Title + + + + + + diff --git a/examples/testium-example-app/public/dynamic.html b/examples/testium-example-app/public/dynamic.html new file mode 100644 index 0000000..3362011 --- /dev/null +++ b/examples/testium-example-app/public/dynamic.html @@ -0,0 +1,27 @@ + + + + +
This just in!
+
This in never!
+
For a limitted time!
+
Here forever!
+ + diff --git a/examples/testium-example-app/public/frame.html b/examples/testium-example-app/public/frame.html new file mode 100644 index 0000000..4c61d1a --- /dev/null +++ b/examples/testium-example-app/public/frame.html @@ -0,0 +1,20 @@ + + + + Some IFrame + + + + +
+ iframe content! +
+ + +
+ + + + diff --git a/examples/testium-example-app/public/index-diff.html b/examples/testium-example-app/public/index-diff.html new file mode 100644 index 0000000..313d9ea --- /dev/null +++ b/examples/testium-example-app/public/index-diff.html @@ -0,0 +1,43 @@ + + + + Test Title + + + +

Test Page!

+ Go to other page! + +
+ +
Message 1
+
Message 2
+
Message 3
+
only one here
+ a transparent pixel + a non-existent image + a non-sourced image + +
+ + + + +
+ + + +
This and everything below should be PURPLE!
+ + Alert + Confirm + Prompt + Clear +
+
+ + + + diff --git a/examples/testium-example-app/public/index.html b/examples/testium-example-app/public/index.html new file mode 100644 index 0000000..9c79b14 --- /dev/null +++ b/examples/testium-example-app/public/index.html @@ -0,0 +1,79 @@ + + + + Test Title + + + + +

Test Page!

+ Go to other page! + +
+ +
Message 1
+
Message 2
+
Message 3
+
only one here
+ a transparent pixel + a non-existent image + a non-sourced image + +
+ + + + +
+ + + + Alert + Confirm + Prompt + Clear +
+
+ + + + diff --git a/examples/testium-example-app/public/other-page.html b/examples/testium-example-app/public/other-page.html new file mode 100644 index 0000000..187cc9a --- /dev/null +++ b/examples/testium-example-app/public/other-page.html @@ -0,0 +1,7 @@ + + + + + h1 Other Page! + + diff --git a/examples/testium-example-app/public/popup.html b/examples/testium-example-app/public/popup.html new file mode 100644 index 0000000..33dfa02 --- /dev/null +++ b/examples/testium-example-app/public/popup.html @@ -0,0 +1,19 @@ + + + + Popup! + + + + + + + + + + diff --git a/examples/testium-example-app/public/redirect-after.html b/examples/testium-example-app/public/redirect-after.html new file mode 100644 index 0000000..d061589 --- /dev/null +++ b/examples/testium-example-app/public/redirect-after.html @@ -0,0 +1,5 @@ + + + + + diff --git a/examples/testium-example-app/public/redirect-to-query.html b/examples/testium-example-app/public/redirect-to-query.html new file mode 100644 index 0000000..f692593 --- /dev/null +++ b/examples/testium-example-app/public/redirect-to-query.html @@ -0,0 +1,5 @@ + + + + + diff --git a/examples/testium-example-app/public/windows.html b/examples/testium-example-app/public/windows.html new file mode 100644 index 0000000..c0c8f00 --- /dev/null +++ b/examples/testium-example-app/public/windows.html @@ -0,0 +1,18 @@ + + + + Test Title + + + + + + + + + + + diff --git a/examples/testium-example-app/server.js b/examples/testium-example-app/server.js new file mode 100644 index 0000000..fe8c7f6 --- /dev/null +++ b/examples/testium-example-app/server.js @@ -0,0 +1,83 @@ +'use strict'; + +var http = require('http'); + +var StaticServer = require('node-static').Server; + +function echo(request, response) { + var data = { + ip: request.connection.remoteAddress, + method: request.method, + url: request.url, + body: '', + headers: request.headers + }; + + request.on('data', function(buffer) { + data.body += buffer.toString(); + }); + + request.on('end', function() { + var body = JSON.stringify(data, null, 2); + response.setHeader('Content-Type', 'application/json'); + response.end(body); + }); +} + +function error(response) { + response.statusCode = 500; + response.end('500 SERVER ERROR'); +} + +function crash(response) { + response.statusCode = 500; + response.socket.destroy(); +} + +function createServer() { + var file = new StaticServer(__dirname + '/public'); + + return http.createServer(function(request, response) { + switch (request.url) { + case '/echo': + return echo(request, response); + + case '/error': + return error(response); + + case '/crash': + return crash(response); + + case '/blackhole': + return; + } + + var listener = request.addListener('end', function() { + file.serve(request, response); + }); + listener.resume(); + }); +} + +var testApp = module.exports = { + listen: function(port, callback) { + this.server = createServer(); + this.server.listen(port, callback); + }, + + kill: function(callback) { + this.server.close(callback); + this.server = null; + } +}; + +if (module === require.main) { + if (process.env.never_listen) { + console.log('Refusing to listen') + setTimeout(function() {}, 100000); + } else { + testApp.listen(process.env.PORT || 4003, function() { + console.log('Listening on port %j', this.address().port); + }); + } +} \ No newline at end of file diff --git a/lib/assert/element.js b/lib/assert/element.js new file mode 100644 index 0000000..1b5a8de --- /dev/null +++ b/lib/assert/element.js @@ -0,0 +1,176 @@ +'use strict'; + +var util = require('util'); + +var assert = require('assertive'); +var _ = require('lodash'); + +function isTextOrRegexp(textOrRegExp) { + return _.isString(textOrRegExp) || _.isRegExp(textOrRegExp); +} + +exports._getElementWithProperty = function _getElementWithProperty(selector, property) { + var element = this._getElement(selector); + return [ element, element.get(property) ]; +}; + +exports._getElement = function _getElement(selector) { + var elements = this.driver.getElements(selector); + var count = elements.length; + + if (count === 0) { + throw new Error('Element not found for selector: ' + selector); + } + if (count !== 1) { + throw new Error( + 'assertion needs a unique selector!\n' + + selector + ' has ' + count + ' hits in the page'); + } + + return elements[0]; +}; + +exports.elementHasAttributes = function elementHasAttributes(doc, selector, attributesObject) { + if (arguments.length === 2) { + attributesObject = selector; + selector = doc; + doc = [ + 'elementHasAttributes - selector:' + selector, + 'attributesObject:' + JSON.stringify(attributesObject) + ].join('\n'); + } else { + assert.hasType('elementHasAttributes(docstring, selector, attributesObject) - requires String docstring', String, doc); + } + + assert.hasType('elementHasAttributes(selector, attributesObject) - requires String selector', String, selector); + assert.hasType('elementHasAttributes(selector, attributesObject) - requires Object attributesObject', Object, attributesObject); + + var element = this._getElement(selector); + + _.each(attributesObject, function(val, attribute) { + var actualVal = element.get(attribute); + var attrDoc = util.format( + '%s\nattribute %j was expected to be %j but was %j.', + doc, attribute, val, actualVal); + + if (_.isString(val)) { + assert.equal(attrDoc, val, actualVal); + } else { + assert.hasType('elementHasAttributes(selector, attributesObject) - attributesObject requires String or RegExp value', RegExp, val); + assert.match(attrDoc, val, actualVal); + } + }); + + return element; +}; + +exports.elementHasText = function elementHasText(doc, selector, textOrRegExp) { + if (arguments.length === 2) { + textOrRegExp = selector; + selector = doc; + doc = 'elementHasText: ' + selector; + } else { + assert.hasType('elementHasText(docstring, selector, textOrRegExp) - requires docstring', String, doc); + } + + assert.hasType('elementHasText(selector, textOrRegExp) - requires selector', String, selector); + assert.truthy('elementHasText(selector, textOrRegExp) - requires textOrRegExp', isTextOrRegexp(textOrRegExp)); + + var result = this._getElementWithProperty(selector, 'text'); + + if (textOrRegExp === '') { + assert.equal(textOrRegExp, result[1]); + } else { + assert.include(doc, textOrRegExp, result[1]); + } + + return result[0]; +}; + +exports.elementLacksText = function elementLacksText(doc, selector, textOrRegExp) { + if (arguments.length === 2) { + textOrRegExp = selector; + selector = doc; + doc = 'elementLacksText: ' + selector; + } else { + assert.hasType('elementLacksText(docstring, selector, textOrRegExp) - requires docstring', String, doc); + } + + assert.hasType('elementLacksText(selector, textOrRegExp) - requires selector', String, selector); + assert.truthy('elementLacksText(selector, textOrRegExp) - requires textOrRegExp', isTextOrRegexp(textOrRegExp)); + + var result = this._getElementWithProperty(selector, 'text'); + + assert.notInclude(doc, textOrRegExp, result[1]); + return result[0]; +}; + +exports.elementHasValue = function elementHasValue(doc, selector, textOrRegExp) { + if (arguments.length === 2) { + textOrRegExp = selector; + selector = doc; + doc = 'elementHasValue: ' + selector; + } else { + assert.hasType('elementHasValue(docstring, selector, textOrRegExp) - requires docstring', String, doc); + } + + assert.hasType('elementHasValue(selector, textOrRegExp) - requires selector', String, selector); + assert.truthy('elementHasValue(selector, textOrRegExp) - requires textOrRegExp', isTextOrRegexp(textOrRegExp)); + + var result = this._getElementWithProperty(selector, 'value'); + + if (textOrRegExp === '') { + assert.equal(textOrRegExp, result[1]); + } else { + assert.include(doc, textOrRegExp, result[1]); + } + + return result[0]; +}; + +exports.elementLacksValue = function elementLacksValue(doc, selector, textOrRegExp) { + if (arguments.length === 2) { + textOrRegExp = selector; + selector = doc; + doc = 'elementLacksValue: ' + selector; + } else { + assert.hasType('elementLacksValue(docstring, selector, textOrRegExp) - requires docstring', String, doc); + } + + assert.hasType('elementLacksValue(selector, textOrRegExp) - requires selector', String, selector); + assert.truthy('elementLacksValue(selector, textOrRegExp) - requires textOrRegExp', isTextOrRegexp(textOrRegExp)); + + var result = this._getElementWithProperty(selector, 'value'); + + assert.notInclude(doc, textOrRegExp, result[1]); + return result[0]; +}; + +exports.elementIsVisible = function elementIsVisible(selector) { + assert.hasType('elementIsVisible(selector) - requires (String) selector', String, selector); + var element = this.browser.getElementWithoutError(selector); + assert.truthy('Element not found for selector: ' + selector, element); + assert.truthy('Element should be visible for selector: ' + selector, element.isVisible()); + return element; +}; + +exports.elementNotVisible = function elementNotVisible(selector) { + assert.hasType('elementNotVisible(selector) - requires (String) selector', String, selector); + var element = this.browser.getElementWithoutError(selector); + assert.truthy('Element not found for selector: ' + selector, element); + assert.falsey('Element should not be visible for selector: ' + selector, element.isVisible()); + return element; +}; + +exports.elementExists = function elementExists(selector) { + assert.hasType('elementExists(selector) - requires (String) selector', String, selector); + var element = this.browser.getElementWithoutError(selector); + assert.truthy('Element not found for selector: ' + selector, element); + return element; +}; + +exports.elementDoesntExist = function elementDoesntExist(selector) { + assert.hasType('elementDoesntExist(selector) - requires (String) selector', String, selector); + var element = this.browser.getElementWithoutError(selector); + assert.falsey('Element found for selector: ' + selector, element); +}; diff --git a/lib/assert/index.js b/lib/assert/index.js new file mode 100644 index 0000000..bc52b95 --- /dev/null +++ b/lib/assert/index.js @@ -0,0 +1,18 @@ +'use strict'; + +var _ = require('lodash'); + +function Assertions(driver, browser) { + this.driver = driver; + this.browser = browser; +} + +_.each([ + require('./element'), + // require('./imgLoaded'), + require('./navigation') +], function(mixin) { + _.extend(Assertions.prototype, mixin); +}); + +module.exports = Assertions; diff --git a/lib/assert/navigation.js b/lib/assert/navigation.js new file mode 100644 index 0000000..6b09225 --- /dev/null +++ b/lib/assert/navigation.js @@ -0,0 +1,9 @@ +'use strict'; + +var assert = require('assertive'); + +exports.httpStatus = function httpStatus(expectedStatus) { + assert.hasType('assert.httpStatus(status) - requires (Number) status', Number, expectedStatus); + var actualStatus = this.browser.getStatusCode(); + assert.equal('statuscode', expectedStatus, actualStatus); +}; diff --git a/lib/browser.js b/lib/browser.js deleted file mode 100644 index d3e0f56..0000000 --- a/lib/browser.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; - -var debug = require('debug')('testium-driver-sync:browser'); -var _ = require('lodash'); - -function Browser(driver, options) { - this.driver = driver; - - options = options || {}; - this.appUrl = options.appUrl; - this._getNewPageUrl = options.getNewPageUrl; -} -module.exports = Browser; - -Browser.prototype._forwardToDriver = function _forwardToDriver(method) { - this[method] = function _forwarded() { - return this.driver[method].apply(this.driver, arguments); - } -} - -Browser.prototype._forwardToDriver('clearCookies'); -Browser.prototype._forwardToDriver('getPageTitle'); -Browser.prototype._forwardToDriver('setPageSize'); -Browser.prototype._forwardToDriver('getPageSize'); - -Browser.prototype.navigateTo = function(url, options) { - this.driver.navigateTo(this._getNewPageUrl(url, options)); -}; diff --git a/lib/browser/cookie.js b/lib/browser/cookie.js new file mode 100644 index 0000000..8badd5c --- /dev/null +++ b/lib/browser/cookie.js @@ -0,0 +1,59 @@ +'use strict'; + +var _ = require('lodash'); +var assert = require('assertive'); + +var getTestiumCookie = require('testium-cookie').getTestiumCookie; + +exports._forwarded = [ + // TODO: Port validateCookie to webdriver-http-sync + 'setCookie', + 'clearCookies' +]; + +exports.setCookies = function(cookies) { + _.each(cookies, this.setCookie, this); + return this; +} + +exports.getCookie = function getCookie(name) { + assert.hasType('getCookie(name) - requires (String) name', String, name); + + var cookies = this.driver.getCookies(); + return _.find(cookies, { name: name }); +}; + +exports.getCookies = function getCookies() { + return _.reject(this.driver.getCookies(), { name: '_testium_' }); +}; + +exports.clearCookie = function clearCookie(name) { + return this.setCookie({ + name: name, + value: 'dummy', // setCookie doesn't allow null values + expiry: 0 + }); +}; + +// BEGIN _testium_ cookie magic + +exports._getTestiumCookieField = function _getTestiumCookieField(name) { + var cookies = this.driver.getCookies(); + var testiumCookie = getTestiumCookie(cookies); + return testiumCookie[name]; +}; + +exports.getStatusCode = function getStatusCode() { + return this._getTestiumCookieField('statusCode'); +}; + +exports.getHeaders = function getHeaders() { + return this._getTestiumCookieField('headers'); +}; + +exports.getHeader = function getHeader(name) { + assert.hasType('getHeader(name) - require (String) name', String, name); + return this.getHeaders()[name]; +}; + +// END _testium_ cookie magic diff --git a/lib/browser/element.js b/lib/browser/element.js new file mode 100644 index 0000000..ab69938 --- /dev/null +++ b/lib/browser/element.js @@ -0,0 +1,125 @@ +'use strict'; + +var util = require('util'); + +var assert = require('assertive'); +var _ = require('lodash'); + +var STALE_MESSAGE = /stale element reference/; + +var NOT_FOUND_MESSAGE = new RegExp([ + 'Unable to locate element', // firefox message + 'Unable to find element', // phantomjs message + 'no such element', // chrome message +].join('|')); + +function visiblePredicate(shouldBeVisible, element) { + return element && element.isVisible() === shouldBeVisible; +} + +function visibleFailure(shouldBeVisible, selector, timeout) { + throw new Error(util.format('Timeout (%dms) waiting for element (%s) to %sbe visible.', + timeout, selector, shouldBeVisible ? '' : 'not ')); +} + +function elementExistsPredicate(element) { + return !!element; +} + +function elementExistsFailure(selector, timeout) { + throw new Error(util.format('Timeout (%dms) waiting for element (%s) to exist in page.', + timeout, selector)); +} + +// Curry some functions for later use +var isVisiblePredicate = _.partial(visiblePredicate, true); +var isntVisiblePredicate = _.partial(visiblePredicate, false); + +var isVisibleFailure = _.partial(visibleFailure, true); +var isntVisibleFailure = _.partial(visibleFailure, false); + +exports._forwarded = [ + // TODO: port type assertion for selector to webdriver-http-sync + 'getElements' +]; + +exports.getElementWithoutError = function getElementWithoutError(selector) { + // TODO: part typeof selector === string check to webdriver-http-sync + assert.hasType('`selector` as to be a String', String, selector); + try { + return this.driver.getElement(selector); + } catch (exception) { + var message = exception.toString(); + + if (NOT_FOUND_MESSAGE.test(message)) { + return null; + } + + throw exception; + } +}; + +exports.getElement = exports.getElementWithoutError; + +exports.getExistingElement = function getExistingElement(selector) { + var element = this.getElement(selector); + assert.truthy('Element not found at selector: ' + selector, element); + return element; +}; + +exports.waitForElementVisible = function waitForElementVisible(selector, timeout) { + return this._waitForElement(selector, isVisiblePredicate, isVisibleFailure, timeout); +}; + +exports.waitForElementNotVisible = function waitForElementNotVisible(selector, timeout) { + return this._waitForElement(selector, isntVisiblePredicate, isntVisibleFailure, timeout); +} + +exports.waitForElementExist = function waitForElementExist(selector, timeout) { + return this._waitForElement(selector, elementExistsPredicate, elementExistsFailure, timeout); +} + +exports.click = function click(selector) { + return this.getExistingElement(selector).click(); +}; + +function tryFindElement(self, selector, predicate, untilTime) { + var element, predicateResult; + + while (Date.now() < untilTime) { + element = self.getElementWithoutError(selector); + + try { + predicateResult = predicate(element); + } catch (exception) { + // Occasionally webdriver throws an error about the element reference being + // stale. Let's handle that case as the element doesn't yet exist. All + // other errors are re thrown. + if (!STALE_MESSAGE.test(exception.toString())) { + throw exception; + } + } + + if (predicateResult) { + return element; + } + } + return null; +} + +// Where predicate takes a single parameter which is an element (or null) and +// returns true when the wait is over +exports._waitForElement = function _waitForElement(selector, predicate, failure, timeout) { + assert.hasType('`selector` as to be a String', String, selector); + timeout = timeout || 3000; + + this.driver.setElementTimeout(timeout); + var foundElement = tryFindElement(this, selector, predicate, Date.now() + timeout); + this.driver.setElementTimeout(0); + + if (foundElement === null) { + return failure(selector, timeout); + } + + return foundElement; +}; diff --git a/lib/browser/index.js b/lib/browser/index.js new file mode 100644 index 0000000..e0cdea0 --- /dev/null +++ b/lib/browser/index.js @@ -0,0 +1,56 @@ +'use strict'; + +var _ = require('lodash'); +var assert = require('assertive'); + +var builtIns = [ + require('./cookie'), + require('./element'), + require('./navigation'), + require('./page') +]; + +function Browser(driver, options) { + this.driver = driver; + + options = options || {}; + this.appUrl = options.appUrl; + this._getNewPageUrl = options.getNewPageUrl; +} +module.exports = Browser; + +Browser.prototype.evaluate = function evaluate() { + var args = _.toArray(arguments); + var clientFunction = args.pop(); + + var invocation = 'evaluate(clientFunction) - requires (Function|String) clientFunction'; + assert.truthy(invocation, clientFunction); + + switch (typeof clientFunction) { + case 'function': + clientFunction = + 'return (' + clientFunction + ').apply(this, ' + JSON.stringify(args) + ');'; + // fall-through + + case 'string': + return this.driver.evaluate(clientFunction); + + default: + throw new Error(invocation); + } +}; + +function forwardToDriver(method) { + Browser.prototype[method] = function() { + return this.driver[method].apply(this.driver, arguments); + }; +} + +function addBuiltIn(builtIn) { + var methods = _.omit(builtIn, '_forwarded'); + if (builtIn._forwarded) { + _.each(builtIn._forwarded, forwardToDriver); + } + _.extend(Browser.prototype, methods); +} +builtIns.forEach(addBuiltIn); diff --git a/lib/browser/makeUrlRegExp.js b/lib/browser/makeUrlRegExp.js new file mode 100644 index 0000000..d79a197 --- /dev/null +++ b/lib/browser/makeUrlRegExp.js @@ -0,0 +1,49 @@ +'use strict'; + +var _ = require('lodash'); + +// TODO: Figure out if there's a non-regex way to achieve the same, +// e.g. by comparing parsed urls. + +function quoteRegExp(string) { + return string.replace(/[-\\\/\[\]{}()*+?.^$|]/g, '\\$&'); +} + +function bothCases(alpha) { + var dn, up; + up = alpha.toUpperCase(); + dn = alpha.toLowerCase(); + return "[" + up + dn + "]"; +} + +var isHexaAlphaRE = /[a-f]/gi; +function matchCharacter(uriEncoded, hex) { + var codepoint = parseInt(hex, 16); + var character = String.fromCharCode(codepoint); + character = quoteRegExp(character); + if (character === ' ') { + character += '|\\+'; + } + return "(?:" + uriEncoded.replace(isHexaAlphaRE, bothCases) + "|" + character + ")"; +} + +var encodedCharRE = /%([0-9a-f]{2})/gi; +function matchURI(stringOrRegExp) { + if (_.isRegExp(stringOrRegExp)) { + return stringOrRegExp.toString().replace(/^\/|\/\w*$/g, ''); + } + + var fullyEncoded = encodeURIComponent(stringOrRegExp); + return quoteRegExp(fullyEncoded).replace(encodedCharRE, matchCharacter); +} + +function makeUrlRegExp(url, query) { + var expr = matchURI(url); + _.each(query || {}, function(val, key) { + key = matchURI(key); + val = matchURI(val); + expr += "(?=(?:\\?|.*&)" + key + "=" + val + ")"; + }); + return new RegExp(expr); +} +module.exports = makeUrlRegExp; diff --git a/lib/browser/navigation.js b/lib/browser/navigation.js new file mode 100644 index 0000000..65c8c30 --- /dev/null +++ b/lib/browser/navigation.js @@ -0,0 +1,41 @@ +'use strict'; + +var Url = require('url'); + +var _ = require('lodash'); +var debug = require('debug')('testium-driver-sync:navigation'); + +var makeUrlRegExp = require('./makeUrlRegExp'); +var waitFor = require('./wait'); + +exports._forwarded = [ + 'refresh', + 'getUrl' +]; + +exports.navigateTo = function navigateTo(url, options) { + var targetUrl = this._getNewPageUrl(url, options); + debug('navigateTo', targetUrl); + this.driver.navigateTo(targetUrl); + + // Save the window handle for referencing later + // in `switchToDefaultWindow` + this.driver.rootWindow = this.driver.getCurrentWindowHandle(); +}; + +exports.getPath = function getPath() { + return Url.parse(this.getUrl()).path; +}; + +exports.waitForUrl = function waitForUrl(url, query, timeout) { + if (typeof query === 'number') { + timeout = query; + } else if (_.isObject(query)) { + url = makeUrlRegExp(url, query); + } + return waitFor(url, 'Url', _.bindKey(this, 'getUrl'), timeout || 5000); +}; + +exports.waitForPath = function waitForPath(path, timeout) { + return waitFor(path, 'Path', _.bindKey(this, 'getPath'), timeout || 5000); +}; diff --git a/lib/browser/page.js b/lib/browser/page.js new file mode 100644 index 0000000..f1981cc --- /dev/null +++ b/lib/browser/page.js @@ -0,0 +1,9 @@ +'use strict'; + +exports._forwarded = [ + 'getPageTitle', + 'getPageSource', + 'getScreenshot', + 'setPageSize', + 'getPageSize' +]; diff --git a/lib/browser/wait.js b/lib/browser/wait.js new file mode 100644 index 0000000..44aa991 --- /dev/null +++ b/lib/browser/wait.js @@ -0,0 +1,41 @@ +'use strict'; + +var util = require('util'); + +var _ = require('lodash'); + +function testEqual(a, b) { return a === b; } + +function matches(stringOrRegex, testUrl) { + return stringOrRegex.test(testUrl); +} + +function createTest(stringOrRegex) { + if (_.isString(stringOrRegex)) { + return _.partial(_.isEqual, stringOrRegex); + } else if (_.isRegExp(stringOrRegex)) { + return _.partial(matches, stringOrRegex); + } else { + throw new Error( + util.format('waitFor%s(urlStringOrRegex) - requires a string or regex param', + waitingFor)); + } +} + +function waitFor(stringOrRegex, waitingFor, getValue, timeout) { + var test = createTest(stringOrRegex); + + var start = Date.now(); + var currentValue; + while ((Date.now() - start) < timeout) { + currentValue = getValue(); + if (test(currentValue)) { + return; + } + } + + throw new Error( + util.format('Timed out (%dms) waiting for %s (%j). Last value was: %j', + timeout, waitingFor.toLowerCase(), stringOrRegex, currentValue)); +} +module.exports = waitFor; diff --git a/lib/testium-driver-sync.js b/lib/testium-driver-sync.js index df28e37..df2a9b2 100644 --- a/lib/testium-driver-sync.js +++ b/lib/testium-driver-sync.js @@ -4,6 +4,7 @@ var WebDriver = require('webdriver-http-sync'); var debug = require('debug')('testium-driver-sync:browser'); var Browser = require('./browser'); +var Assertions = require('./assert'); function createDriver(testium) { var config = testium.config; @@ -18,6 +19,7 @@ function createDriver(testium) { appUrl: 'http://127.0.0.1:' + config.get('app.port'), getNewPageUrl: testium.getNewPageUrl }); + browser.assert = new Assertions(driver, browser); // Default to reasonable size. // This fixes some phantomjs element size/position reporting. diff --git a/package.json b/package.json index aba28a4..65e3ee7 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Sync interface for testium", "main": "lib/testium-driver-sync.js", "scripts": { - "test": "cd examples/hello && babel-tap 'test/**/*.js'" + "test": "mocha" }, "repository": { "type": "git", @@ -23,12 +23,16 @@ }, "homepage": "https://github.com/testiumjs/testium-driver-sync#readme", "devDependencies": { - "babel-tap": "^3.0.1", - "testium-core": "^1.1.0" + "babel-core": "^5.8.25", + "mocha": "^2.3.3", + "node-static": "~0.7.7", + "testium-core": "^1.1.2" }, "dependencies": { + "assertive": "^2.0.2", "debug": "^2.2.0", "lodash": "^3.10.1", + "testium-cookie": "^1.0.0", "webdriver-http-sync": "^1.2.1" } } diff --git a/test/integration/assert/imgLoaded.test.coffee b/test/integration/assert/imgLoaded.test.coffee new file mode 100644 index 0000000..6a9efbe --- /dev/null +++ b/test/integration/assert/imgLoaded.test.coffee @@ -0,0 +1,37 @@ +injectBrowser = require '../../../mocha' +assert = require 'assertive' + +describe 'imgLoaded', -> + before injectBrowser() + + before -> + @browser.navigateTo '/' + + it 'throws an error when the image was not found', -> + msg = 'imgLoaded "img.not-in-the-page": element not found' + err = assert.throws => @browser.assert.imgLoaded 'img.not-in-the-page' + assert.include msg, err.message + + it 'throws an error for non-unique selectors when finding multiple images', -> + msg = 'imgLoaded "img[alt][class]": non-unique selector; count: 3' + err = assert.throws => @browser.assert.imgLoaded 'img[alt][class]' + assert.include msg, err.message + + it 'throws an error for an image not successfully loaded / decoded', -> + msg = 'imgLoaded "img.fail": failed to load ' + err = assert.throws => @browser.assert.imgLoaded 'img.fail' + assert.include msg, err.message + assert.include '/non-existent-image.jpg', err.message + + it 'throws a helpful error for an missing the src attribute', -> + msg = 'imgLoaded "#no": failed to load src-less img#no.src.dude' + err = assert.throws => @browser.assert.imgLoaded '#no' + assert.include msg, err.message + + it 'throws a helpful error when the selector did not match an tag', -> + msg = 'imgLoaded "body": failed to load non-image body' + err = assert.throws => @browser.assert.imgLoaded 'body' + assert.include msg, err.message + + it 'does nothing when the image was successfully loaded and decoded', -> + @browser.assert.imgLoaded 'img.okay' diff --git a/test/integration/element.test.js b/test/integration/element.test.js new file mode 100644 index 0000000..a494422 --- /dev/null +++ b/test/integration/element.test.js @@ -0,0 +1,262 @@ +'use strict'; + +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('element', () => { + let browser; + before(async () => (browser = await getBrowser())); + + before(() => browser.navigateTo('/')); + + it('can get an element\'s text', () => { + var element = browser.getElement('h1'); + var text = element.get('text'); + assert.equal('Element text was not found', 'Test Page!', text); + }); + + it('can get special properties from an element', () => { + // the "checked" property (when it doesn't exist) + // returns a non-standard response from selenium; + // let's make sure we can handle it properly + var element = browser.getElement('#checkbox'); + var checked = element.get('checked'); + assert.equal('checked is null', null, checked); + }); + + it('returns null when the element can not be found', () => { + var element = browser.getElement('.non-existing'); + assert.equal('Element magically appeared on the page', null, element); + }); + + it('can get several elements', () => { + var elements = browser.getElements('.message'); + assert.equal('Messages were not all found', 3, elements.length); + }); + + describe('elementIsVisible', () => { + it('fails if element does not exist', () => { + var error = assert.throws(() => browser.assert.elementIsVisible('.non-existing')); + var expectedError = 'Assertion failed: Element not found for selector: .non-existing\n\u001b[39;49;00mExpected \u001b[31mnull\u001b[39m to be truthy'; + assert.equal(expectedError, error.message); + }); + + it('fails if element exists, but is not visible', () => { + var error = assert.throws(() => browser.assert.elementIsVisible('#hidden_thing')); + var expectedError = 'Assertion failed: Element should be visible for selector: #hidden_thing\n\u001b[39;49;00mExpected \u001b[31mfalse\u001b[39m to be truthy'; + assert.equal(expectedError, error.message); + }); + + it('succeeds if element exists and is visible', () => { + browser.assert.elementIsVisible('h1'); + }); + }); + + describe('elementNotVisible', () => { + it('fails if element does not exist', () => { + var error = assert.throws(() => browser.assert.elementNotVisible('.non-existing')); + var expectedError = 'Assertion failed: Element not found for selector: .non-existing\n\u001b[39;49;00mExpected \u001b[31mnull\u001b[39m to be truthy'; + assert.equal(expectedError, error.message); + }); + + it('fails if element exists, but is visible', () => { + var error = assert.throws(() => browser.assert.elementNotVisible('h1')); + var expectedError = 'Assertion failed: Element should not be visible for selector: h1\n\u001b[39;49;00mExpected \u001b[31mtrue\u001b[39m to be falsey'; + assert.equal(expectedError, error.message); + }); + + it('succeeds if element exists and is not visible', () => { + browser.assert.elementNotVisible('#hidden_thing'); + }); + }); + + describe('elementExists', () => { + it('fails if element does not exist', () => { + var error = assert.throws(() => browser.assert.elementExists('.non-existing')); + var expectedError = 'Assertion failed: Element not found for selector: .non-existing\n\u001b[39;49;00mExpected \u001b[31mnull\u001b[39m to be truthy'; + assert.equal(expectedError, error.message); + }); + + it('succeeds if element exists', () => { + browser.assert.elementExists('h1'); + }); + }); + + describe('elementDoesntExist', () => { + it('succeeds if element does not exist', () => { + browser.assert.elementDoesntExist('.non-existing'); + }); + + it('fails if element exists', () => { + var error = assert.throws(() => browser.assert.elementDoesntExist('h1')); + var expectedError = 'Assertion failed: Element found for selector: h1\n\u001b[39;49;00mExpected \u001b[31mElement\u001b[39m to be falsey'; + assert.equal(expectedError, error.message); + }); + }); + + describe('elementHasText', () => { + it('finds and returns a single element', () => { + var element = browser.assert.elementHasText('.only', 'only one here'); + assert.equal('resolve the element\'s class', 'only', element.get('class')); + }); + + it('finds an element with the wrong text', () => { + var error = assert.throws(() => + browser.assert.elementHasText('.only', 'the wrong text')); + + var expected = 'Assertion failed: elementHasText: .only\n\u001b[39;49;00minclude expected needle to be found in haystack\n- needle: \"the wrong text\"\nhaystack: \"only one here\"'; + assert.equal(expected, error.message); + }); + + it('finds no elements', () => { + var error = assert.throws(() => + browser.assert.elementHasText('.does-not-exist', 'some text')); + + assert.equal('Element not found for selector: .does-not-exist', error.message); + }); + + it('finds many elements', () => { + var error = assert.throws(() => + browser.assert.elementHasText('.message', 'some text')); + + assert.equal('assertion needs a unique selector!\n.message has 3 hits in the page', error.message); + }); + + it('succeeds with empty string', () => { + browser.assert.elementHasText('#blank-input', ''); + }); + }); + + describe('elementLacksText', () => { + it('asserts an element lacks some text, and returns the element', () => { + var element = browser.assert.elementLacksText('.only', 'this text not present'); + assert.equal('resolve the element\'s class', 'only', element.get('class')); + }); + + it('finds an element incorrectly having some text', () => { + var error = assert.throws(() => + browser.assert.elementLacksText('.only', 'only')); + + var expected = 'Assertion failed: elementLacksText: .only\n\u001b[39;49;00mnotInclude expected needle not to be found in haystack\n- needle: \"only\"\nhaystack: \"only one here\"'; + assert.equal(expected, error.message); + }); + }); + + describe('elementHasValue', () => { + it('finds and returns a single element', () => { + var element = browser.assert.elementHasValue('#text-input', 'initialvalue'); + assert.equal('resolve the element\'s id', 'text-input', element.get('id')); + }); + + it('succeeds with empty string', () => { + browser.assert.elementHasValue('#blank-input', ''); + }); + }); + + describe('elementLacksValue', () => { + it('asserts an element lacks some value, and returns the element', () => { + var element = browser.assert.elementLacksValue('#text-input', 'this text not present'); + assert.equal('resolve the element\'s id', 'text-input', element.get('id')); + }); + + it('finds an element incorrectly having some text', () => { + var error = assert.throws(() => + browser.assert.elementLacksValue('#text-input', 'initialvalue')); + + var expected = 'Assertion failed: elementLacksValue: #text-input\n\u001b[39;49;00mnotInclude expected needle not to be found in haystack\n- needle: \"initialvalue\"\nhaystack: \"initialvalue\"'; + assert.equal(expected, error.message); + }); + }); + + describe('waitForElementExist', () => { + before(() => browser.navigateTo('/dynamic.html')); + + it('finds an element after waiting', () => { + browser.assert.elementNotVisible('.load_later'); + browser.waitForElementExist('.load_later'); + }); + + it('finds a hidden element', () => { + browser.assert.elementNotVisible('.load_never'); + browser.waitForElementExist('.load_never'); + }); + + it('fails to find an element that never exists', () => { + var error = assert.throws(() => + browser.waitForElementExist('.does-not-exist', 10)); + assert.equal('Timeout (10ms) waiting for element (.does-not-exist) to exist in page.', error.message); + }); + }); + + describe('waitForElementVisible', () => { + before(() => browser.navigateTo('/dynamic.html')); + + it('finds an element after waiting', () => { + browser.assert.elementNotVisible('.load_later'); + browser.waitForElementVisible('.load_later'); + }); + + it('fails to find a visible element within the timeout', () => { + var error = assert.throws(() => + browser.waitForElementVisible('.load_never', 10)); + assert.equal('Timeout (10ms) waiting for element (.load_never) to be visible.', error.message); + }); + + it('fails to find an element that never exists', () => { + var error = assert.throws(() => + browser.waitForElementVisible('.does-not-exist', 10)); + assert.equal('Timeout (10ms) waiting for element (.does-not-exist) to be visible.', error.message); + }); + }); + + describe('waitForElementNotVisible', () => { + before(() => browser.navigateTo('/dynamic.html')); + + it('does not find an existing element after waiting for it to disappear', () => { + browser.assert.elementIsVisible('.hide_later'); + browser.waitForElementNotVisible('.hide_later'); + }); + + it('fails to find a not-visible element within the timeout', () => { + var error = assert.throws(() => + browser.waitForElementNotVisible('.hide_never', 10)); + assert.equal('Timeout (10ms) waiting for element (.hide_never) to not be visible.', error.message); + }); + + it('fails to find an element that never exists', () => { + var error = assert.throws(() => + browser.waitForElementNotVisible('.does-not-exist', 10)); + assert.equal('Timeout (10ms) waiting for element (.does-not-exist) to not be visible.', error.message); + }); + }); + + describe('#getElement', () => { + before(() => browser.navigateTo('/')); + + it('succeeds if selector is a String', () => { + var element = browser.getElement('body'); + element.getElement('.message'); + }); + + it('return null if not found an element on the message element', () => { + var messageElement = browser.getElement('.message'); + var element = messageElement.getElement('.message'); + assert.falsey(element); + }); + }); + + describe('#getElements', () => { + before(() => browser.navigateTo('/')); + + it('succeeds if selector is a String', () => { + var element = browser.getElement('body'); + element.getElements('.message'); + }); + + it('return empty array if not found an element on the message element', () => { + var messageElement = browser.getElement('.message'); + var elements = messageElement.getElements('.message'); + assert.equal(0, elements.length); + }); + }); +}); diff --git a/test/integration/evaluate.test.js b/test/integration/evaluate.test.js new file mode 100644 index 0000000..51dfece --- /dev/null +++ b/test/integration/evaluate.test.js @@ -0,0 +1,24 @@ +'use strict'; + +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('evaluate', () => { + let browser; + before(async () => (browser = await getBrowser())); + + before(() => browser.navigateTo('/')); + + it('runs JavaScript passed as a String', () => { + var value = browser.evaluate('return 3;'); + assert.equal(3, value); + }); + + it('runs JavaScript passed as a Function', () => { + assert.equal(6, browser.evaluate(() => 6)); + }); + + it('runs JavaScript passed as a Function with optional prepended args', () => { + assert.equal(18, browser.evaluate(3, 6, (a, b) => a * b)); + }); +}); diff --git a/test/integration/navigation.test.js b/test/integration/navigation.test.js new file mode 100644 index 0000000..4feffe8 --- /dev/null +++ b/test/integration/navigation.test.js @@ -0,0 +1,121 @@ +'use strict'; + +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('navigation', () => { + let browser; + before(async () => (browser = await getBrowser())); + + it('supports just a path', () => { + browser.navigateTo('/'); + assert.equal(200, browser.getStatusCode()); + }); + + it('supports query args', () => { + browser.navigateTo('/', { query: { 'a b': 'München', x: 0 } }); + assert.equal(200, browser.getStatusCode()); + + browser.waitForPath('/?a%20b=M%C3%BCnchen&x=0', 100); + }); + + it('with a query string and query arg', () => { + browser.navigateTo('/?x=0', { query: { 'a b': 'München' } }); + assert.equal(200, browser.getStatusCode()); + + browser.waitForPath('/?x=0&a%20b=M%C3%BCnchen', 100); + }); + + it('by clicking a link', () => { + browser.navigateTo('/'); + assert.equal(200, browser.getStatusCode()); + + browser.click('.link-to-other-page'); + assert.equal('/other-page.html', browser.getPath()); + }); + + it('by refreshing', () => { + browser.navigateTo('/'); + assert.equal(200, browser.getStatusCode()); + + browser.refresh(); + assert.equal(200, browser.getStatusCode()); + + // No real way to assert this worked + }); + + describe('waiting for a url', () => { + it('can work with a string', () => { + browser.navigateTo('/redirect-after.html'); + assert.equal(200, browser.getStatusCode()); + + browser.waitForPath('/index.html'); + }); + + it('can work with a regex', () => { + browser.navigateTo('/redirect-after.html'); + assert.equal(200, browser.getStatusCode()); + + browser.waitForUrl(/\/index.html/); + }); + + it('can fail', () => { + browser.navigateTo('/index.html'); + assert.equal(200, browser.getStatusCode()); + + var error = assert.throws(() => browser.waitForUrl('/some-random-place.html', 5)); + var expectedError = /^Timed out \(5ms\) waiting for url \("\/some-random-place\.html"\)\. Last value was: "http:\/\/127\.0\.0\.1:[\d]+\/index\.html"$/; + assert.match(expectedError, error.message); + }); + + describe('groks url and query object', () => { + it('can make its own query regexp', () => { + browser.navigateTo('/redirect-to-query.html'); + browser.waitForUrl('/index.html', { + 'a b': 'A B', + c: '1,7' + }); + assert.equal(200, browser.getStatusCode()); + }); + + it('can find query arguments in any order', () => { + browser.navigateTo('/redirect-to-query.html'); + browser.waitForUrl('/index.html', { + c: '1,7', + 'a b': 'A B' + }); + }); + + it('can handle regexp query arguments', () => { + browser.navigateTo('/redirect-to-query.html'); + browser.waitForUrl('/index.html', { + c: /[\d,]+/, + 'a b': 'A B' + }); + }); + + it('detects non-matches too', () => { + browser.navigateTo('/redirect-to-query.html'); + + var error = assert.throws(() => browser.waitForUrl('/index.html', { no: 'q' }, 200)); + assert.match(/Timed out .* waiting for url/, error.message); + }); + }); + }); + + describe('waiting for a path', () => { + it('can work with a string', () => { + browser.navigateTo('/redirect-after.html'); + assert.equal(200, browser.getStatusCode()); + + browser.waitForPath('/index.html'); + }); + + it('can work with a regex', () => { + browser.navigateTo('/redirect-after.html'); + assert.equal(200, browser.getStatusCode()); + + browser.waitForPath(/index.html/); + }); + }); +}); diff --git a/test/integration/proxy.test.js b/test/integration/proxy.test.js new file mode 100644 index 0000000..16afcf3 --- /dev/null +++ b/test/integration/proxy.test.js @@ -0,0 +1,50 @@ +'use strict'; + +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('proxy', () => { + let browser; + before(async () => (browser = await getBrowser())); + + describe('handles errors', () => { + it('with no content type and preserves status code', () => { + browser.navigateTo('/'); + browser.assert.httpStatus(200); + + browser.navigateTo('/error'); + browser.assert.httpStatus(500); + }); + + it('that crash and preserves status code', () => { + browser.navigateTo('/crash'); + browser.assert.httpStatus(500); + }); + }); + + it('handles request abortion', done => { + // loads a page that has a resource that will + // be black holed + browser.navigateTo('/blackholed-resource.html'); + browser.assert.httpStatus(200); + + setTimeout(() => { + // when navigating away, the proxy should + // abort the resource request; + // this should not interfere with the new page load + // or status code retrieval + browser.navigateTo('/'); + browser.assert.httpStatus(200); + done() + + // this can't simply be sync + // because firefox blocks dom-ready + // if we don't wait on the client-side + }, 50); + }); + + it('handles hashes in urls', () => { + browser.navigateTo('/#deals'); + browser.assert.httpStatus(200); + }); +}); diff --git a/test/log/application.log b/test/log/application.log new file mode 100644 index 0000000..ecfb4f7 --- /dev/null +++ b/test/log/application.log @@ -0,0 +1 @@ +Listening on port 64982 diff --git a/test/log/phantomjs.log b/test/log/phantomjs.log new file mode 100644 index 0000000..77c3686 --- /dev/null +++ b/test/log/phantomjs.log @@ -0,0 +1,129 @@ +PhantomJS is launching GhostDriver... +[DEBUG - 2015-10-12T21:55:20.378Z] Config - config.init - {"ip":"127.0.0.1","port":"64983","hub":null,"logFile":null,"logLevel":"DEBUG","logColor":false} +[INFO - 2015-10-12T21:55:20.386Z] GhostDriver - Main - running on port 64983 +[DEBUG - 2015-10-12T21:55:20.460Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"26","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"desiredCapabilities\":{}}","url":"/session","urlParsed":{"anchor":"","query":"","file":"session","directory":"/","path":"/session","relative":"/session","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session","queryKey":{},"chunks":["session"]}} +[INFO - 2015-10-12T21:55:20.467Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.settings - {"XSSAuditingEnabled":false,"javascriptCanCloseWindows":true,"javascriptCanOpenWindows":true,"javascriptEnabled":true,"loadImages":true,"localToRemoteUrlAccessEnabled":false,"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","webSecurityEnabled":true} +[INFO - 2015-10-12T21:55:20.467Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.customHeaders: - {} +[DEBUG - 2015-10-12T21:55:20.467Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - Session.desiredCapabilities - {} +[INFO - 2015-10-12T21:55:20.467Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - Session.negotiatedCapabilities - {"browserName":"phantomjs","version":"1.9.8","driverName":"ghostdriver","driverVersion":"1.1.0","platform":"mac-unknown-32bit","javascriptEnabled":true,"takesScreenshot":true,"handlesAlerts":false,"databaseEnabled":false,"locationContextEnabled":false,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"cssSelectorsEnabled":true,"webStorageEnabled":false,"rotatable":false,"acceptSslCerts":false,"nativeEvents":true,"proxy":{"proxyType":"direct"}} +[INFO - 2015-10-12T21:55:20.467Z] SessionManagerReqHand - _postNewSessionCommand - New Session Created: ee9039f0-712b-11e5-b44a-3f5088d27053 +[DEBUG - 2015-10-12T21:55:20.471Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"27","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"height\":768,\"width\":1024}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/size","urlParsed":{"anchor":"","query":"","file":"size","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/size","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/size","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/size","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window","current","size"]}} +[DEBUG - 2015-10-12T21:55:20.472Z] SessionReqHand - _doWindowHandleCommands - {"headers":{"Accept":"*/*","Content-Length":"27","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"height\":768,\"width\":1024}","url":"/window/current/size","urlParsed":{"anchor":"","query":"","file":"size","directory":"/window/current/","path":"/window/current/size","relative":"/window/current/size","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/window/current/size","queryKey":{},"chunks":["window","current","size"]},"urlOriginal":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/size"} +[DEBUG - 2015-10-12T21:55:20.474Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"53","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:64984/testium-priming-load\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} +[DEBUG - 2015-10-12T21:55:20.474Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:64984/testium-priming-load +[DEBUG - 2015-10-12T21:55:20.475Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":1,"method":"GET","time":"2015-10-12T21:55:20.475Z","url":"http://127.0.0.1:64984/testium-priming-load"} +[DEBUG - 2015-10-12T21:55:20.475Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadStarted +[DEBUG - 2015-10-12T21:55:20.483Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"text/html","headers":[{"name":"Content-Type","value":"text/html"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":1,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.482Z","url":"http://127.0.0.1:64984/testium-priming-load"} +[DEBUG - 2015-10-12T21:55:20.483Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished +[DEBUG - 2015-10-12T21:55:20.484Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success +[DEBUG - 2015-10-12T21:55:20.485Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false +[DEBUG - 2015-10-12T21:55:20.486Z] SessionReqHand - _SuccessHandler - status: success +[DEBUG - 2015-10-12T21:55:20.487Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"DELETE","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} +[DEBUG - 2015-10-12T21:55:20.492Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"86","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2Fblackholed-resource.html&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} +[DEBUG - 2015-10-12T21:55:20.492Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2Fblackholed-resource.html&redirect=true +[DEBUG - 2015-10-12T21:55:20.492Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":2,"method":"GET","time":"2015-10-12T21:55:20.492Z","url":"http://127.0.0.1:4446/new-page?url=%2Fblackholed-resource.html&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.499Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/blackholed-resource.html"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":2,"redirectURL":"http://127.0.0.1:64984/blackholed-resource.html","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.498Z","url":"http://127.0.0.1:4446/new-page?url=%2Fblackholed-resource.html&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.499Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":3,"method":"GET","time":"2015-10-12T21:55:20.499Z","url":"http://127.0.0.1:64984/blackholed-resource.html"} +[DEBUG - 2015-10-12T21:55:20.503Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: true +[DEBUG - 2015-10-12T21:55:20.520Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":684,"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618542-684-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"684"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQyLTY4NC0xNDQ0Njc5OTM2MDAwXCIiLCJkYXRlIjoiTW9uLCAxMiBPY3QgMjAxNSAyMTo1NToyMCBHTVQiLCJsYXN0LW1vZGlmaWVkIjoiTW9uLCAxMiBPY3QgMjAxNSAxOTo1ODo1NiBHTVQiLCJjb250ZW50LXR5cGUiOiJ0ZXh0L2h0bWwiLCJjb250ZW50LWxlbmd0aCI6IjY4NCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIn0sInN0YXR1c0NvZGUiOjIwMH0=; path=/"}],"id":3,"redirectURL":null,"stage":"start","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.519Z","url":"http://127.0.0.1:64984/blackholed-resource.html"} +[DEBUG - 2015-10-12T21:55:20.520Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618542-684-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"684"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQyLTY4NC0xNDQ0Njc5OTM2MDAwXCIiLCJkYXRlIjoiTW9uLCAxMiBPY3QgMjAxNSAyMTo1NToyMCBHTVQiLCJsYXN0LW1vZGlmaWVkIjoiTW9uLCAxMiBPY3QgMjAxNSAxOTo1ODo1NiBHTVQiLCJjb250ZW50LXR5cGUiOiJ0ZXh0L2h0bWwiLCJjb250ZW50LWxlbmd0aCI6IjY4NCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIn0sInN0YXR1c0NvZGUiOjIwMH0=; path=/"}],"id":3,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.520Z","url":"http://127.0.0.1:64984/blackholed-resource.html"} +[DEBUG - 2015-10-12T21:55:20.522Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished +[DEBUG - 2015-10-12T21:55:20.522Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success +[DEBUG - 2015-10-12T21:55:20.553Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"*/*"},{"name":"Referer","value":"http://127.0.0.1:64984/blackholed-resource.html"}],"id":4,"method":"GET","time":"2015-10-12T21:55:20.553Z","url":"http://127.0.0.1:64984/blackhole"} +[DEBUG - 2015-10-12T21:55:20.604Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false +[DEBUG - 2015-10-12T21:55:20.604Z] SessionReqHand - _SuccessHandler - status: success +[DEBUG - 2015-10-12T21:55:20.607Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} +[DEBUG - 2015-10-12T21:55:20.611Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} +[DEBUG - 2015-10-12T21:55:20.669Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"62","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2F&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} +[DEBUG - 2015-10-12T21:55:20.670Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2F&redirect=true +[DEBUG - 2015-10-12T21:55:20.671Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceError - {"errorCode":5,"errorString":"Operation canceled","id":4,"url":"http://127.0.0.1:64984/blackhole"} +[DEBUG - 2015-10-12T21:55:20.671Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[],"id":4,"redirectURL":null,"stage":"end","status":null,"statusText":null,"time":"2015-10-12T21:55:20.671Z","url":"http://127.0.0.1:64984/blackhole"} +[DEBUG - 2015-10-12T21:55:20.671Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":5,"method":"GET","time":"2015-10-12T21:55:20.671Z","url":"http://127.0.0.1:4446/new-page?url=%2F&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.673Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":5,"redirectURL":"http://127.0.0.1:64984/","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.673Z","url":"http://127.0.0.1:4446/new-page?url=%2F&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.673Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":6,"method":"GET","time":"2015-10-12T21:55:20.673Z","url":"http://127.0.0.1:64984/"} +[DEBUG - 2015-10-12T21:55:20.682Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: true +[DEBUG - 2015-10-12T21:55:20.682Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":2527,"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":6,"redirectURL":null,"stage":"start","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.682Z","url":"http://127.0.0.1:64984/"} +[DEBUG - 2015-10-12T21:55:20.683Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test log entry +[DEBUG - 2015-10-12T21:55:20.683Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test warn entry +[DEBUG - 2015-10-12T21:55:20.683Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test debug entry +[DEBUG - 2015-10-12T21:55:20.683Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test error entry +[DEBUG - 2015-10-12T21:55:20.683Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Referer","value":"http://127.0.0.1:64984/"},{"name":"Accept","value":"*/*"}],"id":7,"method":"GET","time":"2015-10-12T21:55:20.683Z","url":"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP8AACwAAAAAAQABAAACAkwBADs="} +[DEBUG - 2015-10-12T21:55:20.687Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":6,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.687Z","url":"http://127.0.0.1:64984/"} +[DEBUG - 2015-10-12T21:55:20.687Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":35,"contentType":"image/gif","headers":[{"name":"Content-Type","value":"image/gif"},{"name":"Content-Length","value":"35"}],"id":7,"redirectURL":null,"stage":"start","status":null,"statusText":null,"time":"2015-10-12T21:55:20.687Z","url":"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP8AACwAAAAAAQABAAACAkwBADs="} +[DEBUG - 2015-10-12T21:55:20.687Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"image/gif","headers":[{"name":"Content-Type","value":"image/gif"},{"name":"Content-Length","value":"35"}],"id":7,"redirectURL":null,"stage":"end","status":null,"statusText":null,"time":"2015-10-12T21:55:20.687Z","url":"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP8AACwAAAAAAQABAAACAkwBADs="} +[DEBUG - 2015-10-12T21:55:20.688Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Referer","value":"http://127.0.0.1:64984/"},{"name":"Accept","value":"*/*"}],"id":8,"method":"GET","time":"2015-10-12T21:55:20.687Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} +[DEBUG - 2015-10-12T21:55:20.692Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceError - {"errorCode":203,"errorString":"Error downloading http://127.0.0.1:64984/non-existent-image.jpg - server replied: Not Found","id":8,"url":"http://127.0.0.1:64984/non-existent-image.jpg"} +[DEBUG - 2015-10-12T21:55:20.692Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"connection","value":"keep-alive"},{"name":"transfer-encoding","value":"chunked"}],"id":8,"redirectURL":null,"stage":"end","status":404,"statusText":"Not Found","time":"2015-10-12T21:55:20.692Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} +[DEBUG - 2015-10-12T21:55:20.695Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished +[DEBUG - 2015-10-12T21:55:20.695Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success +[DEBUG - 2015-10-12T21:55:20.783Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false +[DEBUG - 2015-10-12T21:55:20.783Z] SessionReqHand - _SuccessHandler - status: success +[DEBUG - 2015-10-12T21:55:20.786Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} +[DEBUG - 2015-10-12T21:55:20.789Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} +[DEBUG - 2015-10-12T21:55:20.793Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"70","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2F%23deals&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} +[DEBUG - 2015-10-12T21:55:20.793Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2F%23deals&redirect=true +[DEBUG - 2015-10-12T21:55:20.794Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":9,"method":"GET","time":"2015-10-12T21:55:20.794Z","url":"http://127.0.0.1:4446/new-page?url=%2F%23deals&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.795Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":9,"redirectURL":"http://127.0.0.1:64984/","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.795Z","url":"http://127.0.0.1:4446/new-page?url=%2F%23deals&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.796Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":10,"method":"GET","time":"2015-10-12T21:55:20.796Z","url":"http://127.0.0.1:64984/"} +[DEBUG - 2015-10-12T21:55:20.801Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":2527,"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":10,"redirectURL":null,"stage":"start","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.801Z","url":"http://127.0.0.1:64984/"} +[DEBUG - 2015-10-12T21:55:20.802Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test log entry +[DEBUG - 2015-10-12T21:55:20.802Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test warn entry +[DEBUG - 2015-10-12T21:55:20.802Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test debug entry +[DEBUG - 2015-10-12T21:55:20.802Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test error entry +[DEBUG - 2015-10-12T21:55:20.803Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":10,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.803Z","url":"http://127.0.0.1:64984/"} +[DEBUG - 2015-10-12T21:55:20.805Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Referer","value":"http://127.0.0.1:64984/"},{"name":"Accept","value":"*/*"}],"id":11,"method":"GET","time":"2015-10-12T21:55:20.804Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} +[DEBUG - 2015-10-12T21:55:20.805Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: true +[DEBUG - 2015-10-12T21:55:20.808Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceError - {"errorCode":203,"errorString":"Error downloading http://127.0.0.1:64984/non-existent-image.jpg - server replied: Not Found","id":11,"url":"http://127.0.0.1:64984/non-existent-image.jpg"} +[DEBUG - 2015-10-12T21:55:20.808Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"connection","value":"keep-alive"},{"name":"transfer-encoding","value":"chunked"}],"id":11,"redirectURL":null,"stage":"end","status":404,"statusText":"Not Found","time":"2015-10-12T21:55:20.808Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} +[DEBUG - 2015-10-12T21:55:20.809Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished +[DEBUG - 2015-10-12T21:55:20.809Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success +[DEBUG - 2015-10-12T21:55:20.906Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false +[DEBUG - 2015-10-12T21:55:20.906Z] SessionReqHand - _SuccessHandler - status: success +[DEBUG - 2015-10-12T21:55:20.908Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} +[DEBUG - 2015-10-12T21:55:20.910Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} +[DEBUG - 2015-10-12T21:55:20.912Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"62","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2F&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} +[DEBUG - 2015-10-12T21:55:20.913Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2F&redirect=true +[DEBUG - 2015-10-12T21:55:20.913Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":12,"method":"GET","time":"2015-10-12T21:55:20.913Z","url":"http://127.0.0.1:4446/new-page?url=%2F&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.914Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":12,"redirectURL":"http://127.0.0.1:64984/","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.914Z","url":"http://127.0.0.1:4446/new-page?url=%2F&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.914Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":13,"method":"GET","time":"2015-10-12T21:55:20.914Z","url":"http://127.0.0.1:64984/"} +[DEBUG - 2015-10-12T21:55:20.918Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":2527,"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":13,"redirectURL":null,"stage":"start","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.918Z","url":"http://127.0.0.1:64984/"} +[DEBUG - 2015-10-12T21:55:20.919Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test log entry +[DEBUG - 2015-10-12T21:55:20.919Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test warn entry +[DEBUG - 2015-10-12T21:55:20.919Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test debug entry +[DEBUG - 2015-10-12T21:55:20.919Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test error entry +[DEBUG - 2015-10-12T21:55:20.920Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":13,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.920Z","url":"http://127.0.0.1:64984/"} +[DEBUG - 2015-10-12T21:55:20.921Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Referer","value":"http://127.0.0.1:64984/"},{"name":"Accept","value":"*/*"}],"id":14,"method":"GET","time":"2015-10-12T21:55:20.921Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} +[DEBUG - 2015-10-12T21:55:20.924Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceError - {"errorCode":203,"errorString":"Error downloading http://127.0.0.1:64984/non-existent-image.jpg - server replied: Not Found","id":14,"url":"http://127.0.0.1:64984/non-existent-image.jpg"} +[DEBUG - 2015-10-12T21:55:20.924Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"connection","value":"keep-alive"},{"name":"transfer-encoding","value":"chunked"}],"id":14,"redirectURL":null,"stage":"end","status":404,"statusText":"Not Found","time":"2015-10-12T21:55:20.924Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} +[DEBUG - 2015-10-12T21:55:20.925Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false +[DEBUG - 2015-10-12T21:55:20.925Z] SessionReqHand - _SuccessHandler - status: success +[DEBUG - 2015-10-12T21:55:20.925Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished +[DEBUG - 2015-10-12T21:55:20.925Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success +[DEBUG - 2015-10-12T21:55:20.926Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} +[DEBUG - 2015-10-12T21:55:20.928Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} +[DEBUG - 2015-10-12T21:55:20.929Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"67","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2Ferror&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} +[DEBUG - 2015-10-12T21:55:20.929Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2Ferror&redirect=true +[DEBUG - 2015-10-12T21:55:20.930Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":15,"method":"GET","time":"2015-10-12T21:55:20.930Z","url":"http://127.0.0.1:4446/new-page?url=%2Ferror&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.931Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/error"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":15,"redirectURL":"http://127.0.0.1:64984/error","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.931Z","url":"http://127.0.0.1:4446/new-page?url=%2Ferror&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.931Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":16,"method":"GET","time":"2015-10-12T21:55:20.931Z","url":"http://127.0.0.1:64984/error"} +[DEBUG - 2015-10-12T21:55:20.935Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":16,"contentType":null,"headers":[{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"connection","value":"keep-alive"},{"name":"content-length","value":"16"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7ImRhdGUiOiJNb24sIDEyIE9jdCAyMDE1IDIxOjU1OjIwIEdNVCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIiwiY29udGVudC1sZW5ndGgiOiIxNiJ9LCJzdGF0dXNDb2RlIjo1MDB9; path=/"},{"name":"cache-control","value":"no-store"}],"id":16,"redirectURL":null,"stage":"start","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.934Z","url":"http://127.0.0.1:64984/error"} +[DEBUG - 2015-10-12T21:55:20.935Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"connection","value":"keep-alive"},{"name":"content-length","value":"16"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7ImRhdGUiOiJNb24sIDEyIE9jdCAyMDE1IDIxOjU1OjIwIEdNVCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIiwiY29udGVudC1sZW5ndGgiOiIxNiJ9LCJzdGF0dXNDb2RlIjo1MDB9; path=/"},{"name":"cache-control","value":"no-store"}],"id":16,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.935Z","url":"http://127.0.0.1:64984/error"} +[DEBUG - 2015-10-12T21:55:20.938Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished +[DEBUG - 2015-10-12T21:55:20.938Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success +[DEBUG - 2015-10-12T21:55:20.940Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false +[DEBUG - 2015-10-12T21:55:20.941Z] SessionReqHand - _SuccessHandler - status: success +[DEBUG - 2015-10-12T21:55:20.942Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} +[DEBUG - 2015-10-12T21:55:20.944Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} +[DEBUG - 2015-10-12T21:55:20.946Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"67","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2Fcrash&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} +[DEBUG - 2015-10-12T21:55:20.946Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2Fcrash&redirect=true +[DEBUG - 2015-10-12T21:55:20.947Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":17,"method":"GET","time":"2015-10-12T21:55:20.947Z","url":"http://127.0.0.1:4446/new-page?url=%2Fcrash&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.953Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/crash"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":17,"redirectURL":"http://127.0.0.1:64984/crash","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.953Z","url":"http://127.0.0.1:4446/new-page?url=%2Fcrash&redirect=true"} +[DEBUG - 2015-10-12T21:55:20.953Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":18,"method":"GET","time":"2015-10-12T21:55:20.953Z","url":"http://127.0.0.1:64984/crash"} +[DEBUG - 2015-10-12T21:55:20.958Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: true +[DEBUG - 2015-10-12T21:55:20.959Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7fSwic3RhdHVzQ29kZSI6NTAwfQ==; path=/"},{"name":"cache-control","value":"no-store"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":18,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.959Z","url":"http://127.0.0.1:64984/crash"} +[DEBUG - 2015-10-12T21:55:20.960Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished +[DEBUG - 2015-10-12T21:55:20.960Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success +[DEBUG - 2015-10-12T21:55:21.059Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false +[DEBUG - 2015-10-12T21:55:21.060Z] SessionReqHand - _SuccessHandler - status: success +[DEBUG - 2015-10-12T21:55:21.062Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} +[DEBUG - 2015-10-12T21:55:21.065Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} diff --git a/test/log/proxy.log b/test/log/proxy.log new file mode 100644 index 0000000..834ad6c --- /dev/null +++ b/test/log/proxy.log @@ -0,0 +1,60 @@ +Listening on port 64984 and proxying to 64982. +Listening for commands on port 4446. +--> GET /testium-priming-load (prime the browser) + +[System] Marking new page request with options: {"url":"/blackholed-resource.html","redirect":true} +--> GET /blackholed-resource.html + {"port":64982,"path":"/blackholed-resource.html","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} +<-- 200 /blackholed-resource.html +--> GET /blackhole + {"port":64982,"path":"/blackhole","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"*/*","referer":"http://127.0.0.1:64984/blackholed-resource.html","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQyLTY4NC0xNDQ0Njc5OTM2MDAwXCIiLCJkYXRlIjoiTW9uLCAxMiBPY3QgMjAxNSAyMTo1NToyMCBHTVQiLCJsYXN0LW1vZGlmaWVkIjoiTW9uLCAxMiBPY3QgMjAxNSAxOTo1ODo1NiBHTVQiLCJjb250ZW50LXR5cGUiOiJ0ZXh0L2h0bWwiLCJjb250ZW50LWxlbmd0aCI6IjY4NCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIn0sInN0YXR1c0NvZGUiOjIwMH0=","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} + +[System] Marking new page request with options: {"url":"/","redirect":true} +[System] Aborting request for: /blackhole +Error: socket hang up + at createHangUpError (_http_client.js:203:15) + at Socket.socketCloseListener (_http_client.js:235:23) + at emitOne (events.js:82:20) + at Socket.emit (events.js:169:7) + at TCP._onclose (net.js:469:12) +<-- 500 /blackhole +--> GET / + {"port":64982,"path":"/","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQyLTY4NC0xNDQ0Njc5OTM2MDAwXCIiLCJkYXRlIjoiTW9uLCAxMiBPY3QgMjAxNSAyMTo1NToyMCBHTVQiLCJsYXN0LW1vZGlmaWVkIjoiTW9uLCAxMiBPY3QgMjAxNSAxOTo1ODo1NiBHTVQiLCJjb250ZW50LXR5cGUiOiJ0ZXh0L2h0bWwiLCJjb250ZW50LWxlbmd0aCI6IjY4NCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIn0sInN0YXR1c0NvZGUiOjIwMH0=","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} +<-- 200 / +--> GET /non-existent-image.jpg + {"port":64982,"path":"/non-existent-image.jpg","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","referer":"http://127.0.0.1:64984/","accept":"*/*","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} +<-- 404 /non-existent-image.jpg + +[System] Marking new page request with options: {"url":"/","redirect":true} +--> GET / + {"port":64982,"path":"/","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} +<-- 200 / +--> GET /non-existent-image.jpg + {"port":64982,"path":"/non-existent-image.jpg","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","referer":"http://127.0.0.1:64984/","accept":"*/*","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} +<-- 404 /non-existent-image.jpg + +[System] Marking new page request with options: {"url":"/","redirect":true} +--> GET / + {"port":64982,"path":"/","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} +<-- 200 / +--> GET /non-existent-image.jpg + {"port":64982,"path":"/non-existent-image.jpg","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","referer":"http://127.0.0.1:64984/","accept":"*/*","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} +<-- 404 /non-existent-image.jpg + +[System] Marking new page request with options: {"url":"/error","redirect":true} +--> GET /error + {"port":64982,"path":"/error","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} +<-- 200 /error + +[System] Marking new page request with options: {"url":"/crash","redirect":true} +--> GET /crash + {"port":64982,"path":"/crash","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","cookie":"_testium_=eyJoZWFkZXJzIjp7ImRhdGUiOiJNb24sIDEyIE9jdCAyMDE1IDIxOjU1OjIwIEdNVCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIiwiY29udGVudC1sZW5ndGgiOiIxNiJ9LCJzdGF0dXNDb2RlIjo1MDB9","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} +Error: socket hang up + at createHangUpError (_http_client.js:203:15) + at Socket.socketOnEnd (_http_client.js:288:23) + at emitNone (events.js:72:20) + at Socket.emit (events.js:166:7) + at endReadableNT (_stream_readable.js:893:12) + at doNTCallback2 (node.js:430:9) + at process._tickCallback (node.js:344:17) +<-- 200 /crash diff --git a/test/mini-testium-mocha.js b/test/mini-testium-mocha.js new file mode 100644 index 0000000..d2c7f63 --- /dev/null +++ b/test/mini-testium-mocha.js @@ -0,0 +1,14 @@ +'use strict'; +// This is a minimal version of `testium-mocha`. +// We're trying to avoid cyclic dependencies. +import initTestium from 'testium-core'; +import {once} from 'lodash'; + +import createDriver from '../'; + +var initOnce = once(initTestium); + +export async function getBrowser(options) { + const { browser } = await initOnce().then(createDriver); + return browser; +} diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..3d5571b --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,2 @@ +--compilers js:babel-core/register +--recursive From 9f22f72697855f57bea738998042a9819b3b718d Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Mon, 12 Oct 2015 15:36:45 -0700 Subject: [PATCH 03/11] Add console message support --- .gitignore | 2 + lib/browser/debug/console.js | 31 ++++++++ lib/browser/debug/index.js | 29 +++++++ lib/browser/index.js | 2 + test/browser/debug.js | 37 +++++++++ test/integration/console.test.js | 46 +++++++++++ test/log/application.log | 1 - test/log/phantomjs.log | 129 ------------------------------- test/log/proxy.log | 60 -------------- 9 files changed, 147 insertions(+), 190 deletions(-) create mode 100644 lib/browser/debug/console.js create mode 100644 lib/browser/debug/index.js create mode 100644 test/browser/debug.js create mode 100644 test/integration/console.test.js delete mode 100644 test/log/application.log delete mode 100644 test/log/phantomjs.log delete mode 100644 test/log/proxy.log diff --git a/.gitignore b/.gitignore index dabed5d..3af2c89 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ node_modules npm-debug.log test/tmp examples/**/log +test/log +test/**/*.coffee diff --git a/lib/browser/debug/console.js b/lib/browser/debug/console.js new file mode 100644 index 0000000..d1b6f97 --- /dev/null +++ b/lib/browser/debug/console.js @@ -0,0 +1,31 @@ +'use strict'; + +var _ = require('lodash'); + +var logMap = { + 'SEVERE': 'error', + 'WARNING': 'warn', + 'INFO': 'log', + 'DEBUG': 'debug' +}; + +function convertLogType(log) { + if (log.level) { + log.type = logMap[log.level]; + delete log.level; + } + return log; +} + +exports.parseLogs = function parseLogs(logs) { + return _.map(logs, convertLogType); +}; + +exports.filterLogs = function filterLogs(logs, type) { + if (!type) { + return { matched: logs }; + } + return _.groupBy(logs, function(log) { + return log.type === type ? 'matched' : 'rest'; + }); +}; diff --git a/lib/browser/debug/index.js b/lib/browser/debug/index.js new file mode 100644 index 0000000..4819740 --- /dev/null +++ b/lib/browser/debug/index.js @@ -0,0 +1,29 @@ +'use strict'; + +var assert = require('assertive'); +var _private = require('./console'); + +var parseLogs = _private.parseLogs; +var filterLogs = _private.filterLogs; + +var TYPES = [ + 'error', + 'warn', + 'log', + 'debug' +]; + +var cachedLogs = []; + +exports.getConsoleLogs = function getConsoleLogs(type) { + if (type) { + assert.include(type, TYPES); + } + + var newLogs = parseLogs(this.driver.getConsoleLogs()); + var logs = cachedLogs.concat(newLogs); + + var filtered = filterLogs(logs, type); + cachedLogs = filtered.rest || [] + return filtered.matched || []; +}; diff --git a/lib/browser/index.js b/lib/browser/index.js index e0cdea0..7cb272c 100644 --- a/lib/browser/index.js +++ b/lib/browser/index.js @@ -5,6 +5,7 @@ var assert = require('assertive'); var builtIns = [ require('./cookie'), + require('./debug'), require('./element'), require('./navigation'), require('./page') @@ -12,6 +13,7 @@ var builtIns = [ function Browser(driver, options) { this.driver = driver; + this.capabilities = driver.capabilities; options = options || {}; this.appUrl = options.appUrl; diff --git a/test/browser/debug.js b/test/browser/debug.js new file mode 100644 index 0000000..5650055 --- /dev/null +++ b/test/browser/debug.js @@ -0,0 +1,37 @@ +import assert from 'assertive'; +import {parseLogs, filterLogs} from '../../lib/browser/debug/console'; + +describe('parseLogs', () => { + it('maps log levels to browser log types', () => { + var logs = [ { level: 'SEVERE' } ]; + var parsed = parseLogs(logs); + var log = parsed[0]; + + assert.equal(log.level, undefined); + assert.equal(log.type, 'error'); + }); +}); + +describe('filterLogs', () => { + it('returns all logs if no type is given', () => { + var logs = [ + { type: 'error', message: 'something broke' }, + { type: 'log', message: 'things are working' } + ]; + + var { matched } = filterLogs(logs); + assert.deepEqual(logs, matched); + }); + + it('filters logs based on type', () => { + var errorItem = { type: 'error', message: 'something broke' }; + var logItem = { type: 'log', message: 'things are working' }; + var logs = [ logItem, errorItem ]; + + var { matched, rest } = filterLogs(logs, 'error'); + assert.equal(errorItem, matched[0]); + assert.equal(1, matched.length); + assert.equal(logItem, rest[0]); + assert.equal(1, rest.length); + }); +}); diff --git a/test/integration/console.test.js b/test/integration/console.test.js new file mode 100644 index 0000000..a6b57fa --- /dev/null +++ b/test/integration/console.test.js @@ -0,0 +1,46 @@ +'use strict'; + +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('console', () => { + let browser; + before(async () => (browser = await getBrowser())); + + before(() => { + browser.navigateTo('/'); + browser.assert.httpStatus(200); + }); + + // Each browser fails to implement the WebDriver spec + // for console.logs differently. + // Use at your own risk. + it('can all be retrieved', () => { + var { browserName } = browser.capabilities; + var logs; + + switch (browserName) { + case 'firefox': + // firefox ignores this entirely + break; + + case 'chrome': + logs = browser.getConsoleLogs(); + assert.truthy('console.logs length', logs.length > 0); + + logs = browser.getConsoleLogs(); + assert.equal(0, logs.length); + + browser.click('#log-button'); + + logs = browser.getConsoleLogs(); + assert.truthy('console.logs length', logs.length > 0); + break; + + default: + logs = browser.getConsoleLogs(); + assert.truthy('console.logs length', logs.length > 0); + break; + } + }); +}); diff --git a/test/log/application.log b/test/log/application.log deleted file mode 100644 index ecfb4f7..0000000 --- a/test/log/application.log +++ /dev/null @@ -1 +0,0 @@ -Listening on port 64982 diff --git a/test/log/phantomjs.log b/test/log/phantomjs.log deleted file mode 100644 index 77c3686..0000000 --- a/test/log/phantomjs.log +++ /dev/null @@ -1,129 +0,0 @@ -PhantomJS is launching GhostDriver... -[DEBUG - 2015-10-12T21:55:20.378Z] Config - config.init - {"ip":"127.0.0.1","port":"64983","hub":null,"logFile":null,"logLevel":"DEBUG","logColor":false} -[INFO - 2015-10-12T21:55:20.386Z] GhostDriver - Main - running on port 64983 -[DEBUG - 2015-10-12T21:55:20.460Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"26","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"desiredCapabilities\":{}}","url":"/session","urlParsed":{"anchor":"","query":"","file":"session","directory":"/","path":"/session","relative":"/session","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session","queryKey":{},"chunks":["session"]}} -[INFO - 2015-10-12T21:55:20.467Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.settings - {"XSSAuditingEnabled":false,"javascriptCanCloseWindows":true,"javascriptCanOpenWindows":true,"javascriptEnabled":true,"loadImages":true,"localToRemoteUrlAccessEnabled":false,"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","webSecurityEnabled":true} -[INFO - 2015-10-12T21:55:20.467Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.customHeaders: - {} -[DEBUG - 2015-10-12T21:55:20.467Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - Session.desiredCapabilities - {} -[INFO - 2015-10-12T21:55:20.467Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - Session.negotiatedCapabilities - {"browserName":"phantomjs","version":"1.9.8","driverName":"ghostdriver","driverVersion":"1.1.0","platform":"mac-unknown-32bit","javascriptEnabled":true,"takesScreenshot":true,"handlesAlerts":false,"databaseEnabled":false,"locationContextEnabled":false,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"cssSelectorsEnabled":true,"webStorageEnabled":false,"rotatable":false,"acceptSslCerts":false,"nativeEvents":true,"proxy":{"proxyType":"direct"}} -[INFO - 2015-10-12T21:55:20.467Z] SessionManagerReqHand - _postNewSessionCommand - New Session Created: ee9039f0-712b-11e5-b44a-3f5088d27053 -[DEBUG - 2015-10-12T21:55:20.471Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"27","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"height\":768,\"width\":1024}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/size","urlParsed":{"anchor":"","query":"","file":"size","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/size","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/size","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/size","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window","current","size"]}} -[DEBUG - 2015-10-12T21:55:20.472Z] SessionReqHand - _doWindowHandleCommands - {"headers":{"Accept":"*/*","Content-Length":"27","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"height\":768,\"width\":1024}","url":"/window/current/size","urlParsed":{"anchor":"","query":"","file":"size","directory":"/window/current/","path":"/window/current/size","relative":"/window/current/size","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/window/current/size","queryKey":{},"chunks":["window","current","size"]},"urlOriginal":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window/current/size"} -[DEBUG - 2015-10-12T21:55:20.474Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"53","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:64984/testium-priming-load\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} -[DEBUG - 2015-10-12T21:55:20.474Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:64984/testium-priming-load -[DEBUG - 2015-10-12T21:55:20.475Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":1,"method":"GET","time":"2015-10-12T21:55:20.475Z","url":"http://127.0.0.1:64984/testium-priming-load"} -[DEBUG - 2015-10-12T21:55:20.475Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadStarted -[DEBUG - 2015-10-12T21:55:20.483Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"text/html","headers":[{"name":"Content-Type","value":"text/html"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":1,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.482Z","url":"http://127.0.0.1:64984/testium-priming-load"} -[DEBUG - 2015-10-12T21:55:20.483Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished -[DEBUG - 2015-10-12T21:55:20.484Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success -[DEBUG - 2015-10-12T21:55:20.485Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false -[DEBUG - 2015-10-12T21:55:20.486Z] SessionReqHand - _SuccessHandler - status: success -[DEBUG - 2015-10-12T21:55:20.487Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"DELETE","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} -[DEBUG - 2015-10-12T21:55:20.492Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"86","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2Fblackholed-resource.html&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} -[DEBUG - 2015-10-12T21:55:20.492Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2Fblackholed-resource.html&redirect=true -[DEBUG - 2015-10-12T21:55:20.492Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":2,"method":"GET","time":"2015-10-12T21:55:20.492Z","url":"http://127.0.0.1:4446/new-page?url=%2Fblackholed-resource.html&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.499Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/blackholed-resource.html"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":2,"redirectURL":"http://127.0.0.1:64984/blackholed-resource.html","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.498Z","url":"http://127.0.0.1:4446/new-page?url=%2Fblackholed-resource.html&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.499Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":3,"method":"GET","time":"2015-10-12T21:55:20.499Z","url":"http://127.0.0.1:64984/blackholed-resource.html"} -[DEBUG - 2015-10-12T21:55:20.503Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: true -[DEBUG - 2015-10-12T21:55:20.520Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":684,"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618542-684-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"684"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQyLTY4NC0xNDQ0Njc5OTM2MDAwXCIiLCJkYXRlIjoiTW9uLCAxMiBPY3QgMjAxNSAyMTo1NToyMCBHTVQiLCJsYXN0LW1vZGlmaWVkIjoiTW9uLCAxMiBPY3QgMjAxNSAxOTo1ODo1NiBHTVQiLCJjb250ZW50LXR5cGUiOiJ0ZXh0L2h0bWwiLCJjb250ZW50LWxlbmd0aCI6IjY4NCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIn0sInN0YXR1c0NvZGUiOjIwMH0=; path=/"}],"id":3,"redirectURL":null,"stage":"start","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.519Z","url":"http://127.0.0.1:64984/blackholed-resource.html"} -[DEBUG - 2015-10-12T21:55:20.520Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618542-684-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"684"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQyLTY4NC0xNDQ0Njc5OTM2MDAwXCIiLCJkYXRlIjoiTW9uLCAxMiBPY3QgMjAxNSAyMTo1NToyMCBHTVQiLCJsYXN0LW1vZGlmaWVkIjoiTW9uLCAxMiBPY3QgMjAxNSAxOTo1ODo1NiBHTVQiLCJjb250ZW50LXR5cGUiOiJ0ZXh0L2h0bWwiLCJjb250ZW50LWxlbmd0aCI6IjY4NCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIn0sInN0YXR1c0NvZGUiOjIwMH0=; path=/"}],"id":3,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.520Z","url":"http://127.0.0.1:64984/blackholed-resource.html"} -[DEBUG - 2015-10-12T21:55:20.522Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished -[DEBUG - 2015-10-12T21:55:20.522Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success -[DEBUG - 2015-10-12T21:55:20.553Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"*/*"},{"name":"Referer","value":"http://127.0.0.1:64984/blackholed-resource.html"}],"id":4,"method":"GET","time":"2015-10-12T21:55:20.553Z","url":"http://127.0.0.1:64984/blackhole"} -[DEBUG - 2015-10-12T21:55:20.604Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false -[DEBUG - 2015-10-12T21:55:20.604Z] SessionReqHand - _SuccessHandler - status: success -[DEBUG - 2015-10-12T21:55:20.607Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} -[DEBUG - 2015-10-12T21:55:20.611Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} -[DEBUG - 2015-10-12T21:55:20.669Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"62","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2F&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} -[DEBUG - 2015-10-12T21:55:20.670Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2F&redirect=true -[DEBUG - 2015-10-12T21:55:20.671Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceError - {"errorCode":5,"errorString":"Operation canceled","id":4,"url":"http://127.0.0.1:64984/blackhole"} -[DEBUG - 2015-10-12T21:55:20.671Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[],"id":4,"redirectURL":null,"stage":"end","status":null,"statusText":null,"time":"2015-10-12T21:55:20.671Z","url":"http://127.0.0.1:64984/blackhole"} -[DEBUG - 2015-10-12T21:55:20.671Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":5,"method":"GET","time":"2015-10-12T21:55:20.671Z","url":"http://127.0.0.1:4446/new-page?url=%2F&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.673Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":5,"redirectURL":"http://127.0.0.1:64984/","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.673Z","url":"http://127.0.0.1:4446/new-page?url=%2F&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.673Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":6,"method":"GET","time":"2015-10-12T21:55:20.673Z","url":"http://127.0.0.1:64984/"} -[DEBUG - 2015-10-12T21:55:20.682Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: true -[DEBUG - 2015-10-12T21:55:20.682Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":2527,"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":6,"redirectURL":null,"stage":"start","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.682Z","url":"http://127.0.0.1:64984/"} -[DEBUG - 2015-10-12T21:55:20.683Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test log entry -[DEBUG - 2015-10-12T21:55:20.683Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test warn entry -[DEBUG - 2015-10-12T21:55:20.683Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test debug entry -[DEBUG - 2015-10-12T21:55:20.683Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test error entry -[DEBUG - 2015-10-12T21:55:20.683Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Referer","value":"http://127.0.0.1:64984/"},{"name":"Accept","value":"*/*"}],"id":7,"method":"GET","time":"2015-10-12T21:55:20.683Z","url":"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP8AACwAAAAAAQABAAACAkwBADs="} -[DEBUG - 2015-10-12T21:55:20.687Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":6,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.687Z","url":"http://127.0.0.1:64984/"} -[DEBUG - 2015-10-12T21:55:20.687Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":35,"contentType":"image/gif","headers":[{"name":"Content-Type","value":"image/gif"},{"name":"Content-Length","value":"35"}],"id":7,"redirectURL":null,"stage":"start","status":null,"statusText":null,"time":"2015-10-12T21:55:20.687Z","url":"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP8AACwAAAAAAQABAAACAkwBADs="} -[DEBUG - 2015-10-12T21:55:20.687Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"image/gif","headers":[{"name":"Content-Type","value":"image/gif"},{"name":"Content-Length","value":"35"}],"id":7,"redirectURL":null,"stage":"end","status":null,"statusText":null,"time":"2015-10-12T21:55:20.687Z","url":"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP8AACwAAAAAAQABAAACAkwBADs="} -[DEBUG - 2015-10-12T21:55:20.688Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Referer","value":"http://127.0.0.1:64984/"},{"name":"Accept","value":"*/*"}],"id":8,"method":"GET","time":"2015-10-12T21:55:20.687Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} -[DEBUG - 2015-10-12T21:55:20.692Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceError - {"errorCode":203,"errorString":"Error downloading http://127.0.0.1:64984/non-existent-image.jpg - server replied: Not Found","id":8,"url":"http://127.0.0.1:64984/non-existent-image.jpg"} -[DEBUG - 2015-10-12T21:55:20.692Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"connection","value":"keep-alive"},{"name":"transfer-encoding","value":"chunked"}],"id":8,"redirectURL":null,"stage":"end","status":404,"statusText":"Not Found","time":"2015-10-12T21:55:20.692Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} -[DEBUG - 2015-10-12T21:55:20.695Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished -[DEBUG - 2015-10-12T21:55:20.695Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success -[DEBUG - 2015-10-12T21:55:20.783Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false -[DEBUG - 2015-10-12T21:55:20.783Z] SessionReqHand - _SuccessHandler - status: success -[DEBUG - 2015-10-12T21:55:20.786Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} -[DEBUG - 2015-10-12T21:55:20.789Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} -[DEBUG - 2015-10-12T21:55:20.793Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"70","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2F%23deals&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} -[DEBUG - 2015-10-12T21:55:20.793Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2F%23deals&redirect=true -[DEBUG - 2015-10-12T21:55:20.794Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":9,"method":"GET","time":"2015-10-12T21:55:20.794Z","url":"http://127.0.0.1:4446/new-page?url=%2F%23deals&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.795Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":9,"redirectURL":"http://127.0.0.1:64984/","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.795Z","url":"http://127.0.0.1:4446/new-page?url=%2F%23deals&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.796Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":10,"method":"GET","time":"2015-10-12T21:55:20.796Z","url":"http://127.0.0.1:64984/"} -[DEBUG - 2015-10-12T21:55:20.801Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":2527,"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":10,"redirectURL":null,"stage":"start","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.801Z","url":"http://127.0.0.1:64984/"} -[DEBUG - 2015-10-12T21:55:20.802Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test log entry -[DEBUG - 2015-10-12T21:55:20.802Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test warn entry -[DEBUG - 2015-10-12T21:55:20.802Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test debug entry -[DEBUG - 2015-10-12T21:55:20.802Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test error entry -[DEBUG - 2015-10-12T21:55:20.803Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":10,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.803Z","url":"http://127.0.0.1:64984/"} -[DEBUG - 2015-10-12T21:55:20.805Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Referer","value":"http://127.0.0.1:64984/"},{"name":"Accept","value":"*/*"}],"id":11,"method":"GET","time":"2015-10-12T21:55:20.804Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} -[DEBUG - 2015-10-12T21:55:20.805Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: true -[DEBUG - 2015-10-12T21:55:20.808Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceError - {"errorCode":203,"errorString":"Error downloading http://127.0.0.1:64984/non-existent-image.jpg - server replied: Not Found","id":11,"url":"http://127.0.0.1:64984/non-existent-image.jpg"} -[DEBUG - 2015-10-12T21:55:20.808Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"connection","value":"keep-alive"},{"name":"transfer-encoding","value":"chunked"}],"id":11,"redirectURL":null,"stage":"end","status":404,"statusText":"Not Found","time":"2015-10-12T21:55:20.808Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} -[DEBUG - 2015-10-12T21:55:20.809Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished -[DEBUG - 2015-10-12T21:55:20.809Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success -[DEBUG - 2015-10-12T21:55:20.906Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false -[DEBUG - 2015-10-12T21:55:20.906Z] SessionReqHand - _SuccessHandler - status: success -[DEBUG - 2015-10-12T21:55:20.908Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} -[DEBUG - 2015-10-12T21:55:20.910Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} -[DEBUG - 2015-10-12T21:55:20.912Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"62","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2F&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} -[DEBUG - 2015-10-12T21:55:20.913Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2F&redirect=true -[DEBUG - 2015-10-12T21:55:20.913Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":12,"method":"GET","time":"2015-10-12T21:55:20.913Z","url":"http://127.0.0.1:4446/new-page?url=%2F&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.914Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":12,"redirectURL":"http://127.0.0.1:64984/","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.914Z","url":"http://127.0.0.1:4446/new-page?url=%2F&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.914Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":13,"method":"GET","time":"2015-10-12T21:55:20.914Z","url":"http://127.0.0.1:64984/"} -[DEBUG - 2015-10-12T21:55:20.918Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":2527,"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":13,"redirectURL":null,"stage":"start","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.918Z","url":"http://127.0.0.1:64984/"} -[DEBUG - 2015-10-12T21:55:20.919Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test log entry -[DEBUG - 2015-10-12T21:55:20.919Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test warn entry -[DEBUG - 2015-10-12T21:55:20.919Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test debug entry -[DEBUG - 2015-10-12T21:55:20.919Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onConsoleMessage - a test error entry -[DEBUG - 2015-10-12T21:55:20.920Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":"text/html","headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"cache-control","value":"no-store"},{"name":"etag","value":"\"25618546-2527-1444679936000\""},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"last-modified","value":"Mon, 12 Oct 2015 19:58:56 GMT"},{"name":"content-type","value":"text/html"},{"name":"content-length","value":"2527"},{"name":"connection","value":"keep-alive"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==; path=/"}],"id":13,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.920Z","url":"http://127.0.0.1:64984/"} -[DEBUG - 2015-10-12T21:55:20.921Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Referer","value":"http://127.0.0.1:64984/"},{"name":"Accept","value":"*/*"}],"id":14,"method":"GET","time":"2015-10-12T21:55:20.921Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} -[DEBUG - 2015-10-12T21:55:20.924Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceError - {"errorCode":203,"errorString":"Error downloading http://127.0.0.1:64984/non-existent-image.jpg - server replied: Not Found","id":14,"url":"http://127.0.0.1:64984/non-existent-image.jpg"} -[DEBUG - 2015-10-12T21:55:20.924Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"server","value":"node-static/0.7.7"},{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"connection","value":"keep-alive"},{"name":"transfer-encoding","value":"chunked"}],"id":14,"redirectURL":null,"stage":"end","status":404,"statusText":"Not Found","time":"2015-10-12T21:55:20.924Z","url":"http://127.0.0.1:64984/non-existent-image.jpg"} -[DEBUG - 2015-10-12T21:55:20.925Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false -[DEBUG - 2015-10-12T21:55:20.925Z] SessionReqHand - _SuccessHandler - status: success -[DEBUG - 2015-10-12T21:55:20.925Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished -[DEBUG - 2015-10-12T21:55:20.925Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success -[DEBUG - 2015-10-12T21:55:20.926Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} -[DEBUG - 2015-10-12T21:55:20.928Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} -[DEBUG - 2015-10-12T21:55:20.929Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"67","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2Ferror&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} -[DEBUG - 2015-10-12T21:55:20.929Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2Ferror&redirect=true -[DEBUG - 2015-10-12T21:55:20.930Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":15,"method":"GET","time":"2015-10-12T21:55:20.930Z","url":"http://127.0.0.1:4446/new-page?url=%2Ferror&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.931Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/error"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":15,"redirectURL":"http://127.0.0.1:64984/error","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.931Z","url":"http://127.0.0.1:4446/new-page?url=%2Ferror&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.931Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":16,"method":"GET","time":"2015-10-12T21:55:20.931Z","url":"http://127.0.0.1:64984/error"} -[DEBUG - 2015-10-12T21:55:20.935Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"bodySize":16,"contentType":null,"headers":[{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"connection","value":"keep-alive"},{"name":"content-length","value":"16"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7ImRhdGUiOiJNb24sIDEyIE9jdCAyMDE1IDIxOjU1OjIwIEdNVCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIiwiY29udGVudC1sZW5ndGgiOiIxNiJ9LCJzdGF0dXNDb2RlIjo1MDB9; path=/"},{"name":"cache-control","value":"no-store"}],"id":16,"redirectURL":null,"stage":"start","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.934Z","url":"http://127.0.0.1:64984/error"} -[DEBUG - 2015-10-12T21:55:20.935Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"connection","value":"keep-alive"},{"name":"content-length","value":"16"},{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7ImRhdGUiOiJNb24sIDEyIE9jdCAyMDE1IDIxOjU1OjIwIEdNVCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIiwiY29udGVudC1sZW5ndGgiOiIxNiJ9LCJzdGF0dXNDb2RlIjo1MDB9; path=/"},{"name":"cache-control","value":"no-store"}],"id":16,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.935Z","url":"http://127.0.0.1:64984/error"} -[DEBUG - 2015-10-12T21:55:20.938Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished -[DEBUG - 2015-10-12T21:55:20.938Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success -[DEBUG - 2015-10-12T21:55:20.940Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false -[DEBUG - 2015-10-12T21:55:20.941Z] SessionReqHand - _SuccessHandler - status: success -[DEBUG - 2015-10-12T21:55:20.942Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} -[DEBUG - 2015-10-12T21:55:20.944Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} -[DEBUG - 2015-10-12T21:55:20.946Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"67","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"POST","post":"{\"url\":\"http://127.0.0.1:4446/new-page?url=%2Fcrash&redirect=true\"}","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/url","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","url"]}} -[DEBUG - 2015-10-12T21:55:20.946Z] SessionReqHand - _postUrlCommand - Session 'ee9039f0-712b-11e5-b44a-3f5088d27053' is about to load URL: http://127.0.0.1:4446/new-page?url=%2Fcrash&redirect=true -[DEBUG - 2015-10-12T21:55:20.947Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":17,"method":"GET","time":"2015-10-12T21:55:20.947Z","url":"http://127.0.0.1:4446/new-page?url=%2Fcrash&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.953Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Location","value":"http://127.0.0.1:64984/crash"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":17,"redirectURL":"http://127.0.0.1:64984/crash","stage":"end","status":302,"statusText":"Found","time":"2015-10-12T21:55:20.953Z","url":"http://127.0.0.1:4446/new-page?url=%2Fcrash&redirect=true"} -[DEBUG - 2015-10-12T21:55:20.953Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceRequested - {"headers":[{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34"},{"name":"Accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}],"id":18,"method":"GET","time":"2015-10-12T21:55:20.953Z","url":"http://127.0.0.1:64984/crash"} -[DEBUG - 2015-10-12T21:55:20.958Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: true -[DEBUG - 2015-10-12T21:55:20.959Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - page.onResourceReceived - {"contentType":null,"headers":[{"name":"Set-Cookie","value":"_testium_=eyJoZWFkZXJzIjp7fSwic3RhdHVzQ29kZSI6NTAwfQ==; path=/"},{"name":"cache-control","value":"no-store"},{"name":"Date","value":"Mon, 12 Oct 2015 21:55:20 GMT"},{"name":"Connection","value":"keep-alive"},{"name":"Transfer-Encoding","value":"chunked"}],"id":18,"redirectURL":null,"stage":"end","status":200,"statusText":"OK","time":"2015-10-12T21:55:20.959Z","url":"http://127.0.0.1:64984/crash"} -[DEBUG - 2015-10-12T21:55:20.960Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _oneShotCallback - onLoadFinished -[DEBUG - 2015-10-12T21:55:20.960Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - onLoadFinished: success -[DEBUG - 2015-10-12T21:55:21.059Z] Session [ee9039f0-712b-11e5-b44a-3f5088d27053] - _execFuncAndWaitForLoadDecorator - Page Loading in Session: false -[DEBUG - 2015-10-12T21:55:21.060Z] SessionReqHand - _SuccessHandler - status: success -[DEBUG - 2015-10-12T21:55:21.062Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","urlParsed":{"anchor":"","query":"","file":"window_handle","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/window_handle","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","window_handle"]}} -[DEBUG - 2015-10-12T21:55:21.065Z] RouterReqHand - _handle - {"headers":{"Accept":"*/*","Content-Length":"0","Content-Type":"application/json","Host":"127.0.0.1:64983"},"httpVersion":"1.1","method":"GET","url":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/","path":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","relative":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/ee9039f0-712b-11e5-b44a-3f5088d27053/cookie","queryKey":{},"chunks":["session","ee9039f0-712b-11e5-b44a-3f5088d27053","cookie"]}} diff --git a/test/log/proxy.log b/test/log/proxy.log deleted file mode 100644 index 834ad6c..0000000 --- a/test/log/proxy.log +++ /dev/null @@ -1,60 +0,0 @@ -Listening on port 64984 and proxying to 64982. -Listening for commands on port 4446. ---> GET /testium-priming-load (prime the browser) - -[System] Marking new page request with options: {"url":"/blackholed-resource.html","redirect":true} ---> GET /blackholed-resource.html - {"port":64982,"path":"/blackholed-resource.html","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} -<-- 200 /blackholed-resource.html ---> GET /blackhole - {"port":64982,"path":"/blackhole","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"*/*","referer":"http://127.0.0.1:64984/blackholed-resource.html","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQyLTY4NC0xNDQ0Njc5OTM2MDAwXCIiLCJkYXRlIjoiTW9uLCAxMiBPY3QgMjAxNSAyMTo1NToyMCBHTVQiLCJsYXN0LW1vZGlmaWVkIjoiTW9uLCAxMiBPY3QgMjAxNSAxOTo1ODo1NiBHTVQiLCJjb250ZW50LXR5cGUiOiJ0ZXh0L2h0bWwiLCJjb250ZW50LWxlbmd0aCI6IjY4NCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIn0sInN0YXR1c0NvZGUiOjIwMH0=","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} - -[System] Marking new page request with options: {"url":"/","redirect":true} -[System] Aborting request for: /blackhole -Error: socket hang up - at createHangUpError (_http_client.js:203:15) - at Socket.socketCloseListener (_http_client.js:235:23) - at emitOne (events.js:82:20) - at Socket.emit (events.js:169:7) - at TCP._onclose (net.js:469:12) -<-- 500 /blackhole ---> GET / - {"port":64982,"path":"/","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQyLTY4NC0xNDQ0Njc5OTM2MDAwXCIiLCJkYXRlIjoiTW9uLCAxMiBPY3QgMjAxNSAyMTo1NToyMCBHTVQiLCJsYXN0LW1vZGlmaWVkIjoiTW9uLCAxMiBPY3QgMjAxNSAxOTo1ODo1NiBHTVQiLCJjb250ZW50LXR5cGUiOiJ0ZXh0L2h0bWwiLCJjb250ZW50LWxlbmd0aCI6IjY4NCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIn0sInN0YXR1c0NvZGUiOjIwMH0=","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} -<-- 200 / ---> GET /non-existent-image.jpg - {"port":64982,"path":"/non-existent-image.jpg","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","referer":"http://127.0.0.1:64984/","accept":"*/*","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} -<-- 404 /non-existent-image.jpg - -[System] Marking new page request with options: {"url":"/","redirect":true} ---> GET / - {"port":64982,"path":"/","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} -<-- 200 / ---> GET /non-existent-image.jpg - {"port":64982,"path":"/non-existent-image.jpg","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","referer":"http://127.0.0.1:64984/","accept":"*/*","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} -<-- 404 /non-existent-image.jpg - -[System] Marking new page request with options: {"url":"/","redirect":true} ---> GET / - {"port":64982,"path":"/","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} -<-- 200 / ---> GET /non-existent-image.jpg - {"port":64982,"path":"/non-existent-image.jpg","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","referer":"http://127.0.0.1:64984/","accept":"*/*","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} -<-- 404 /non-existent-image.jpg - -[System] Marking new page request with options: {"url":"/error","redirect":true} ---> GET /error - {"port":64982,"path":"/error","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","cookie":"_testium_=eyJoZWFkZXJzIjp7InNlcnZlciI6Im5vZGUtc3RhdGljLzAuNy43IiwiY2FjaGUtY29udHJvbCI6Im1heC1hZ2U9MzYwMCIsImV0YWciOiJcIjI1NjE4NTQ2LTI1MjctMTQ0NDY3OTkzNjAwMFwiIiwiZGF0ZSI6Ik1vbiwgMTIgT2N0IDIwMTUgMjE6NTU6MjAgR01UIiwibGFzdC1tb2RpZmllZCI6Ik1vbiwgMTIgT2N0IDIwMTUgMTk6NTg6NTYgR01UIiwiY29udGVudC10eXBlIjoidGV4dC9odG1sIiwiY29udGVudC1sZW5ndGgiOiIyNTI3IiwiY29ubmVjdGlvbiI6ImtlZXAtYWxpdmUifSwic3RhdHVzQ29kZSI6MjAwfQ==","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} -<-- 200 /error - -[System] Marking new page request with options: {"url":"/crash","redirect":true} ---> GET /crash - {"port":64982,"path":"/crash","method":"GET","headers":{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.8 Safari/534.34","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","cookie":"_testium_=eyJoZWFkZXJzIjp7ImRhdGUiOiJNb24sIDEyIE9jdCAyMDE1IDIxOjU1OjIwIEdNVCIsImNvbm5lY3Rpb24iOiJrZWVwLWFsaXZlIiwiY29udGVudC1sZW5ndGgiOiIxNiJ9LCJzdGF0dXNDb2RlIjo1MDB9","connection":"keep-alive","accept-encoding":"gzip","accept-language":"en-US,*","host":"127.0.0.1:64984","cache-control":"no-store"}} -Error: socket hang up - at createHangUpError (_http_client.js:203:15) - at Socket.socketOnEnd (_http_client.js:288:23) - at emitNone (events.js:72:20) - at Socket.emit (events.js:166:7) - at endReadableNT (_stream_readable.js:893:12) - at doNTCallback2 (node.js:430:9) - at process._tickCallback (node.js:344:17) -<-- 200 /crash From b0980181c95502846078edd5b3aceabfbcbee54d Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Mon, 12 Oct 2015 15:55:51 -0700 Subject: [PATCH 04/11] Add cookie tests --- test/integration/console.test.js | 2 -- test/integration/cookie.test.js | 54 +++++++++++++++++++++++++++++ test/integration/element.test.js | 2 -- test/integration/evaluate.test.js | 2 -- test/integration/navigation.test.js | 2 -- test/integration/proxy.test.js | 2 -- 6 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 test/integration/cookie.test.js diff --git a/test/integration/console.test.js b/test/integration/console.test.js index a6b57fa..dfc4799 100644 --- a/test/integration/console.test.js +++ b/test/integration/console.test.js @@ -1,5 +1,3 @@ -'use strict'; - import {getBrowser} from '../mini-testium-mocha'; import assert from 'assertive'; diff --git a/test/integration/cookie.test.js b/test/integration/cookie.test.js new file mode 100644 index 0000000..e313691 --- /dev/null +++ b/test/integration/cookie.test.js @@ -0,0 +1,54 @@ +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('cookie', () => { + let browser; + before(async () => (browser = await getBrowser())); + + it('can be set individually', () => { + browser.setCookie({ + name: 'test_cookie', + value: '3' + }); + + var cookie = browser.getCookie('test_cookie'); + assert.equal('3', cookie.value); + }); + + it('can be set in groups', () => { + browser.setCookies([ + { name: 'test_cookie1', value: '5' }, + { name: 'test_cookie2', value: '7' } + ]); + + var cookie1 = browser.getCookie('test_cookie1'); + var cookie2 = browser.getCookie('test_cookie2'); + + assert.equal('5', cookie1.value); + assert.equal('7', cookie2.value); + }); + + it('can be cleared as a group', () => { + browser.setCookie({ + name: 'test_cookie', + value: '9' + }); + browser.clearCookies(); + + var cookies = browser.getCookies(); + + assert.equal(0, cookies.length); + }); + + it('can be cleared individually', () => { + browser.setCookie({ + name: 'test_cookie', + value: '4' + }); + + browser.clearCookie('test_cookie'); + + var cookie = browser.getCookie('test_cookie'); + assert.falsey(cookie); + }); +}); diff --git a/test/integration/element.test.js b/test/integration/element.test.js index a494422..760931e 100644 --- a/test/integration/element.test.js +++ b/test/integration/element.test.js @@ -1,5 +1,3 @@ -'use strict'; - import {getBrowser} from '../mini-testium-mocha'; import assert from 'assertive'; diff --git a/test/integration/evaluate.test.js b/test/integration/evaluate.test.js index 51dfece..a2a77c2 100644 --- a/test/integration/evaluate.test.js +++ b/test/integration/evaluate.test.js @@ -1,5 +1,3 @@ -'use strict'; - import {getBrowser} from '../mini-testium-mocha'; import assert from 'assertive'; diff --git a/test/integration/navigation.test.js b/test/integration/navigation.test.js index 4feffe8..7282135 100644 --- a/test/integration/navigation.test.js +++ b/test/integration/navigation.test.js @@ -1,5 +1,3 @@ -'use strict'; - import {getBrowser} from '../mini-testium-mocha'; import assert from 'assertive'; diff --git a/test/integration/proxy.test.js b/test/integration/proxy.test.js index 16afcf3..97d2237 100644 --- a/test/integration/proxy.test.js +++ b/test/integration/proxy.test.js @@ -1,5 +1,3 @@ -'use strict'; - import {getBrowser} from '../mini-testium-mocha'; import assert from 'assertive'; From 0a583a63581cce07d3bc59e78bcab63409d74e2a Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Mon, 12 Oct 2015 16:25:52 -0700 Subject: [PATCH 05/11] Port alert, form, and header tests --- lib/browser/alert.js | 8 ++++ lib/browser/index.js | 2 + lib/browser/input.js | 28 +++++++++++ test/integration/dialog.test.js | 85 +++++++++++++++++++++++++++++++++ test/integration/form.test.js | 61 +++++++++++++++++++++++ test/integration/header.test.js | 36 ++++++++++++++ 6 files changed, 220 insertions(+) create mode 100644 lib/browser/alert.js create mode 100644 lib/browser/input.js create mode 100644 test/integration/dialog.test.js create mode 100644 test/integration/form.test.js create mode 100644 test/integration/header.test.js diff --git a/lib/browser/alert.js b/lib/browser/alert.js new file mode 100644 index 0000000..f07775f --- /dev/null +++ b/lib/browser/alert.js @@ -0,0 +1,8 @@ +'use strict'; + +exports._forwarded = [ + 'acceptAlert', + 'dismissAlert', + 'getAlertText', + 'typeAlert' +]; diff --git a/lib/browser/index.js b/lib/browser/index.js index 7cb272c..aac20c1 100644 --- a/lib/browser/index.js +++ b/lib/browser/index.js @@ -4,9 +4,11 @@ var _ = require('lodash'); var assert = require('assertive'); var builtIns = [ + require('./alert'), require('./cookie'), require('./debug'), require('./element'), + require('./input'), require('./navigation'), require('./page') ]; diff --git a/lib/browser/input.js b/lib/browser/input.js new file mode 100644 index 0000000..b361b9e --- /dev/null +++ b/lib/browser/input.js @@ -0,0 +1,28 @@ +'use strict'; + +var assert = require('assertive'); +var _ = require('lodash'); + +exports.clear = function clear(selector) { + assert.hasType('clear(selector) - requires (String) selector', String, selector); + return this.getExistingElement(selector).clear(); +}; + +exports.type = function type(selector) { + var keys = _.toArray(arguments).slice(1); + assert.hasType('type(selector, ...keys) - requires (String) selector', String, selector); + assert.truthy('type(selector, ...keys) - requires keys', keys.length > 0); + var element = this.getExistingElement(selector); + return element.type.apply(element, keys); +}; + +exports.setValue = function setValue(selector) { + var keys = _.toArray(arguments).slice(1); + assert.hasType('setValue(selector, ...keys) - requires (String) selector', String, selector); + assert.truthy('setValue(selector, ...keys) - requires keys', keys.length > 0); + + var element = this.getExistingElement(selector); + element.clear(); + return element.type.apply(element, keys); +}; +exports.clearAndType = exports.setValue; diff --git a/test/integration/dialog.test.js b/test/integration/dialog.test.js new file mode 100644 index 0000000..d82b0ec --- /dev/null +++ b/test/integration/dialog.test.js @@ -0,0 +1,85 @@ +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +import Config from 'testium-core/lib/config'; + +var browserName = Config.load().get('browser'); + +describe('dialogs', () => { + if (browserName === 'phantomjs') { + xit('skipping tests because browser phantomjs doesn\'t support alerts'); + return; + } + + let browser, target; + before(async () => (browser = await getBrowser())); + + before(() => { + browser.navigateTo('/'); + browser.assert.httpStatus(200); + + target = browser.getElement('#alert_target'); + browser.click('.link_to_clear_alert_target'); + }); + + xdescribe('alert', () => { + beforeEach(() => browser.click('.link_to_open_an_alert')); + + it('can get an alert text', () => { + var text = browser.getAlertText(); + browser.acceptAlert(); + assert.equal('Alert text was not found', 'An alert!', text); + }); + + it('can accept an alert', () => { + browser.acceptAlert(); + assert.equal('alerted', target.get('text')); + }); + + it('can dismiss an alert', () => { + browser.dismissAlert(); + assert.equal('alerted', target.get('text')); + }); + }); + + describe('confirm', () => { + beforeEach(() => browser.click('.link_to_open_a_confirm')); + + it('can get confirm text', () => { + var text = browser.getAlertText(); + browser.acceptAlert(); + assert.equal('Confirm text was not found', 'A confirmation!', text); + }); + + it('can accept a confirm', () => { + browser.acceptAlert(); + assert.equal('confirmed', target.get('text')); + }); + + it('can dismiss a confirm', () => { + browser.dismissAlert(); + assert.equal('dismissed', target.get('text')); + }); + }); + + describe('prompt', () => { + beforeEach(() => browser.click('.link_to_open_a_prompt')); + + it('can get prompt text', () => { + text = browser.getAlertText(); + browser.acceptAlert(); + assert.equal('Confirm text was not found', 'A prompt!', text); + }); + + it('can send text to and accept a prompt', () => { + browser.typeAlert('Some words'); + browser.acceptAlert(); + assert.equal('Some words', target.get('text')); + }); + + it('can dismiss a prompt', () => { + browser.dismissAlert(); + assert.equal('dismissed', target.get('text')); + }); + }); +}); diff --git a/test/integration/form.test.js b/test/integration/form.test.js new file mode 100644 index 0000000..06a9960 --- /dev/null +++ b/test/integration/form.test.js @@ -0,0 +1,61 @@ +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('evaluate', () => { + let browser; + before(async () => (browser = await getBrowser())); + + before(() => { + browser.navigateTo('/'); + browser.assert.httpStatus(200); + }); + + it('can get an input\'s value', () => { + var element = browser.getElement('#text-input'); + var value = element.get('value'); + assert.equal('Input value was not found', 'initialvalue', value); + }); + + it('can clear an input\'s value', () => { + var element = browser.getElement('#text-input'); + element.clear(); + var value = element.get('value'); + assert.equal('Input value was not cleared', '', value); + }); + + it('can type into an input', () => { + var element = browser.getElement('#text-input'); + element.type('new stuff'); + var value = element.get('value'); + assert.equal('Input value was not typed', 'new stuff', value); + }); + + it('can replace the input\'s value', () => { + var element = browser.getElement('#text-input'); + var value = element.get('value'); + assert.notEqual('Input value is already empty', '', value); + browser.clearAndType('#text-input', 'new stuff2'); + value = element.get('value'); + assert.equal('Input value was not typed', 'new stuff2', value); + }); + + it('can get a textarea\'s value', () => { + var element = browser.getElement('#text-area'); + var value = element.get('value'); + assert.equal('Input value was not found', 'initialvalue', value); + }); + + it('can clear an textarea\'s value', () => { + var element = browser.getElement('#text-area'); + element.clear(); + var value = element.get('value'); + assert.equal('Input value was not cleared', '', value); + }); + + it('can type into a textarea', () => { + var element = browser.getElement('#text-area'); + element.type('new stuff'); + var value = element.get('value'); + assert.equal('Input value was not typed', 'new stuff', value); + }); +}); diff --git a/test/integration/header.test.js b/test/integration/header.test.js new file mode 100644 index 0000000..ac4103f --- /dev/null +++ b/test/integration/header.test.js @@ -0,0 +1,36 @@ +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('header', () => { + let browser; + before(async () => (browser = await getBrowser())); + + describe('can be retireved', () => { + before(() => { + browser.navigateTo('/'); + browser.assert.httpStatus(200); + }); + + it('as a group', () => { + var headers = browser.getHeaders(); + var contentType = headers['content-type']; + assert.equal('text/html', contentType); + }); + + it('individually', () => { + var contentType = browser.getHeader('content-type'); + assert.equal('text/html', contentType); + }); + }); + + describe('can be set', () => { + before(() => + browser.navigateTo('/echo', { headers: { 'x-something': 'that place' } })); + + it('to new values', () => { + var source = browser.getElement('body').get('text'); + var body = JSON.parse(source); + assert.equal(body.headers['x-something'], 'that place'); + }); + }); +}); From 914ba0dc56c6d0b00148dd15970ce6d892204908 Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Mon, 12 Oct 2015 17:04:52 -0700 Subject: [PATCH 06/11] Add tls, unicode, and window test --- lib/browser/index.js | 3 +- lib/browser/window.js | 24 ++++++++++++++ test/integration/non_browser.test.js | 17 ++++++++++ test/integration/page_data.test.js | 15 +++++++++ test/integration/ssl.test.js | 14 ++++++++ test/integration/unicode.test.js | 17 ++++++++++ test/integration/window.test.js | 48 ++++++++++++++++++++++++++++ 7 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 lib/browser/window.js create mode 100644 test/integration/non_browser.test.js create mode 100644 test/integration/page_data.test.js create mode 100644 test/integration/ssl.test.js create mode 100644 test/integration/unicode.test.js create mode 100644 test/integration/window.test.js diff --git a/lib/browser/index.js b/lib/browser/index.js index aac20c1..e92d2bc 100644 --- a/lib/browser/index.js +++ b/lib/browser/index.js @@ -10,7 +10,8 @@ var builtIns = [ require('./element'), require('./input'), require('./navigation'), - require('./page') + require('./page'), + require('./window') ]; function Browser(driver, options) { diff --git a/lib/browser/window.js b/lib/browser/window.js new file mode 100644 index 0000000..0d148e2 --- /dev/null +++ b/lib/browser/window.js @@ -0,0 +1,24 @@ +'use strict'; + +var assert = require('assertive'); + +exports._forwarded = [ + 'switchToWindow', + 'closeWindow' +]; + +exports.switchToDefaultFrame = function switchToDefaultFrame() { + return this.driver.switchToFrame(null); +}; + +exports.switchToFrame = function switchToFrame(indexOrNameOrId) { + assert.truthy('switchToFrame(indexOrNameOrId) - requires (Number|String) indexOrNameOrId', + indexOrNameOrId); + return this.driver.switchToFrame(indexOrNameOrId); +}; + +exports.switchToDefaultWindow = function switchToDefaultWindow() { + assert.truthy('Attempted to locate the root window, but failed. Did you navigate to a URL first?', + this.driver.rootWindow); + return this.driver.switchToWindow(this.driver.rootWindow); +}; diff --git a/test/integration/non_browser.test.js b/test/integration/non_browser.test.js new file mode 100644 index 0000000..6af250b --- /dev/null +++ b/test/integration/non_browser.test.js @@ -0,0 +1,17 @@ +import {get} from 'http'; + +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('Non-browser test', () => { + let browser; + before(async () => (browser = await getBrowser())); + + it('can make a request without using the browser', done => { + var url = `${browser.appUrl}/echo`; + get(url, response => { + assert.equal(200, response.statusCode); + done(); + }).on('error', done); + }); +}); diff --git a/test/integration/page_data.test.js b/test/integration/page_data.test.js new file mode 100644 index 0000000..31bcca8 --- /dev/null +++ b/test/integration/page_data.test.js @@ -0,0 +1,15 @@ +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('header', () => { + let browser; + before(async () => (browser = await getBrowser())); + + before(() => browser.navigateTo('/')); + + it('title', () => + assert.equal('Test Title', browser.getPageTitle())); + + it('source', () => + assert.include('DOCTYPE', browser.getPageSource())); +}); diff --git a/test/integration/ssl.test.js b/test/integration/ssl.test.js new file mode 100644 index 0000000..5f347ce --- /dev/null +++ b/test/integration/ssl.test.js @@ -0,0 +1,14 @@ +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('ssl/tls', () => { + let browser; + before(async () => (browser = await getBrowser())); + + it('TLS is supported', () => { + browser.navigateTo('https://www.howsmyssl.com/a/check'); + var raw = browser.getExistingElement('pre').get('text'); + var sslReport = JSON.parse(raw); + assert.match(/^TLS/, sslReport.tls_version); + }); +}); diff --git a/test/integration/unicode.test.js b/test/integration/unicode.test.js new file mode 100644 index 0000000..f8992a2 --- /dev/null +++ b/test/integration/unicode.test.js @@ -0,0 +1,17 @@ +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('unicode support', () => { + let browser; + before(async () => (browser = await getBrowser())); + + before(() => browser.navigateTo('/')); + + it('multibyte unicode can pass through and back from WebDriver', () => { + var multibyteText = '日本語 text'; + var element = browser.getElement('#blank-input'); + element.type(multibyteText); + var result = element.get('value'); + assert.equal(result, multibyteText); + }); +}); diff --git a/test/integration/window.test.js b/test/integration/window.test.js new file mode 100644 index 0000000..19fad58 --- /dev/null +++ b/test/integration/window.test.js @@ -0,0 +1,48 @@ +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('window api', () => { + let browser; + before(async () => (browser = await getBrowser())); + + describe('frames', () => { + before(() => { + browser.navigateTo('/windows.html'); + browser.assert.httpStatus(200); + }); + + it('can be switched', () => { + browser.switchToFrame('cool-frame'); + var iframeContent = browser.getElement('.in-iframe-only').get('text'); + browser.switchToDefaultFrame(); + var primaryContent = browser.getElement('.in-iframe-only'); + assert.equal('iframe content!', iframeContent); + assert.equal(null, primaryContent); + }); + + it('can be found when nested', () => { + browser.switchToFrame('cool-frame'); + browser.switchToFrame('nested-frame'); + var element = browser.getElement('#nested-frame-div'); + assert.truthy('nested frame content', element); + }); + }); + + describe('popups', () => { + before(() => { + browser.navigateTo('/windows.html'); + browser.assert.httpStatus(200); + }); + + it('can be opened', () => { + browser.click('#open-popup'); + browser.switchToWindow('popup1'); + var popupContent = browser.getElement('.popup-only').get('text'); + browser.closeWindow(); + browser.switchToDefaultWindow(); + var primaryContent = browser.getElement('.popup-only'); + assert.equal('popup content!', popupContent); + assert.equal(null, primaryContent); + }); + }); +}); From fb042f55328a093b6a9007e78aabe42832c2e44c Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Mon, 12 Oct 2015 17:38:51 -0700 Subject: [PATCH 07/11] Port img loaded and screenshot tests --- lib/assert/imgLoaded.js | 34 ++++++++++++++ lib/assert/imgLoaded_client.js | 36 +++++++++++++++ lib/assert/index.js | 2 +- test/integration/assert/imgLoaded.test.coffee | 37 ---------------- test/integration/assert/imgLoaded.test.js | 44 +++++++++++++++++++ test/integration/screenshot.test.js | 19 ++++++++ 6 files changed, 134 insertions(+), 38 deletions(-) create mode 100644 lib/assert/imgLoaded.js create mode 100644 lib/assert/imgLoaded_client.js delete mode 100644 test/integration/assert/imgLoaded.test.coffee create mode 100644 test/integration/assert/imgLoaded.test.js create mode 100644 test/integration/screenshot.test.js diff --git a/lib/assert/imgLoaded.js b/lib/assert/imgLoaded.js new file mode 100644 index 0000000..95c219c --- /dev/null +++ b/lib/assert/imgLoaded.js @@ -0,0 +1,34 @@ +'use strict'; + +var assert = require('assertive'); +var imgLoadedFn = require('./imgLoaded_client'); +var _ = require('lodash'); + +exports.imgLoaded = function imgLoaded(doc, selector) { + if (arguments.length === 1) { + selector = doc; + doc = undefined; + } + assert.hasType('imgLoaded(selector) - requires (String) selector', String, selector); + + var result = this.browser.evaluate(selector, imgLoadedFn); + if (result === true) { + return; + } + + function fail(help) { + var message = 'imgLoaded ' + JSON.stringify(selector) + ': ' + help; + if (doc) { + message = doc + '\n' + message; + } + throw new Error(message); + } + + if (result === 0) { + fail('element not found'); + } else if (_.isNumber(result)) { + fail('non-unique selector; count: ' + result); + } else { + fail('failed to load ' + result); + } +}; diff --git a/lib/assert/imgLoaded_client.js b/lib/assert/imgLoaded_client.js new file mode 100644 index 0000000..5adf829 --- /dev/null +++ b/lib/assert/imgLoaded_client.js @@ -0,0 +1,36 @@ +'use strict'; + +// returns true if the image is loaded and decoded, +// or a number, if it didn't find one single image, +// or a helpful error if it wasn't an image, +// or the path, if it found some non-loaded image +module.exports = function imgLoaded(selector) { + function describe(elem) { + var tag = (elem.tagName || '').toLowerCase(); + if (elem.id) { + tag += '#' + elem.id; + } + var classes = elem.className.replace(/^\s+|\s+$/g, ''); + if (classes) { + tag += '.' + classes.replace(/\s+/g, '.'); + } + return tag; + } + + var imgs = document.querySelectorAll(selector); + if (imgs.length !== 1) { + return imgs.length; + } + img = imgs[0]; + + if (!img.src) { + var oops = describe(img); + if ((img.tagName || '').match(/^img$/i)) { + return 'src-less ' + describe(img); + } else { + return 'non-image ' + describe(img); + } + } + + return img.complete && img.naturalWidth ? true : img.src; +}; diff --git a/lib/assert/index.js b/lib/assert/index.js index bc52b95..5349772 100644 --- a/lib/assert/index.js +++ b/lib/assert/index.js @@ -9,7 +9,7 @@ function Assertions(driver, browser) { _.each([ require('./element'), - // require('./imgLoaded'), + require('./imgLoaded'), require('./navigation') ], function(mixin) { _.extend(Assertions.prototype, mixin); diff --git a/test/integration/assert/imgLoaded.test.coffee b/test/integration/assert/imgLoaded.test.coffee deleted file mode 100644 index 6a9efbe..0000000 --- a/test/integration/assert/imgLoaded.test.coffee +++ /dev/null @@ -1,37 +0,0 @@ -injectBrowser = require '../../../mocha' -assert = require 'assertive' - -describe 'imgLoaded', -> - before injectBrowser() - - before -> - @browser.navigateTo '/' - - it 'throws an error when the image was not found', -> - msg = 'imgLoaded "img.not-in-the-page": element not found' - err = assert.throws => @browser.assert.imgLoaded 'img.not-in-the-page' - assert.include msg, err.message - - it 'throws an error for non-unique selectors when finding multiple images', -> - msg = 'imgLoaded "img[alt][class]": non-unique selector; count: 3' - err = assert.throws => @browser.assert.imgLoaded 'img[alt][class]' - assert.include msg, err.message - - it 'throws an error for an image not successfully loaded / decoded', -> - msg = 'imgLoaded "img.fail": failed to load ' - err = assert.throws => @browser.assert.imgLoaded 'img.fail' - assert.include msg, err.message - assert.include '/non-existent-image.jpg', err.message - - it 'throws a helpful error for an missing the src attribute', -> - msg = 'imgLoaded "#no": failed to load src-less img#no.src.dude' - err = assert.throws => @browser.assert.imgLoaded '#no' - assert.include msg, err.message - - it 'throws a helpful error when the selector did not match an tag', -> - msg = 'imgLoaded "body": failed to load non-image body' - err = assert.throws => @browser.assert.imgLoaded 'body' - assert.include msg, err.message - - it 'does nothing when the image was successfully loaded and decoded', -> - @browser.assert.imgLoaded 'img.okay' diff --git a/test/integration/assert/imgLoaded.test.js b/test/integration/assert/imgLoaded.test.js new file mode 100644 index 0000000..01142e5 --- /dev/null +++ b/test/integration/assert/imgLoaded.test.js @@ -0,0 +1,44 @@ +import {getBrowser} from '../../mini-testium-mocha'; +import assert from 'assertive'; + +describe('imgLoaded', () => { + let browser; + before(async () => (browser = await getBrowser())); + + before(() => browser.navigateTo('/')); + + it('throws an error when the image was not found', () => { + var msg = 'imgLoaded "img.not-in-the-page": element not found'; + var err = assert.throws(() => browser.assert.imgLoaded('img.not-in-the-page')); + assert.include(msg, err.message); + }); + + it('throws an error for non-unique selectors when finding multiple images', () => { + var msg = 'imgLoaded "img[alt][class]": non-unique selector; count: 3'; + var err = assert.throws(() => browser.assert.imgLoaded('img[alt][class]')); + assert.include(msg, err.message); + }); + + it('throws an error for an image not successfully loaded / decoded', () => { + var msg = 'imgLoaded "img.fail": failed to load '; + var err = assert.throws(() => browser.assert.imgLoaded('img.fail')); + assert.include(msg, err.message); + assert.include('/non-existent-image.jpg', err.message); + }); + + it('throws a helpful error for an missing the src attribute', () => { + var msg = 'imgLoaded "#no": failed to load src-less img#no.src.dude'; + var err = assert.throws(() => browser.assert.imgLoaded('#no')); + assert.include(msg, err.message); + }); + + it('throws a helpful error when the selector did not match an tag', () => { + var msg = 'imgLoaded "body": failed to load non-image body'; + var err = assert.throws(() => browser.assert.imgLoaded('body')); + assert.include(msg, err.message); + }); + + it('does nothing when the image was successfully loaded and decoded', () => { + browser.assert.imgLoaded('img.okay'); + }); +}); diff --git a/test/integration/screenshot.test.js b/test/integration/screenshot.test.js new file mode 100644 index 0000000..574963c --- /dev/null +++ b/test/integration/screenshot.test.js @@ -0,0 +1,19 @@ +import {getBrowser} from '../mini-testium-mocha'; +import assert from 'assertive'; + +describe('screenshots', () => { + let browser; + before(async () => (browser = await getBrowser())); + + describe('taking', () => { + let screenshot; + before(() => { + browser.navigateTo('/'); + browser.assert.httpStatus(200); + screenshot = browser.getScreenshot(); + }); + + it('captures the page', () => + assert.expect(screenshot.length > 0)); + }); +}); From 33f0c35522d03821d8abb41b2026b22b0779487c Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Tue, 13 Oct 2015 09:34:07 -0700 Subject: [PATCH 08/11] Add eslint configuration --- .eslintrc | 9 +++ lib/assert/element.js | 4 +- lib/assert/imgLoaded_client.js | 7 +- lib/assert/index.js | 4 +- lib/browser/alert.js | 2 +- lib/browser/cookie.js | 8 +-- lib/browser/debug/console.js | 4 +- lib/browser/debug/index.js | 4 +- lib/browser/element.js | 18 +++-- lib/browser/index.js | 23 +++---- lib/browser/makeUrlRegExp.js | 13 ++-- lib/browser/navigation.js | 2 +- lib/browser/page.js | 2 +- lib/browser/wait.js | 13 ++-- lib/browser/window.js | 2 +- lib/testium-driver-sync.js | 2 +- package.json | 5 +- test/.eslintrc | 9 +++ test/browser/debug.js | 20 +++--- test/integration/assert/imgLoaded.test.js | 20 +++--- test/integration/console.test.js | 36 +++++----- test/integration/cookie.test.js | 18 ++--- test/integration/dialog.test.js | 11 +-- test/integration/element.test.js | 82 +++++++++++------------ test/integration/evaluate.test.js | 2 +- test/integration/form.test.js | 34 +++++----- test/integration/header.test.js | 10 +-- test/integration/navigation.test.js | 12 ++-- test/integration/non_browser.test.js | 2 +- test/integration/proxy.test.js | 10 ++- test/integration/ssl.test.js | 4 +- test/integration/unicode.test.js | 6 +- test/integration/window.test.js | 10 +-- test/mini-testium-mocha.js | 5 +- 34 files changed, 212 insertions(+), 201 deletions(-) create mode 100644 .eslintrc create mode 100644 test/.eslintrc diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..68d14a4 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,9 @@ +{ + "extends": "airbnb/legacy", + "rules": { + "id-length": 0, + "vars-on-top": 0, + "strict": [2, "global"], + "no-param-reassign": 0 + } +} diff --git a/lib/assert/element.js b/lib/assert/element.js index 1b5a8de..3b763f6 100644 --- a/lib/assert/element.js +++ b/lib/assert/element.js @@ -36,7 +36,7 @@ exports.elementHasAttributes = function elementHasAttributes(doc, selector, attr selector = doc; doc = [ 'elementHasAttributes - selector:' + selector, - 'attributesObject:' + JSON.stringify(attributesObject) + 'attributesObject:' + JSON.stringify(attributesObject), ].join('\n'); } else { assert.hasType('elementHasAttributes(docstring, selector, attributesObject) - requires String docstring', String, doc); @@ -47,7 +47,7 @@ exports.elementHasAttributes = function elementHasAttributes(doc, selector, attr var element = this._getElement(selector); - _.each(attributesObject, function(val, attribute) { + _.each(attributesObject, function verifyAttribute(val, attribute) { var actualVal = element.get(attribute); var attrDoc = util.format( '%s\nattribute %j was expected to be %j but was %j.', diff --git a/lib/assert/imgLoaded_client.js b/lib/assert/imgLoaded_client.js index 5adf829..fab7a04 100644 --- a/lib/assert/imgLoaded_client.js +++ b/lib/assert/imgLoaded_client.js @@ -1,3 +1,4 @@ +/* jshint browser: true */ 'use strict'; // returns true if the image is loaded and decoded, @@ -21,15 +22,13 @@ module.exports = function imgLoaded(selector) { if (imgs.length !== 1) { return imgs.length; } - img = imgs[0]; + var img = imgs[0]; if (!img.src) { - var oops = describe(img); if ((img.tagName || '').match(/^img$/i)) { return 'src-less ' + describe(img); - } else { - return 'non-image ' + describe(img); } + return 'non-image ' + describe(img); } return img.complete && img.naturalWidth ? true : img.src; diff --git a/lib/assert/index.js b/lib/assert/index.js index 5349772..0ec646e 100644 --- a/lib/assert/index.js +++ b/lib/assert/index.js @@ -10,8 +10,8 @@ function Assertions(driver, browser) { _.each([ require('./element'), require('./imgLoaded'), - require('./navigation') -], function(mixin) { + require('./navigation'), +], function applyMixin(mixin) { _.extend(Assertions.prototype, mixin); }); diff --git a/lib/browser/alert.js b/lib/browser/alert.js index f07775f..9949f7a 100644 --- a/lib/browser/alert.js +++ b/lib/browser/alert.js @@ -4,5 +4,5 @@ exports._forwarded = [ 'acceptAlert', 'dismissAlert', 'getAlertText', - 'typeAlert' + 'typeAlert', ]; diff --git a/lib/browser/cookie.js b/lib/browser/cookie.js index 8badd5c..f04c87f 100644 --- a/lib/browser/cookie.js +++ b/lib/browser/cookie.js @@ -8,13 +8,13 @@ var getTestiumCookie = require('testium-cookie').getTestiumCookie; exports._forwarded = [ // TODO: Port validateCookie to webdriver-http-sync 'setCookie', - 'clearCookies' + 'clearCookies', ]; -exports.setCookies = function(cookies) { +exports.setCookies = function setCookies(cookies) { _.each(cookies, this.setCookie, this); return this; -} +}; exports.getCookie = function getCookie(name) { assert.hasType('getCookie(name) - requires (String) name', String, name); @@ -31,7 +31,7 @@ exports.clearCookie = function clearCookie(name) { return this.setCookie({ name: name, value: 'dummy', // setCookie doesn't allow null values - expiry: 0 + expiry: 0, }); }; diff --git a/lib/browser/debug/console.js b/lib/browser/debug/console.js index d1b6f97..1bc001d 100644 --- a/lib/browser/debug/console.js +++ b/lib/browser/debug/console.js @@ -6,7 +6,7 @@ var logMap = { 'SEVERE': 'error', 'WARNING': 'warn', 'INFO': 'log', - 'DEBUG': 'debug' + 'DEBUG': 'debug', }; function convertLogType(log) { @@ -25,7 +25,7 @@ exports.filterLogs = function filterLogs(logs, type) { if (!type) { return { matched: logs }; } - return _.groupBy(logs, function(log) { + return _.groupBy(logs, function byMatched(log) { return log.type === type ? 'matched' : 'rest'; }); }; diff --git a/lib/browser/debug/index.js b/lib/browser/debug/index.js index 4819740..7282eed 100644 --- a/lib/browser/debug/index.js +++ b/lib/browser/debug/index.js @@ -10,7 +10,7 @@ var TYPES = [ 'error', 'warn', 'log', - 'debug' + 'debug', ]; var cachedLogs = []; @@ -24,6 +24,6 @@ exports.getConsoleLogs = function getConsoleLogs(type) { var logs = cachedLogs.concat(newLogs); var filtered = filterLogs(logs, type); - cachedLogs = filtered.rest || [] + cachedLogs = filtered.rest || []; return filtered.matched || []; }; diff --git a/lib/browser/element.js b/lib/browser/element.js index ab69938..2ea735f 100644 --- a/lib/browser/element.js +++ b/lib/browser/element.js @@ -10,7 +10,7 @@ var STALE_MESSAGE = /stale element reference/; var NOT_FOUND_MESSAGE = new RegExp([ 'Unable to locate element', // firefox message 'Unable to find element', // phantomjs message - 'no such element', // chrome message + 'no such element', // chrome message ].join('|')); function visiblePredicate(shouldBeVisible, element) { @@ -40,7 +40,7 @@ var isntVisibleFailure = _.partial(visibleFailure, false); exports._forwarded = [ // TODO: port type assertion for selector to webdriver-http-sync - 'getElements' + 'getElements', ]; exports.getElementWithoutError = function getElementWithoutError(selector) { @@ -73,24 +73,26 @@ exports.waitForElementVisible = function waitForElementVisible(selector, timeout exports.waitForElementNotVisible = function waitForElementNotVisible(selector, timeout) { return this._waitForElement(selector, isntVisiblePredicate, isntVisibleFailure, timeout); -} +}; exports.waitForElementExist = function waitForElementExist(selector, timeout) { return this._waitForElement(selector, elementExistsPredicate, elementExistsFailure, timeout); -} +}; exports.click = function click(selector) { return this.getExistingElement(selector).click(); }; function tryFindElement(self, selector, predicate, untilTime) { - var element, predicateResult; + var element; while (Date.now() < untilTime) { element = self.getElementWithoutError(selector); try { - predicateResult = predicate(element); + if (predicate(element)) { + return element; + } } catch (exception) { // Occasionally webdriver throws an error about the element reference being // stale. Let's handle that case as the element doesn't yet exist. All @@ -99,10 +101,6 @@ function tryFindElement(self, selector, predicate, untilTime) { throw exception; } } - - if (predicateResult) { - return element; - } } return null; } diff --git a/lib/browser/index.js b/lib/browser/index.js index e92d2bc..966b458 100644 --- a/lib/browser/index.js +++ b/lib/browser/index.js @@ -11,7 +11,7 @@ var builtIns = [ require('./input'), require('./navigation'), require('./page'), - require('./window') + require('./window'), ]; function Browser(driver, options) { @@ -32,21 +32,20 @@ Browser.prototype.evaluate = function evaluate() { assert.truthy(invocation, clientFunction); switch (typeof clientFunction) { - case 'function': - clientFunction = - 'return (' + clientFunction + ').apply(this, ' + JSON.stringify(args) + ');'; - // fall-through - - case 'string': - return this.driver.evaluate(clientFunction); - - default: - throw new Error(invocation); + case 'function': + clientFunction = + 'return (' + clientFunction + ').apply(this, ' + JSON.stringify(args) + ');'; + /* falls through */ + case 'string': + return this.driver.evaluate(clientFunction); + + default: + throw new Error(invocation); } }; function forwardToDriver(method) { - Browser.prototype[method] = function() { + Browser.prototype[method] = function _forwarded() { return this.driver[method].apply(this.driver, arguments); }; } diff --git a/lib/browser/makeUrlRegExp.js b/lib/browser/makeUrlRegExp.js index d79a197..c34f4f9 100644 --- a/lib/browser/makeUrlRegExp.js +++ b/lib/browser/makeUrlRegExp.js @@ -10,10 +10,9 @@ function quoteRegExp(string) { } function bothCases(alpha) { - var dn, up; - up = alpha.toUpperCase(); - dn = alpha.toLowerCase(); - return "[" + up + dn + "]"; + var up = alpha.toUpperCase(); + var dn = alpha.toLowerCase(); + return '[' + up + dn + ']'; } var isHexaAlphaRE = /[a-f]/gi; @@ -24,7 +23,7 @@ function matchCharacter(uriEncoded, hex) { if (character === ' ') { character += '|\\+'; } - return "(?:" + uriEncoded.replace(isHexaAlphaRE, bothCases) + "|" + character + ")"; + return '(?:' + uriEncoded.replace(isHexaAlphaRE, bothCases) + '|' + character + ')'; } var encodedCharRE = /%([0-9a-f]{2})/gi; @@ -39,10 +38,10 @@ function matchURI(stringOrRegExp) { function makeUrlRegExp(url, query) { var expr = matchURI(url); - _.each(query || {}, function(val, key) { + _.each(query || {}, function queryParamMatcher(val, key) { key = matchURI(key); val = matchURI(val); - expr += "(?=(?:\\?|.*&)" + key + "=" + val + ")"; + expr += '(?=(?:\\?|.*&)' + key + '=' + val + ')'; }); return new RegExp(expr); } diff --git a/lib/browser/navigation.js b/lib/browser/navigation.js index 65c8c30..ae55e7b 100644 --- a/lib/browser/navigation.js +++ b/lib/browser/navigation.js @@ -10,7 +10,7 @@ var waitFor = require('./wait'); exports._forwarded = [ 'refresh', - 'getUrl' + 'getUrl', ]; exports.navigateTo = function navigateTo(url, options) { diff --git a/lib/browser/page.js b/lib/browser/page.js index f1981cc..ecfa936 100644 --- a/lib/browser/page.js +++ b/lib/browser/page.js @@ -5,5 +5,5 @@ exports._forwarded = [ 'getPageSource', 'getScreenshot', 'setPageSize', - 'getPageSize' + 'getPageSize', ]; diff --git a/lib/browser/wait.js b/lib/browser/wait.js index 44aa991..ff17e13 100644 --- a/lib/browser/wait.js +++ b/lib/browser/wait.js @@ -4,26 +4,23 @@ var util = require('util'); var _ = require('lodash'); -function testEqual(a, b) { return a === b; } - function matches(stringOrRegex, testUrl) { return stringOrRegex.test(testUrl); } -function createTest(stringOrRegex) { +function createTest(stringOrRegex, waitingFor) { if (_.isString(stringOrRegex)) { return _.partial(_.isEqual, stringOrRegex); } else if (_.isRegExp(stringOrRegex)) { return _.partial(matches, stringOrRegex); - } else { - throw new Error( - util.format('waitFor%s(urlStringOrRegex) - requires a string or regex param', - waitingFor)); } + throw new Error( + util.format('waitFor%s(urlStringOrRegex) - requires a string or regex param', + waitingFor)); } function waitFor(stringOrRegex, waitingFor, getValue, timeout) { - var test = createTest(stringOrRegex); + var test = createTest(stringOrRegex, waitingFor); var start = Date.now(); var currentValue; diff --git a/lib/browser/window.js b/lib/browser/window.js index 0d148e2..e6c8b11 100644 --- a/lib/browser/window.js +++ b/lib/browser/window.js @@ -4,7 +4,7 @@ var assert = require('assertive'); exports._forwarded = [ 'switchToWindow', - 'closeWindow' + 'closeWindow', ]; exports.switchToDefaultFrame = function switchToDefaultFrame() { diff --git a/lib/testium-driver-sync.js b/lib/testium-driver-sync.js index df2a9b2..e61897f 100644 --- a/lib/testium-driver-sync.js +++ b/lib/testium-driver-sync.js @@ -17,7 +17,7 @@ function createDriver(testium) { var browser = testium.browser = new Browser(driver, { appUrl: 'http://127.0.0.1:' + config.get('app.port'), - getNewPageUrl: testium.getNewPageUrl + getNewPageUrl: testium.getNewPageUrl, }); browser.assert = new Assertions(driver, browser); diff --git a/package.json b/package.json index 65e3ee7..9dfeb63 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Sync interface for testium", "main": "lib/testium-driver-sync.js", "scripts": { - "test": "mocha" + "test": "eslint lib test && mocha" }, "repository": { "type": "git", @@ -24,6 +24,9 @@ "homepage": "https://github.com/testiumjs/testium-driver-sync#readme", "devDependencies": { "babel-core": "^5.8.25", + "babel-eslint": "^4.1.3", + "eslint": "^1.6.0", + "eslint-config-airbnb": "~0.1.0", "mocha": "^2.3.3", "node-static": "~0.7.7", "testium-core": "^1.1.2" diff --git a/test/.eslintrc b/test/.eslintrc new file mode 100644 index 0000000..cdb7351 --- /dev/null +++ b/test/.eslintrc @@ -0,0 +1,9 @@ +{ + "extends": "airbnb/base", + "env": { + "mocha": true + }, + "rules": { + "id-length": 0 + } +} diff --git a/test/browser/debug.js b/test/browser/debug.js index 5650055..b388a30 100644 --- a/test/browser/debug.js +++ b/test/browser/debug.js @@ -3,9 +3,9 @@ import {parseLogs, filterLogs} from '../../lib/browser/debug/console'; describe('parseLogs', () => { it('maps log levels to browser log types', () => { - var logs = [ { level: 'SEVERE' } ]; - var parsed = parseLogs(logs); - var log = parsed[0]; + const logs = [ { level: 'SEVERE' } ]; + const parsed = parseLogs(logs); + const log = parsed[0]; assert.equal(log.level, undefined); assert.equal(log.type, 'error'); @@ -14,21 +14,21 @@ describe('parseLogs', () => { describe('filterLogs', () => { it('returns all logs if no type is given', () => { - var logs = [ + const logs = [ { type: 'error', message: 'something broke' }, - { type: 'log', message: 'things are working' } + { type: 'log', message: 'things are working' }, ]; - var { matched } = filterLogs(logs); + const { matched } = filterLogs(logs); assert.deepEqual(logs, matched); }); it('filters logs based on type', () => { - var errorItem = { type: 'error', message: 'something broke' }; - var logItem = { type: 'log', message: 'things are working' }; - var logs = [ logItem, errorItem ]; + const errorItem = { type: 'error', message: 'something broke' }; + const logItem = { type: 'log', message: 'things are working' }; + const logs = [ logItem, errorItem ]; - var { matched, rest } = filterLogs(logs, 'error'); + const { matched, rest } = filterLogs(logs, 'error'); assert.equal(errorItem, matched[0]); assert.equal(1, matched.length); assert.equal(logItem, rest[0]); diff --git a/test/integration/assert/imgLoaded.test.js b/test/integration/assert/imgLoaded.test.js index 01142e5..07df077 100644 --- a/test/integration/assert/imgLoaded.test.js +++ b/test/integration/assert/imgLoaded.test.js @@ -8,33 +8,33 @@ describe('imgLoaded', () => { before(() => browser.navigateTo('/')); it('throws an error when the image was not found', () => { - var msg = 'imgLoaded "img.not-in-the-page": element not found'; - var err = assert.throws(() => browser.assert.imgLoaded('img.not-in-the-page')); + const msg = 'imgLoaded "img.not-in-the-page": element not found'; + const err = assert.throws(() => browser.assert.imgLoaded('img.not-in-the-page')); assert.include(msg, err.message); }); it('throws an error for non-unique selectors when finding multiple images', () => { - var msg = 'imgLoaded "img[alt][class]": non-unique selector; count: 3'; - var err = assert.throws(() => browser.assert.imgLoaded('img[alt][class]')); + const msg = 'imgLoaded "img[alt][class]": non-unique selector; count: 3'; + const err = assert.throws(() => browser.assert.imgLoaded('img[alt][class]')); assert.include(msg, err.message); }); it('throws an error for an image not successfully loaded / decoded', () => { - var msg = 'imgLoaded "img.fail": failed to load '; - var err = assert.throws(() => browser.assert.imgLoaded('img.fail')); + const msg = 'imgLoaded "img.fail": failed to load '; + const err = assert.throws(() => browser.assert.imgLoaded('img.fail')); assert.include(msg, err.message); assert.include('/non-existent-image.jpg', err.message); }); it('throws a helpful error for an missing the src attribute', () => { - var msg = 'imgLoaded "#no": failed to load src-less img#no.src.dude'; - var err = assert.throws(() => browser.assert.imgLoaded('#no')); + const msg = 'imgLoaded "#no": failed to load src-less img#no.src.dude'; + const err = assert.throws(() => browser.assert.imgLoaded('#no')); assert.include(msg, err.message); }); it('throws a helpful error when the selector did not match an tag', () => { - var msg = 'imgLoaded "body": failed to load non-image body'; - var err = assert.throws(() => browser.assert.imgLoaded('body')); + const msg = 'imgLoaded "body": failed to load non-image body'; + const err = assert.throws(() => browser.assert.imgLoaded('body')); assert.include(msg, err.message); }); diff --git a/test/integration/console.test.js b/test/integration/console.test.js index dfc4799..9b327da 100644 --- a/test/integration/console.test.js +++ b/test/integration/console.test.js @@ -14,31 +14,31 @@ describe('console', () => { // for console.logs differently. // Use at your own risk. it('can all be retrieved', () => { - var { browserName } = browser.capabilities; - var logs; + const { browserName } = browser.capabilities; + let logs; switch (browserName) { - case 'firefox': - // firefox ignores this entirely - break; + case 'firefox': + // firefox ignores this entirely + break; - case 'chrome': - logs = browser.getConsoleLogs(); - assert.truthy('console.logs length', logs.length > 0); + case 'chrome': + logs = browser.getConsoleLogs(); + assert.truthy('console.logs length', logs.length > 0); - logs = browser.getConsoleLogs(); - assert.equal(0, logs.length); + logs = browser.getConsoleLogs(); + assert.equal(0, logs.length); - browser.click('#log-button'); + browser.click('#log-button'); - logs = browser.getConsoleLogs(); - assert.truthy('console.logs length', logs.length > 0); - break; + logs = browser.getConsoleLogs(); + assert.truthy('console.logs length', logs.length > 0); + break; - default: - logs = browser.getConsoleLogs(); - assert.truthy('console.logs length', logs.length > 0); - break; + default: + logs = browser.getConsoleLogs(); + assert.truthy('console.logs length', logs.length > 0); + break; } }); }); diff --git a/test/integration/cookie.test.js b/test/integration/cookie.test.js index e313691..5299727 100644 --- a/test/integration/cookie.test.js +++ b/test/integration/cookie.test.js @@ -8,21 +8,21 @@ describe('cookie', () => { it('can be set individually', () => { browser.setCookie({ name: 'test_cookie', - value: '3' + value: '3', }); - var cookie = browser.getCookie('test_cookie'); + const cookie = browser.getCookie('test_cookie'); assert.equal('3', cookie.value); }); it('can be set in groups', () => { browser.setCookies([ { name: 'test_cookie1', value: '5' }, - { name: 'test_cookie2', value: '7' } + { name: 'test_cookie2', value: '7' }, ]); - var cookie1 = browser.getCookie('test_cookie1'); - var cookie2 = browser.getCookie('test_cookie2'); + const cookie1 = browser.getCookie('test_cookie1'); + const cookie2 = browser.getCookie('test_cookie2'); assert.equal('5', cookie1.value); assert.equal('7', cookie2.value); @@ -31,11 +31,11 @@ describe('cookie', () => { it('can be cleared as a group', () => { browser.setCookie({ name: 'test_cookie', - value: '9' + value: '9', }); browser.clearCookies(); - var cookies = browser.getCookies(); + const cookies = browser.getCookies(); assert.equal(0, cookies.length); }); @@ -43,12 +43,12 @@ describe('cookie', () => { it('can be cleared individually', () => { browser.setCookie({ name: 'test_cookie', - value: '4' + value: '4', }); browser.clearCookie('test_cookie'); - var cookie = browser.getCookie('test_cookie'); + const cookie = browser.getCookie('test_cookie'); assert.falsey(cookie); }); }); diff --git a/test/integration/dialog.test.js b/test/integration/dialog.test.js index d82b0ec..ff27fa5 100644 --- a/test/integration/dialog.test.js +++ b/test/integration/dialog.test.js @@ -3,7 +3,7 @@ import assert from 'assertive'; import Config from 'testium-core/lib/config'; -var browserName = Config.load().get('browser'); +const browserName = Config.load().get('browser'); describe('dialogs', () => { if (browserName === 'phantomjs') { @@ -11,9 +11,10 @@ describe('dialogs', () => { return; } - let browser, target; + let browser; before(async () => (browser = await getBrowser())); + let target; before(() => { browser.navigateTo('/'); browser.assert.httpStatus(200); @@ -26,7 +27,7 @@ describe('dialogs', () => { beforeEach(() => browser.click('.link_to_open_an_alert')); it('can get an alert text', () => { - var text = browser.getAlertText(); + const text = browser.getAlertText(); browser.acceptAlert(); assert.equal('Alert text was not found', 'An alert!', text); }); @@ -46,7 +47,7 @@ describe('dialogs', () => { beforeEach(() => browser.click('.link_to_open_a_confirm')); it('can get confirm text', () => { - var text = browser.getAlertText(); + const text = browser.getAlertText(); browser.acceptAlert(); assert.equal('Confirm text was not found', 'A confirmation!', text); }); @@ -66,7 +67,7 @@ describe('dialogs', () => { beforeEach(() => browser.click('.link_to_open_a_prompt')); it('can get prompt text', () => { - text = browser.getAlertText(); + const text = browser.getAlertText(); browser.acceptAlert(); assert.equal('Confirm text was not found', 'A prompt!', text); }); diff --git a/test/integration/element.test.js b/test/integration/element.test.js index 760931e..1406f94 100644 --- a/test/integration/element.test.js +++ b/test/integration/element.test.js @@ -8,8 +8,8 @@ describe('element', () => { before(() => browser.navigateTo('/')); it('can get an element\'s text', () => { - var element = browser.getElement('h1'); - var text = element.get('text'); + const element = browser.getElement('h1'); + const text = element.get('text'); assert.equal('Element text was not found', 'Test Page!', text); }); @@ -17,31 +17,31 @@ describe('element', () => { // the "checked" property (when it doesn't exist) // returns a non-standard response from selenium; // let's make sure we can handle it properly - var element = browser.getElement('#checkbox'); - var checked = element.get('checked'); + const element = browser.getElement('#checkbox'); + const checked = element.get('checked'); assert.equal('checked is null', null, checked); }); it('returns null when the element can not be found', () => { - var element = browser.getElement('.non-existing'); + const element = browser.getElement('.non-existing'); assert.equal('Element magically appeared on the page', null, element); }); it('can get several elements', () => { - var elements = browser.getElements('.message'); + const elements = browser.getElements('.message'); assert.equal('Messages were not all found', 3, elements.length); }); describe('elementIsVisible', () => { it('fails if element does not exist', () => { - var error = assert.throws(() => browser.assert.elementIsVisible('.non-existing')); - var expectedError = 'Assertion failed: Element not found for selector: .non-existing\n\u001b[39;49;00mExpected \u001b[31mnull\u001b[39m to be truthy'; + const error = assert.throws(() => browser.assert.elementIsVisible('.non-existing')); + const expectedError = 'Assertion failed: Element not found for selector: .non-existing\n\u001b[39;49;00mExpected \u001b[31mnull\u001b[39m to be truthy'; assert.equal(expectedError, error.message); }); it('fails if element exists, but is not visible', () => { - var error = assert.throws(() => browser.assert.elementIsVisible('#hidden_thing')); - var expectedError = 'Assertion failed: Element should be visible for selector: #hidden_thing\n\u001b[39;49;00mExpected \u001b[31mfalse\u001b[39m to be truthy'; + const error = assert.throws(() => browser.assert.elementIsVisible('#hidden_thing')); + const expectedError = 'Assertion failed: Element should be visible for selector: #hidden_thing\n\u001b[39;49;00mExpected \u001b[31mfalse\u001b[39m to be truthy'; assert.equal(expectedError, error.message); }); @@ -52,14 +52,14 @@ describe('element', () => { describe('elementNotVisible', () => { it('fails if element does not exist', () => { - var error = assert.throws(() => browser.assert.elementNotVisible('.non-existing')); - var expectedError = 'Assertion failed: Element not found for selector: .non-existing\n\u001b[39;49;00mExpected \u001b[31mnull\u001b[39m to be truthy'; + const error = assert.throws(() => browser.assert.elementNotVisible('.non-existing')); + const expectedError = 'Assertion failed: Element not found for selector: .non-existing\n\u001b[39;49;00mExpected \u001b[31mnull\u001b[39m to be truthy'; assert.equal(expectedError, error.message); }); it('fails if element exists, but is visible', () => { - var error = assert.throws(() => browser.assert.elementNotVisible('h1')); - var expectedError = 'Assertion failed: Element should not be visible for selector: h1\n\u001b[39;49;00mExpected \u001b[31mtrue\u001b[39m to be falsey'; + const error = assert.throws(() => browser.assert.elementNotVisible('h1')); + const expectedError = 'Assertion failed: Element should not be visible for selector: h1\n\u001b[39;49;00mExpected \u001b[31mtrue\u001b[39m to be falsey'; assert.equal(expectedError, error.message); }); @@ -70,8 +70,8 @@ describe('element', () => { describe('elementExists', () => { it('fails if element does not exist', () => { - var error = assert.throws(() => browser.assert.elementExists('.non-existing')); - var expectedError = 'Assertion failed: Element not found for selector: .non-existing\n\u001b[39;49;00mExpected \u001b[31mnull\u001b[39m to be truthy'; + const error = assert.throws(() => browser.assert.elementExists('.non-existing')); + const expectedError = 'Assertion failed: Element not found for selector: .non-existing\n\u001b[39;49;00mExpected \u001b[31mnull\u001b[39m to be truthy'; assert.equal(expectedError, error.message); }); @@ -86,35 +86,35 @@ describe('element', () => { }); it('fails if element exists', () => { - var error = assert.throws(() => browser.assert.elementDoesntExist('h1')); - var expectedError = 'Assertion failed: Element found for selector: h1\n\u001b[39;49;00mExpected \u001b[31mElement\u001b[39m to be falsey'; + const error = assert.throws(() => browser.assert.elementDoesntExist('h1')); + const expectedError = 'Assertion failed: Element found for selector: h1\n\u001b[39;49;00mExpected \u001b[31mElement\u001b[39m to be falsey'; assert.equal(expectedError, error.message); }); }); describe('elementHasText', () => { it('finds and returns a single element', () => { - var element = browser.assert.elementHasText('.only', 'only one here'); + const element = browser.assert.elementHasText('.only', 'only one here'); assert.equal('resolve the element\'s class', 'only', element.get('class')); }); it('finds an element with the wrong text', () => { - var error = assert.throws(() => + const error = assert.throws(() => browser.assert.elementHasText('.only', 'the wrong text')); - var expected = 'Assertion failed: elementHasText: .only\n\u001b[39;49;00minclude expected needle to be found in haystack\n- needle: \"the wrong text\"\nhaystack: \"only one here\"'; + const expected = 'Assertion failed: elementHasText: .only\n\u001b[39;49;00minclude expected needle to be found in haystack\n- needle: \"the wrong text\"\nhaystack: \"only one here\"'; assert.equal(expected, error.message); }); it('finds no elements', () => { - var error = assert.throws(() => + const error = assert.throws(() => browser.assert.elementHasText('.does-not-exist', 'some text')); assert.equal('Element not found for selector: .does-not-exist', error.message); }); it('finds many elements', () => { - var error = assert.throws(() => + const error = assert.throws(() => browser.assert.elementHasText('.message', 'some text')); assert.equal('assertion needs a unique selector!\n.message has 3 hits in the page', error.message); @@ -127,22 +127,22 @@ describe('element', () => { describe('elementLacksText', () => { it('asserts an element lacks some text, and returns the element', () => { - var element = browser.assert.elementLacksText('.only', 'this text not present'); + const element = browser.assert.elementLacksText('.only', 'this text not present'); assert.equal('resolve the element\'s class', 'only', element.get('class')); }); it('finds an element incorrectly having some text', () => { - var error = assert.throws(() => + const error = assert.throws(() => browser.assert.elementLacksText('.only', 'only')); - var expected = 'Assertion failed: elementLacksText: .only\n\u001b[39;49;00mnotInclude expected needle not to be found in haystack\n- needle: \"only\"\nhaystack: \"only one here\"'; + const expected = 'Assertion failed: elementLacksText: .only\n\u001b[39;49;00mnotInclude expected needle not to be found in haystack\n- needle: \"only\"\nhaystack: \"only one here\"'; assert.equal(expected, error.message); }); }); describe('elementHasValue', () => { it('finds and returns a single element', () => { - var element = browser.assert.elementHasValue('#text-input', 'initialvalue'); + const element = browser.assert.elementHasValue('#text-input', 'initialvalue'); assert.equal('resolve the element\'s id', 'text-input', element.get('id')); }); @@ -153,15 +153,15 @@ describe('element', () => { describe('elementLacksValue', () => { it('asserts an element lacks some value, and returns the element', () => { - var element = browser.assert.elementLacksValue('#text-input', 'this text not present'); + const element = browser.assert.elementLacksValue('#text-input', 'this text not present'); assert.equal('resolve the element\'s id', 'text-input', element.get('id')); }); it('finds an element incorrectly having some text', () => { - var error = assert.throws(() => + const error = assert.throws(() => browser.assert.elementLacksValue('#text-input', 'initialvalue')); - var expected = 'Assertion failed: elementLacksValue: #text-input\n\u001b[39;49;00mnotInclude expected needle not to be found in haystack\n- needle: \"initialvalue\"\nhaystack: \"initialvalue\"'; + const expected = 'Assertion failed: elementLacksValue: #text-input\n\u001b[39;49;00mnotInclude expected needle not to be found in haystack\n- needle: \"initialvalue\"\nhaystack: \"initialvalue\"'; assert.equal(expected, error.message); }); }); @@ -180,7 +180,7 @@ describe('element', () => { }); it('fails to find an element that never exists', () => { - var error = assert.throws(() => + const error = assert.throws(() => browser.waitForElementExist('.does-not-exist', 10)); assert.equal('Timeout (10ms) waiting for element (.does-not-exist) to exist in page.', error.message); }); @@ -195,13 +195,13 @@ describe('element', () => { }); it('fails to find a visible element within the timeout', () => { - var error = assert.throws(() => + const error = assert.throws(() => browser.waitForElementVisible('.load_never', 10)); assert.equal('Timeout (10ms) waiting for element (.load_never) to be visible.', error.message); }); it('fails to find an element that never exists', () => { - var error = assert.throws(() => + const error = assert.throws(() => browser.waitForElementVisible('.does-not-exist', 10)); assert.equal('Timeout (10ms) waiting for element (.does-not-exist) to be visible.', error.message); }); @@ -216,13 +216,13 @@ describe('element', () => { }); it('fails to find a not-visible element within the timeout', () => { - var error = assert.throws(() => + const error = assert.throws(() => browser.waitForElementNotVisible('.hide_never', 10)); assert.equal('Timeout (10ms) waiting for element (.hide_never) to not be visible.', error.message); }); it('fails to find an element that never exists', () => { - var error = assert.throws(() => + const error = assert.throws(() => browser.waitForElementNotVisible('.does-not-exist', 10)); assert.equal('Timeout (10ms) waiting for element (.does-not-exist) to not be visible.', error.message); }); @@ -232,13 +232,13 @@ describe('element', () => { before(() => browser.navigateTo('/')); it('succeeds if selector is a String', () => { - var element = browser.getElement('body'); + const element = browser.getElement('body'); element.getElement('.message'); }); it('return null if not found an element on the message element', () => { - var messageElement = browser.getElement('.message'); - var element = messageElement.getElement('.message'); + const messageElement = browser.getElement('.message'); + const element = messageElement.getElement('.message'); assert.falsey(element); }); }); @@ -247,13 +247,13 @@ describe('element', () => { before(() => browser.navigateTo('/')); it('succeeds if selector is a String', () => { - var element = browser.getElement('body'); + const element = browser.getElement('body'); element.getElements('.message'); }); it('return empty array if not found an element on the message element', () => { - var messageElement = browser.getElement('.message'); - var elements = messageElement.getElements('.message'); + const messageElement = browser.getElement('.message'); + const elements = messageElement.getElements('.message'); assert.equal(0, elements.length); }); }); diff --git a/test/integration/evaluate.test.js b/test/integration/evaluate.test.js index a2a77c2..4d5b695 100644 --- a/test/integration/evaluate.test.js +++ b/test/integration/evaluate.test.js @@ -8,7 +8,7 @@ describe('evaluate', () => { before(() => browser.navigateTo('/')); it('runs JavaScript passed as a String', () => { - var value = browser.evaluate('return 3;'); + const value = browser.evaluate('return 3;'); assert.equal(3, value); }); diff --git a/test/integration/form.test.js b/test/integration/form.test.js index 06a9960..a92dd45 100644 --- a/test/integration/form.test.js +++ b/test/integration/form.test.js @@ -11,51 +11,51 @@ describe('evaluate', () => { }); it('can get an input\'s value', () => { - var element = browser.getElement('#text-input'); - var value = element.get('value'); + const element = browser.getElement('#text-input'); + const value = element.get('value'); assert.equal('Input value was not found', 'initialvalue', value); }); it('can clear an input\'s value', () => { - var element = browser.getElement('#text-input'); + const element = browser.getElement('#text-input'); element.clear(); - var value = element.get('value'); + const value = element.get('value'); assert.equal('Input value was not cleared', '', value); }); it('can type into an input', () => { - var element = browser.getElement('#text-input'); + const element = browser.getElement('#text-input'); element.type('new stuff'); - var value = element.get('value'); + const value = element.get('value'); assert.equal('Input value was not typed', 'new stuff', value); }); it('can replace the input\'s value', () => { - var element = browser.getElement('#text-input'); - var value = element.get('value'); - assert.notEqual('Input value is already empty', '', value); + const element = browser.getElement('#text-input'); + const valueBefore = element.get('value'); + assert.notEqual('Input value is already empty', '', valueBefore); browser.clearAndType('#text-input', 'new stuff2'); - value = element.get('value'); - assert.equal('Input value was not typed', 'new stuff2', value); + const valueAfter = element.get('value'); + assert.equal('Input value was not typed', 'new stuff2', valueAfter); }); it('can get a textarea\'s value', () => { - var element = browser.getElement('#text-area'); - var value = element.get('value'); + const element = browser.getElement('#text-area'); + const value = element.get('value'); assert.equal('Input value was not found', 'initialvalue', value); }); it('can clear an textarea\'s value', () => { - var element = browser.getElement('#text-area'); + const element = browser.getElement('#text-area'); element.clear(); - var value = element.get('value'); + const value = element.get('value'); assert.equal('Input value was not cleared', '', value); }); it('can type into a textarea', () => { - var element = browser.getElement('#text-area'); + const element = browser.getElement('#text-area'); element.type('new stuff'); - var value = element.get('value'); + const value = element.get('value'); assert.equal('Input value was not typed', 'new stuff', value); }); }); diff --git a/test/integration/header.test.js b/test/integration/header.test.js index ac4103f..8fdd653 100644 --- a/test/integration/header.test.js +++ b/test/integration/header.test.js @@ -12,13 +12,13 @@ describe('header', () => { }); it('as a group', () => { - var headers = browser.getHeaders(); - var contentType = headers['content-type']; + const headers = browser.getHeaders(); + const contentType = headers['content-type']; assert.equal('text/html', contentType); }); it('individually', () => { - var contentType = browser.getHeader('content-type'); + const contentType = browser.getHeader('content-type'); assert.equal('text/html', contentType); }); }); @@ -28,8 +28,8 @@ describe('header', () => { browser.navigateTo('/echo', { headers: { 'x-something': 'that place' } })); it('to new values', () => { - var source = browser.getElement('body').get('text'); - var body = JSON.parse(source); + const source = browser.getElement('body').get('text'); + const body = JSON.parse(source); assert.equal(body.headers['x-something'], 'that place'); }); }); diff --git a/test/integration/navigation.test.js b/test/integration/navigation.test.js index 7282135..808e1d5 100644 --- a/test/integration/navigation.test.js +++ b/test/integration/navigation.test.js @@ -61,8 +61,8 @@ describe('navigation', () => { browser.navigateTo('/index.html'); assert.equal(200, browser.getStatusCode()); - var error = assert.throws(() => browser.waitForUrl('/some-random-place.html', 5)); - var expectedError = /^Timed out \(5ms\) waiting for url \("\/some-random-place\.html"\)\. Last value was: "http:\/\/127\.0\.0\.1:[\d]+\/index\.html"$/; + const error = assert.throws(() => browser.waitForUrl('/some-random-place.html', 5)); + const expectedError = /^Timed out \(5ms\) waiting for url \("\/some-random-place\.html"\)\. Last value was: "http:\/\/127\.0\.0\.1:[\d]+\/index\.html"$/; assert.match(expectedError, error.message); }); @@ -71,7 +71,7 @@ describe('navigation', () => { browser.navigateTo('/redirect-to-query.html'); browser.waitForUrl('/index.html', { 'a b': 'A B', - c: '1,7' + c: '1,7', }); assert.equal(200, browser.getStatusCode()); }); @@ -80,7 +80,7 @@ describe('navigation', () => { browser.navigateTo('/redirect-to-query.html'); browser.waitForUrl('/index.html', { c: '1,7', - 'a b': 'A B' + 'a b': 'A B', }); }); @@ -88,14 +88,14 @@ describe('navigation', () => { browser.navigateTo('/redirect-to-query.html'); browser.waitForUrl('/index.html', { c: /[\d,]+/, - 'a b': 'A B' + 'a b': 'A B', }); }); it('detects non-matches too', () => { browser.navigateTo('/redirect-to-query.html'); - var error = assert.throws(() => browser.waitForUrl('/index.html', { no: 'q' }, 200)); + const error = assert.throws(() => browser.waitForUrl('/index.html', { no: 'q' }, 200)); assert.match(/Timed out .* waiting for url/, error.message); }); }); diff --git a/test/integration/non_browser.test.js b/test/integration/non_browser.test.js index 6af250b..0afec06 100644 --- a/test/integration/non_browser.test.js +++ b/test/integration/non_browser.test.js @@ -8,7 +8,7 @@ describe('Non-browser test', () => { before(async () => (browser = await getBrowser())); it('can make a request without using the browser', done => { - var url = `${browser.appUrl}/echo`; + const url = `${browser.appUrl}/echo`; get(url, response => { assert.equal(200, response.statusCode); done(); diff --git a/test/integration/proxy.test.js b/test/integration/proxy.test.js index 97d2237..db49a97 100644 --- a/test/integration/proxy.test.js +++ b/test/integration/proxy.test.js @@ -1,5 +1,4 @@ import {getBrowser} from '../mini-testium-mocha'; -import assert from 'assertive'; describe('proxy', () => { let browser; @@ -26,6 +25,9 @@ describe('proxy', () => { browser.navigateTo('/blackholed-resource.html'); browser.assert.httpStatus(200); + // this can't simply be sync + // because firefox blocks dom-ready + // if we don't wait on the client-side setTimeout(() => { // when navigating away, the proxy should // abort the resource request; @@ -33,11 +35,7 @@ describe('proxy', () => { // or status code retrieval browser.navigateTo('/'); browser.assert.httpStatus(200); - done() - - // this can't simply be sync - // because firefox blocks dom-ready - // if we don't wait on the client-side + done(); }, 50); }); diff --git a/test/integration/ssl.test.js b/test/integration/ssl.test.js index 5f347ce..0a71bff 100644 --- a/test/integration/ssl.test.js +++ b/test/integration/ssl.test.js @@ -7,8 +7,8 @@ describe('ssl/tls', () => { it('TLS is supported', () => { browser.navigateTo('https://www.howsmyssl.com/a/check'); - var raw = browser.getExistingElement('pre').get('text'); - var sslReport = JSON.parse(raw); + const raw = browser.getExistingElement('pre').get('text'); + const sslReport = JSON.parse(raw); assert.match(/^TLS/, sslReport.tls_version); }); }); diff --git a/test/integration/unicode.test.js b/test/integration/unicode.test.js index f8992a2..db2c5f6 100644 --- a/test/integration/unicode.test.js +++ b/test/integration/unicode.test.js @@ -8,10 +8,10 @@ describe('unicode support', () => { before(() => browser.navigateTo('/')); it('multibyte unicode can pass through and back from WebDriver', () => { - var multibyteText = '日本語 text'; - var element = browser.getElement('#blank-input'); + const multibyteText = '日本語 text'; + const element = browser.getElement('#blank-input'); element.type(multibyteText); - var result = element.get('value'); + const result = element.get('value'); assert.equal(result, multibyteText); }); }); diff --git a/test/integration/window.test.js b/test/integration/window.test.js index 19fad58..ba81e16 100644 --- a/test/integration/window.test.js +++ b/test/integration/window.test.js @@ -13,9 +13,9 @@ describe('window api', () => { it('can be switched', () => { browser.switchToFrame('cool-frame'); - var iframeContent = browser.getElement('.in-iframe-only').get('text'); + const iframeContent = browser.getElement('.in-iframe-only').get('text'); browser.switchToDefaultFrame(); - var primaryContent = browser.getElement('.in-iframe-only'); + const primaryContent = browser.getElement('.in-iframe-only'); assert.equal('iframe content!', iframeContent); assert.equal(null, primaryContent); }); @@ -23,7 +23,7 @@ describe('window api', () => { it('can be found when nested', () => { browser.switchToFrame('cool-frame'); browser.switchToFrame('nested-frame'); - var element = browser.getElement('#nested-frame-div'); + const element = browser.getElement('#nested-frame-div'); assert.truthy('nested frame content', element); }); }); @@ -37,10 +37,10 @@ describe('window api', () => { it('can be opened', () => { browser.click('#open-popup'); browser.switchToWindow('popup1'); - var popupContent = browser.getElement('.popup-only').get('text'); + const popupContent = browser.getElement('.popup-only').get('text'); browser.closeWindow(); browser.switchToDefaultWindow(); - var primaryContent = browser.getElement('.popup-only'); + const primaryContent = browser.getElement('.popup-only'); assert.equal('popup content!', popupContent); assert.equal(null, primaryContent); }); diff --git a/test/mini-testium-mocha.js b/test/mini-testium-mocha.js index d2c7f63..a548755 100644 --- a/test/mini-testium-mocha.js +++ b/test/mini-testium-mocha.js @@ -1,4 +1,3 @@ -'use strict'; // This is a minimal version of `testium-mocha`. // We're trying to avoid cyclic dependencies. import initTestium from 'testium-core'; @@ -6,9 +5,9 @@ import {once} from 'lodash'; import createDriver from '../'; -var initOnce = once(initTestium); +const initOnce = once(initTestium); -export async function getBrowser(options) { +export async function getBrowser() { const { browser } = await initOnce().then(createDriver); return browser; } From 18eb792f2b5fa826a24cd6517575c973dd1a0c17 Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Tue, 13 Oct 2015 11:03:12 -0700 Subject: [PATCH 09/11] Add minimal README --- README.md | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/README.md b/README.md index 4732bf1..ac044a5 100644 --- a/README.md +++ b/README.md @@ -1 +1,63 @@ # Testium: Sync + +Provides a sync API for [testium](https://www.npmjs.com/package/testium). +Uses [webdriver-http-sync](https://www.npmjs.com/package/webdriver-http-sync) for interacting with selenium. + +Check out [testium's documentation](https://www.npmjs.com/package/testium) for more information on the `browser` API. + +## Usage + +```js +import initTestium from 'testium-core'; +import createDriver from 'testium-driver-sync'; + +async function runTests() { + const { browser } = initTestium().then(createDriver); + browser.navigateTo('/'); +} +runTests(); +``` + +```coffee +initTestium = require 'testium-core'; +createDriver = require 'testium-driver-sync'; + +initTestium() + .then(createDriver) + .then ({browser}) -> + browser.navigateTo '/' +``` + +## License *(BSD-3-Clause)* + +``` +Copyright (c) 2015, Groupon, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of GROUPON nor the names of its contributors may be +used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` From a696a2a2f462183ac0d41bc8bbcb38c6aff6b60b Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Tue, 13 Oct 2015 11:42:59 -0700 Subject: [PATCH 10/11] Use testium-example-app from npm --- .testiumrc | 2 +- .../public/blackholed-resource.html | 28 ------- .../testium-example-app/public/dynamic.html | 27 ------ .../testium-example-app/public/frame.html | 20 ----- .../public/index-diff.html | 43 ---------- .../testium-example-app/public/index.html | 79 ------------------ .../public/other-page.html | 7 -- .../testium-example-app/public/popup.html | 19 ----- .../public/redirect-after.html | 5 -- .../public/redirect-to-query.html | 5 -- .../testium-example-app/public/windows.html | 18 ---- examples/testium-example-app/server.js | 83 ------------------- package.json | 3 +- 13 files changed, 3 insertions(+), 336 deletions(-) delete mode 100644 examples/testium-example-app/public/blackholed-resource.html delete mode 100644 examples/testium-example-app/public/dynamic.html delete mode 100644 examples/testium-example-app/public/frame.html delete mode 100644 examples/testium-example-app/public/index-diff.html delete mode 100644 examples/testium-example-app/public/index.html delete mode 100644 examples/testium-example-app/public/other-page.html delete mode 100644 examples/testium-example-app/public/popup.html delete mode 100644 examples/testium-example-app/public/redirect-after.html delete mode 100644 examples/testium-example-app/public/redirect-to-query.html delete mode 100644 examples/testium-example-app/public/windows.html delete mode 100644 examples/testium-example-app/server.js diff --git a/.testiumrc b/.testiumrc index ce5a357..66e7106 100644 --- a/.testiumrc +++ b/.testiumrc @@ -1,6 +1,6 @@ { "launch": true, "app": { - "command": "node examples/testium-example-app/server.js" + "command": "testium-example-app" } } diff --git a/examples/testium-example-app/public/blackholed-resource.html b/examples/testium-example-app/public/blackholed-resource.html deleted file mode 100644 index 400fb75..0000000 --- a/examples/testium-example-app/public/blackholed-resource.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - Test Title - - - - - - diff --git a/examples/testium-example-app/public/dynamic.html b/examples/testium-example-app/public/dynamic.html deleted file mode 100644 index 3362011..0000000 --- a/examples/testium-example-app/public/dynamic.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - -
This just in!
-
This in never!
-
For a limitted time!
-
Here forever!
- - diff --git a/examples/testium-example-app/public/frame.html b/examples/testium-example-app/public/frame.html deleted file mode 100644 index 4c61d1a..0000000 --- a/examples/testium-example-app/public/frame.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - Some IFrame - - - - -
- iframe content! -
- - -
- - - - diff --git a/examples/testium-example-app/public/index-diff.html b/examples/testium-example-app/public/index-diff.html deleted file mode 100644 index 313d9ea..0000000 --- a/examples/testium-example-app/public/index-diff.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - Test Title - - - -

Test Page!

- Go to other page! - -
- -
Message 1
-
Message 2
-
Message 3
-
only one here
- a transparent pixel - a non-existent image - a non-sourced image - -
- - - - -
- - - -
This and everything below should be PURPLE!
- - Alert - Confirm - Prompt - Clear -
-
- - - - diff --git a/examples/testium-example-app/public/index.html b/examples/testium-example-app/public/index.html deleted file mode 100644 index 9c79b14..0000000 --- a/examples/testium-example-app/public/index.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - Test Title - - - - -

Test Page!

- Go to other page! - -
- -
Message 1
-
Message 2
-
Message 3
-
only one here
- a transparent pixel - a non-existent image - a non-sourced image - -
- - - - -
- - - - Alert - Confirm - Prompt - Clear -
-
- - - - diff --git a/examples/testium-example-app/public/other-page.html b/examples/testium-example-app/public/other-page.html deleted file mode 100644 index 187cc9a..0000000 --- a/examples/testium-example-app/public/other-page.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - h1 Other Page! - - diff --git a/examples/testium-example-app/public/popup.html b/examples/testium-example-app/public/popup.html deleted file mode 100644 index 33dfa02..0000000 --- a/examples/testium-example-app/public/popup.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - Popup! - - - - - - - - - - diff --git a/examples/testium-example-app/public/redirect-after.html b/examples/testium-example-app/public/redirect-after.html deleted file mode 100644 index d061589..0000000 --- a/examples/testium-example-app/public/redirect-after.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/examples/testium-example-app/public/redirect-to-query.html b/examples/testium-example-app/public/redirect-to-query.html deleted file mode 100644 index f692593..0000000 --- a/examples/testium-example-app/public/redirect-to-query.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/examples/testium-example-app/public/windows.html b/examples/testium-example-app/public/windows.html deleted file mode 100644 index c0c8f00..0000000 --- a/examples/testium-example-app/public/windows.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - Test Title - - - - - - - - - - - diff --git a/examples/testium-example-app/server.js b/examples/testium-example-app/server.js deleted file mode 100644 index fe8c7f6..0000000 --- a/examples/testium-example-app/server.js +++ /dev/null @@ -1,83 +0,0 @@ -'use strict'; - -var http = require('http'); - -var StaticServer = require('node-static').Server; - -function echo(request, response) { - var data = { - ip: request.connection.remoteAddress, - method: request.method, - url: request.url, - body: '', - headers: request.headers - }; - - request.on('data', function(buffer) { - data.body += buffer.toString(); - }); - - request.on('end', function() { - var body = JSON.stringify(data, null, 2); - response.setHeader('Content-Type', 'application/json'); - response.end(body); - }); -} - -function error(response) { - response.statusCode = 500; - response.end('500 SERVER ERROR'); -} - -function crash(response) { - response.statusCode = 500; - response.socket.destroy(); -} - -function createServer() { - var file = new StaticServer(__dirname + '/public'); - - return http.createServer(function(request, response) { - switch (request.url) { - case '/echo': - return echo(request, response); - - case '/error': - return error(response); - - case '/crash': - return crash(response); - - case '/blackhole': - return; - } - - var listener = request.addListener('end', function() { - file.serve(request, response); - }); - listener.resume(); - }); -} - -var testApp = module.exports = { - listen: function(port, callback) { - this.server = createServer(); - this.server.listen(port, callback); - }, - - kill: function(callback) { - this.server.close(callback); - this.server = null; - } -}; - -if (module === require.main) { - if (process.env.never_listen) { - console.log('Refusing to listen') - setTimeout(function() {}, 100000); - } else { - testApp.listen(process.env.PORT || 4003, function() { - console.log('Listening on port %j', this.address().port); - }); - } -} \ No newline at end of file diff --git a/package.json b/package.json index 9dfeb63..dff42c7 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "eslint-config-airbnb": "~0.1.0", "mocha": "^2.3.3", "node-static": "~0.7.7", - "testium-core": "^1.1.2" + "testium-core": "^1.1.2", + "testium-example-app": "^1.0.4" }, "dependencies": { "assertive": "^2.0.2", From c6c1ea8939429e34b8e9e4f365d4ecf276b374e4 Mon Sep 17 00:00:00 2001 From: Jan Krems Date: Tue, 13 Oct 2015 13:52:00 -0700 Subject: [PATCH 11/11] Be more conservative about browser sessions --- lib/browser/index.js | 7 +++++++ package.json | 1 + test/mini-testium-mocha.js | 11 ++++++++--- test/mocha.opts | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/browser/index.js b/lib/browser/index.js index 966b458..bb4ddcc 100644 --- a/lib/browser/index.js +++ b/lib/browser/index.js @@ -2,6 +2,7 @@ var _ = require('lodash'); var assert = require('assertive'); +var Bluebird = require('bluebird'); var builtIns = [ require('./alert'), @@ -44,6 +45,12 @@ Browser.prototype.evaluate = function evaluate() { } }; +Browser.prototype.close = function close(callback) { + return Bluebird + .try(this.driver.close, [], this.driver) + .nodeify(callback); // compatible with testium +}; + function forwardToDriver(method) { Browser.prototype[method] = function _forwarded() { return this.driver[method].apply(this.driver, arguments); diff --git a/package.json b/package.json index dff42c7..75f2966 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ }, "dependencies": { "assertive": "^2.0.2", + "bluebird": "~2.10.2", "debug": "^2.2.0", "lodash": "^3.10.1", "testium-cookie": "^1.0.0", diff --git a/test/mini-testium-mocha.js b/test/mini-testium-mocha.js index a548755..3f09361 100644 --- a/test/mini-testium-mocha.js +++ b/test/mini-testium-mocha.js @@ -5,9 +5,14 @@ import {once} from 'lodash'; import createDriver from '../'; -const initOnce = once(initTestium); +let browser = null; -export async function getBrowser() { - const { browser } = await initOnce().then(createDriver); +async function createBrowser() { + const testium = await initTestium().then(createDriver); + browser = testium.browser; return browser; } + +after(() => browser && browser.close()); + +export const getBrowser = once(createBrowser); diff --git a/test/mocha.opts b/test/mocha.opts index 3d5571b..50c2600 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,2 +1,3 @@ --compilers js:babel-core/register --recursive +--timeout 20000