Repository: saucelabs/node-saucelabs
Pull request #68 (2019-07-08 08:20:58)

feat(request): support proxy option
this allows to pass in a proxy to be used via options. It essentially mimics the behavior of passing in the username/accesskey either via ENVs or options. Moreover this used to be available in v1 and now with the PR shouldn't be a breaking change any longer.


Patch:
diff --git a/README.md b/README.md
index cb7351c..8516d23 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,15 @@ Default: `false`
 
 ## Usage
 
-All accessible API commands with descriptions can be found [here](docs/interface.md). In order to route requests through a proxy set `HTTP_PROXY`, `HTTPS_PROXY` or `NO_PROXY` as environment variable. For more information on this, read [here](https://github.com/request/request#controlling-proxy-behaviour-using-environment-variables).
+All accessible API commands with descriptions can be found [here](docs/interface.md). In order to route requests through a proxy set `HTTP_PROXY`, `HTTPS_PROXY` or `NO_PROXY` as environment variable. For more information on this, read [here](https://github.com/request/request#controlling-proxy-behaviour-using-environment-variables). Alternatively you can pass the proxy to be used during initialization:
+
+```js
+import SauceLabs from 'saucelabs';
+
+...
+
+const myAccount = new SauceLabs({ proxy: 'http://localproxy.com' });
+```
 
 ### As CLI Tool
 
@@ -93,7 +101,7 @@ import SauceLabs from 'saucelabs';
 (async () => {
     const myAccount = new SauceLabs();
     // using constructor options
-    // const myAccount = new SauceLabs({ user: "YOUR-USER", key: "YOUR-ACCESS-KEY"}); 
+    // const myAccount = new SauceLabs({ user: "YOUR-USER", key: "YOUR-ACCESS-KEY"});
 
     // get job details of last run job
     const job = await myAccount.listJobs(
@@ -165,9 +173,9 @@ Below, you can find the list of the mapped method names:
 | deleteTunnel(id, callback) | async deleteTunnel(username, id) |
 | getServiceStatus(callback) |async getStatus() |
 | getBrowsers(callback) | ? |
-| getAllBrowsers(callback) | ? |
-| getSeleniumBrowsers(callback) | ? |
-| getWebDriverBrowsers(callback) | ? |
+| getAllBrowsers(callback) | async listPlatforms(platform)  // pass "all" |
+| getSeleniumBrowsers(callback) | Selenium-RC no longer supported |
+| getWebDriverBrowsers(callback) | async listPlatforms(platform) // pass "webdriver" |
 | getTestCounter(callback) | ? |
 | updateSubAccount(data, callback) | ? |
 | deleteSubAccount(callback) | ? |
diff --git a/scripts/generate-typings.js b/scripts/generate-typings.js
index 89b8717..136493e 100644
--- a/scripts/generate-typings.js
+++ b/scripts/generate-typings.js
@@ -58,6 +58,7 @@ export interface SauceLabsOptions {
     key: string;
     region?: ${regions};
     headless?: boolean;
+    proxy?: string;
 }`
 
     const methods = files.map((api) => {
diff --git a/src/constants.js b/src/constants.js
index cd806c2..459088e 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -98,4 +98,8 @@ export const CLI_PARAMS = [{
     name: 'headless',
     default: DEFAULT_OPTIONS.headless,
     description: 'if set to true you are accessing the headless Sauce instances (this discards the `region` option)'
+}, {
+    alias: 'p',
+    name: 'proxy',
+    description: 'use a proxy for fetching data instead of environment variables'
 }]
diff --git a/src/index.js b/src/index.js
index 52f7ae6..048e8df 100644
--- a/src/index.js
+++ b/src/index.js
@@ -22,6 +22,7 @@ export default class SauceLabs {
             user: this.username,
             pass: this._accessKey
         }
+        this.proxy = this._options.proxy
 
         /**
          * public fields
@@ -152,6 +153,7 @@ export default class SauceLabs {
                 json: true,
                 auth: this._auth,
                 strictSSL: getStrictSsl(),
+                proxy: this.proxy,
                 useQuerystring: true
             }, (err, response, body) => {
                 /* istanbul ignore if */
@@ -184,6 +186,7 @@ export default class SauceLabs {
             const req = request({
                 method: 'GET',
                 strictSSL: getStrictSsl(),
+                proxy: this.proxy,
                 uri: `${host}/jobs/${jobId}/${assetName}?ts=${Date.now()}&auth=${hmac}`
             }, (err, res, body) => {
                 /**


Test patch:
diff --git a/tests/index.test.js b/tests/index.test.js
index 9075e3b..4685621 100644
--- a/tests/index.test.js
+++ b/tests/index.test.js
@@ -147,6 +147,16 @@ it('should fail if parameters are not given properly', async () => {
     await expect(api.downloadJobAsset(123, 'bar')).rejects.toEqual(error)
 })
 
+test('should support proxy options', async () => {
+    const proxy = 'https://my.proxy.com'
+    const api = new SauceLabs({ user: 'foo', key: 'bar', proxy })
+    await api.downloadJobAsset('some-id', 'performance.json')
+    const requestOptions = request.mock.calls[0][0]
+
+    await expect(requestOptions.proxy).toBeDefined()
+    await expect(requestOptions.proxy).toEqual(proxy)
+})
+
 test('should handle asset response properly', async () => {
     const api = new SauceLabs({ user: 'foo', key: 'bar' })
     await api.downloadJobAsset('some-id', 'performance.json')