gkushang/nemo-saucelabs

View on GitHub
lib/saucelabs.js

Summary

Maintainability
A
2 hrs
Test Coverage
/*-----------------------------------------------------------------------------------------*\
 |  The MIT License (MIT)                                                                    |
 |                                                                                           |
 |  Copyright (c) 2015 PayPal                                                                |
 |                                                                                           |
 |  Permission is hereby granted, free of charge, to any person obtaining a copy             |
 |  of this software and associated documentation files (the 'Software'), to deal            |
 |  in the Software without restriction, including without limitation the rights             |
 |  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell                |
 |  copies of the Software, and to permit persons to whom the Software is                    |
 |  furnished to do so, subject to the following conditions:                                 |
 |                                                                                           |
 |      The above copyright notice and this permission notice shall be included in           |
 |  all copies or substantial portions of the Software.                                      |
 |                                                                                           |
 |      THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR           |
 |  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,                 |
 |      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE          |
 |  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                   |
 |  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,            |
 |      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN            |
 |  THE SOFTWARE.                                                                            |
 \*---------------------------------------------------------------------------------------- */

/*
 data: {
 name: test-name,
 cucumber_tags: scenarios.getTags(),
 tags: array of tags
 passed: true/false,
 build: build_id,
 'custom-data': {error: 'cause of failure}}
 */

'use strict';

const defaults = require('lodash.defaults');
const request = require('requestretry');
const debug = require('debug');
const log = debug('nemo-saucelabs:log');

const DEFAULTS = {
  host: 'https://saucelabs.com',
  base: 'rest/v1',
  json: true,
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  }
};

function SauceLabs(options) {
  if (options.username === undefined || options.accessKey === undefined) {
    throw new Error('Sauce Labs username and/or accessKey is undefined. Please specify through config.');
  }

  this.options = defaults({}, DEFAULTS, options);
}

SauceLabs.prototype.updateJob = function(data) {
  const { cucumber_tags: cucumberTags } = data;
  const tags = [];
  if (cucumberTags && Array.isArray(cucumberTags)) {
    cucumberTags.map(function(tag) {
      tags.push(tag.name);
    });

    data.tags = data.tags || [];
    data.tags.push(tags);
  }

  return this.put({ body: data });
};

SauceLabs.prototype.isJobPassed = function(isPassed) {
  return this.put({
    body: { passed: isPassed }
  });
};

SauceLabs.prototype.getJobUrl = function() {
  return this.options.driver.getSession().then(session => {
    return [this.options.host, 'beta/tests', session.getId()].join('/');
  });
};

SauceLabs.prototype.put = function(data) {
  const {
    options: {
      username,
      accessKey,
      session_id,
      host,
      base,
    }
  } = this;

  function makeRequest(message) {
    Object.assign(message, {
      auth: {
        user: username,
        pass: accessKey,
      },
      maxAttempts: 5,
      retryDelay: 5000,
      retryStrategy: request.RetryStrategies.HTTPOrNetworkError,
    });

    log('[nemo-saucelabs] Request to Sauce Labs API with parameters:', message);

    return new Promise(function(resolve, reject) {
      request(message, function(err, response) {

        if (err) {
          const errMessage = `Error in processing Sauce Labs request: ${err.message}`;
          debug(errMessage);
          return reject(errMessage);
        }

        if (response.statusCode === 200) {
          debug('Successful response from Sauce Labs API');
          return resolve();
        }

        const errMessage = `Request to Sauce Labs API is unsuccessful with statusCode: ${response.statusCode}`;
        debug(errMessage);
        return reject(errMessage);
      })
    })
  }

  return this.options.driver.getSession().then(function(session) {
    const sessionId = session_id || session.getId();
    Object.assign(data, {
      url: `${host}/${base}/${username}/jobs/${sessionId}`,
      method: 'PUT',
    });
    const message = Object.assign({}, DEFAULTS, data);
    return makeRequest(message);
  });
};

module.exports = SauceLabs;