Skip to content

Commit f83fe22

Browse files
clydinmgechev
authored andcommitted
test: integrate browser testing for differential loading (#15065)
1 parent 15b9ea8 commit f83fe22

File tree

8 files changed

+304
-0
lines changed

8 files changed

+304
-0
lines changed

.circleci/config.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,29 @@ jobs:
212212
PATH=~/.npm-global/bin:$PATH npm install --global npm
213213
- run: PATH=~/.npm-global/bin:$PATH node ./tests/legacy-cli/run_e2e --nb-shards=${CIRCLE_NODE_TOTAL} --shard=${CIRCLE_NODE_INDEX}
214214

215+
test-browsers:
216+
executor:
217+
name: test-executor
218+
environment:
219+
E2E_BROWSERS: true
220+
steps:
221+
- attach_workspace: *attach_options
222+
- run:
223+
name: Initialize Environment
224+
command: ./.circleci/env.sh
225+
- run:
226+
name: Initialize Saucelabs
227+
command: setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
228+
- run:
229+
name: Start Saucelabs Tunnel
230+
command: ./scripts/saucelabs/start-tunnel.sh
231+
background: true
232+
# Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests
233+
# too early without Saucelabs not being ready.
234+
- run: ./scripts/saucelabs/wait-for-tunnel.sh
235+
- run: PATH=~/.npm-global/bin:$PATH node ./tests/legacy-cli/run_e2e ./tests/legacy-cli/e2e/tests/misc/browsers.ts
236+
- run: ./scripts/saucelabs/stop-tunnel.sh
237+
215238
build:
216239
executor: action-executor
217240
steps:
@@ -346,6 +369,9 @@ workflows:
346369
<<: *ignore_pull_requests
347370
requires:
348371
- e2e-cli
372+
- test-browsers:
373+
requires:
374+
- build
349375
- snapshot_publish:
350376
<<: *ignore_pull_requests
351377
requires:

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
"pidtree": "^0.3.0",
129129
"pidusage": "^2.0.17",
130130
"rxjs": "~6.4.0",
131+
"sauce-connect": "https://saucelabs.com/downloads/sc-4.5.4-linux.tar.gz",
131132
"semver": "6.2.0",
132133
"source-map": "^0.5.6",
133134
"source-map-support": "^0.5.0",

scripts/saucelabs/start-tunnel.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env bash
2+
3+
set -x -u -e -o pipefail
4+
5+
readonly currentDir=$(cd $(dirname $0); pwd)
6+
7+
# Command arguments that will be passed to sauce-connect. By default we disable SSL bumping for
8+
# all requests. This is because SSL bumping is not needed for our test setup and in order
9+
# to perform the SSL bumping, Saucelabs intercepts all HTTP requests in the tunnel VM and modifies
10+
# them. This can cause flakiness as it makes all requests dependent on the SSL bumping middleware.
11+
# See: https://wiki.saucelabs.com/display/DOCS/Troubleshooting+Sauce+Connect#TroubleshootingSauceConnect-DisablingSSLBumping
12+
sauceArgs="--no-ssl-bump-domains all"
13+
14+
if [[ ! -z "${SAUCE_LOG_FILE:-}" ]]; then
15+
mkdir -p $(dirname ${SAUCE_LOG_FILE})
16+
sauceArgs="${sauceArgs} --logfile ${SAUCE_LOG_FILE}"
17+
fi
18+
19+
if [[ ! -z "${SAUCE_READY_FILE:-}" ]]; then
20+
mkdir -p $(dirname ${SAUCE_READY_FILE})
21+
sauceArgs="${sauceArgs} --readyfile ${SAUCE_READY_FILE}"
22+
fi
23+
24+
if [[ ! -z "${SAUCE_PID_FILE:-}" ]]; then
25+
mkdir -p $(dirname ${SAUCE_PID_FILE})
26+
sauceArgs="${sauceArgs} --pidfile ${SAUCE_PID_FILE}"
27+
fi
28+
29+
if [[ ! -z "${SAUCE_TUNNEL_IDENTIFIER:-}" ]]; then
30+
sauceArgs="${sauceArgs} --tunnel-identifier ${SAUCE_TUNNEL_IDENTIFIER}"
31+
fi
32+
33+
echo "Starting Sauce Connect. Passed arguments: ${sauceArgs}"
34+
35+
${currentDir}/../../node_modules/sauce-connect/bin/sc -u ${SAUCE_USERNAME} -k ${SAUCE_ACCESS_KEY} ${sauceArgs}

scripts/saucelabs/stop-tunnel.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
3+
# Disable printing of any executed command because this would cause a lot
4+
# of spam due to the loop.
5+
set +x -u -e -o pipefail
6+
7+
if [[ ! -f ${SAUCE_PID_FILE} ]]; then
8+
echo "Could not find Saucelabs tunnel PID file. Cannot stop tunnel.."
9+
exit 1
10+
fi
11+
12+
echo "Shutting down Sauce Connect tunnel"
13+
14+
# The process id for the sauce-connect instance is stored inside of the pidfile.
15+
tunnelProcessId=$(cat ${SAUCE_PID_FILE})
16+
17+
# Kill the process by using the PID that has been read from the pidfile. Note that
18+
# we cannot use killall because CircleCI base container images don't have it installed.
19+
kill ${tunnelProcessId}
20+
21+
while (ps -p ${tunnelProcessId} &> /dev/null); do
22+
printf "."
23+
sleep .5
24+
done
25+
26+
echo ""
27+
echo "Sauce Connect tunnel has been shut down"

scripts/saucelabs/wait-for-tunnel.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env bash
2+
3+
# Disable printing of any executed command because this would cause a lot
4+
# of spam due to the loop.
5+
set +x -u -e -o pipefail
6+
7+
# Waits for Saucelabs Connect to be ready before executing any tests.
8+
counter=0
9+
10+
while [[ ! -f ${SAUCE_READY_FILE} ]]; do
11+
counter=$((counter + 1))
12+
13+
# Counter needs to be multiplied by two because the while loop only sleeps a half second.
14+
# This has been made in favor of better progress logging (printing dots every half second)
15+
if [ $counter -gt $[${SAUCE_READY_FILE_TIMEOUT} * 2] ]; then
16+
echo "Timed out after ${SAUCE_READY_FILE_TIMEOUT} seconds waiting for tunnel ready file."
17+
echo "Printing logfile output:"
18+
echo ""
19+
cat ${SAUCE_LOG_FILE}
20+
exit 5
21+
fi
22+
23+
printf "."
24+
sleep 0.5
25+
done
26+
27+
echo ""
28+
echo "Connected to Saucelabs"
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// @ts-check
2+
// Protractor configuration file, see link for more information
3+
// https://github.com/angular/protractor/blob/master/lib/config.ts
4+
5+
const { SpecReporter } = require('jasmine-spec-reporter');
6+
7+
const tunnelIdentifier = process.env['SAUCE_TUNNEL_IDENTIFIER'];
8+
9+
/**
10+
* @type { import("protractor").Config }
11+
*/
12+
exports.config = {
13+
sauceUser: process.env['SAUCE_USERNAME'],
14+
sauceKey: process.env['SAUCE_ACCESS_KEY'],
15+
16+
allScriptsTimeout: 11000,
17+
specs: ['./src/**/*.e2e-spec.ts'],
18+
19+
multiCapabilities: [
20+
{
21+
browserName: 'chrome',
22+
version: '41',
23+
tunnelIdentifier,
24+
},
25+
{
26+
browserName: 'chrome',
27+
version: '75',
28+
tunnelIdentifier,
29+
},
30+
{
31+
browserName: 'safari',
32+
platform: 'OS X 10.11',
33+
version: '9.0',
34+
tunnelIdentifier,
35+
},
36+
// TODO: Investigate. Failure:
37+
// Failed: Error while running testForAngular: undefined is not an object (evaluating 'd.prototype[b].apply')
38+
// {
39+
// browserName: 'safari',
40+
// platform: 'OS X 10.12',
41+
// version: '10.1',
42+
// tunnelIdentifier,
43+
// },
44+
{
45+
browserName: 'safari',
46+
platform: 'macOS 10.13',
47+
version: '11.1',
48+
tunnelIdentifier,
49+
},
50+
{
51+
browserName: 'safari',
52+
platform: 'macOS 10.13',
53+
version: '12.1',
54+
tunnelIdentifier,
55+
},
56+
{
57+
browserName: 'firefox',
58+
version: '48',
59+
tunnelIdentifier,
60+
},
61+
{
62+
browserName: 'firefox',
63+
version: '60',
64+
tunnelIdentifier,
65+
},
66+
{
67+
browserName: 'firefox',
68+
version: '68',
69+
tunnelIdentifier,
70+
},
71+
{
72+
browserName: 'internet explorer',
73+
platform: 'Windows 8',
74+
version: '10',
75+
tunnelIdentifier,
76+
},
77+
{
78+
browserName: 'internet explorer',
79+
platform: 'Windows 8.1',
80+
version: '11',
81+
tunnelIdentifier,
82+
},
83+
{
84+
browserName: "MicrosoftEdge",
85+
platform: 'Windows 10',
86+
version: "14.14393",
87+
tunnelIdentifier,
88+
},
89+
{
90+
browserName: "MicrosoftEdge",
91+
platform: 'Windows 10',
92+
version: "17.17134",
93+
tunnelIdentifier,
94+
},
95+
{
96+
browserName: "MicrosoftEdge",
97+
platform: 'Windows 10',
98+
version: "18.17763",
99+
tunnelIdentifier,
100+
},
101+
],
102+
103+
baseUrl: 'http://localhost:2000/',
104+
framework: 'jasmine',
105+
jasmineNodeOpts: {
106+
showColors: true,
107+
defaultTimeoutInterval: 30000,
108+
print: function() {},
109+
},
110+
111+
onPrepare() {
112+
// Fix for Safari 12 -- https://github.com/angular/protractor/issues/4964
113+
browser.resetUrl = 'about:blank';
114+
115+
require('ts-node').register({
116+
project: require('path').join(__dirname, './tsconfig.json'),
117+
});
118+
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
119+
},
120+
};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import * as express from 'express';
2+
import * as path from 'path';
3+
import { copyProjectAsset } from '../../utils/assets';
4+
import { replaceInFile } from '../../utils/fs';
5+
import { ng } from '../../utils/process';
6+
7+
export default async function () {
8+
if (!process.env['E2E_BROWSERS']) {
9+
return;
10+
}
11+
12+
// Ensure SauceLabs configuration
13+
if (!process.env['SAUCE_USERNAME'] || !process.env['SAUCE_ACCESS_KEY']) {
14+
throw new Error('SauceLabs is not configured.');
15+
}
16+
17+
await ng('build', '--prod');
18+
19+
// Add Protractor configuration
20+
await copyProjectAsset('protractor-saucelabs.conf.js', 'e2e/protractor-saucelabs.conf.js');
21+
22+
// Remove browser log checks as they are only supported with the chrome webdriver
23+
await replaceInFile(
24+
'e2e/src/app.e2e-spec.ts',
25+
'await browser.manage().logs().get(logging.Type.BROWSER)',
26+
'[]',
27+
);
28+
29+
// Workaround defect in getText WebDriver implementation for Safari/Edge
30+
// Leading and trailing space is not removed
31+
await replaceInFile(
32+
'e2e/src/app.e2e-spec.ts',
33+
'\'should display welcome message\',',
34+
'\'should display welcome message\', async',
35+
);
36+
await replaceInFile(
37+
'e2e/src/app.e2e-spec.ts',
38+
'page.navigateTo();',
39+
'await page.navigateTo();',
40+
);
41+
await replaceInFile(
42+
'e2e/src/app.e2e-spec.ts',
43+
'page.getTitleText()',
44+
'(await page.getTitleText()).trim()',
45+
);
46+
47+
// Setup server
48+
const app = express();
49+
app.use(express.static(path.resolve('dist/test-project')));
50+
const server = app.listen(2000, 'localhost');
51+
52+
try {
53+
// Execute application's E2E tests with SauceLabs
54+
await ng(
55+
'e2e',
56+
'test-project',
57+
'--protractorConfig=e2e/protractor-saucelabs.conf.js',
58+
'--devServerTarget=',
59+
);
60+
} finally {
61+
server.close();
62+
}
63+
}

yarn.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9096,6 +9096,10 @@ sauce-connect-launcher@^1.2.4:
90969096
lodash "^4.16.6"
90979097
rimraf "^2.5.4"
90989098

9099+
"sauce-connect@https://saucelabs.com/downloads/sc-4.5.4-linux.tar.gz":
9100+
version "0.0.0"
9101+
resolved "https://saucelabs.com/downloads/sc-4.5.4-linux.tar.gz#dc5efcd2be24ddb099a85b923d6e754754651fa8"
9102+
90999103
saucelabs@^1.5.0:
91009104
version "1.5.0"
91019105
resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.5.0.tgz#9405a73c360d449b232839919a86c396d379fd9d"

0 commit comments

Comments
 (0)