Skip to content

Commit 7f09d08

Browse files
committed
Fix tests and type comments
1 parent c191029 commit 7f09d08

File tree

6 files changed

+141
-34
lines changed

6 files changed

+141
-34
lines changed

common/api-review/analytics-exp.api.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

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

9-
// @public (undocumented)
9+
// @public
1010
export interface Analytics {
1111
app: FirebaseApp;
1212
}
@@ -16,6 +16,12 @@ export interface AnalyticsCallOptions {
1616
global: boolean;
1717
}
1818

19+
// @public
20+
export interface AnalyticsOptions {
21+
// (undocumented)
22+
config: GtagConfigParams | EventParams;
23+
}
24+
1925
// @public
2026
export interface ControlParams {
2127
// (undocumented)
@@ -45,6 +51,8 @@ export type EventNameString = 'add_payment_info' | 'add_shipping_info' | 'add_to
4551

4652
// @public
4753
export interface EventParams {
54+
// (undocumented)
55+
[key: string]: unknown;
4856
// (undocumented)
4957
affiliation?: string;
5058
// (undocumented)
@@ -110,6 +118,45 @@ export interface EventParams {
110118
// @public
111119
export function getAnalytics(app: FirebaseApp): Analytics;
112120

121+
// @public
122+
export interface GtagConfigParams {
123+
// (undocumented)
124+
'allow_google_signals?': boolean;
125+
// (undocumented)
126+
[key: string]: unknown;
127+
// (undocumented)
128+
'allow_ad_personalization_signals'?: boolean;
129+
// (undocumented)
130+
'anonymize_ip'?: boolean;
131+
// (undocumented)
132+
'cookie_domain'?: string;
133+
// (undocumented)
134+
'cookie_expires'?: number;
135+
// (undocumented)
136+
'cookie_flags'?: string;
137+
// (undocumented)
138+
'cookie_prefix'?: string;
139+
// (undocumented)
140+
'cookie_update'?: boolean;
141+
// (undocumented)
142+
'custom_map'?: {
143+
[key: string]: unknown;
144+
};
145+
// (undocumented)
146+
'link_attribution'?: boolean;
147+
// (undocumented)
148+
'page_location'?: string;
149+
// (undocumented)
150+
'page_path'?: string;
151+
// (undocumented)
152+
'page_title'?: string;
153+
// (undocumented)
154+
'send_page_view'?: boolean;
155+
}
156+
157+
// @public
158+
export function initializeAnalytics(app: FirebaseApp, options?: AnalyticsOptions): Analytics;
159+
113160
// @public
114161
export function isSupported(): Promise<boolean>;
115162

packages-exp/analytics-exp/src/api.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import {
4848
setUserProperties as internalSetUserProperties,
4949
setAnalyticsCollectionEnabled as internalSetAnalyticsCollectionEnabled
5050
} from './functions';
51+
import { ERROR_FACTORY, AnalyticsError } from './errors';
5152

5253
export { settings } from './factory';
5354

@@ -95,9 +96,7 @@ export function initializeAnalytics(
9596
ANALYTICS_TYPE
9697
);
9798
if (analyticsProvider.isInitialized()) {
98-
return analyticsProvider.getImmediate();
99-
// TODO: Throw an analytics specific error.
100-
// _fail(analyticsInstance, AuthErrorCode.ALREADY_INITIALIZED);
99+
throw ERROR_FACTORY.create(AnalyticsError.ALREADY_INITIALIZED);
101100
}
102101
const analyticsInstance = analyticsProvider.getImmediate();
103102
// do init settings stuff here

packages-exp/analytics-exp/src/errors.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { ErrorFactory, ErrorMap } from '@firebase/util';
2020
export const enum AnalyticsError {
2121
ALREADY_EXISTS = 'already-exists',
2222
ALREADY_INITIALIZED = 'already-initialized',
23+
ALREADY_INITIALIZED_SETTINGS = 'already-initialized-settings',
2324
INTEROP_COMPONENT_REG_FAILED = 'interop-component-reg-failed',
2425
INVALID_ANALYTICS_CONTEXT = 'invalid-analytics-context',
2526
INDEXEDDB_UNAVAILABLE = 'indexeddb-unavailable',
@@ -35,6 +36,10 @@ const ERRORS: ErrorMap<AnalyticsError> = {
3536
' already exists. ' +
3637
'Only one Firebase Analytics instance can be created for each appId.',
3738
[AnalyticsError.ALREADY_INITIALIZED]:
39+
'Firebase Analytics has already been initialized. ' +
40+
'initializeAnalytics() must only be called once. getAnalytics() can be used ' +
41+
'to get a reference to the already-intialized instance.',
42+
[AnalyticsError.ALREADY_INITIALIZED_SETTINGS]:
3843
'Firebase Analytics has already been initialized.' +
3944
'settings() must be called before initializing any Analytics instance' +
4045
'or it will have no effect.',

packages-exp/analytics-exp/src/factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export function getGlobalVars(): {
136136
*/
137137
export function settings(options: SettingsOptions): void {
138138
if (globalInitDone) {
139-
throw ERROR_FACTORY.create(AnalyticsError.ALREADY_INITIALIZED);
139+
throw ERROR_FACTORY.create(AnalyticsError.ALREADY_INITIALIZED_SETTINGS);
140140
}
141141
if (options.dataLayerName) {
142142
dataLayerName = options.dataLayerName;

packages-exp/analytics-exp/src/public-types.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { FirebaseApp } from '@firebase/app-exp';
2020
/**
2121
* A set of common Analytics config settings recognized by
2222
* gtag.
23+
* @public
2324
*/
2425
export interface GtagConfigParams {
2526
'send_page_view'?: boolean;
@@ -41,6 +42,7 @@ export interface GtagConfigParams {
4142

4243
/**
4344
* Analytics initialization options.
45+
* @public
4446
*/
4547
export interface AnalyticsOptions {
4648
config: GtagConfigParams | EventParams;
@@ -49,6 +51,7 @@ export interface AnalyticsOptions {
4951
/**
5052
* Additional options that can be passed to Firebase Analytics method
5153
* calls such as `logEvent`, `setCurrentScreen`, etc.
54+
* @public
5255
*/
5356
export interface AnalyticsCallOptions {
5457
/**
@@ -58,6 +61,10 @@ export interface AnalyticsCallOptions {
5861
global: boolean;
5962
}
6063

64+
/**
65+
* An instance of Firebase Analytics.
66+
* @public
67+
*/
6168
export interface Analytics {
6269
/**
6370
* The FirebaseApp this Functions instance is associated with.
@@ -68,6 +75,7 @@ export interface Analytics {
6875
/**
6976
* Specifies custom options for your Firebase Analytics instance.
7077
* You must set these before initializing `firebase.analytics()`.
78+
* @public
7179
*/
7280
export interface SettingsOptions {
7381
/** Sets custom name for `gtag` function. */
@@ -78,13 +86,15 @@ export interface SettingsOptions {
7886

7987
/**
8088
* Any custom params the user may pass to gtag.js.
89+
* @public
8190
*/
8291
export interface CustomParams {
8392
[key: string]: unknown;
8493
}
8594
/**
8695
* Type for standard gtag.js event names. `logEvent` also accepts any
8796
* custom string and interprets it as a custom event name.
97+
* @public
8898
*/
8999
export type EventNameString =
90100
| 'add_payment_info'
@@ -115,9 +125,15 @@ export type EventNameString =
115125
| 'view_promotion'
116126
| 'view_search_results';
117127

128+
/**
129+
* @public
130+
*/
118131
export type Currency = string | number;
119132

120133
/* eslint-disable camelcase */
134+
/**
135+
* @public
136+
*/
121137
export interface Item {
122138
item_id?: string;
123139
item_name?: string;
@@ -151,7 +167,10 @@ export interface Item {
151167
name?: string;
152168
}
153169

154-
/** @deprecated Use Item instead. */
170+
/**
171+
* @deprecated Use Item instead.
172+
* @public
173+
*/
155174
export interface Promotion {
156175
creative_name?: string;
157176
creative_slot?: string;
@@ -164,6 +183,7 @@ export interface Promotion {
164183
* For more information, see
165184
* {@link https://developers.google.com/gtagjs/reference/parameter
166185
* | the gtag.js documentation on parameters}.
186+
* @public
167187
*/
168188
export interface ControlParams {
169189
groups?: string | string[];
@@ -177,6 +197,7 @@ export interface ControlParams {
177197
* For more information, see
178198
* {@link https://developers.google.com/gtagjs/reference/parameter
179199
* | the gtag.js documentation on parameters}.
200+
* @public
180201
*/
181202
export interface EventParams {
182203
checkout_option?: string;

packages-exp/analytics-exp/testing/integration-tests/integration.ts

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@
1717

1818
import { initializeApp, deleteApp, FirebaseApp } from '@firebase/app-exp';
1919
import '@firebase/installations-exp';
20-
import { getAnalytics, logEvent } from '../../src/index';
20+
import { getAnalytics, initializeAnalytics, logEvent } from '../../src/index';
2121
import '../setup';
2222
import { expect } from 'chai';
2323
import { stub } from 'sinon';
24+
import { AnalyticsError } from '../../src/errors';
2425

2526
let config: Record<string, string>;
2627
try {
@@ -36,36 +37,70 @@ const RETRY_INTERVAL = 1000;
3637

3738
describe('FirebaseAnalytics Integration Smoke Tests', () => {
3839
let app: FirebaseApp;
39-
afterEach(() => deleteApp(app));
40-
it('logEvent() sends correct network request.', async () => {
41-
app = initializeApp(config);
42-
logEvent(getAnalytics(app), 'login', { method: 'email' });
43-
async function checkForEventCalls(): Promise<number> {
44-
await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));
45-
const resources = performance.getEntriesByType('resource');
46-
const callsWithEvent = resources.filter(
47-
resource =>
48-
resource.name.includes('google-analytics.com') &&
49-
resource.name.includes('en=login')
50-
);
51-
if (callsWithEvent.length === 0) {
52-
return checkForEventCalls();
53-
} else {
54-
return callsWithEvent.length;
40+
describe('Using getAnalytics()', () => {
41+
afterEach(() => deleteApp(app));
42+
it('logEvent() sends correct network request.', async () => {
43+
app = initializeApp(config);
44+
logEvent(getAnalytics(app), 'login', { method: 'email' });
45+
async function checkForEventCalls(): Promise<number> {
46+
await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));
47+
const resources = performance.getEntriesByType('resource');
48+
const callsWithEvent = resources.filter(
49+
resource =>
50+
resource.name.includes('google-analytics.com') &&
51+
resource.name.includes('en=login')
52+
);
53+
if (callsWithEvent.length === 0) {
54+
return checkForEventCalls();
55+
} else {
56+
return callsWithEvent.length;
57+
}
5558
}
56-
}
57-
const eventCallCount = await checkForEventCalls();
58-
expect(eventCallCount).to.equal(1);
59+
const eventCallCount = await checkForEventCalls();
60+
expect(eventCallCount).to.equal(1);
61+
});
62+
it("Warns if measurement ID doesn't match.", done => {
63+
const warnStub = stub(console, 'warn').callsFake(() => {
64+
expect(warnStub.args[0][1]).to.include('does not match');
65+
done();
66+
});
67+
app = initializeApp({
68+
...config,
69+
measurementId: 'wrong-id'
70+
});
71+
getAnalytics(app);
72+
});
5973
});
60-
it("Warns if measurement ID doesn't match.", done => {
61-
const warnStub = stub(console, 'warn').callsFake(() => {
62-
expect(warnStub.args[0][1]).to.include('does not match');
63-
done();
74+
describe('Using initializeAnalytics()', () => {
75+
it('logEvent() sends correct network request.', async () => {
76+
app = initializeApp(config);
77+
logEvent(initializeAnalytics(app), 'login', { method: 'email' });
78+
async function checkForEventCalls(): Promise<number> {
79+
await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));
80+
const resources = performance.getEntriesByType('resource');
81+
const callsWithEvent = resources.filter(
82+
resource =>
83+
resource.name.includes('google-analytics.com') &&
84+
resource.name.includes('en=login')
85+
);
86+
if (callsWithEvent.length === 0) {
87+
return checkForEventCalls();
88+
} else {
89+
return callsWithEvent.length;
90+
}
91+
}
92+
const eventCallCount = await checkForEventCalls();
93+
expect(eventCallCount).to.equal(1);
94+
});
95+
it('getAnalytics() does not throw if called after initializeAnalytics().', async () => {
96+
const analyticsInstance = getAnalytics(app);
97+
expect(analyticsInstance.app).to.equal(app);
6498
});
65-
app = initializeApp({
66-
...config,
67-
measurementId: 'wrong-id'
99+
it('initializeAnalytics() throws if called more than once.', async () => {
100+
expect(() => initializeAnalytics(app)).to.throw(
101+
AnalyticsError.ALREADY_INITIALIZED
102+
);
103+
await deleteApp(app);
68104
});
69-
getAnalytics(app);
70105
});
71106
});

0 commit comments

Comments
 (0)