forked from nightwatchjs/nightwatch
/
browserstack.js
166 lines (134 loc) · 4.85 KB
/
browserstack.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
const stripAnsi = require('strip-ansi');
const {Logger} = require('../../../utils');
const AppiumBaseServer = require('../appiumBase.js');
const defaultsDeep = require('lodash.defaultsdeep');
class Browserstack extends AppiumBaseServer {
bStackOptions() {
return this.settings.desiredCapabilities['bstack:options'];
}
get accessKey() {
return this.bStackOptions().accessKey;
}
get username() {
return this.bStackOptions().userName;
}
get build() {
return this.bStackOptions().buildName;
}
get local() {
return this.bStackOptions().local;
}
constructor(nightwatchInstance, browserName) {
super(nightwatchInstance, browserName);
this.useLocal = false;
this.nightwatchInstance.on('nightwatch:session.create', (data) => {
this.sessionId = data.sessionId;
this.getBuildId().then(buildId => {
if (buildId) {
this.buildId = buildId;
}
});
});
}
adaptSettings() {
this.settings.webdriver.start_process = false;
this.settings.webdriver.port = Number(this.settings.webdriver.port);
const {desiredCapabilities} = this.settings;
// checking for legacy-ways for providing config
this.settings.desiredCapabilities['bstack:options'] = defaultsDeep(this.settings.desiredCapabilities['bstack:options'], {
userName: desiredCapabilities['browserstack.user'],
accessKey: desiredCapabilities['browserstack.key'],
buildName: desiredCapabilities.build || desiredCapabilities.buildName,
local: desiredCapabilities['browserstack.local']
});
if (!this.accessKey && process.env.BROWSERSTACK_KEY) {
this.settings.desiredCapabilities['bstack:options'].accessKey = process.env.BROWSERSTACK_KEY;
}
if (!this.username && process.env.BROWSERSTACK_USER) {
this.settings.desiredCapabilities['bstack:options'].userName = process.env.BROWSERSTACK_USER;
}
if (!this.build) {
this.settings.desiredCapabilities['bstack:options'].buildName = 'nightwatch-test-build';
}
if (this.local) {
this.useLocal = true;
}
}
verifySettings() {
if (this.settings.webdriver.port !== 443) {
// eslint-disable-next-line no-console
console.warn(Logger.colors.brown('Using insecure HTTP connection on port 80. Consider using SSL by ' +
'setting port to 443 in your Nightwatch configuration.'));
}
if (!this.accessKey) {
throw new Error('BrowserStack access key is not set. Verify that "browserstack.key" capability is set correctly or ' +
'set BROWSERSTACK_KEY environment variable (.env files are supported).');
}
if (!this.username) {
throw new Error('BrowserStack username is not set. Verify that "browserstack.user" capability is set correctly or ' +
'set BROWSERSTACK_USER environment variable (.env files are supported).');
}
}
createSession({argv, moduleKey}) {
this.adaptSettings();
this.verifySettings();
return super.createSession({argv, moduleKey});
}
async getBuildId() {
try {
const builds = await this.sendHttpRequest({
url: `${this.ApiUrl}/builds.json`,
method: 'GET',
use_ssl: true,
auth: {
user: this.username,
pass: this.accessKey
}
});
const currentBuild = builds.find((item) => {
return item.automation_build.name === this.build;
});
return currentBuild && currentBuild.automation_build.hashed_id;
} catch (err) {
console.error(err);
}
}
async sendReasonToBrowserstack(isFailure = false, reason = '') {
reason = stripAnsi(reason);
await this.sendHttpRequest({
url: `${this.ApiUrl}/sessions/${this.sessionId}.json`,
method: 'PUT',
use_ssl: true,
data: {
status: isFailure ? 'failed' : 'passed',
reason
},
auth: {
user: this.username,
pass: this.accessKey
}
});
}
async testSuiteFinished(failures) {
try {
const reason = failures instanceof Error ? `${failures.name}: ${failures.message}` : '';
await this.sendReasonToBrowserstack(!!failures, 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}`));
if (this.uploadedAppUrl) {
// App was uploaded to BrowserStack and custom_id not being used
// eslint-disable-next-line no-console
console.log('\n ' + Logger.colors.light_cyan(
`Please set 'appium:app' capability to '${this.uploadedAppUrl}' to avoid uploading the app again in future runs.`
) + '\n');
}
this.sessionId = null;
return true;
} catch (err) {
Logger.error(err);
return false;
}
}
}
module.exports = Browserstack;