Skip to content

Commit e8d9bd6

Browse files
committed
Add custom karma-safari-launcher plugin
1 parent 3f2c12a commit e8d9bd6

File tree

8 files changed

+158
-32
lines changed

8 files changed

+158
-32
lines changed

config/karma.base.js

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,66 @@ const path = require('path');
2020
const webpackTestConfig = require('./webpack.test');
2121
const { argv } = require('yargs');
2222

23+
function determineBrowsers() {
24+
const supportedBrowsers = ['ChromeHeadless', 'Safari', 'Firefox'];
25+
26+
if (process.env.BROWSERS) {
27+
const browsers = process.env.BROWSERS.split(',');
28+
29+
const validBrowsers = browsers.filter(browser =>
30+
supportedBrowsers.includes(browser)
31+
);
32+
if (validBrowsers.length === 0) {
33+
console.error(
34+
`The \'BROWSER\' environment variable was set, but no supported browsers were listed. The supported browsers are ${JSON.stringify(
35+
supportedBrowsers
36+
)}.`
37+
);
38+
return [];
39+
}
40+
41+
if (browsers.includes('Safari') && process.platform !== 'darwin') {
42+
console.error(
43+
"The 'BROWSER' environment variable includes 'Safari', which is not supported on this platform. The only supported platform is darwin."
44+
);
45+
return [];
46+
}
47+
48+
if (browsers.includes('Safari')) {
49+
console.log(
50+
"\x1b[38;2;255;165;0mSafari browser testing has been enabled. This requires Full Disk Access be granted to the executor. To grant Full Disk Access on macOS > 13, visit 'System Settings' > 'Privacy & Security' > 'Full Disk Access'.\x1b[0m"
51+
); // Log in orange
52+
}
53+
54+
return validBrowsers;
55+
} else {
56+
/**
57+
* By default we only run the Chrome tests locally since the Safari launcher has some quirks
58+
* that make local testing annoying:
59+
* - Tabs from previous test runs are restored, causing the tests to be ran once on each tab.
60+
* To prevent this, Safari has to be manually re-opened and then quit after every test run.
61+
* - Full Disk Access has to be manually enabled
62+
*
63+
* Running the browser tests in Chrome should catch most browser bugs. If that's not the case,
64+
* the bugs will be caught when the browser tests are ran on Safari in CI.
65+
*/
66+
console.log(
67+
"The 'BROWSER' environment variable is undefined. Defaulting to 'ChromeHeadless'."
68+
);
69+
return ['ChromeHeadless'];
70+
}
71+
}
72+
2373
const config = {
74+
// See: https://karma-runner.github.io/6.4/config/plugins.html#loading-plugins
75+
plugins: [
76+
// We use our own custom Safari launcher plugin since https://github.com/karma-runner/karma-safari-launcher
77+
// does not work and is not maintained.
78+
require('../tools/karma-safari-launcher'),
79+
// Include all other plugins from our npm modules
80+
'karma-*'
81+
],
82+
2483
// disable watcher
2584
autoWatch: false,
2685

@@ -57,10 +116,11 @@ const config = {
57116
// changes
58117
autoWatch: false,
59118

60-
// start these browsers
61-
// available browser launchers:
62-
// https://npmjs.org/browse/keyword/karma-launcher
63-
browsers: process.env?.BROWSERS?.split(',') ?? ['ChromeHeadless'],
119+
// Browsers to launch for testing
120+
// To use a custom set of browsers, define the BROWSERS environment variable as a comma-seperated list.
121+
// Supported browsers are 'ChromeHeadless', 'Safari', and 'Firefox'.
122+
// See: https://karma-runner.github.io/6.4/config/browsers.html
123+
browsers: determineBrowsers(),
64124

65125
webpack: webpackTestConfig,
66126

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@
120120
"karma-firefox-launcher": "2.1.3",
121121
"karma-mocha": "2.0.1",
122122
"karma-mocha-reporter": "2.2.5",
123-
"karma-safari-launcher": "1.0.0",
124123
"karma-sourcemap-loader": "0.4.0",
125124
"karma-spec-reporter": "0.0.36",
126125
"karma-summary-reporter": "3.1.1",

packages/auth-compat/karma.conf.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ const files = ['src/**/*.test.ts'];
2323

2424
module.exports = function (config) {
2525
const karmaConfig = Object.assign({}, karmaBase, {
26-
browsers: getTestBrowsers(argv),
2726
// files to load into karma
2827
files: getTestFiles(),
2928
preprocessors: { '**/*.ts': ['webpack', 'sourcemap'] },
@@ -56,14 +55,6 @@ function getTestFiles() {
5655
}
5756
}
5857

59-
function getTestBrowsers(argv) {
60-
let browsers = ['ChromeHeadless'];
61-
if (process.env?.BROWSERS && argv.unit) {
62-
browsers = process.env?.BROWSERS?.split(',');
63-
}
64-
return browsers;
65-
}
66-
6758
function getClientConfig() {
6859
if (!argv.integration) {
6960
return {};

packages/auth/karma.conf.js

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const { argv } = require('yargs');
2121

2222
module.exports = function (config) {
2323
const karmaConfig = Object.assign({}, karmaBase, {
24-
browsers: getTestBrowsers(argv),
2524
// files to load into karma
2625
files: getTestFiles(argv),
2726
// frameworks to use
@@ -60,7 +59,7 @@ function getTestFiles(argv) {
6059
} else if (argv.cordova) {
6160
return ['src/platform_cordova/**/*.test.ts'];
6261
} else {
63-
// For the catch-all yarn:test, ignore the phone integration test
62+
// For the catch-all yarn browser:test, ignore the phone integration test
6463
return [
6564
'src/**/*.test.ts',
6665
'test/helpers/**/*.test.ts',
@@ -71,14 +70,6 @@ function getTestFiles(argv) {
7170
}
7271
}
7372

74-
function getTestBrowsers(argv) {
75-
let browsers = ['ChromeHeadless'];
76-
if (process.env?.BROWSERS && argv.unit) {
77-
browsers = process.env?.BROWSERS?.split(',');
78-
}
79-
return browsers;
80-
}
81-
8273
function getClientConfig(argv) {
8374
if (!argv.local) {
8475
return {};

packages/auth/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,12 @@
9393
"build:scripts": "tsc -moduleResolution node --module commonjs scripts/*.ts && ls scripts/*.js | xargs -I % sh -c 'terser % -o %'",
9494
"dev": "rollup -c -w",
9595
"test": "run-p --npm-path npm lint test:all",
96-
"test:all": "run-p --npm-path npm test:browser:unit test:node:unit test:integration test:browser:integration:prodbackend",
97-
"test:integration": "firebase emulators:exec --project emulatedproject --only auth \"run-s --npm-path npm test:browser:integration:local test:node:integration:local test:webdriver\"",
96+
"test:all": "run-p --npm-path npm test:browser:unit test:node:unit test:integration",
97+
"test:integration": "firebase emulators:exec --project emulatedproject --only auth \"run-s --npm-path npm test:browser:integration:local test:browser:integration:prodbackend test:node:integration:local test:webdriver\"",
9898
"test:ci": "node ../../scripts/run_tests_in_ci.js -s test:all",
9999
"test:integration:local": "run-s --npm-path npm test:node:integration:local test:browser:integration:local test:webdriver",
100-
"test:browser": "karma start --single-run --local",
100+
"test:browser": "karma start --single-run",
101+
"test:browser:local": "karma start --single-run --local",
101102
"test:browser:unit": "karma start --single-run --unit",
102103
"test:browser:integration": "karma start --single-run --integration",
103104
"test:browser:integration:local": "karma start --single-run --integration --local",

tools/karma-safari-launcher/index.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* @license
3+
* Copyright 2024 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
// See: https://karma-runner.github.io/6.4/dev/plugins.html
19+
const fs = require('fs');
20+
const os = require('os');
21+
const path = require('path');
22+
23+
var SafariBrowser = function (baseBrowserDecorator) {
24+
baseBrowserDecorator(this);
25+
26+
// This is the only directory that we can open files from in Safari without causing a
27+
// dialog to open.
28+
// Reading and writing to this directory requires Full Disk access, which can be granted on macOS > 13 at
29+
// 'System Settings' > 'Privacy & Security' > 'Full Disk Access'.
30+
const SAFARI_DATA_DIR = path.join(
31+
os.homedir(),
32+
'Library/Containers/com.apple.Safari/Data'
33+
);
34+
const HTML_TRAMPOLINE_PATH = path.join(SAFARI_DATA_DIR, 'redirect.html');
35+
36+
this._start = function (url) {
37+
var self = this;
38+
39+
// HTML trampoline to redirect Safari to the URL where the tests are hosted.
40+
// This is necessary because Safari assumes the location we pass as an argument is a path
41+
// in the Safari Data directory. So, if we were to pass 'http://localhost:3000' as an argument,
42+
// Safari would attempt to open
43+
// 'file:///Users/<user>/Library/Containers/com.apple.Safari/Data/http:/localhost:3000'.
44+
const htmlTrampoline = `
45+
<!DOCTYPE html>
46+
<html lang="en">
47+
<head>
48+
<meta charset="UTF-8">
49+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
50+
<title>Redirect</title>
51+
<meta http-equiv="refresh" content="0; url=${url}">
52+
</head>
53+
<body>
54+
<p>If you are not redirected automatically, please click <a href="${url}">here</a>.</p>
55+
</body>
56+
</html>
57+
`;
58+
59+
fs.writeFile(HTML_TRAMPOLINE_PATH, htmlTrampoline, function (err) {
60+
if (err) {
61+
console.error('Error writing file:', err);
62+
return;
63+
}
64+
65+
// Open the HTMl trampoline in Safari
66+
self._execCommand(self._getCommand(), [HTML_TRAMPOLINE_PATH]);
67+
});
68+
};
69+
};
70+
71+
SafariBrowser.prototype = {
72+
name: 'Safari',
73+
DEFAULT_CMD: {
74+
darwin: '/Applications/Safari.app/Contents/MacOS/Safari'
75+
},
76+
ENV_CMD: 'SAFARI_BIN'
77+
};
78+
79+
SafariBrowser.$inject = ['baseBrowserDecorator'];
80+
81+
module.exports = {
82+
'launcher:Safari': ['type', SafariBrowser]
83+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "karma-safari-launcher",
3+
"version": "1.0.0",
4+
"description": "A Karma plugin to launch a Safari browser",
5+
"main": "index.js"
6+
}

yarn.lock

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11337,11 +11337,6 @@ [email protected]:
1133711337
dependencies:
1133811338
minimist "^1.2.3"
1133911339

11340-
11341-
version "1.0.0"
11342-
resolved "https://registry.npmjs.org/karma-safari-launcher/-/karma-safari-launcher-1.0.0.tgz"
11343-
integrity sha1-lpgqLMR9BmquccVTursoMZEVos4=
11344-
1134511340
1134611341
version "0.4.0"
1134711342
resolved "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.4.0.tgz"

0 commit comments

Comments
 (0)