Skip to content

Commit

Permalink
feat: add option 'sessionRequestTimeout'
Browse files Browse the repository at this point in the history
  • Loading branch information
DudaGod committed Dec 20, 2016
1 parent 4b1e0fe commit a15b022
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 78 deletions.
5 changes: 5 additions & 0 deletions README.md
Expand Up @@ -30,6 +30,7 @@ Hermione is the utility for integration testing of web pages using [WebdriverIO]
- [gridUrl](#gridurl)
- [baseUrl](#baseurl)
- [httpTimeout](#httptimeout)
- [sessionRequestTimeout](#sessionrequesttimeout)
- [sessionQuitTimeout](#sessionquittimeout)
- [waitTimeout](#waittimeout)
- [sessionsPerBrowser](#sessionsperbrowser)
Expand Down Expand Up @@ -409,6 +410,7 @@ Option name | Description
`baseUrl` | Base service-under-test url. Default value is `http://localhost`.
`waitTimeout` | Timeout for web page event. Default value is `1000` ms.
`httpTimeout` | Timeout for any requests to Selenium server. Default value is `90000` ms.
`sessionRequestTimeout` | Timeout for getting of a browser session. Default value is `httpTimeout`.
`sessionQuitTimeout` | Timeout for session quit. Default value is `httpTimeout`.
`sessionsPerBrowser` | Number of sessions which are run simultaneously. Default value is `1`.
`retry` | How many times test should be rerun. Default value is `0`.
Expand All @@ -423,6 +425,9 @@ Base service-under-test url. Default value is `http://localhost`.
### httpTimeout
Timeout for any requests to Selenium server. Default value is `90000` ms.

### sessionRequestTimeout
Timeout for getting of a browser session. Default value is `httpTimeout`.

### sessionQuitTimeout
Timeout for session quit. Default value is `httpTimeout`.

Expand Down
60 changes: 40 additions & 20 deletions lib/browser.js
Expand Up @@ -25,8 +25,12 @@ module.exports = class Browser {
}

init() {
return q(() => this._session = this._createSession().init())
return q(() => this._session = this._createSession())
.call()
.then(() => this._setHttpTimeout(this._config.sessionRequestTimeout))
.then(() => this._session.init())
.then(() => this._restoreHttpTimeout())
.then(() => this._switchOnScreenshotOnReject())
.thenResolve(this);
}

Expand All @@ -35,14 +39,10 @@ module.exports = class Browser {
return q();
}

const optionsOnEnd = {
connectionRetryTimeout: this._config.sessionQuitTimeout || this._config.httpTimeout,
screenshotOnReject: false
};

// Не работает без then в виду особенностей реализации в webdriverio.js
return this._session
.then(() => this._session.extendOptions(optionsOnEnd))
.then(() => this._setHttpTimeout(this._config.sessionQuitTimeout))
.then(() => this._switchOffScreenshotOnReject())
.then(() => this._session.end())
.catch((e) => logger.warn(`WARNING: Can not close session: ${e.message}`));
}
Expand All @@ -62,10 +62,6 @@ module.exports = class Browser {
_createSession() {
const config = this._config;
const gridUri = new URI(config.gridUrl);
const screenshotOnReject = config.screenshotOnReject;
const screenshotOnRejectOpts = _.isObject(screenshotOnReject)
? {connectionRetryTimeout: screenshotOnReject.httpTimeout}
: screenshotOnReject;

const session = webdriverio.remote({
host: this._getGridHost(gridUri),
Expand All @@ -76,7 +72,7 @@ module.exports = class Browser {
logLevel: this._debug ? 'verbose' : 'error',
coloredLogs: true,
screenshotPath: config.screenshotPath,
screenshotOnReject: screenshotOnRejectOpts,
screenshotOnReject: false,
connectionRetryTimeout: config.httpTimeout,
connectionRetryCount: 0, // hermione has its own advanced retries
baseUrl: config.baseUrl
Expand All @@ -93,6 +89,38 @@ module.exports = class Browser {
return session;
}

_setHttpTimeout(timeout) {
this._session.extendOptions({connectionRetryTimeout: timeout});
}

_restoreHttpTimeout() {
this._setHttpTimeout(this._config.httpTimeout);
}

_switchOnScreenshotOnReject() {
this._session.extendOptions({screenshotOnReject: this._getScreenshotOnRejectOpts()});
}

_switchOffScreenshotOnReject() {
this._session.extendOptions({screenshotOnReject: false});
}

_getScreenshotOnRejectOpts() {
const screenshotOnReject = this._config.screenshotOnReject;

return _.isObject(screenshotOnReject)
? {connectionRetryTimeout: screenshotOnReject.httpTimeout}
: screenshotOnReject;
}

_getGridHost(url) {
return new URI({
username: url.username(),
password: url.password(),
hostname: url.hostname()
}).toString().slice(2); // URIjs leaves `//` prefix, removing it
}

_addMetaAccessCommands(session) {
session.addCommand('setMeta', (key, value) => this._meta[key] = value);
session.addCommand('getMeta', (key) => this._meta[key]);
Expand All @@ -116,14 +144,6 @@ module.exports = class Browser {
}, true); // overwrite original `url` method
}

_getGridHost(url) {
return new URI({
username: url.username(),
password: url.password(),
hostname: url.hostname()
}).toString().slice(2); // URIjs leaves `//` prefix, removing it
}

_getMetaUrl(uri) {
return this._config.baseUrl && uri[0] === '/'
? URI(this._config.baseUrl + uri).normalize().toString()
Expand Down
4 changes: 3 additions & 1 deletion lib/config/browser-options.js
Expand Up @@ -69,7 +69,9 @@ function buildBrowserOptions(defaultFactory, extra) {

httpTimeout: options.nonNegativeInteger('httpTimeout'),

sessionQuitTimeout: options.optionalNonNegativeInterger('sessionQuitTimeout'),
sessionRequestTimeout: options.optionalNonNegativeInteger('sessionRequestTimeout'),

sessionQuitTimeout: options.optionalNonNegativeInteger('sessionQuitTimeout'),

waitTimeout: options.positiveInteger('waitTimeout'),

Expand Down
7 changes: 5 additions & 2 deletions lib/config/defaults.js
@@ -1,5 +1,7 @@
'use strict';

const DEFAULT_HTTP_TIMEOUT = 90000;

module.exports = {
baseUrl: 'http://localhost',
gridUrl: 'http://localhost:4444/wd/hub',
Expand All @@ -10,8 +12,9 @@ module.exports = {
prepareEnvironment: null,
specs: null,
waitTimeout: 1000,
httpTimeout: 90000,
sessionQuitTimeout: null,
httpTimeout: DEFAULT_HTTP_TIMEOUT,
sessionRequestTimeout: DEFAULT_HTTP_TIMEOUT,
sessionQuitTimeout: DEFAULT_HTTP_TIMEOUT,
reporters: ['flat'],
debug: false,
sessionsPerBrowser: 1,
Expand Down
4 changes: 2 additions & 2 deletions lib/config/options-builder.js
Expand Up @@ -20,7 +20,7 @@ module.exports = (defaultFactory) => {
optionalFunction,
anyObject,
nonNegativeInteger,
optionalNonNegativeInterger,
optionalNonNegativeInteger,
string,
optionalString,
positiveInteger
Expand Down Expand Up @@ -64,7 +64,7 @@ module.exports = (defaultFactory) => {
});
}

function optionalNonNegativeInterger(name) {
function optionalNonNegativeInteger(name) {
return option({
parseEnv: Number,
parseCli: Number,
Expand Down
150 changes: 98 additions & 52 deletions test/lib/browser.js
Expand Up @@ -20,6 +20,7 @@ describe('Browser', () => {
screenshotPath: 'path/to/screenshots',
screenshotOnReject: true,
httpTimeout: 3000,
sessionRequestTimeout: null,
sessionQuitTimeout: null
});

Expand All @@ -39,7 +40,10 @@ describe('Browser', () => {
session.requestHandler = {defaultOptions: {}};

session.addCommand = () => {};
sandbox.stub(session, 'addCommand', (name, command) => session[name] = command);
sandbox.stub(session, 'addCommand', (name, command) => {
session[name] = command;
sandbox.spy(session, name);
});

return session;
}
Expand Down Expand Up @@ -70,47 +74,13 @@ describe('Browser', () => {
logLevel: 'verbose',
coloredLogs: true,
screenshotPath: 'path/to/screenshots',
screenshotOnReject: true,
screenshotOnReject: false,
connectionRetryTimeout: 3000,
connectionRetryCount: 0,
baseUrl: 'http://base_url'
}));
});

it('should set screenshotOnReject as "true"', () => {
const browser = mkBrowser_({screenshotOnReject: true});

return browser
.init()
.then(() => assert.calledWithMatch(webdriverio.remote, {screenshotOnReject: true}));
});

it('should set screenshotOnReject as "false"', () => {
const browser = mkBrowser_({screenshotOnReject: false});

return browser
.init()
.then(() => assert.calledWithMatch(webdriverio.remote, {screenshotOnReject: false}));
});

it('should set screenshotOnReject option', () => {
const browser = mkBrowser_({
screenshotOnReject: {
httpTimeout: 666
}
});

return browser
.init()
.then(() => {
assert.calledWithMatch(webdriverio.remote, {
screenshotOnReject: {
connectionRetryTimeout: 666
}
});
});
});

it('should initialize webdriver.io session', () => {
return mkBrowser_()
.init()
Expand All @@ -137,6 +107,95 @@ describe('Browser', () => {
});
});

it('should set custom options before initializing of a session', () => {
return mkBrowser_()
.init()
.then(() => assert.callOrder(session.extendOptions, session.init));
});

it('should use session request timeout for initializing of a session', () => {
return mkBrowser_({sessionRequestTimeout: 100500, httpTimeout: 500100})
.init()
.then(() => {
assert.calledWithMatch(session.extendOptions.firstCall, {connectionRetryTimeout: 100500});
});
});

it('should set option "screenshotOnReject" to "false" before initializing of a session', () => {
return mkBrowser_()
.init()
.then(() => assert.calledWithMatch(webdriverio.remote, {screenshotOnReject: false}));
});

it('should reset options to default after initializing of a session', () => {
return mkBrowser_()
.init()
.then(() => assert.callOrder(session.init, session.extendOptions));
});

it('should reset http timeout to default after initializing of a session', () => {
return mkBrowser_({sessionRequestTimeout: 100500, httpTimeout: 500100})
.init()
.then(() => {
assert.propertyVal(session.requestHandler.defaultOptions, 'connectionRetryTimeout', 500100);
});
});

it('should set option "screenshotOnReject" after initializing of a session', () => {
return mkBrowser_({screenshotOnReject: true})
.init()
.then(() => assert.propertyVal(session.requestHandler.defaultOptions, 'screenshotOnReject', true));
});

describe('"extendOptions" command', () => {
it('should add command', () => {
return mkBrowser_()
.init()
.then(() => assert.calledWith(session.addCommand, 'extendOptions'));
});

it('should add new option to "requestHandler" options', () => {
return mkBrowser_()
.init()
.then(() => {
session.extendOptions({newOption: 'foo'});
assert.propertyVal(session.requestHandler.defaultOptions, 'newOption', 'foo');
});
});

it('should override "requestHandler" option', () => {
return mkBrowser_({screenshotOnReject: true})
.init()
.then(() => {
session.extendOptions({screenshotOnReject: false});
assert.propertyVal(session.requestHandler.defaultOptions, 'screenshotOnReject', false);
});
});
});

describe('screenshotOnReject option', () => {
it('should support boolean notation', () => {
return mkBrowser_({screenshotOnReject: false})
.init()
.then(() => assert.propertyVal(session.requestHandler.defaultOptions, 'screenshotOnReject', false));
});

it('should support object notation', () => {
const browser = mkBrowser_({
screenshotOnReject: {
httpTimeout: 666
}
});

return browser
.init()
.then(() => {
assert.deepPropertyVal(session.requestHandler.defaultOptions,
'screenshotOnReject.connectionRetryTimeout', 666);
});
});
});

describe('session.url decorator', () => {
it('should force rewrite base `url` method', () => {
return mkBrowser_()
Expand Down Expand Up @@ -234,30 +293,17 @@ describe('Browser', () => {

it('should set custom options before finalizing of a session', () => {
return mkBrowser_()
.init()
.then((browser) => {
sandbox.spy(session, 'extendOptions');

return browser.quit();
})
.then(() => assert.callOrder(session.extendOptions, session.end));
});

it('should use common http timeout for finalizing of a session', () => {
return mkBrowser_({httpTimeout: 100500})
.init()
.then((browser) => browser.quit())
.then(() => {
assert.propertyVal(session.requestHandler.defaultOptions, 'connectionRetryTimeout', 100500);
});
.then(() => assert.callOrder(session.extendOptions, session.end));
});

it('should use session quit timeout for finalizing of a session', () => {
return mkBrowser_({sessionQuitTimeout: 500100})
return mkBrowser_({sessionQuitTimeout: 100500, httpTimeout: 500100})
.init()
.then((browser) => browser.quit())
.then(() => {
assert.propertyVal(session.requestHandler.defaultOptions, 'connectionRetryTimeout', 500100);
assert.propertyVal(session.requestHandler.defaultOptions, 'connectionRetryTimeout', 100500);
});
});

Expand Down
2 changes: 1 addition & 1 deletion test/lib/config/browser-options.js
Expand Up @@ -374,7 +374,7 @@ describe('config browser-options', () => {
});
});

['retry', 'httpTimeout', 'sessionQuitTimeout'].forEach((option) => {
['retry', 'httpTimeout', 'sessionRequestTimeout', 'sessionQuitTimeout'].forEach((option) => {
describe(`${option}`, () => {
it(`should throw error if ${option} is not a number`, () => {
const readConfig = mkConfig_({
Expand Down

0 comments on commit a15b022

Please sign in to comment.