Skip to content

Commit f8c0784

Browse files
authored
Determine the correct OS version using browserstack API(closes DevExpress/testcafe#7006) (#168)
* determine the correct OS version using browserstack API * fix tests * fix Windows 11 test * fix code style * fix testcafe version * add tests without testcafe integration * increase connection timeout * fix tests
1 parent d8ea468 commit f8c0784

7 files changed

Lines changed: 132 additions & 33 deletions

File tree

Gulpfile.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
const path = require('path');
2-
const { spawn } = require('child_process');
3-
const gulp = require('gulp');
4-
const eslint = require('gulp-eslint');
5-
const del = require('del');
1+
const path = require('path');
2+
const { spawn } = require('child_process');
3+
const gulp = require('gulp');
4+
const eslint = require('gulp-eslint');
5+
const del = require('del');
66

77

88
const PACKAGE_PARENT_DIR = path.join(__dirname, '../');
@@ -102,4 +102,4 @@ exports.testMochaAutomate = testMochaAutomate;
102102
exports.testTestcafeRest = gulp.series(exports.build, testTestcafeRest);
103103
exports.testTestcafeAutomate = gulp.series(exports.build, testTestcafeAutomate);
104104

105-
exports.test = gulp.series(exports.build, testMochaRest, testMochaAutomate, testTestcafeRest, testTestcafeAutomate);
105+
exports.test = gulp.series(exports.build, testMochaRest, testMochaAutomate, testTestcafeRest, testTestcafeAutomate);

src/backends/automate.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,10 @@ export default class AutomateBackend extends BaseBackend {
109109
}
110110
}
111111

112-
async _requestSessionUrl (id) {
112+
async _requestSessionInfo (id) {
113113
var sessionInfo = await requestApiBase(BROWSERSTACK_API_PATHS.getStatus(this.sessions[id].sessionId));
114114

115-
return sessionInfo['automation_session']['browser_url'];
115+
return sessionInfo['automation_session'];
116116
}
117117

118118
async _requestCurrentWindowSize (id) {
@@ -134,6 +134,13 @@ export default class AutomateBackend extends BaseBackend {
134134
return this.sessions[id] ? this.sessions[id].sessionUrl : '';
135135
}
136136

137+
async getOSInfo (id) {
138+
if (this.sessions[id])
139+
return this.sessions[id].osInfo;
140+
141+
return null;
142+
}
143+
137144
async openBrowser (id, pageUrl, capabilities) {
138145
var { localIdentifier, local, ...restCapabilities } = capabilities;
139146

@@ -151,7 +158,14 @@ export default class AutomateBackend extends BaseBackend {
151158

152159
AutomateBackend._ensureSessionId(this.sessions[id]);
153160

154-
this.sessions[id].sessionUrl = await this._requestSessionUrl(id);
161+
const sessionInfo = await this._requestSessionInfo(id);
162+
const osInfo = {
163+
name: sessionInfo['os'] || '',
164+
version: sessionInfo['os_version'] || ''
165+
};
166+
167+
this.sessions[id].sessionUrl = sessionInfo['browser_url'];
168+
this.sessions[id].osInfo = osInfo;
155169

156170
var sessionId = this.sessions[id].sessionId;
157171

src/backends/base.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,8 @@ export default class BaseBackend {
3737
getSessionUrl (/*id*/) {
3838
throw new Error(ERROR_MESSAGES.API_METHOD_NOT_IMPLEMENTED());
3939
}
40+
41+
async getOSInfo (/*id*/) {
42+
throw new Error(ERROR_MESSAGES.API_METHOD_NOT_IMPLEMENTED());
43+
}
4044
}

src/backends/js-testing.js

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,32 @@ const TESTS_TIMEOUT = process.env['BROWSERSTACK_TEST_TIMEOUT'] || 1800;
88

99
const BROWSERSTACK_API_PATHS = {
1010
browserList: {
11-
url: 'https://api.browserstack.com/4/browsers?flat=true'
11+
url: 'https://api.browserstack.com/4/browsers?flat=true',
1212
},
1313

1414
newWorker: {
1515
url: 'https://api.browserstack.com/4/worker',
16-
method: 'POST'
16+
method: 'POST',
1717
},
1818

1919
getWorkerInfo: id => ({
20-
url: `https://api.browserstack.com/4/worker/${id}`
20+
url: `https://api.browserstack.com/4/worker/${id}`,
2121
}),
2222

2323
deleteWorker: id => ({
2424
url: `https://api.browserstack.com/4/worker/${id}`,
25-
method: 'DELETE'
25+
method: 'DELETE',
2626
}),
2727

2828
screenshot: id => ({
2929
url: `https://api.browserstack.com/4/worker/${id}/screenshot.png`,
30-
encoding: null
30+
encoding: null,
3131
}),
3232

3333
setStatus: id => ({
3434
url: `https://api.browserstack.com/automate/sessions/${id}.json`,
35-
method: 'PUT'
36-
})
35+
method: 'PUT',
36+
}),
3737
};
3838

3939
export default class JSTestingBackend extends BaseBackend {
@@ -43,10 +43,8 @@ export default class JSTestingBackend extends BaseBackend {
4343
this.workers = {};
4444
}
4545

46-
async _requestSessionUrl (id) {
47-
var workerInfo = await requestApi(BROWSERSTACK_API_PATHS.getWorkerInfo(this.workers[id].id));
48-
49-
return workerInfo['browser_url'];
46+
async _requestSessionInfo (id) {
47+
return await requestApi(BROWSERSTACK_API_PATHS.getWorkerInfo(this.workers[id].id));
5048
}
5149

5250
async _getSessionId (id) {
@@ -65,6 +63,13 @@ export default class JSTestingBackend extends BaseBackend {
6563
return this.workers[id] ? this.workers[id].sessionUrl : '';
6664
}
6765

66+
async getOSInfo (id) {
67+
if (this.workers[id])
68+
return this.workers[id].osInfo;
69+
70+
return null;
71+
}
72+
6873
async openBrowser (id, pageUrl, capabilities) {
6974
var { local, ...restCapabilities } = capabilities;
7075

@@ -74,22 +79,29 @@ export default class JSTestingBackend extends BaseBackend {
7479
timeout: TESTS_TIMEOUT,
7580
url: pageUrl,
7681

77-
...restCapabilities
82+
...restCapabilities,
7883
};
7984

8085
this.workers[id] = await requestApi(BROWSERSTACK_API_PATHS.newWorker, {
8186
executeImmediately: true,
8287

83-
...capabilities
88+
...capabilities,
8489
});
8590

91+
const sessionInfo = await this._requestSessionInfo(id);
92+
const osInfo = {
93+
name: sessionInfo['os'] || '',
94+
version: sessionInfo['os_version'] || ''
95+
};
96+
8697
this.workers[id].started = Date.now();
87-
this.workers[id].sessionUrl = await this._requestSessionUrl(id);
98+
this.workers[id].sessionUrl = sessionInfo['browser_url'];
99+
this.workers[id].osInfo = osInfo;
88100
this.workers[id].sessionId = await this._getSessionId(id);
89101
}
90102

91103
async closeBrowser (id) {
92-
var workerId = this.workers[id].id;
104+
var workerId = this.workers[id].id;
93105

94106
// Return incase of invalid workerId
95107
if (!workerId || workerId === '')
@@ -101,7 +113,7 @@ export default class JSTestingBackend extends BaseBackend {
101113

102114
async takeScreenshot (id, screenshotPath) {
103115
var buffer = await requestApi(BROWSERSTACK_API_PATHS.screenshot(this.workers[id].id));
104-
var image = await jimp.read(buffer);
116+
var image = await jimp.read(buffer);
105117

106118
await image.writeAsync(screenshotPath);
107119
}

src/index.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,11 @@ module.exports = {
166166
var isAnyPlatform = query.platform === 'any';
167167

168168
var desktopBrowserMatched = browserNameMatched &&
169-
(browserVersionMatched || isAnyVersion) &&
170-
(platformNameMatched || isAnyPlatform);
169+
(browserVersionMatched || isAnyVersion) &&
170+
(platformNameMatched || isAnyPlatform);
171171

172172
var mobileBrowserMatched = deviceNameMatched &&
173-
(platformVersionMatched || isAnyVersion);
173+
(platformVersionMatched || isAnyVersion);
174174

175175
return desktopBrowserMatched || mobileBrowserMatched;
176176
});
@@ -237,7 +237,7 @@ module.exports = {
237237
...this._getAdditionalCapabilities()
238238
};
239239

240-
capabilities.local = isLocalEnabled();
240+
capabilities.local = isLocalEnabled();
241241

242242
// Give preference to the already running local identifier
243243
capabilities.localIdentifier = process.env.BROWSERSTACK_LOCAL_IDENTIFIER;
@@ -317,5 +317,9 @@ module.exports = {
317317

318318
async reportJobResult (id, jobResult, jobData) {
319319
await this.backend.reportJobResult(id, jobResult, jobData, this.JOB_RESULT);
320+
},
321+
322+
async getOSInfo (id) {
323+
return await this.backend.getOSInfo(id);
320324
}
321325
};

test/mocha/get-os-info-test.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
var expect = require('chai').expect;
2+
const browserStackProvider = require('../../');
3+
4+
(process.env.BROWSERSTACK_USE_AUTOMATE === '1' ? describe.skip : describe)('Get OS info test', function () {
5+
this.timeout(20000);
6+
7+
const browserID = {
8+
'Win10': 't1t1t1t1',
9+
'Win11': 't2t2t2t2',
10+
'Invalid': 'invalid'
11+
};
12+
const browserSettings = {
13+
'Win10': 'chrome@101.0:Windows 10',
14+
'Win11': 'chrome@101.0:Windows 11'
15+
};
16+
17+
const providerMock = {
18+
...browserStackProvider,
19+
setUserAgentMetaInfo: () => {
20+
}
21+
};
22+
23+
before(async function () {
24+
await providerMock.init();
25+
26+
await providerMock.openBrowser(browserID.Win10, 'example.org', browserSettings.Win10);
27+
await providerMock.openBrowser(browserID.Win11, 'example.org', browserSettings.Win11);
28+
29+
});
30+
31+
after(async function () {
32+
await providerMock.closeBrowser(browserID.Win10);
33+
await providerMock.closeBrowser(browserID.Win11);
34+
35+
await providerMock.dispose();
36+
});
37+
38+
it('getOSInfo should return a correct OS version', async function () {
39+
const expectedResults = {
40+
'Win10': {
41+
name: 'Windows',
42+
version: '10'
43+
},
44+
'Win11': {
45+
name: 'Windows',
46+
version: '11'
47+
}
48+
};
49+
50+
const win10Info = await providerMock.getOSInfo(browserID.Win10);
51+
const win11Info = await providerMock.getOSInfo(browserID.Win11);
52+
53+
54+
expect(win10Info).eql(expectedResults.Win10);
55+
expect(win11Info).eql(expectedResults.Win11);
56+
});
57+
58+
it('Should return null if specified browser id is incorrect', async function () {
59+
const osInfo = await providerMock.getOSInfo(browserID.Invalid);
60+
61+
expect(osInfo).to.be.null;
62+
});
63+
64+
});

test/mocha/testcafe-integration-test.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
var expect = require('chai').expect;
1+
var expect = require('chai').expect;
22
var createTestCafe = require('testcafe');
33

4+
45
describe('TestCafe integration', function () {
56
this.timeout(2 * 60 * 1000);
67

@@ -30,7 +31,7 @@ describe('TestCafe integration', function () {
3031
},
3132
end: function (data) {
3233
report += data;
33-
}
34+
},
3435
})
3536
.run()
3637
.then(function (failedCount) {
@@ -56,7 +57,7 @@ describe('TestCafe integration', function () {
5657
},
5758
end: function (data) {
5859
report += data;
59-
}
60+
},
6061
})
6162
.run()
6263
.then(function () {
@@ -80,7 +81,7 @@ describe('TestCafe integration', function () {
8081
},
8182
end: function (data) {
8283
report += data;
83-
}
84+
},
8485
})
8586
.run()
8687
.then(function () {

0 commit comments

Comments
 (0)