Skip to content

Commit 38c1bd5

Browse files
committed
WIP
ds
1 parent d8e77d6 commit 38c1bd5

20 files changed

+441
-119
lines changed

.circleci/config.yml

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,17 +312,35 @@ jobs:
312312
resource_class: xlarge
313313
environment:
314314
SAUCE_USERNAME: "angular-components"
315-
SAUCE_ACCESS_KEY: "63348201a846-eeb9-3ee4-300f-ea990b8a"
316-
# Note: This number should not be too high because otherwise we might run into
317-
# a rate limit exception.
318-
KARMA_PARALLEL_BROWSERS: 2
315+
SAUCE_ACCESS_KEY: "a8b099ae-f003-4ee3-9bee-648a10284336"
316+
SAUCE_TUNNEL_IDENTIFIER: angular-material-<< pipeline.id >>
319317
steps:
320318
- checkout_and_rebase
321319
- *restore_cache
322320
- *setup_bazel_ci_config
323321
- *yarn_install
324322

325-
- run: ./scripts/circleci/run-saucelabs-tests.sh
323+
- run:
324+
name: Saucelabs tunnel
325+
command: ./scripts/saucelabs/start-tunnel.sh
326+
background: true
327+
- run:
328+
name: Waiting for Saucelabs tunnel
329+
command: ./scripts/saucelabs/wait-tunnel.sh
330+
- run:
331+
name: Saucelabs browser daemon
332+
command: yarn -s sauce-bazel-daemon
333+
background: true
334+
335+
- run:
336+
name: Running tests
337+
command: |
338+
TESTS=$(yarn -s bazel query --output label 'attr("tags", "saucelabs", //src/...)')
339+
yarn -s bazel test ${TESTS} --jobs=2
340+
341+
- run:
342+
name: Shutting down tunnel
343+
command: ./scripts/saucelabs/stop-tunnel.sh
326344
- *slack_notify_on_failure
327345

328346
# ----------------------------------

BUILD.bazel

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,3 @@ genrule(
2626
outs = ["entry_points_manifest.json"],
2727
cmd = "echo '%s' > $@" % entryPoints,
2828
)
29-
30-
genrule(
31-
name = "saucelabs_tunnel_identifier",
32-
outs = ["saucelabs_tunnel_identifier.txt"],
33-
cmd = "$(execpath //scripts/saucelabs:extract-tunnel-identifier) > $@",
34-
stamp = True,
35-
tools = ["//scripts/saucelabs:extract-tunnel-identifier"],
36-
)

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@
4848
"integration-tests:size-test": "bazel test //integration/size-test/...",
4949
"check-mdc-tests": "ts-node --project scripts/tsconfig.json scripts/check-mdc-tests.ts",
5050
"check-mdc-exports": "ts-node --project scripts/tsconfig.json scripts/check-mdc-exports.ts",
51-
"check-tools": "yarn tsc --project tools/tsconfig-ci.json"
51+
"check-tools": "yarn tsc --project tools/tsconfig-ci.json",
52+
"sauce-bazel-daemon": "ts-node --project tools/saucelabs-bazel/tsconfig.json tools/saucelabs-bazel/background-service/cli.ts"
5253
},
5354
"version": "12.1.0-next.0",
5455
"dependencies": {

scripts/circleci/run-saucelabs-tests.sh

Lines changed: 0 additions & 33 deletions
This file was deleted.

scripts/saucelabs/BUILD.bazel

Lines changed: 0 additions & 6 deletions
This file was deleted.

scripts/saucelabs/extract-tunnel-identifier.sh

Lines changed: 0 additions & 13 deletions
This file was deleted.

test/karma-browsers.json

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
{
2-
"ChromeHeadlessCI": {
3-
"base": "ChromeHeadless",
4-
"flags": [
5-
"--window-size=1024,768",
6-
"--no-sandbox"
7-
]
8-
},
92
"ChromeLocalDebug": {
103
"base": "Chrome",
114
"flags": [

test/karma-saucelabs.conf.js

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,18 @@
1-
const {readFileSync} = require('fs');
21
const {customLaunchers, platformMap} = require('./browser-providers');
32

43
module.exports = karmaConfig => {
54
const config = {
65
plugins: [
7-
require('karma-sauce-launcher')
6+
require('angular_material/tools/saucelabs-bazel/launcher'),
87
],
98
customLaunchers: customLaunchers,
10-
sauceLabs: {
11-
testName: 'Angular Material Unit Tests',
12-
startConnect: false,
13-
recordVideo: false,
14-
recordScreenshots: false,
15-
idleTimeout: 600,
16-
commandTimeout: 600,
17-
maxDuration: 5400,
18-
},
19-
browserNoActivityTimeout: 300000,
20-
browserDisconnectTimeout: 180000,
21-
browserDisconnectTolerance: 3,
22-
captureTimeout: 180000,
9+
browserNoActivityTimeout: 90000,
10+
browserDisconnectTimeout: 90000,
11+
browserDisconnectTolerance: 2,
12+
captureTimeout: 90000,
2313
browsers: platformMap.saucelabs,
24-
25-
// Try Websocket for a faster transmission first. Fallback to polling if necessary.
26-
transports: ['websocket', 'polling'],
14+
transports: ['polling', 'websocket'],
2715
};
2816

29-
// The tunnel identifier has been written to a stamped genrule that access the tunnel
30-
// identifier through a volatile status key. This ensures that test and build results
31-
// are not invalidated whenever the tunnel identifier changes (which it does for each PR).
32-
const tunnelIdentifier = readFileSync(
33-
require.resolve('../saucelabs_tunnel_identifier.txt'), 'utf8');
34-
35-
config.sauceLabs.build = tunnelIdentifier;
36-
config.sauceLabs.tunnelIdentifier = tunnelIdentifier;
37-
3817
karmaConfig.set(config);
3918
};

tools/defaults.bzl

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -156,22 +156,25 @@ def ng_e2e_test_library(deps = [], tsconfig = None, **kwargs):
156156
)
157157

158158
def karma_web_test(name, **kwargs):
159-
tags = kwargs.pop("tags", [])
160-
# Custom standalone web test that can be run to test against any browser
161-
# that is manually connected to.
162-
_karma_web_test(
163-
name = "%s_bin" % name,
164-
tags = ["manual"],
165-
**kwargs
166-
)
167-
168-
# Workaround for: https://github.com/bazelbuild/rules_nodejs/issues/1429
169-
native.sh_test(
170-
name = "%s" % name,
171-
srcs = ["%s_bin" % name],
172-
tags = tags + ["ibazel_notify_changes"],
173-
)
159+
tags = kwargs.pop("tags", [])
160+
timeout = kwargs.pop("timeout", None)
174161

162+
# Custom standalone web test that can be run to test against any browser
163+
# that is manually connected to.
164+
_karma_web_test(
165+
name = "%s_bin" % name,
166+
tags = ["manual"],
167+
timeout = timeout,
168+
**kwargs
169+
)
170+
171+
# Workaround for: https://github.com/bazelbuild/rules_nodejs/issues/1429
172+
native.sh_test(
173+
name = "%s" % name,
174+
srcs = ["%s_bin" % name],
175+
timeout = timeout,
176+
tags = tags + ["ibazel_notify_changes"],
177+
)
175178

176179
def karma_web_test_suite(name, **kwargs):
177180
web_test_args = {}
@@ -205,12 +208,11 @@ def karma_web_test_suite(name, **kwargs):
205208

206209
sauce_web_test_args = dict(**web_test_args)
207210
sauce_web_test_args["data"] = sauce_web_test_args.get("data", []) + [
208-
"//:saucelabs_tunnel_identifier",
209-
"//test:browser-providers.js",
210-
"//test:karma-browsers.json"
211+
"//test:browser-providers.js",
212+
"//test:karma-browsers.json",
211213
]
212214
sauce_web_test_args["deps"] = sauce_web_test_args.get("deps", []) + [
213-
"@npm//karma-sauce-launcher"
215+
"//tools/saucelabs-bazel/launcher",
214216
]
215217

216218
# Add a saucelabs target for these karma tests
@@ -219,6 +221,7 @@ def karma_web_test_suite(name, **kwargs):
219221
timeout = "long",
220222
config_file = "//test:karma-saucelabs.conf.js",
221223
tags = ["manual", "saucelabs", "no-remote-exec"],
224+
flaky = False,
222225
**sauce_web_test_args
223226
)
224227

tools/saucelabs-bazel/BUILD.bazel

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
load("//tools:defaults.bzl", "ts_library")
2+
3+
package(default_visibility = ["//visibility:public"])
4+
5+
ts_library(
6+
name = "saucelabs-bazel",
7+
srcs = [
8+
"browser.ts",
9+
"ipc-messages.ts",
10+
],
11+
deps = [],
12+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
load("//tools:defaults.bzl", "ts_library")
2+
3+
package(default_visibility = ["//visibility:public"])
4+
5+
ts_library(
6+
name = "background-service",
7+
srcs = glob(["**/*.ts"]),
8+
deps = [
9+
"//tools/saucelabs-bazel",
10+
"@npm//@types/node",
11+
"@npm//@types/selenium-webdriver",
12+
"@npm//chalk",
13+
],
14+
)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import {Browser} from '../browser';
2+
import {SaucelabsDaemon} from './saucelabs-daemon';
3+
4+
//process.env.SAUCE_USERNAME = 'angular-components';
5+
//process.env.SAUCE_ACCESS_KEY = 'a8b099ae-f003-4ee3-9bee-648a10284336';
6+
//process.env.SAUCE_TUNNEL_IDENTIFIER = 'angular-material-d35114de-1499-47a4-8179-643a25ea97c6';
7+
8+
const parallelExecutions = 2;
9+
const {platformMap, customLaunchers} = require('../../../test/browser-providers');
10+
11+
const username = process.env.SAUCE_USERNAME;
12+
const accessKey = process.env.SAUCE_ACCESS_KEY;
13+
const tunnelIdentifier = process.env.SAUCE_TUNNEL_IDENTIFIER;
14+
15+
if (!username || !accessKey) {
16+
throw Error('Please set the `SAUCE_USERNAME` and `SAUCE_ACCESS_KEY` variables.');
17+
}
18+
19+
if (!tunnelIdentifier) {
20+
throw Error('No tunnel set up. Please set the `SAUCE_TUNNEL_IDENTIFIER` variable.');
21+
}
22+
23+
const saucelabsBrowsers: Browser[] = platformMap.saucelabs
24+
.map((n: string) => customLaunchers[n]);
25+
const browserInstances: Browser[] = [];
26+
27+
for (let i = 0; i < parallelExecutions; i++) {
28+
browserInstances.push(...saucelabsBrowsers);
29+
}
30+
31+
console.error(browserInstances.map(d => d.browserName));
32+
33+
// Start the daemon and launch the given browser.
34+
new SaucelabsDaemon(username, accessKey, {tunnelIdentifier})
35+
.launchBrowsers(browserInstances);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import {createServer, Server, Socket} from 'net';
2+
import {BackgroundServiceReceiveMessages, NoAvailableBrowserMessage} from '../ipc-messages';
3+
import {SaucelabsDaemon} from './saucelabs-daemon';
4+
5+
let nextSocketId = 0;
6+
7+
export class IpcServer {
8+
private readonly _server: Server;
9+
private _connections = new Map<number, Socket>();
10+
11+
constructor(private _service: SaucelabsDaemon, port = 5324) {
12+
this._server = createServer(this._connectionHandler.bind(this));
13+
this._server.listen(port, () => console.info('Daemon IPC server listening.'));
14+
}
15+
16+
private _connectionHandler(socket: Socket) {
17+
const socketId = nextSocketId++;
18+
this._connections.set(socketId, socket);
19+
socket.on('data', b => this._processMessage(socket, socketId, JSON.parse(b.toString())));
20+
}
21+
22+
private _processMessage(
23+
socket: Socket, socketId: number, message: BackgroundServiceReceiveMessages) {
24+
switch (message.type) {
25+
case 'start-test':
26+
console.debug(`Starting tests for ${socketId}`);
27+
if (!this._service.startTest(
28+
{testId: socketId, pageUrl: message.url, requestedBrowserId: message.browserId})) {
29+
this._noAvailableBrowser(socket);
30+
}
31+
break;
32+
case 'end-test':
33+
console.debug(`Ending tests for ${socketId}`);
34+
this._service.endTest(socketId);
35+
break;
36+
}
37+
}
38+
39+
private _noAvailableBrowser(socket: Socket) {
40+
socket.write(JSON.stringify(new NoAvailableBrowserMessage()));
41+
}
42+
}

0 commit comments

Comments
 (0)