/** * @flow * This file is generated automatically, run npm run build to re-generate. **/ import type { HttpMethod } from './flow-types/http-method'; import type { WebdriverResponse } from './flow-types/webdriver-response'; import type { HttpResponse } from './flow-types/http-response'; import type { Session } from './flow-types/session-data'; import type Debug from './debug'; import autoRequest from 'sync-request'; import autoSleep from 'thread-sleep'; import parseResponse from './utils/parse-response'; class Connection { /* * The name or url of the selenium webdriver server (e.g. 'chromedriver') */ remote: string; /* * The url of the selenium web-driver server */ remoteURI: string; /* * Reference to the debug context * * @private */ debug: Debug; constructor(remote: string, remoteURI: string, debug: Debug) { this.remote = remote; this.remoteURI = remoteURI.replace(/\/$/, ''); this.debug = debug; } /* * Session request with automatic parsing for errors */ requestWithSession(session: Session, method: HttpMethod, uri: string, options?: Object): WebdriverResponse { if (!/^https?\:\:\/\//.test(uri)) { uri = '/session/' + session.sessionID + uri; } const response = this.request(method, uri, options); return parseResponse(response); } /* * Make a request without using the current session. */ request(method: HttpMethod, uri: string, options?: Object): HttpResponse { if (!/^https?\:\:\/\//.test(uri)) { uri = this.remoteURI + uri; } let lastEx = null; const maxAttempts = options && options.noRetries ? 1 : 10; for (let i = 0; i < maxAttempts; i++) { try { this.debug.onRequest({ method, uri, options }); const response = autoRequest(method, uri, options); this.debug.onResponse(response); return response; } catch (ex) { lastEx = ex; // sleep for 100ms, 200ms, 300ms, 400ms and so on autoSleep(i * 100 + 100); } } if (!lastEx) { // this code sould be unreachable throw new Error('Unknown error'); } const err = improveError(this.remote, lastEx); (err: any).code = (lastEx: any).code; throw err; } } function improveError(remote: string, err: Error) { switch (remote) { case 'chromedriver': if (err.code === 'ECONNREFUSED') { return new Error('Could not connect to chromedriver.\r\nThe easiest way to use chromedriver is to download the latest ' + 'release from http://chromedriver.chromium.org/downloads (just look for the highest version ' + 'number), then run `./chromedriver` in a separate terminal.'); } break; case 'taxirank': if (err.code === 'ECONNREFUSED') { return new Error('Could not connect to taxirank.\r\nThe easiest way to use taxirank is to run:\r\n\r\n' + ' npm install -g taxi-rank\r\n taxi-rank\r\n\r\n' + 'in your command line/terminal application.'); } break; case 'saucelabs': if (err.code === 'ECONNREFUSED' || err.code === 'ENOTFOUND') { return new Error('Could not connect to saucelabs.\r\nMake sure you are connected to the internet. If you are connected to ' + 'the internet, you could check their status page at https://status.saucelabs.com/'); } break; case 'browserstack': if (err.code === 'ECONNREFUSED' || err.code === 'ENOTFOUND') { return new Error('Could not connect to browserstack.\r\nMake sure you are connected to the internet. If you are connected to ' + 'the internet, you could check their twitter feed at https://twitter.com/browserstack'); } break; case 'testingbot': if (err.code === 'ECONNREFUSED' || err.code === 'ENOTFOUND') { return new Error('Could not connect to testingbot.\r\nMake sure you are connected to the internet. If you are connected to ' + 'the internet, you could check their status page at https://testingbot.statuspage.io/'); } break; } return err; } export default Connection;