123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- var crypto = require('crypto');
- var https = require('https');
- var querystring = require('querystring');
- var utils = require('./utils');
- var HttpsProxyAgent = require('https-proxy-agent');
- var url = require('url');
- var extend = utils.extend;
- var replace = utils.replace;
- var DEFAULTS = {
- username: null,
- password: null,
- proxy: null,
- hostname: 'saucelabs.com',
- base: '/rest/v1/',
- port: '443'
- };
- function SauceLabs(options) {
- this.options = extend({}, DEFAULTS, options);
- this.options.auth = this.options.username + ':' + this.options.password;
- }
- module.exports = SauceLabs;
- // API
- SauceLabs.prototype.getAccountDetails = function (callback) {
- this.send({
- method: 'GET',
- path: 'users/:username'
- }, callback);
- };
- SauceLabs.prototype.getAccountLimits = function (callback) {
- this.send({
- method: 'GET',
- path: ':username/limits'
- }, callback);
- };
- SauceLabs.prototype.getUserActivity = function (start, end, callback) {
- if (typeof start === 'function') {
- callback = start;
- start = null;
- end = null;
- } else if (typeof end === 'function') {
- callback = end;
- end = null;
- }
- var dates = (start != null || end != null) ? {} : null;
- if (start != null) {
- dates.start = formatDate(start);
- }
- if (end != null) {
- dates.end = formatDate(end);
- }
- this.send({
- method: 'GET',
- path: ':username/activity',
- query: dates
- }, callback);
- };
- SauceLabs.prototype.getUserConcurrency = function (callback) {
- this.send({
- method: 'GET',
- path: 'users/:username/concurrency'
- }, callback);
- };
- SauceLabs.prototype.getAccountUsage = function (callback) {
- this.send({
- method: 'GET',
- path: 'users/:username/usage'
- }, callback);
- };
- SauceLabs.prototype.getJobs = function (callback) {
- this.send({
- method: 'GET',
- path: ':username/jobs',
- query: { full: true }
- }, callback);
- };
- SauceLabs.prototype.showJob = function (id, callback) {
- this.send({
- method: 'GET',
- path: ':username/jobs/:id',
- args: { id: id }
- }, callback);
- };
- SauceLabs.prototype.showJobAssets = function (id, callback) {
- this.send({
- method: 'GET',
- path: ':username/jobs/:id/assets',
- args: { id: id }
- }, callback);
- };
- SauceLabs.prototype.updateJob = function (id, data, callback) {
- this.send({
- method: 'PUT',
- path: ':username/jobs/:id',
- args: { id: id },
- data: data
- }, callback);
- };
- SauceLabs.prototype.stopJob = function (id, data, callback) {
- this.send({
- method: 'PUT',
- path: ':username/jobs/:id/stop',
- args: { id: id },
- data: data
- }, callback);
- };
- SauceLabs.prototype.deleteJob = function (id, callback) {
- this.send({
- method: 'DELETE',
- path: ':username/jobs/:id',
- args: { id: id }
- }, callback);
- };
- SauceLabs.prototype.getActiveTunnels = function (callback) {
- this.send({
- method: 'GET',
- path: ':username/tunnels'
- }, callback);
- };
- SauceLabs.prototype.getTunnel = function (id, callback){
- this.send({
- method: 'GET',
- path: ':username/tunnels/:id',
- args: { id: id }
- }, callback);
- };
- SauceLabs.prototype.deleteTunnel = function (id, callback){
- this.send({
- method: 'DELETE',
- path: ':username/tunnels/:id',
- args: { id: id }
- }, callback);
- };
- SauceLabs.prototype.getServiceStatus = function (callback) {
- this.send({
- method: 'GET',
- path: 'info/status'
- }, callback);
- };
- SauceLabs.prototype.getBrowsers = function (callback) {
- this.send({
- method: 'GET',
- path: 'info/browsers'
- }, callback);
- };
- SauceLabs.prototype.getAllBrowsers = function (callback) {
- this.send({
- method: 'GET',
- path: 'info/browsers/all'
- }, callback);
- };
- SauceLabs.prototype.getSeleniumBrowsers = function (callback) {
- this.send({
- method: 'GET',
- path: 'info/browsers/selenium-rc'
- }, callback);
- };
- SauceLabs.prototype.getWebDriverBrowsers = function (callback) {
- this.send({
- method: 'GET',
- path: 'info/browsers/webdriver'
- }, callback);
- };
- SauceLabs.prototype.getTestCounter = function (callback) {
- this.send({
- method: 'GET',
- path: 'info/counter'
- }, callback);
- };
- SauceLabs.prototype.updateSubAccount = function (data, callback) {
- this.send({
- method: 'POST',
- path: 'users/:username/subscription',
- data: data
- }, callback);
- };
- SauceLabs.prototype.deleteSubAccount = function (callback) {
- this.send({
- method: 'DELETE',
- path: 'users/:username/subscription'
- }, callback);
- };
- SauceLabs.prototype.createSubAccount = function (data, callback) {
- this.send({
- method: 'POST',
- path: 'users/:username',
- data: data
- }, callback);
- };
- SauceLabs.prototype.createPublicLink = function (id, date, useHour, callback) {
- if (typeof date === 'function') {
- callback = date;
- date = null;
- useHour = false;
- } else if (typeof useHour === 'function') {
- callback = useHour;
- useHour = false;
- }
- if (date != null) {
- date = formatDate(date, useHour);
- }
- var link = generateLink(this.options.hostname, this.options.auth, date, id);
- callback(null, link);
- };
- SauceLabs.prototype.send = function (message, callback) {
- var method = message.method,
- path = message.path,
- args = message.args,
- query = message.query,
- data = message.data,
- body = JSON.stringify(data);
- // Build path with base, placeholders, and query.
- path = this.options.base + replace(path, extend({}, this.options, args));
- if (query != null) {
- path += '?' + querystring.stringify(query);
- }
- // Make the request.
- var options = extend({}, this.options, {
- method: method,
- path: path,
- headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json',
- 'Content-Length': body != null ? Buffer.byteLength(body) : 0
- }
- });
- makeRequest(options, body, callback);
- };
- SauceLabs.prototype.getSubAccountList = function (callback) {
- this.send({
- method: 'GET',
- path: 'users/:username/list-subaccounts'
- }, callback);
- };
- SauceLabs.prototype.getSubAccounts = function (callback) {
- this.send({
- method: 'GET',
- path: 'users/:username/subaccounts'
- }, callback);
- };
- // Helpers
- function formatDate(date, useHour) {
- return date.toISOString().replace(/T(\d+).*/, (useHour ? '-$1' : ''));
- }
- function generateToken(auth, date, job) {
- var key = auth + (date ? ':' + date : '');
- return crypto
- .createHmac('md5', key)
- .update(job)
- .digest('hex');
- }
- function generateLink(hostname, auth, date, job) {
- return replace('https://:hostname/jobs/:id?auth=:token', {
- hostname: hostname,
- id: job,
- token: generateToken(auth, date, job)
- });
- }
- function makeRequest(options, body, callback) {
- if(options.proxy){
- options.agent = new HttpsProxyAgent(url.parse(options.proxy));
- }
- var request = https.request(options, function (response) {
- var result = '';
- if (callback) {
- response
- .on('data', function (chunk) {
- result += chunk;
- })
- .on('end', function () {
- var res;
- try {
- res = JSON.parse(result);
- } catch (e) {
- callback('Could not parse response: ' + result);
- return;
- }
- if (response.statusCode === 200) {
- callback(null, res);
- } else {
- callback(res);
- }
- });
- }
- });
- request
- .on('error', function (err) {
- callback('Could not send request: ' + err.message);
- });
- if (body != null) {
- request.write(body);
- }
- request.end();
- }
|