Skip to content

Commit

Permalink
Fix API calls and improve integration with Turboscale. (#4347)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rohannagariya1 authored Jan 6, 2025
1 parent df4d7fb commit 22d6221
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 3 deletions.
2 changes: 1 addition & 1 deletion lib/http/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class HttpRequest extends EventEmitter {
this.setPathPrefix(options);

const {method} = options;
if (options.data && !(method === 'POST' || method === 'PUT')) {
if (options.data && !(method === 'POST' || method === 'PUT' || method === 'PATCH')) {
options.data = '';
}

Expand Down
12 changes: 11 additions & 1 deletion lib/transport/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@ module.exports = class TransportFactory {
}
}

static usingBrowserstackTurboScale(settings) {
return settings.webdriver.host && (settings.webdriver.host.endsWith('.browserstack-ats.com') || settings.webdriver.host.startsWith('browserstack-turboscale-grid'));
}

static usingBrowserstack(settings) {
return settings.webdriver.host && (settings.webdriver.host.endsWith('.browserstack.com') || settings.webdriver.host.endsWith('.browserstack-ats.com') || settings.webdriver.host.startsWith('browserstack-turboscale-grid'));
return settings.webdriver.host && (settings.webdriver.host.endsWith('.browserstack.com') || TransportFactory.usingBrowserstackTurboScale(settings));
}

static getBrowserName(nightwatchInstance) {
Expand Down Expand Up @@ -124,6 +128,12 @@ module.exports = class TransportFactory {
return new AppAutomate(nightwatchInstance, browserName);
}

if (TransportFactory.usingBrowserstackTurboScale(nightwatchInstance.settings)) {
const AutomateTurboScale = require('./selenium-webdriver/browserstack/automateTurboScale.js');

return new AutomateTurboScale(nightwatchInstance, browserName);
}

const Automate = require('./selenium-webdriver/browserstack/automate.js');

return new Automate(nightwatchInstance, browserName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
const stripAnsi = require('strip-ansi');
const Automate = require('./automate.js');

class AutomateTurboScale extends Automate {
get buildUrl() {
return `https://${this.productNamespace}.browserstack.com/dashboard`;
}

get ApiUrl() {
return 'https://api.browserstack.com/automate-turboscale/v1';
}

get productNamespace() {
return 'grid';
}

async getBuildId() {
try {
const builds = await this.sendHttpRequest({
url: `${this.ApiUrl}/builds?status=running`,
method: 'GET',
use_ssl: true,
port: 443,
auth: {
user: this.username,
pass: this.accessKey
}
});

const buildData = builds.builds;
const currentBuild = buildData.find((item) => {
return item.name === this.build;
});

return currentBuild && currentBuild.hashed_id;
} catch (err) {
console.error(err);
}
}

async sendReasonToBrowserstack(isFailure = false, reason = '') {
const sessionDetails = await this.sendHttpRequest({
url: `${this.ApiUrl}/sessions/${this.sessionId}`,
method: 'GET',
use_ssl: true,
port: 443,
auth: {
user: this.username,
pass: this.accessKey
}
});

const status = sessionDetails?.status;
if (['passed', 'failed'].includes(status)) {
// status has already been set by user
return;
}

reason = stripAnsi(reason);
await this.sendHttpRequest({
url: `${this.ApiUrl}/sessions/${this.sessionId}`,
method: 'PATCH',
use_ssl: true,
port: 443,
data: {
status: isFailure ? 'failed' : 'passed',
reason
},
auth: {
user: this.username,
pass: this.accessKey
}
});
}
}

module.exports = AutomateTurboScale;
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ class Browserstack extends AppiumBaseServer {
return this.settings.desiredCapabilities['bstack:options'];
}

get buildUrl() {
return `https://${this.productNamespace}.browserstack.com`;
}

get accessKey() {
return this.bStackOptions().accessKey;
}
Expand Down Expand Up @@ -167,7 +171,7 @@ class Browserstack extends AppiumBaseServer {
await this.sendReasonToBrowserstack(!!err, reason);
// eslint-disable-next-line no-console
console.log('\n ' + 'See more info, video, & screenshots on Browserstack:\n' +
' ' + Logger.colors.light_cyan(`https://${this.productNamespace}.browserstack.com/builds/${this.buildId}/sessions/${this.sessionId}`));
' ' + Logger.colors.light_cyan(`${this.buildUrl}/builds/${this.buildId}/sessions/${this.sessionId}`));
}

if (this.uploadedAppUrl) {
Expand Down
85 changes: 85 additions & 0 deletions test/src/index/transport/testBrowserstackTransport.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const NightwatchClient = common.require('index.js');
const SeleniumRemote = common.require('transport/selenium-webdriver/selenium.js');
const Automate = common.require('transport/selenium-webdriver/browserstack/automate.js');
const AppAutomate = common.require('transport/selenium-webdriver/browserstack/appAutomate.js');
const AutomateTurboScale = common.require('transport/selenium-webdriver/browserstack/automateTurboScale.js');

describe('BrowserstackTransport', function () {
beforeEach(function() {
Expand All @@ -15,6 +16,7 @@ describe('BrowserstackTransport', function () {
});

afterEach(function() {
nock.cleanAll();
nock.restore();
});

Expand Down Expand Up @@ -339,7 +341,90 @@ describe('BrowserstackTransport', function () {
assert.strictEqual(transport.sessionId, null);

assert.strictEqual(transport.buildId, '123-567-89');
});

it('test create Transport for Browserstack - Automate TurboScale', async function() {
const client = NightwatchClient.client({
webdriver: {
host: 'hub-cloud.browserstack-ats.com',
port: 443,
start_process: true
},
desiredCapabilities: {
'browserstack.user': 'test-access-user',
'browserstack.key': 'test-access-key',
browserName: 'chrome'
}
});

nock('https://hub-cloud.browserstack-ats.com')
.post('/wd/hub/session')
.reply(201, function (uri, requestBody) {
return {
value: {
sessionId: '1352110219202',
capabilities: requestBody.capabilities
}
};
});

nock('https://api.browserstack.com')
.get('/automate-turboscale/v1/builds?status=running')
.reply(200, {
'builds': [
{
name: 'nightwatch-test-build',
hashed_id: '123-567-89'
},
{
name: 'test-build'
}
]
});

assert.ok(client.transport instanceof AutomateTurboScale);
assert.strictEqual(client.settings.webdriver.host, 'hub-cloud.browserstack-ats.com');
assert.strictEqual(client.settings.webdriver.default_path_prefix, '/wd/hub');
assert.strictEqual(client.settings.webdriver.ssl, true);

const {transport} = client;
assert.ok(transport instanceof SeleniumRemote);

let result = await transport.createSession({argv: undefined, moduleKey: ''});
assert.strictEqual(result.sessionId, '1352110219202');

client.emit('nightwatch:session.create', result);

assert.strictEqual(transport.username, 'test-access-user');
assert.strictEqual(transport.accessKey, 'test-access-key');
assert.strictEqual(client.settings.webdriver.start_process, false);

let sessionNockCalled = 0;

nock('https://api.browserstack.com')
.get('/automate-turboscale/v1/sessions/1352110219202')
.reply(200, function(){
sessionNockCalled++;

return {status: 'done'};
});
nock('https://api.browserstack.com')
.patch('/automate-turboscale/v1/sessions/1352110219202', {
status: 'passed',
reason: ''
})
.reply(200, function(){
sessionNockCalled++;

return {};
});

result = await transport.testSuiteFinished(false);
assert.strictEqual(result, true);
assert.strictEqual(transport.sessionId, null);

assert.strictEqual(sessionNockCalled, 2);
assert.strictEqual(transport.buildId, '123-567-89');
});

it('test create Transport for Browserstack with failures', async function() {
Expand Down

0 comments on commit 22d6221

Please sign in to comment.