Skip to content

Commit 5bd49d8

Browse files
committed
ds
1 parent 8d60c1f commit 5bd49d8

File tree

7 files changed

+42
-11
lines changed

7 files changed

+42
-11
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ jobs:
338338
name: Running tests
339339
command: |
340340
TESTS=$(yarn -s bazel query --output label 'attr("tags", "saucelabs", //src/...)')
341+
yarn -s bazel build ${TESTS}
341342
yarn -s bazel test ${TESTS} --jobs=2
342343
343344
- run:

tools/saucelabs-bazel/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ ts_library(
66
name = "saucelabs-bazel",
77
srcs = [
88
"browser.ts",
9+
"ipc-defaults.ts",
910
"ipc-messages.ts",
1011
],
1112
deps = [],

tools/saucelabs-bazel/background-service/ipc.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {createServer, Server, Socket} from 'net';
2+
import { IPC_PORT } from '../ipc-defaults';
23
import {BackgroundServiceReceiveMessages, NoAvailableBrowserMessage} from '../ipc-messages';
34
import {SaucelabsDaemon} from './saucelabs-daemon';
45

@@ -8,9 +9,9 @@ export class IpcServer {
89
private readonly _server: Server;
910
private _connections = new Map<number, Socket>();
1011

11-
constructor(private _service: SaucelabsDaemon, port = 5324) {
12+
constructor(private _service: SaucelabsDaemon) {
1213
this._server = createServer(this._connectionHandler.bind(this));
13-
this._server.listen(port, () => console.info('Daemon IPC server listening.'));
14+
this._server.listen(IPC_PORT, () => console.info('Daemon IPC server listening.'));
1415
}
1516

1617
private _connectionHandler(socket: Socket) {

tools/saucelabs-bazel/background-service/saucelabs-daemon.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,32 @@ interface BrowserTest {
2727
}
2828

2929
export class SaucelabsDaemon {
30+
/**
31+
* Map of browsers and their pending tests. If a browser is acquired on the
32+
* remote selenium server, the browser is not immediately ready. If the browser
33+
* becomes active, the pending tests will be started.
34+
*/
3035
private _pendingTests = new Map<RemoteBrowser, BrowserTest>();
31-
_browsers = new Set<RemoteBrowser>();
36+
37+
/** List of active browsers that are managed by the daemon. */
38+
private _activeBrowsers = new Set<RemoteBrowser>();
39+
40+
/** Map that contains test ids with their acquired browser. */
3241
private _runningTests = new Map<number, RemoteBrowser>();
42+
43+
/** Server used for communication with the Karma launcher. */
3344
private _server = new IpcServer(this);
45+
46+
/** Base selenium capabilities that will be added to each browser. */
3447
private _baseCapabilities = {...defaultCapabilities, ...this._userCapabilities};
48+
49+
/** Id of the keep alive interval that ensures no remote browsers time out. */
3550
private _keepAliveIntervalId: NodeJS.Timeout|null = null;
3651

3752
constructor(
3853
private _username: string, private _accessKey: string,
3954
private _userCapabilities: object = {}) {
40-
// Starts the heartbeat for browsers.
55+
// Starts the keep alive loop for all active browsers.
4156
this._keepAliveLoop();
4257
}
4358

@@ -51,7 +66,7 @@ export class SaucelabsDaemon {
5166

5267
// Keep track of the launched browser. We do this before it even completed the
5368
// launch as we can then handle scheduled tests when the browser is still launching.
54-
this._browsers.add(launched);
69+
this._activeBrowsers.add(launched);
5570

5671
// See the following link for public API of the selenium server.
5772
// https://wiki.saucelabs.com/display/DOCS/Instant+Selenium+Node.js+Tests
@@ -80,12 +95,12 @@ export class SaucelabsDaemon {
8095
}
8196

8297
async quitAllBrowsers() {
83-
this._browsers.forEach(b => {
98+
this._activeBrowsers.forEach(b => {
8499
if (b.driver !== null) {
85100
b.driver.quit();
86101
}
87102
});
88-
this._browsers.clear();
103+
this._activeBrowsers.clear();
89104
this._runningTests.clear();
90105
this._pendingTests.clear();
91106
}
@@ -140,7 +155,7 @@ export class SaucelabsDaemon {
140155

141156
private _findMatchingBrowsers(browserId: string): RemoteBrowser[] {
142157
const browsers: RemoteBrowser[] = [];
143-
for (let browser of this._browsers) {
158+
for (let browser of this._activeBrowsers) {
144159
if (browser.id === browserId) {
145160
browsers.push(browser);
146161
}
@@ -153,7 +168,7 @@ export class SaucelabsDaemon {
153168
// https://saucelabs.com/blog/selenium-tips-how-to-coordinate-multiple-browsers-in-sauce-ondemand.
154169
private _keepAliveLoop = async () => {
155170
const pendingCommands: promise.Promise<any>[] = [];
156-
for (const browser of this._browsers) {
171+
for (const browser of this._activeBrowsers) {
157172
if (browser.driver !== null) {
158173
pendingCommands.push(browser.driver.getTitle());
159174
}

tools/saucelabs-bazel/browser.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** Definition of a test browser. */
12
export interface Browser {
23
browserName: string;
34
browserVersion?: string;
@@ -6,8 +7,13 @@ export interface Browser {
67
deviceName?: string;
78
}
89

10+
/**
11+
* Gets a unique id for the specified browser. This id can be shared
12+
* across the background service and launcher using IPC.
13+
*/
914
export function getUniqueId(browser: Browser): string {
1015
let result = '';
11-
Object.keys(browser).sort().forEach((k) => result += `${k}=${browser[k as keyof Browser]}`);
16+
Object.keys(browser).sort()
17+
.forEach((key) => result += `${key}=${browser[key as keyof Browser]}`);
1218
return result;
1319
}

tools/saucelabs-bazel/ipc-messages.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1+
/** Message that can be sent to the daemon to start a given test. */
12
export class StartTestMessage {
23
readonly type = 'start-test';
34
constructor(public url: string, public browserId: string) {}
45
}
56

7+
/** Message that can be sent to the daemon if a test completed. */
68
export class EndTestMessage {
79
readonly type = 'end-test';
810
}
911

12+
/** Message being sent from the daemon if a request browser is not available. */
1013
export class NoAvailableBrowserMessage {
1114
readonly type = 'browser-not-ready';
1215
}
1316

17+
/** Type of messages the background service can receive. */
1418
export type BackgroundServiceReceiveMessages = StartTestMessage|EndTestMessage;
19+
20+
/** Type of messages the background services can send to clients. */
1521
export type BackgroundServiceSendMessages = NoAvailableBrowserMessage;

tools/saucelabs-bazel/launcher/launcher.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {createConnection, Socket} from 'net';
22
import {Browser, getUniqueId} from '../browser';
3+
import { IPC_PORT } from '../ipc-defaults';
34
import {BackgroundServiceSendMessages, EndTestMessage, StartTestMessage} from '../ipc-messages';
45

56
export function SaucelabsLauncher(this: any,
@@ -26,7 +27,7 @@ export function SaucelabsLauncher(this: any,
2627
this.name = browserDisplayName + ' on SauceLabs (daemon)';
2728

2829
this.on('start', (pageUrl: string) => {
29-
daemonConnection = createConnection({port: 5324},
30+
daemonConnection = createConnection({port: IPC_PORT},
3031
() => _startBrowserTest(pageUrl, args));
3132

3233
daemonConnection.on('data', b => _processMessage(

0 commit comments

Comments
 (0)