@amazon/vinyl-build-utils 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -0
- package/dist/babel/compatTransform.d.ts +20 -0
- package/dist/babel/compatTransform.d.ts.map +1 -0
- package/dist/babel/compatTransform.js +46 -0
- package/dist/browserstack/BrowserStackWorker.d.ts +150 -0
- package/dist/browserstack/BrowserStackWorker.d.ts.map +1 -0
- package/dist/browserstack/BrowserStackWorker.js +280 -0
- package/dist/browserstack/BrowserStackWorkerController.d.ts +103 -0
- package/dist/browserstack/BrowserStackWorkerController.d.ts.map +1 -0
- package/dist/browserstack/BrowserStackWorkerController.js +199 -0
- package/dist/browserstack/browserStackLocal.d.ts +3 -0
- package/dist/browserstack/browserStackLocal.d.ts.map +1 -0
- package/dist/browserstack/browserStackLocal.js +36 -0
- package/dist/browserstack/browserStackRestApi.d.ts +304 -0
- package/dist/browserstack/browserStackRestApi.d.ts.map +1 -0
- package/dist/browserstack/browserStackRestApi.js +121 -0
- package/dist/browserstack/configureReporterApi.d.ts +85 -0
- package/dist/browserstack/configureReporterApi.d.ts.map +1 -0
- package/dist/browserstack/configureReporterApi.js +51 -0
- package/dist/browserstack/runBrowserStack.d.ts +123 -0
- package/dist/browserstack/runBrowserStack.d.ts.map +1 -0
- package/dist/browserstack/runBrowserStack.js +204 -0
- package/dist/esbuild/CompatTransformPlugin.d.ts +6 -0
- package/dist/esbuild/CompatTransformPlugin.d.ts.map +1 -0
- package/dist/esbuild/CompatTransformPlugin.js +59 -0
- package/dist/esbuild/PureExportsPlugin.d.ts +11 -0
- package/dist/esbuild/PureExportsPlugin.d.ts.map +1 -0
- package/dist/esbuild/PureExportsPlugin.js +55 -0
- package/dist/esbuild/TypeDeclarationsPlugin.d.ts +9 -0
- package/dist/esbuild/TypeDeclarationsPlugin.d.ts.map +1 -0
- package/dist/esbuild/TypeDeclarationsPlugin.js +60 -0
- package/dist/esbuild/analyzeExports.d.ts +7 -0
- package/dist/esbuild/analyzeExports.d.ts.map +1 -0
- package/dist/esbuild/analyzeExports.js +78 -0
- package/dist/esbuild/buildAll.d.ts +12 -0
- package/dist/esbuild/buildAll.d.ts.map +1 -0
- package/dist/esbuild/buildAll.js +16 -0
- package/dist/esbuild/optionalEntryPoints.d.ts +8 -0
- package/dist/esbuild/optionalEntryPoints.d.ts.map +1 -0
- package/dist/esbuild/optionalEntryPoints.js +20 -0
- package/dist/express/serve.d.ts +33 -0
- package/dist/express/serve.d.ts.map +1 -0
- package/dist/express/serve.js +31 -0
- package/dist/express/startExpressServer.d.ts +80 -0
- package/dist/express/startExpressServer.d.ts.map +1 -0
- package/dist/express/startExpressServer.js +114 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/typescript/buildTypeDeclarations.d.ts +47 -0
- package/dist/typescript/buildTypeDeclarations.d.ts.map +1 -0
- package/dist/typescript/buildTypeDeclarations.js +65 -0
- package/dist/typescript/parseTsConfig.d.ts +13 -0
- package/dist/typescript/parseTsConfig.d.ts.map +1 -0
- package/dist/typescript/parseTsConfig.js +23 -0
- package/dist/typescript/replacePathAliases.d.ts +10 -0
- package/dist/typescript/replacePathAliases.d.ts.map +1 -0
- package/dist/typescript/replacePathAliases.js +26 -0
- package/dist/typescript/resolveProjectReferences.d.ts +8 -0
- package/dist/typescript/resolveProjectReferences.d.ts.map +1 -0
- package/dist/typescript/resolveProjectReferences.js +42 -0
- package/dist/typescript/tsc.d.ts +15 -0
- package/dist/typescript/tsc.d.ts.map +1 -0
- package/dist/typescript/tsc.js +28 -0
- package/dist/util/Logger.d.ts +34 -0
- package/dist/util/Logger.d.ts.map +1 -0
- package/dist/util/Logger.js +88 -0
- package/dist/util/TaskQueue.d.ts +30 -0
- package/dist/util/TaskQueue.d.ts.map +1 -0
- package/dist/util/TaskQueue.js +55 -0
- package/dist/util/console.d.ts +22 -0
- package/dist/util/console.d.ts.map +1 -0
- package/dist/util/console.js +58 -0
- package/dist/util/copyFiles.d.ts +33 -0
- package/dist/util/copyFiles.d.ts.map +1 -0
- package/dist/util/copyFiles.js +55 -0
- package/dist/util/extractArgs.d.ts +12 -0
- package/dist/util/extractArgs.d.ts.map +1 -0
- package/dist/util/extractArgs.js +23 -0
- package/dist/util/getRootProjectDir.d.ts +2 -0
- package/dist/util/getRootProjectDir.d.ts.map +1 -0
- package/dist/util/getRootProjectDir.js +14 -0
- package/dist/util/prompt.d.ts +2 -0
- package/dist/util/prompt.d.ts.map +1 -0
- package/dist/util/prompt.js +15 -0
- package/dist/util/sleep.d.ts +6 -0
- package/dist/util/sleep.d.ts.map +1 -0
- package/dist/util/sleep.js +13 -0
- package/dist/util/string.d.ts +22 -0
- package/dist/util/string.d.ts.map +1 -0
- package/dist/util/string.js +35 -0
- package/dist/util/writeIndexFile.d.ts +13 -0
- package/dist/util/writeIndexFile.d.ts.map +1 -0
- package/dist/util/writeIndexFile.js +92 -0
- package/dist/vinyl/buildVinylPackage.d.ts +40 -0
- package/dist/vinyl/buildVinylPackage.d.ts.map +1 -0
- package/dist/vinyl/buildVinylPackage.js +167 -0
- package/dist/vinyl/vinylDefaultBrowserStackOptions.d.ts +25 -0
- package/dist/vinyl/vinylDefaultBrowserStackOptions.d.ts.map +1 -0
- package/dist/vinyl/vinylDefaultBrowserStackOptions.js +28 -0
- package/dist/vinyl/vinylDefaultTscOptions.d.ts +3 -0
- package/dist/vinyl/vinylDefaultTscOptions.d.ts.map +1 -0
- package/dist/vinyl/vinylDefaultTscOptions.js +11 -0
- package/dist/vinyl/vinylSupportedBrowsers.d.ts +18 -0
- package/dist/vinyl/vinylSupportedBrowsers.d.ts.map +1 -0
- package/dist/vinyl/vinylSupportedBrowsers.js +55 -0
- package/package.json +52 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { BrowserStackWorker } from './BrowserStackWorker';
|
|
6
|
+
import { logger } from '../util/Logger';
|
|
7
|
+
export class BrowserStackWorkerController {
|
|
8
|
+
deps;
|
|
9
|
+
options;
|
|
10
|
+
/**
|
|
11
|
+
* Set to observe state updates.
|
|
12
|
+
*/
|
|
13
|
+
onUpdate = () => { };
|
|
14
|
+
_state;
|
|
15
|
+
workers;
|
|
16
|
+
/**
|
|
17
|
+
* Maps the worker's local id to the worker.
|
|
18
|
+
*/
|
|
19
|
+
localIdToWorkerMap;
|
|
20
|
+
sessionPollIntervalId = null;
|
|
21
|
+
/**
|
|
22
|
+
* Tracks an in-flight startSessions invocation. While set, additional calls
|
|
23
|
+
* are deferred until the current one settles to avoid redundant API calls
|
|
24
|
+
* and racing state updates.
|
|
25
|
+
*/
|
|
26
|
+
startSessionsInFlight = null;
|
|
27
|
+
/**
|
|
28
|
+
* If set during an in-flight startSessions, indicates another invocation
|
|
29
|
+
* was requested and should run after the current one settles.
|
|
30
|
+
*/
|
|
31
|
+
startSessionsRequested = false;
|
|
32
|
+
constructor(deps, browsers, options) {
|
|
33
|
+
this.deps = deps;
|
|
34
|
+
this.options = options;
|
|
35
|
+
this.workers = browsers.map((browser) => new BrowserStackWorker(deps, browser, options?.worker));
|
|
36
|
+
this._state = {
|
|
37
|
+
workers: this.workers.map((worker) => worker.state),
|
|
38
|
+
pending: this.workers.length,
|
|
39
|
+
remaining: this.workers.length,
|
|
40
|
+
running: 0,
|
|
41
|
+
failed: 0,
|
|
42
|
+
passed: 0,
|
|
43
|
+
percentComplete: 0,
|
|
44
|
+
total: this.workers.length,
|
|
45
|
+
};
|
|
46
|
+
this.localIdToWorkerMap = new Map(this.workers.map((worker) => {
|
|
47
|
+
return [worker.state.localId, worker];
|
|
48
|
+
}));
|
|
49
|
+
// Observe state on all workers
|
|
50
|
+
for (const worker of this.workers) {
|
|
51
|
+
worker.onUpdate = this.updateHandler;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
get state() {
|
|
55
|
+
return this._state;
|
|
56
|
+
}
|
|
57
|
+
shouldHandleRequest(id) {
|
|
58
|
+
return this.localIdToWorkerMap.has(id);
|
|
59
|
+
}
|
|
60
|
+
onStarted(request) {
|
|
61
|
+
const worker = this.localIdToWorkerMap.get(request.id);
|
|
62
|
+
worker.totalSpecs = request.totalSpecs;
|
|
63
|
+
}
|
|
64
|
+
onProgress(request) {
|
|
65
|
+
const worker = this.localIdToWorkerMap.get(request.id);
|
|
66
|
+
worker.totalCompleted = request.totalCompleted;
|
|
67
|
+
worker.appendLogs(request.logs);
|
|
68
|
+
}
|
|
69
|
+
onDone(request) {
|
|
70
|
+
const worker = this.localIdToWorkerMap.get(request.id);
|
|
71
|
+
void worker.done(request.overallStatus === 'passed', request.reason ?? '');
|
|
72
|
+
}
|
|
73
|
+
refreshState() {
|
|
74
|
+
const state = this._state;
|
|
75
|
+
let running = 0;
|
|
76
|
+
let pending = 0;
|
|
77
|
+
let failed = 0;
|
|
78
|
+
let passed = 0;
|
|
79
|
+
let percentSum = 0;
|
|
80
|
+
for (const worker of this.workers) {
|
|
81
|
+
const completed = worker.completed;
|
|
82
|
+
if (completed) {
|
|
83
|
+
if (worker.passed)
|
|
84
|
+
passed++;
|
|
85
|
+
else
|
|
86
|
+
failed++;
|
|
87
|
+
percentSum++;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
if (worker.state.started)
|
|
91
|
+
running++;
|
|
92
|
+
else
|
|
93
|
+
pending++;
|
|
94
|
+
percentSum +=
|
|
95
|
+
worker.state.totalCompleted / (worker.state.totalSpecs || 1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
state.running = running;
|
|
99
|
+
state.pending = pending;
|
|
100
|
+
state.failed = failed;
|
|
101
|
+
state.passed = passed;
|
|
102
|
+
state.remaining = running + pending;
|
|
103
|
+
state.percentComplete = percentSum / (state.total || 1);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Refreshes the current state and invokes the onUpdate callback.
|
|
107
|
+
*/
|
|
108
|
+
updateHandler = () => {
|
|
109
|
+
const state = this._state;
|
|
110
|
+
const previousRunning = state.running;
|
|
111
|
+
this.refreshState();
|
|
112
|
+
if (previousRunning !== state.running)
|
|
113
|
+
this.startSessions();
|
|
114
|
+
this.onUpdate();
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Begins new workers until the maximum parallel sessions is reached.
|
|
118
|
+
* Reentrancy-safe: if invoked while a previous invocation is still
|
|
119
|
+
* running, schedules a single follow-up to run after it settles.
|
|
120
|
+
*/
|
|
121
|
+
startSessions() {
|
|
122
|
+
if (this.startSessionsInFlight) {
|
|
123
|
+
this.startSessionsRequested = true;
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const run = (async () => {
|
|
127
|
+
const state = this._state;
|
|
128
|
+
if (state.pending === 0)
|
|
129
|
+
return;
|
|
130
|
+
const client = this.deps.client;
|
|
131
|
+
const planDetails = await client.getPlan();
|
|
132
|
+
const remainingOpenSessions = Math.min(this.options?.maxSessions ?? Number.MAX_SAFE_INTEGER, planDetails.parallel_sessions_max_allowed) -
|
|
133
|
+
Math.max(state.running, planDetails.parallel_sessions_running);
|
|
134
|
+
logger.debug('Plan parallel sessions:', `${planDetails.parallel_sessions_running} running, ${planDetails.parallel_sessions_max_allowed} allowed`);
|
|
135
|
+
// Takes up to [remainingOpenSessions] pending workers, starts them in parallel, and awaits their startup.
|
|
136
|
+
const workersToStart = this.workers
|
|
137
|
+
.filter((worker) => !worker.state.started)
|
|
138
|
+
.slice(0, remainingOpenSessions);
|
|
139
|
+
if (workersToStart.length) {
|
|
140
|
+
logger.debug(`Starting ${workersToStart.length} sessions...`);
|
|
141
|
+
// Start all workers in parallel
|
|
142
|
+
await Promise.all(workersToStart.map((worker) => worker.start().catch(() => { })));
|
|
143
|
+
}
|
|
144
|
+
this.refreshState();
|
|
145
|
+
if (this._state.pending > 0) {
|
|
146
|
+
// There are pending sessions that were not started, either due
|
|
147
|
+
// no open sessions or a worker start failure.
|
|
148
|
+
// Check if a session opens up after a timeout.
|
|
149
|
+
logger.debug('No open sessions, checking again in 15s.');
|
|
150
|
+
this.clearOpenSessionPollTimeout();
|
|
151
|
+
this.sessionPollIntervalId = setTimeout(() => this.startSessions(), 15000);
|
|
152
|
+
}
|
|
153
|
+
})()
|
|
154
|
+
.catch((error) => {
|
|
155
|
+
logger.warn('startSessions failed', error);
|
|
156
|
+
// Schedule a retry rather than abandoning all pending workers;
|
|
157
|
+
// a transient API failure should not permanently strand them.
|
|
158
|
+
this.clearOpenSessionPollTimeout();
|
|
159
|
+
this.sessionPollIntervalId = setTimeout(() => this.startSessions(), 15000);
|
|
160
|
+
})
|
|
161
|
+
.finally(() => {
|
|
162
|
+
this.startSessionsInFlight = null;
|
|
163
|
+
if (this.startSessionsRequested) {
|
|
164
|
+
this.startSessionsRequested = false;
|
|
165
|
+
// A coalesced request supersedes any retry scheduled by
|
|
166
|
+
// .catch(); otherwise both the immediate run here and the
|
|
167
|
+
// delayed timeout below would fire startSessions().
|
|
168
|
+
this.clearOpenSessionPollTimeout();
|
|
169
|
+
this.startSessions();
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
this.startSessionsInFlight = run;
|
|
173
|
+
}
|
|
174
|
+
clearOpenSessionPollTimeout() {
|
|
175
|
+
if (this.sessionPollIntervalId != null) {
|
|
176
|
+
clearTimeout(this.sessionPollIntervalId);
|
|
177
|
+
this.sessionPollIntervalId = null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
get allPassed() {
|
|
181
|
+
return this.workers.every((worker) => worker.passed);
|
|
182
|
+
}
|
|
183
|
+
start() {
|
|
184
|
+
logger.debug(`BrowserStackWorkerController start`);
|
|
185
|
+
this.startSessions();
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Terminates all running workers.
|
|
189
|
+
*/
|
|
190
|
+
async terminate() {
|
|
191
|
+
logger.debug(`Terminating workers`);
|
|
192
|
+
this.clearOpenSessionPollTimeout();
|
|
193
|
+
await Promise.all(this.workers.map((worker) => worker.terminate().catch(() => {
|
|
194
|
+
logger.warn(`Could not terminate worker: '${worker.state.workerOptions.name}'`);
|
|
195
|
+
}))).finally(() => {
|
|
196
|
+
logger.debug('terminate done');
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browserStackLocal.d.ts","sourceRoot":"","sources":["../../src/browserstack/browserStackLocal.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoB,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAKnE,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAC1B,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAe9B"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { Local as BsLocal } from 'browserstack-local';
|
|
6
|
+
import { logger } from '../util/Logger';
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
export function startBrowserStackLocal(options) {
|
|
10
|
+
if (options.logFile)
|
|
11
|
+
fs.mkdirSync(path.dirname(options.logFile), { recursive: true });
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const bsLocal = new BsLocal();
|
|
14
|
+
logger.info('Starting BrowserStackLocal...');
|
|
15
|
+
bsLocal.start(options, (error) => {
|
|
16
|
+
if (error) {
|
|
17
|
+
reject(error);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
logger.info('Started BrowserStackLocal');
|
|
21
|
+
resolve(() => closeBsLocal(bsLocal));
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Promisifies closing the local connection.
|
|
27
|
+
*/
|
|
28
|
+
function closeBsLocal(bsLocal) {
|
|
29
|
+
return new Promise((resolve) => {
|
|
30
|
+
logger.debug('Stopping BrowserStackLocal...');
|
|
31
|
+
bsLocal.stop(() => {
|
|
32
|
+
logger.debug('Stopped BrowserStackLocal');
|
|
33
|
+
resolve();
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browserstack Automate credentials.
|
|
3
|
+
*/
|
|
4
|
+
export interface BrowserStackCredentials {
|
|
5
|
+
readonly username: string;
|
|
6
|
+
readonly key: string;
|
|
7
|
+
}
|
|
8
|
+
export interface BrowserDetails {
|
|
9
|
+
/**
|
|
10
|
+
* Specifies the Browser in the combination.
|
|
11
|
+
*/
|
|
12
|
+
readonly browser?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Specifies the version of the browser in the combination.
|
|
15
|
+
*/
|
|
16
|
+
readonly browser_version?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Specifies the OS in the combination.
|
|
19
|
+
*/
|
|
20
|
+
readonly os: string;
|
|
21
|
+
/**
|
|
22
|
+
* Specifies the version of the OS in the combination.
|
|
23
|
+
*/
|
|
24
|
+
readonly os_version: string;
|
|
25
|
+
/**
|
|
26
|
+
* Specifies the device name (in case of mobile device), null otherwise.
|
|
27
|
+
*/
|
|
28
|
+
readonly device?: string | null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Worker configuration. Valid browsers and devices can be obtained using the SDK config
|
|
32
|
+
* generator at:
|
|
33
|
+
* {@link https://www.browserstack.com/docs/automate/selenium/sdk-config-generator}
|
|
34
|
+
*/
|
|
35
|
+
export interface WorkerOptions extends BrowserDetails {
|
|
36
|
+
/**
|
|
37
|
+
* Set the resolution of VM before the beginning of your test. Available for Desktop only.
|
|
38
|
+
* Default is 1024x768.
|
|
39
|
+
*/
|
|
40
|
+
readonly resolution?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Provide a name to the session/worker.
|
|
43
|
+
* Accepted characters are A-Z, a-z, 0-9, ., :, -, [], /, @, &, ', _.
|
|
44
|
+
*/
|
|
45
|
+
readonly name?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Time in seconds before the worker is terminated.
|
|
48
|
+
* Defaults to 300 seconds.
|
|
49
|
+
* Irrespective of this value, a browser worker is alive for a maximum time of 1800 seconds.
|
|
50
|
+
*/
|
|
51
|
+
readonly timeout?: number;
|
|
52
|
+
/**
|
|
53
|
+
* A valid url to navigate the browser to.
|
|
54
|
+
*/
|
|
55
|
+
readonly url: string;
|
|
56
|
+
/**
|
|
57
|
+
* Optional name of the build the session is running under.
|
|
58
|
+
*/
|
|
59
|
+
readonly build?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Optional name of the project the build is under.
|
|
62
|
+
*/
|
|
63
|
+
readonly project?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Optional flag to enable video recording in your test.
|
|
66
|
+
* Default: true
|
|
67
|
+
*/
|
|
68
|
+
readonly video?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Required if you want to capture network logs for your test. Network Logs are supported
|
|
71
|
+
* for all desktop browsers, Android and iOS devices with a few exceptions - IE 10 on any
|
|
72
|
+
* OS; IE 11 on Windows 7 / 8.1 and any browser on MacOS High Sierra and Mojave.
|
|
73
|
+
*/
|
|
74
|
+
readonly networkLogs?: boolean;
|
|
75
|
+
}
|
|
76
|
+
export interface NewWorker {
|
|
77
|
+
/**
|
|
78
|
+
* The identifier of the new Worker. Can be used to get worker details which includes the session id.
|
|
79
|
+
*/
|
|
80
|
+
readonly id: number;
|
|
81
|
+
/**
|
|
82
|
+
* The url of the worker.
|
|
83
|
+
*/
|
|
84
|
+
readonly url: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* https://www.browserstack.com/docs/automate/api-reference/selenium/session#set-test-status
|
|
88
|
+
*/
|
|
89
|
+
export type SessionUpdateStatus = 'passed' | 'failed';
|
|
90
|
+
export interface UpdateSessionOptions {
|
|
91
|
+
/**
|
|
92
|
+
* Set session status to either passed or failed.
|
|
93
|
+
*/
|
|
94
|
+
readonly status?: SessionUpdateStatus;
|
|
95
|
+
/**
|
|
96
|
+
* Name of your session.
|
|
97
|
+
*/
|
|
98
|
+
readonly name?: string;
|
|
99
|
+
/**
|
|
100
|
+
* Reason for session failure.
|
|
101
|
+
*/
|
|
102
|
+
readonly reason?: string;
|
|
103
|
+
}
|
|
104
|
+
export interface GetSessionsOptions {
|
|
105
|
+
/**
|
|
106
|
+
* Specify the number of results to be displayed. The default value is 10, and the maximum value is 100.
|
|
107
|
+
*/
|
|
108
|
+
readonly limit?: number;
|
|
109
|
+
/**
|
|
110
|
+
* Retrieve builds from a specific point using the offset parameter.
|
|
111
|
+
*/
|
|
112
|
+
readonly offset?: number;
|
|
113
|
+
/**
|
|
114
|
+
* Filters the returned sessions to this status.
|
|
115
|
+
*/
|
|
116
|
+
readonly status?: ExecutionStatus;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* https://www.browserstack.com/docs/automate/api-reference/selenium/build#update-build-details
|
|
120
|
+
*/
|
|
121
|
+
export interface UpdateBuildOptions {
|
|
122
|
+
/**
|
|
123
|
+
* The new name of the build.
|
|
124
|
+
*/
|
|
125
|
+
readonly name?: string;
|
|
126
|
+
}
|
|
127
|
+
export type BuildStatus = 'running' | 'done' | 'timeout' | 'failed';
|
|
128
|
+
/**
|
|
129
|
+
* An empty record.
|
|
130
|
+
*/
|
|
131
|
+
export type AnyRecord = Record<never, any>;
|
|
132
|
+
export interface PlanDetails {
|
|
133
|
+
/**
|
|
134
|
+
* Specifies your Automate plan name.
|
|
135
|
+
*/
|
|
136
|
+
readonly automate_plan: string;
|
|
137
|
+
/**
|
|
138
|
+
* Number of parallel sessions currently running.
|
|
139
|
+
*/
|
|
140
|
+
readonly parallel_sessions_running: number;
|
|
141
|
+
/**
|
|
142
|
+
* Maximum number of parallel sessions allowed in a team.
|
|
143
|
+
*/
|
|
144
|
+
readonly team_parallel_sessions_max_allowed: number;
|
|
145
|
+
/**
|
|
146
|
+
* Maximum number of parallel sessions you can run.
|
|
147
|
+
*/
|
|
148
|
+
readonly parallel_sessions_max_allowed: number;
|
|
149
|
+
/**
|
|
150
|
+
* Number of sessions currently queued.
|
|
151
|
+
*/
|
|
152
|
+
readonly queued_sessions: number;
|
|
153
|
+
/**
|
|
154
|
+
* Maximum number of sessions that can be queued.
|
|
155
|
+
*/
|
|
156
|
+
readonly queued_sessions_max_allowed: number;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Information about the worker.
|
|
160
|
+
*/
|
|
161
|
+
export interface WorkerDetails extends BrowserDetails {
|
|
162
|
+
readonly id: number;
|
|
163
|
+
readonly status: SessionStatus;
|
|
164
|
+
readonly real_mobile: null | boolean;
|
|
165
|
+
readonly browser_url: string;
|
|
166
|
+
readonly sessionId: string;
|
|
167
|
+
}
|
|
168
|
+
export interface DeleteWorkerResponse {
|
|
169
|
+
readonly time: number;
|
|
170
|
+
}
|
|
171
|
+
export type SessionStatus = 'passed' | 'failed' | 'timeout' | 'running' | 'queued';
|
|
172
|
+
export type ExecutionStatus = 'running' | 'done' | 'timeout' | 'queued';
|
|
173
|
+
export interface SessionDetails extends BrowserDetails {
|
|
174
|
+
readonly status: SessionStatus;
|
|
175
|
+
/**
|
|
176
|
+
* Name of your session.
|
|
177
|
+
*/
|
|
178
|
+
readonly name: null | string;
|
|
179
|
+
/**
|
|
180
|
+
* Time taken to run the session.
|
|
181
|
+
*/
|
|
182
|
+
readonly duration: null | number;
|
|
183
|
+
/**
|
|
184
|
+
* ID of the session.
|
|
185
|
+
*/
|
|
186
|
+
readonly hashed_id: string;
|
|
187
|
+
/**
|
|
188
|
+
* Reason for test status.
|
|
189
|
+
*/
|
|
190
|
+
readonly reason: string | null;
|
|
191
|
+
/**
|
|
192
|
+
* Name of the build.
|
|
193
|
+
*/
|
|
194
|
+
readonly build_name: string;
|
|
195
|
+
/**
|
|
196
|
+
* Name of the project.
|
|
197
|
+
*/
|
|
198
|
+
readonly project_name: string | null;
|
|
199
|
+
/**
|
|
200
|
+
* The build id.
|
|
201
|
+
*/
|
|
202
|
+
readonly build_hashed_id: string;
|
|
203
|
+
}
|
|
204
|
+
export interface FullSessionDetails extends SessionDetails {
|
|
205
|
+
/**
|
|
206
|
+
* URL to view the session logs.
|
|
207
|
+
*/
|
|
208
|
+
readonly logs: string;
|
|
209
|
+
/**
|
|
210
|
+
* Execution status of the session.
|
|
211
|
+
*/
|
|
212
|
+
readonly browserstack_status: ExecutionStatus;
|
|
213
|
+
/**
|
|
214
|
+
* URL to view the session on Automate dashboard.
|
|
215
|
+
*/
|
|
216
|
+
readonly browser_url: string;
|
|
217
|
+
/**
|
|
218
|
+
* URL to view the session publicly.
|
|
219
|
+
*/
|
|
220
|
+
readonly public_url: string;
|
|
221
|
+
/**
|
|
222
|
+
* URL to view appium logs.
|
|
223
|
+
*/
|
|
224
|
+
readonly appium_logs_url: string;
|
|
225
|
+
/**
|
|
226
|
+
* URL to view session video.
|
|
227
|
+
*/
|
|
228
|
+
readonly video_url: string;
|
|
229
|
+
/**
|
|
230
|
+
* URL to view browser’s console logs.
|
|
231
|
+
*/
|
|
232
|
+
readonly browser_console_logs_url: string;
|
|
233
|
+
/**
|
|
234
|
+
* URL to view browser logs.
|
|
235
|
+
*/
|
|
236
|
+
readonly har_logs_url: string;
|
|
237
|
+
/**
|
|
238
|
+
* URL to view selenium logs.
|
|
239
|
+
*/
|
|
240
|
+
readonly selenium_logs_url: string;
|
|
241
|
+
/**
|
|
242
|
+
* URL to view telemetry logs if it is enabled in your Selenium 4 session.
|
|
243
|
+
*/
|
|
244
|
+
readonly selenium_telemetry_logs_url: string;
|
|
245
|
+
}
|
|
246
|
+
export interface DeleteResponse {
|
|
247
|
+
readonly status: 'ok' | string;
|
|
248
|
+
readonly message: string;
|
|
249
|
+
}
|
|
250
|
+
export interface GetBuildsOptions {
|
|
251
|
+
/**
|
|
252
|
+
* Specify the number of results to be displayed. The default value is 10, and the maximum value is 100.
|
|
253
|
+
*/
|
|
254
|
+
readonly limit?: number;
|
|
255
|
+
/**
|
|
256
|
+
* Retrieve builds from a specific point using the offset parameter.
|
|
257
|
+
*/
|
|
258
|
+
readonly offset?: number;
|
|
259
|
+
/**
|
|
260
|
+
* The status parameter filters your results by the status of the build.
|
|
261
|
+
* The values accepted by this parameter are running, done, timeout, and failed.
|
|
262
|
+
*/
|
|
263
|
+
readonly status?: BuildStatus;
|
|
264
|
+
/**
|
|
265
|
+
* Retrieve all builds related to the specified project ID.
|
|
266
|
+
*/
|
|
267
|
+
readonly projectId?: number;
|
|
268
|
+
}
|
|
269
|
+
export type RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
270
|
+
declare class BrowserStackClient {
|
|
271
|
+
readonly credentials: BrowserStackCredentials;
|
|
272
|
+
constructor(credentials: BrowserStackCredentials);
|
|
273
|
+
createWorker(options: WorkerOptions): Promise<NewWorker>;
|
|
274
|
+
deleteWorker(workerId: number): Promise<DeleteWorkerResponse>;
|
|
275
|
+
getWorker(workerId: number): Promise<WorkerDetails>;
|
|
276
|
+
/**
|
|
277
|
+
* Deletes a build and all sessions contained within it. Builds once deleted cannot be recovered.
|
|
278
|
+
* @param buildId
|
|
279
|
+
*/
|
|
280
|
+
deleteBuild(buildId: number): Promise<DeleteWorkerResponse>;
|
|
281
|
+
protected doRequest(url: string, method: RequestMethod, body?: any, type?: 'json' | 'text', retries?: number): Promise<any>;
|
|
282
|
+
}
|
|
283
|
+
export declare class ServiceResponseError extends Error {
|
|
284
|
+
readonly url: string;
|
|
285
|
+
readonly method: RequestMethod;
|
|
286
|
+
readonly response: Response;
|
|
287
|
+
constructor(url: string, method: RequestMethod, response: Response);
|
|
288
|
+
}
|
|
289
|
+
export declare class BrowserStackAutomateClient extends BrowserStackClient {
|
|
290
|
+
getPlan(): Promise<PlanDetails>;
|
|
291
|
+
getSessions(buildId: string, options: GetSessionsOptions): Promise<readonly FullSessionDetails[]>;
|
|
292
|
+
getSession(sessionId: string): Promise<FullSessionDetails>;
|
|
293
|
+
updateSession(sessionId: string, options: UpdateSessionOptions): Promise<SessionDetails>;
|
|
294
|
+
/**
|
|
295
|
+
* Deletes a session.
|
|
296
|
+
* Sessions once deleted cannot be recovered.
|
|
297
|
+
* @param sessionId
|
|
298
|
+
*/
|
|
299
|
+
deleteSession(sessionId: string): Promise<DeleteResponse>;
|
|
300
|
+
getBuilds(options: GetBuildsOptions): Promise<WorkerDetails | AnyRecord>;
|
|
301
|
+
updateBuild(buildId: string, buildOptions: UpdateBuildOptions): Promise<WorkerDetails | AnyRecord>;
|
|
302
|
+
}
|
|
303
|
+
export {};
|
|
304
|
+
//# sourceMappingURL=browserStackRestApi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browserStackRestApi.d.ts","sourceRoot":"","sources":["../../src/browserstack/browserStackRestApi.ts"],"names":[],"mappings":"AAeA;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,cAAc;IAC3B;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IAEzB;;OAEG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IAEjC;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAE3B;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAClC;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAc,SAAQ,cAAc;IACjD;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAE5B;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IAEtB;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IAEzB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IAEpB;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IAEvB;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IAEzB;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;IAExB;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CACjC;AAED,MAAM,WAAW,SAAS;IACtB;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAErD,MAAM,WAAW,oBAAoB;IACjC;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAA;IAErC;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IAEtB;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,kBAAkB;IAC/B;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IAEvB;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IAExB;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAA;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEnE;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;AAE1C,MAAM,WAAW,WAAW;IACxB;;OAEG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAE9B;;OAEG;IACH,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAA;IAE1C;;OAEG;IACH,QAAQ,CAAC,kCAAkC,EAAE,MAAM,CAAA;IAEnD;;OAEG;IACH,QAAQ,CAAC,6BAA6B,EAAE,MAAM,CAAA;IAE9C;;OAEG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAEhC;;OAEG;IACH,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAA;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,cAAc;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,QAAQ,CAAC,WAAW,EAAE,IAAI,GAAG,OAAO,CAAA;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,MAAM,aAAa,GACnB,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,SAAS,GACT,QAAQ,CAAA;AAEd,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEvE,MAAM,WAAW,cAAe,SAAQ,cAAc;IAClD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAE9B;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAAA;IAE5B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAA;IAEhC;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAE1B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAE9B;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAE3B;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAEpC;;OAEG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CACnC;AAED,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACtD;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB;;OAEG;IACH,QAAQ,CAAC,mBAAmB,EAAE,eAAe,CAAA;IAE7C;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAE5B;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAE3B;;OAEG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAEhC;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAE1B;;OAEG;IACH,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAA;IAEzC;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAE7B;;OAEG;IACH,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAElC;;OAEG;IACH,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAA;CAC/C;AAED,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,MAAM,EAAE,IAAI,GAAG,MAAM,CAAA;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC7B;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IAEvB;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IAExB;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAE7B;;OAEG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC9B;AAYD,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAA;AAE7D,cAAM,kBAAkB;IACR,QAAQ,CAAC,WAAW,EAAE,uBAAuB;gBAApC,WAAW,EAAE,uBAAuB;IAEnD,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IAIxD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAI7D,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAWzD;;;OAGG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;cAIjD,SAAS,CACrB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,aAAa,EACrB,IAAI,CAAC,EAAE,GAAG,EACV,IAAI,GAAE,MAAM,GAAG,MAAe,EAC9B,OAAO,SAAI,GACZ,OAAO,CAAC,GAAG,CAAC;CAkClB;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAEvC,QAAQ,CAAC,GAAG,EAAE,MAAM;IACpB,QAAQ,CAAC,MAAM,EAAE,aAAa;IAC9B,QAAQ,CAAC,QAAQ,EAAE,QAAQ;gBAFlB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,QAAQ;CAMlC;AAID,qBAAa,0BAA2B,SAAQ,kBAAkB;IACxD,OAAO,IAAI,OAAO,CAAC,WAAW,CAAC;IAI/B,WAAW,CACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,GAC5B,OAAO,CAAC,SAAS,kBAAkB,EAAE,CAAC;IAYnC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAS1D,aAAa,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,oBAAoB,GAC9B,OAAO,CAAC,cAAc,CAAC;IAU1B;;;;OAIG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAOzD,SAAS,CACX,OAAO,EAAE,gBAAgB,GAC1B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAI/B,WAAW,CACb,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,kBAAkB,GACjC,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;CAOxC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* A partial, typed implementation of the BrowserStack Automate REST API.
|
|
7
|
+
* https://www.browserstack.com/docs/automate/api-reference/selenium/introduction
|
|
8
|
+
* https://www.browserstack.com/docs/automate/capabilities#reference-main-section
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { sleep } from '../util/sleep';
|
|
12
|
+
import { logger } from '../util/Logger';
|
|
13
|
+
const API = 'https://api.browserstack.com/5';
|
|
14
|
+
const retryableStatuses = new Set([
|
|
15
|
+
400, // Bad request
|
|
16
|
+
429, // Too many requests
|
|
17
|
+
502, // Bad gateway
|
|
18
|
+
503, // Service unavailable
|
|
19
|
+
504, // Gateway timeout
|
|
20
|
+
]);
|
|
21
|
+
class BrowserStackClient {
|
|
22
|
+
credentials;
|
|
23
|
+
constructor(credentials) {
|
|
24
|
+
this.credentials = credentials;
|
|
25
|
+
}
|
|
26
|
+
async createWorker(options) {
|
|
27
|
+
return this.doRequest(`${API}/worker`, 'POST', options);
|
|
28
|
+
}
|
|
29
|
+
async deleteWorker(workerId) {
|
|
30
|
+
return this.doRequest(`${API}/worker/${workerId}`, 'DELETE');
|
|
31
|
+
}
|
|
32
|
+
async getWorker(workerId) {
|
|
33
|
+
const workerDetails = await this.doRequest(`${API}/worker/${workerId}`, 'GET');
|
|
34
|
+
if (!('sessionId' in workerDetails)) {
|
|
35
|
+
throw new Error(`worker ${workerId} not found`);
|
|
36
|
+
}
|
|
37
|
+
return workerDetails;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Deletes a build and all sessions contained within it. Builds once deleted cannot be recovered.
|
|
41
|
+
* @param buildId
|
|
42
|
+
*/
|
|
43
|
+
async deleteBuild(buildId) {
|
|
44
|
+
return this.doRequest(`${API}/builds/${buildId}`, 'DELETE');
|
|
45
|
+
}
|
|
46
|
+
async doRequest(url, method, body, type = 'json', retries = 3) {
|
|
47
|
+
let response = null;
|
|
48
|
+
let error = null;
|
|
49
|
+
let retryable = retries > 0;
|
|
50
|
+
try {
|
|
51
|
+
response = await fetch(url, {
|
|
52
|
+
method,
|
|
53
|
+
headers: {
|
|
54
|
+
Authorization: `Basic ${Buffer.from(`${this.credentials.username}:${this.credentials.key}`).toString('base64')}`,
|
|
55
|
+
'Content-Type': type === 'json' ? 'application/json' : 'text/plain',
|
|
56
|
+
},
|
|
57
|
+
body: body ? JSON.stringify(body) : null,
|
|
58
|
+
});
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
error = new ServiceResponseError(url, method, response);
|
|
61
|
+
retryable &&= retryableStatuses.has(response.status);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
error = e;
|
|
66
|
+
}
|
|
67
|
+
if (error) {
|
|
68
|
+
if (retryable) {
|
|
69
|
+
logger.warn(`${error.message}, retrying in 5s`);
|
|
70
|
+
await sleep(5);
|
|
71
|
+
return this.doRequest(url, method, body, type, retries - 1);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return type === 'json' ? await response.json() : await response.text();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export class ServiceResponseError extends Error {
|
|
81
|
+
url;
|
|
82
|
+
method;
|
|
83
|
+
response;
|
|
84
|
+
constructor(url, method, response) {
|
|
85
|
+
super(`BrowserStack API error: ${url} ${method} ${response.status} ${response.statusText}`);
|
|
86
|
+
this.url = url;
|
|
87
|
+
this.method = method;
|
|
88
|
+
this.response = response;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const AUTOMATE_API = 'https://api.browserstack.com/automate';
|
|
92
|
+
export class BrowserStackAutomateClient extends BrowserStackClient {
|
|
93
|
+
async getPlan() {
|
|
94
|
+
return await this.doRequest(`${AUTOMATE_API}/plan.json`, 'GET');
|
|
95
|
+
}
|
|
96
|
+
async getSessions(buildId, options) {
|
|
97
|
+
return (await this.doRequest(`${AUTOMATE_API}/builds/${buildId}/sessions.json`, 'GET', options)).map((element) => {
|
|
98
|
+
return element['automation_session'];
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async getSession(sessionId) {
|
|
102
|
+
return (await this.doRequest(`${AUTOMATE_API}/sessions/${sessionId}.json`, 'GET'))['automation_session'];
|
|
103
|
+
}
|
|
104
|
+
async updateSession(sessionId, options) {
|
|
105
|
+
return (await this.doRequest(`${AUTOMATE_API}/sessions/${sessionId}.json`, 'PUT', options))['automation_session'];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Deletes a session.
|
|
109
|
+
* Sessions once deleted cannot be recovered.
|
|
110
|
+
* @param sessionId
|
|
111
|
+
*/
|
|
112
|
+
async deleteSession(sessionId) {
|
|
113
|
+
return this.doRequest(`${AUTOMATE_API}/sessions/${sessionId}.json`, 'DELETE');
|
|
114
|
+
}
|
|
115
|
+
async getBuilds(options) {
|
|
116
|
+
return this.doRequest(`${AUTOMATE_API}/builds.json`, 'GET', options);
|
|
117
|
+
}
|
|
118
|
+
async updateBuild(buildId, buildOptions) {
|
|
119
|
+
return this.doRequest(`${AUTOMATE_API}/builds/${buildId}.json`, 'PUT', buildOptions);
|
|
120
|
+
}
|
|
121
|
+
}
|