Skip to content

Commit 785a385

Browse files
committed
Fix up tests
1 parent 5796037 commit 785a385

File tree

11 files changed

+324
-127
lines changed

11 files changed

+324
-127
lines changed

common/api-review/app-check-exp.api.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66

77
import { FirebaseApp } from '@firebase/app-exp';
88

9-
// @public
10-
export function activate(app: FirebaseApp, siteKeyOrProvider: string | AppCheckProvider, isTokenAutoRefreshEnabled?: boolean): void;
11-
129
// @public
1310
export interface AppCheck {
1411
app: FirebaseApp;
@@ -20,6 +17,12 @@ export type _AppCheckComponentName = 'app-check-exp';
2017
// @internal (undocumented)
2118
export type _AppCheckInternalComponentName = 'app-check-internal';
2219

20+
// @public
21+
export interface AppCheckOptions {
22+
isTokenAutoRefreshEnabled?: boolean;
23+
provider: AppCheckProvider;
24+
}
25+
2326
// @public
2427
export interface AppCheckProvider {
2528
getToken(): Promise<AppCheckToken>;
@@ -33,7 +36,13 @@ export interface AppCheckToken {
3336
}
3437

3538
// @public
36-
export function getAppCheck(app?: FirebaseApp): AppCheck;
39+
export function initializeAppCheck(app: FirebaseApp | undefined, options: AppCheckOptions): AppCheck;
40+
41+
// @public
42+
export class ReCaptchaV3Provider implements AppCheckProvider {
43+
constructor(siteKey: string);
44+
getToken(): Promise<AppCheckToken>;
45+
}
3746

3847
// @public
3948
export function setTokenAutoRefreshEnabled(app: FirebaseApp, isTokenAutoRefreshEnabled: boolean): void;

packages-exp/app-check-exp/src/api.test.ts

Lines changed: 99 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,54 +17,81 @@
1717
import '../test/setup';
1818
import { expect } from 'chai';
1919
import { stub } from 'sinon';
20-
import { activate, setTokenAutoRefreshEnabled } from './api';
20+
import {
21+
_activate as activate,
22+
setTokenAutoRefreshEnabled,
23+
initializeAppCheck
24+
} from './api';
2125
import {
2226
FAKE_SITE_KEY,
2327
getFakeApp,
24-
getFakeCustomTokenProvider
28+
getFakeCustomTokenProvider,
29+
getFakePlatformLoggingProvider
2530
} from '../test/util';
2631
import { getState } from './state';
2732
import * as reCAPTCHA from './recaptcha';
28-
import { FirebaseApp } from '@firebase/app-exp';
33+
import {
34+
deleteApp,
35+
FirebaseApp,
36+
initializeApp,
37+
_registerComponent
38+
} from '@firebase/app-exp';
39+
import { Component, ComponentType } from '@firebase/component';
40+
import { AppCheckService } from './factory';
41+
import { ReCaptchaV3Provider } from './providers';
42+
import { PlatformLoggerService } from '@firebase/app-exp/dist/packages-exp/app-exp/src/types';
2943

3044
describe('api', () => {
31-
describe('activate()', () => {
32-
let app: FirebaseApp;
33-
34-
beforeEach(() => {
35-
app = getFakeApp();
36-
});
37-
38-
it('sets activated to true', () => {
39-
expect(getState(app).activated).to.equal(false);
40-
activate(app, FAKE_SITE_KEY);
41-
expect(getState(app).activated).to.equal(true);
42-
});
45+
let app: FirebaseApp;
4346

44-
it('isTokenAutoRefreshEnabled value defaults to global setting', () => {
45-
app = getFakeApp({ automaticDataCollectionEnabled: false });
46-
activate(app, FAKE_SITE_KEY);
47-
expect(getState(app).isTokenAutoRefreshEnabled).to.equal(false);
48-
});
47+
beforeEach(() => {
48+
app = initializeApp(
49+
{ apiKey: 'fdsa', appId: 'fdsafg' },
50+
'initializeAppCheckTests'
51+
);
52+
_registerComponent(
53+
new Component(
54+
'platform-logger',
55+
() => {
56+
return {} as PlatformLoggerService;
57+
},
58+
ComponentType.PUBLIC
59+
)
60+
);
61+
_registerComponent(
62+
new Component(
63+
'app-check-exp',
64+
() => {
65+
return {} as AppCheckService;
66+
},
67+
ComponentType.PUBLIC
68+
)
69+
);
70+
});
4971

50-
it('sets isTokenAutoRefreshEnabled correctly, overriding global setting', () => {
51-
app = getFakeApp({ automaticDataCollectionEnabled: false });
52-
activate(app, FAKE_SITE_KEY, true);
53-
expect(getState(app).isTokenAutoRefreshEnabled).to.equal(true);
54-
});
72+
afterEach(() => {
73+
return deleteApp(app);
74+
});
5575

76+
describe('initializeAppCheck()', () => {
5677
it('can only be called once', () => {
57-
activate(app, FAKE_SITE_KEY);
58-
expect(() => activate(app, FAKE_SITE_KEY)).to.throw(
59-
/AppCheck can only be activated once/
60-
);
78+
initializeAppCheck(app, {
79+
provider: new ReCaptchaV3Provider(FAKE_SITE_KEY)
80+
});
81+
expect(() =>
82+
initializeAppCheck(app, {
83+
provider: new ReCaptchaV3Provider(FAKE_SITE_KEY)
84+
})
85+
).to.throw(/appCheck\/already-initialized/);
6186
});
6287

6388
it('initialize reCAPTCHA when a sitekey is provided', () => {
6489
const initReCAPTCHAStub = stub(reCAPTCHA, 'initialize').returns(
6590
Promise.resolve({} as any)
6691
);
67-
activate(app, FAKE_SITE_KEY);
92+
initializeAppCheck(app, {
93+
provider: new ReCaptchaV3Provider(FAKE_SITE_KEY)
94+
});
6895
expect(initReCAPTCHAStub).to.have.been.calledWithExactly(
6996
app,
7097
FAKE_SITE_KEY
@@ -74,11 +101,51 @@ describe('api', () => {
74101
it('does NOT initialize reCAPTCHA when a custom token provider is provided', () => {
75102
const fakeCustomTokenProvider = getFakeCustomTokenProvider();
76103
const initReCAPTCHAStub = stub(reCAPTCHA, 'initialize');
77-
activate(app, fakeCustomTokenProvider);
78-
expect(getState(app).customProvider).to.equal(fakeCustomTokenProvider);
104+
initializeAppCheck(app, {
105+
provider: fakeCustomTokenProvider
106+
});
107+
expect(getState(app).provider).to.equal(fakeCustomTokenProvider);
79108
expect(initReCAPTCHAStub).to.have.not.been.called;
80109
});
81110
});
111+
describe('activate()', () => {
112+
let app: FirebaseApp;
113+
114+
beforeEach(() => {
115+
app = getFakeApp();
116+
});
117+
118+
it('sets activated to true', () => {
119+
expect(getState(app).activated).to.equal(false);
120+
activate(
121+
app,
122+
new ReCaptchaV3Provider(FAKE_SITE_KEY),
123+
getFakePlatformLoggingProvider()
124+
);
125+
expect(getState(app).activated).to.equal(true);
126+
});
127+
128+
it('isTokenAutoRefreshEnabled value defaults to global setting', () => {
129+
app.automaticDataCollectionEnabled = false;
130+
activate(
131+
app,
132+
new ReCaptchaV3Provider(FAKE_SITE_KEY),
133+
getFakePlatformLoggingProvider()
134+
);
135+
expect(getState(app).isTokenAutoRefreshEnabled).to.equal(false);
136+
});
137+
138+
it('sets isTokenAutoRefreshEnabled correctly, overriding global setting', () => {
139+
app.automaticDataCollectionEnabled = false;
140+
activate(
141+
app,
142+
new ReCaptchaV3Provider(FAKE_SITE_KEY),
143+
getFakePlatformLoggingProvider(),
144+
true
145+
);
146+
expect(getState(app).isTokenAutoRefreshEnabled).to.equal(true);
147+
});
148+
});
82149
describe('setTokenAutoRefreshEnabled()', () => {
83150
it('sets isTokenAutoRefreshEnabled correctly', () => {
84151
const app = getFakeApp({ automaticDataCollectionEnabled: false });

packages-exp/app-check-exp/src/api.ts

Lines changed: 26 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { AppCheck, AppCheckProvider } from './public-types';
18+
import { AppCheck, AppCheckOptions, AppCheckProvider } from './public-types';
1919
import { ERROR_FACTORY, AppCheckError } from './errors';
2020
import { initialize as initializeRecaptcha } from './recaptcha';
2121
import { getState, setState, AppCheckState } from './state';
2222
import { FirebaseApp, getApp, _getProvider } from '@firebase/app-exp';
23-
import { Provider } from '@firebase/component';
2423
import { getModularInstance } from '@firebase/util';
2524
import { AppCheckService } from './factory';
25+
import { ReCaptchaV3Provider } from './providers';
26+
import { Provider } from '@firebase/component';
2627

2728
declare module '@firebase/component' {
2829
interface NameServiceMapping {
@@ -31,37 +32,18 @@ declare module '@firebase/component' {
3132
}
3233

3334
/**
34-
* Returns a Firebase AppCheck instance for the given app.
35-
*
35+
* Activate AppCheck for the given app. Can be called only once per app.
36+
* @param app - the FirebaseApp to activate AppCheck for
37+
* @param options - Provider implementation that can return an AppCheck token
3638
* @public
37-
*
38-
* @param app - The FirebaseApp to use.
3939
*/
40-
export function getAppCheck(app: FirebaseApp = getApp()): AppCheck {
41-
app = getModularInstance(app);
42-
// Dependencies
43-
const appCheckProvider: Provider<'app-check-exp'> = _getProvider(
44-
app,
45-
'app-check-exp'
46-
);
47-
48-
if (appCheckProvider.isInitialized()) {
49-
return appCheckProvider.getImmediate();
50-
}
51-
return initializeAppCheck(app);
52-
}
53-
54-
interface AppCheckOptions {
55-
provider: AppCheckProvider;
56-
isTokenAutoRefreshEnabled?: boolean;
57-
}
58-
5940
export function initializeAppCheck(
6041
app: FirebaseApp = getApp(),
61-
options?: AppCheckOptions
42+
options: AppCheckOptions
6243
): AppCheck {
6344
app = getModularInstance(app);
6445
const provider = _getProvider(app, 'app-check-exp');
46+
const platformLoggerProvider = _getProvider(app, 'platform-logger');
6547

6648
if (provider.isInitialized()) {
6749
throw ERROR_FACTORY.create(AppCheckError.ALREADY_INITIALIZED, {
@@ -70,39 +52,38 @@ export function initializeAppCheck(
7052
}
7153

7254
const appCheck = provider.initialize({ options });
55+
_activate(
56+
app,
57+
options.provider,
58+
platformLoggerProvider,
59+
options.isTokenAutoRefreshEnabled
60+
);
7361

7462
return appCheck;
7563
}
7664

7765
/**
7866
* Activate AppCheck
7967
* @param app - Firebase app to activate AppCheck for.
80-
* @param siteKeyOrProvider - reCAPTCHA v3 site key (public key) or
68+
* @param provider - reCAPTCHA v3 provider or
8169
* custom token provider.
8270
* @param isTokenAutoRefreshEnabled - If true, the SDK automatically
8371
* refreshes App Check tokens as needed. If undefined, defaults to the
8472
* value of `app.automaticDataCollectionEnabled`, which defaults to
8573
* false and can be set in the app config.
86-
* @public
74+
*
75+
* @internal
8776
*/
88-
export function activate(
77+
export function _activate(
8978
app: FirebaseApp,
90-
siteKeyOrProvider: string | AppCheckProvider,
79+
provider: AppCheckProvider,
80+
platformLoggerProvider: Provider<'platform-logger'>,
9181
isTokenAutoRefreshEnabled?: boolean
9282
): void {
9383
const state = getState(app);
94-
if (state.activated) {
95-
throw ERROR_FACTORY.create(AppCheckError.ALREADY_ACTIVATED, {
96-
appName: app.name
97-
});
98-
}
9984

10085
const newState: AppCheckState = { ...state, activated: true };
101-
if (typeof siteKeyOrProvider === 'string') {
102-
newState.siteKey = siteKeyOrProvider;
103-
} else {
104-
newState.customProvider = siteKeyOrProvider;
105-
}
86+
newState.provider = provider;
10687

10788
// Use value of global `automaticDataCollectionEnabled` (which
10889
// itself defaults to false if not specified in config) if
@@ -115,8 +96,10 @@ export function activate(
11596
setState(app, newState);
11697

11798
// initialize reCAPTCHA if siteKey is provided
118-
if (newState.siteKey) {
119-
initializeRecaptcha(app, newState.siteKey).catch(() => {
99+
if (newState.provider instanceof ReCaptchaV3Provider) {
100+
// These need to be injected for ReCaptchaV3Provider's getToken() to work.
101+
newState.provider.initialize(app, platformLoggerProvider);
102+
initializeRecaptcha(app, newState.provider.siteKey).catch(() => {
120103
/* we don't care about the initialization result in activate() */
121104
});
122105
}
@@ -126,7 +109,7 @@ export function activate(
126109
*
127110
* @param isTokenAutoRefreshEnabled - If true, the SDK automatically
128111
* refreshes App Check tokens as needed. This overrides any value set
129-
* during `activate()`.
112+
* during `initializeAppCheck()`.
130113
* @public
131114
*/
132115
export function setTokenAutoRefreshEnabled(

packages-exp/app-check-exp/src/errors.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import { ErrorFactory, ErrorMap } from '@firebase/util';
1919

2020
export const enum AppCheckError {
21-
ALREADY_ACTIVATED = 'already-activated',
2221
ALREADY_INITIALIZED = 'already-initialized',
2322
USE_BEFORE_ACTIVATION = 'use-before-activation',
2423
FETCH_NETWORK_ERROR = 'fetch-network-error',
@@ -31,16 +30,12 @@ export const enum AppCheckError {
3130
}
3231

3332
const ERRORS: ErrorMap<AppCheckError> = {
34-
[AppCheckError.ALREADY_ACTIVATED]:
35-
'You are trying to activate AppCheck for FirebaseApp {$appName}, ' +
36-
'while it is already activated. ' +
37-
'AppCheck can only be activated once.',
3833
[AppCheckError.ALREADY_INITIALIZED]:
3934
'You have already called initializeAppCheck() for FirebaseApp {$appName}, ' +
4035
'initializeAppCheck() can only be called once.',
4136
[AppCheckError.USE_BEFORE_ACTIVATION]:
42-
'AppCheck is being used before activate() is called for FirebaseApp {$appName}. ' +
43-
'Please make sure you call activate() before instantiating other Firebase services.',
37+
'AppCheck is being used before initializeAppCheck() is called for FirebaseApp {$appName}. ' +
38+
'Please make sure you call initializeAppCheck() before instantiating other Firebase services.',
4439
[AppCheckError.FETCH_NETWORK_ERROR]:
4540
'Fetch failed to connect to a network. Check Internet connection. ' +
4641
'Original error: {$originalErrorMessage}.',
@@ -59,7 +54,6 @@ const ERRORS: ErrorMap<AppCheckError> = {
5954
};
6055

6156
interface ErrorParams {
62-
[AppCheckError.ALREADY_ACTIVATED]: { appName: string };
6357
[AppCheckError.ALREADY_INITIALIZED]: { appName: string };
6458
[AppCheckError.USE_BEFORE_ACTIVATION]: { appName: string };
6559
[AppCheckError.FETCH_NETWORK_ERROR]: { originalErrorMessage: string };

packages-exp/app-check-exp/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export { _AppCheckInternalComponentName };
2727

2828
export * from './api';
2929
export * from './public-types';
30+
export * from './providers';
3031

3132
const APP_CHECK_NAME: _AppCheckComponentName = 'app-check-exp';
3233
const APP_CHECK_NAME_INTERNAL: _AppCheckInternalComponentName =

0 commit comments

Comments
 (0)