Skip to content

Commit 3ed0b08

Browse files
authored
[Auth] Add support for using the emulator for integration tests (#4564)
* Integration tests with emulator * Missing file * Go back to 'getAuth' * Add script for helping run node tests as they were getting out of hand * Fix lint issues * Fix issue * Formatting, license * Fix command
1 parent 57c73a0 commit 3ed0b08

File tree

7 files changed

+236
-17
lines changed

7 files changed

+236
-17
lines changed

packages-exp/auth-exp/.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
module.exports = {
1919
extends: '../../config/.eslintrc.js',
20-
ignorePatterns: ['demo/'],
20+
ignorePatterns: ['demo/', 'scripts/'],
2121
parserOptions: {
2222
project: 'tsconfig.json',
2323
// to make vscode-eslint work with monorepo

packages-exp/auth-exp/karma.conf.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ module.exports = function (config) {
2424
files: getTestFiles(argv),
2525
// frameworks to use
2626
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
27-
frameworks: ['mocha']
27+
frameworks: ['mocha'],
28+
29+
client: Object.assign({}, karmaBase.client, getClientConfig(argv))
2830
});
2931

3032
config.set(karmaConfig);
@@ -48,4 +50,19 @@ function getTestFiles(argv) {
4850
}
4951
}
5052

53+
function getClientConfig(argv) {
54+
if (!argv.local) {
55+
return {};
56+
}
57+
58+
return {
59+
authAppConfig: {
60+
apiKey: 'local-api-key',
61+
projectId: 'test-emulator',
62+
authDomain: 'local-auth-domain'
63+
},
64+
authEmulatorPort: '9099'
65+
};
66+
}
67+
5168
module.exports.files = getTestFiles(argv);

packages-exp/auth-exp/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,23 @@
2020
"build": "rollup -c && yarn api-report",
2121
"build:deps": "lerna run --scope @firebase/auth-exp --include-dependencies build",
2222
"build:release": "rollup -c rollup.config.release.js && yarn api-report && yarn typings:public",
23+
"build:scripts": "tsc -moduleResolution node --module commonjs scripts/*.ts && ls scripts/*.js | xargs -I % sh -c 'terser % -o %'",
2324
"dev": "rollup -c -w",
2425
"test": "run-p lint test:all",
2526
"test:all": "run-p test:browser test:node",
2627
"test:ci": "node ../../scripts/run_tests_in_ci.js -s test:all",
2728
"test:browser": "karma start --single-run",
2829
"test:browser:unit": "karma start --single-run --unit",
2930
"test:browser:integration": "karma start --single-run --integration",
31+
"test:browser:integration:local": "karma start --single-run --integration --local --auto-watch",
3032
"test:browser:debug": "karma start --auto-watch",
3133
"test:browser:unit:debug": "karma start --auto-watch --unit",
3234
"test:cordova": "karma start --single-run --cordova",
3335
"test:cordova:debug": "karma start --auto-watch --cordova",
3436
"test:node": "run-s test:node:unit test:node:integration",
35-
"test:node:unit": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha 'src/!(platform_browser|platform_react_native|platform_cordova)/**/*.test.ts' --file index.node.ts --config ../../config/mocharc.node.js",
36-
"test:node:integration": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha 'test/integration/flows/{email,anonymous}.test.ts' --config ../../config/mocharc.node.js",
37+
"test:node:unit": "node ./scripts/run-node-tests.js",
38+
"test:node:integration": "node ./scripts/run-node-tests.js --integration",
39+
"test:node:integration:local": "node ./scripts/run-node-tests.js --integration --local",
3740
"api-report": "api-extractor run --local --verbose",
3841
"predoc": "node ../../scripts/exp/remove-exp.js temp",
3942
"doc": "api-documenter markdown --input temp --output docs",
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @license
3+
* Copyright 2020 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+
'use strict';
19+
var __spreadArrays =
20+
(this && this.__spreadArrays) ||
21+
function () {
22+
for (var s = 0, i = 0, il = arguments.length; i < il; i++)
23+
s += arguments[i].length;
24+
for (var r = Array(s), k = 0, i = 0; i < il; i++)
25+
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
26+
r[k] = a[j];
27+
return r;
28+
};
29+
exports.__esModule = true;
30+
var path_1 = require('path');
31+
var child_process_promise_1 = require('child-process-promise');
32+
var yargs = require('yargs');
33+
var argv = yargs.options({
34+
local: { type: 'boolean' },
35+
integration: { type: 'boolean' }
36+
}).argv;
37+
var nyc = path_1.resolve(__dirname, '../../../node_modules/.bin/nyc');
38+
var mocha = path_1.resolve(__dirname, '../../../node_modules/.bin/mocha');
39+
process.env.TS_NODE_COMPILER_OPTIONS = '{"module":"commonjs"}';
40+
var testConfig = [
41+
'src/!(platform_browser|platform_react_native|platform_cordova)/**/*.test.ts',
42+
'--file',
43+
'index.node.ts'
44+
];
45+
if (argv.integration) {
46+
testConfig = ['test/integration/flows/{email,anonymous}.test.ts'];
47+
}
48+
var args = __spreadArrays(['--reporter', 'lcovonly', mocha], testConfig, [
49+
'--config',
50+
'../../config/mocharc.node.js'
51+
]);
52+
if (argv.local) {
53+
process.env.AUTH_EMULATOR_PORT = '9099';
54+
process.env.AUTH_EMULATOR_PROJECT_ID = 'test-emulator';
55+
}
56+
args = args.concat(argv._);
57+
var childProcess = child_process_promise_1.spawn(nyc, args, {
58+
stdio: 'inherit',
59+
cwd: process.cwd()
60+
}).childProcess;
61+
process.once('exit', function () {
62+
return childProcess.kill();
63+
});
64+
process.once('SIGINT', function () {
65+
return childProcess.kill('SIGINT');
66+
});
67+
process.once('SIGTERM', function () {
68+
return childProcess.kill('SIGTERM');
69+
});
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* @license
3+
* Copyright 2020 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+
import { resolve } from 'path';
19+
20+
import { spawn } from 'child-process-promise';
21+
import * as yargs from 'yargs';
22+
23+
const argv = yargs.options({
24+
local: {
25+
type: 'boolean'
26+
},
27+
integration: {
28+
type: 'boolean'
29+
}
30+
}).argv;
31+
32+
const nyc = resolve(__dirname, '../../../node_modules/.bin/nyc');
33+
const mocha = resolve(__dirname, '../../../node_modules/.bin/mocha');
34+
35+
process.env.TS_NODE_COMPILER_OPTIONS = '{"module":"commonjs"}';
36+
37+
let testConfig = [
38+
'src/!(platform_browser|platform_react_native|platform_cordova)/**/*.test.ts',
39+
'--file',
40+
'index.node.ts'
41+
];
42+
43+
if (argv.integration) {
44+
testConfig = ['test/integration/flows/{email,anonymous}.test.ts'];
45+
}
46+
47+
let args = [
48+
'--reporter',
49+
'lcovonly',
50+
mocha,
51+
...testConfig,
52+
'--config',
53+
'../../config/mocharc.node.js'
54+
];
55+
56+
if (argv.local) {
57+
process.env.AUTH_EMULATOR_PORT = '9099';
58+
process.env.AUTH_EMULATOR_PROJECT_ID = 'test-emulator';
59+
}
60+
61+
args = args.concat(argv._ as string[]);
62+
63+
const childProcess = spawn(nyc, args, {
64+
stdio: 'inherit',
65+
cwd: process.cwd()
66+
}).childProcess;
67+
68+
process.once('exit', () => childProcess.kill());
69+
process.once('SIGINT', () => childProcess.kill('SIGINT'));
70+
process.once('SIGTERM', () => childProcess.kill('SIGTERM'));

packages-exp/auth-exp/test/helpers/integration/helpers.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,9 @@
1818
import { deleteApp, initializeApp } from '@firebase/app-exp';
1919
import { Auth, User } from '../../../src/model/public_types';
2020

21-
import { getAuth } from '../../../'; // Use browser OR node dist entrypoint depending on test env.
21+
import { getAuth, useAuthEmulator } from '../../../'; // Use browser OR node dist entrypoint depending on test env.
2222
import { _generateEventId } from '../../../src/core/util/event_id';
23-
24-
// eslint-disable-next-line @typescript-eslint/no-require-imports
25-
const PROJECT_CONFIG = require('../../../../../config/project.json');
26-
27-
export const PROJECT_ID = PROJECT_CONFIG.projectId;
28-
export const AUTH_DOMAIN = PROJECT_CONFIG.authDomain;
29-
export const API_KEY = PROJECT_CONFIG.apiKey;
23+
import { getAppConfig, getEmulatorUrl } from './settings';
3024

3125
interface IntegrationTestAuth extends Auth {
3226
cleanUp(): Promise<void>;
@@ -37,15 +31,16 @@ export function randomEmail(): string {
3731
}
3832

3933
export function getTestInstance(): Auth {
40-
const app = initializeApp({
41-
apiKey: API_KEY,
42-
projectId: PROJECT_ID,
43-
authDomain: AUTH_DOMAIN
44-
});
34+
const app = initializeApp(getAppConfig());
4535

4636
const createdUsers: User[] = [];
4737
const auth = getAuth(app) as IntegrationTestAuth;
4838
auth.settings.appVerificationDisabledForTesting = true;
39+
const emulatorUrl = getEmulatorUrl();
40+
41+
if (emulatorUrl) {
42+
useAuthEmulator(auth, emulatorUrl, { disableWarnings: true });
43+
}
4944

5045
auth.onAuthStateChanged(user => {
5146
if (user) {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* @license
3+
* Copyright 2020 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+
import { FirebaseOptions } from '@firebase/app-exp';
19+
20+
// __karma__ is an untyped global
21+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
22+
declare const __karma__: any;
23+
24+
// eslint-disable-next-line @typescript-eslint/no-require-imports
25+
const PROJECT_CONFIG = require('../../../../../config/project.json');
26+
27+
const EMULATOR_PORT = process.env.AUTH_EMULATOR_PORT;
28+
const EMULATOR_PROJECT_ID = process.env.AUTH_EMULATOR_PROJECT_ID;
29+
30+
export const USE_EMULATOR = !!EMULATOR_PORT;
31+
32+
export const PROJECT_ID = USE_EMULATOR
33+
? EMULATOR_PROJECT_ID
34+
: PROJECT_CONFIG.projectId;
35+
export const AUTH_DOMAIN = USE_EMULATOR
36+
? 'emulator-auth-domain'
37+
: PROJECT_CONFIG.authDomain;
38+
export const API_KEY = USE_EMULATOR
39+
? 'emulator-api-key'
40+
: PROJECT_CONFIG.apiKey;
41+
42+
export function getAppConfig(): FirebaseOptions {
43+
// Prefer the karma config, then fallback on node process.env stuff
44+
return (
45+
getKarma()?.config?.authAppConfig || {
46+
apiKey: API_KEY,
47+
projectId: PROJECT_ID,
48+
authDomain: AUTH_DOMAIN
49+
}
50+
);
51+
}
52+
53+
export function getEmulatorUrl(): string | null {
54+
// Check karma first, then fallback on node process
55+
const emulatorPort: string | null =
56+
getKarma()?.config?.authEmulatorPort ||
57+
(USE_EMULATOR ? EMULATOR_PORT : null);
58+
59+
return emulatorPort ? `http://localhost:${emulatorPort}` : null;
60+
}
61+
62+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
63+
function getKarma(): any {
64+
return typeof __karma__ !== 'undefined' ? __karma__ : undefined;
65+
}

0 commit comments

Comments
 (0)