Skip to content

Commit 5cd0438

Browse files
feat: integration tests
1 parent ada9bd3 commit 5cd0438

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+4676
-1839
lines changed

integration_test/.env.example

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,9 @@ DATABASE_URL=
44
STORAGE_BUCKET=
55
NODE_VERSION=18
66
FIREBASE_ADMIN=^10.0.0
7-
GOOGLE_APPLICATION_CREDENTIALS=
7+
FIREBASE_APP_ID=
8+
FIREBASE_MEASUREMENT_ID=
9+
FIREBASE_AUTH_DOMAIN=
10+
FIREBASE_API_KEY=
11+
GOOGLE_APPLICATION_CREDENTIALS=./serviceAccount.json
12+
GOOGLE_ANALYTICS_API_SECRET=

integration_test/README.md

+17-7
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@
44

55
### Prerequisites
66

7-
Tests use locally installed firebase to invoke commands for deploying function.
8-
The test also requires that you have gcloud CLI installed and authenticated
7+
Tests use locally installed firebase to invoke commands for deploying functions.
8+
The tests also require that you have gcloud CLI installed and authenticated
99
(`gcloud auth login`).
1010

1111
Tests are deployed with a unique identifier, which enables the teardown of its own resources, without affecting other test runs.
1212

1313
1. Add a service account at root serviceAccount.json
1414
2. Add a .env `cp .env.example .env`
15+
3. Ensure service account has required roles for each cloud service
16+
4. Ensure any resources such as eventarc channel ("firebase" is used as default) are configured
1517

1618
### Running setup and tests
1719

18-
This will deploy functions with unique names, set up environment for running the
19-
jest files, and run the jest test suite.
20+
This will deploy functions with unique names, set up environment for running the jest files, and run the jest test suite.
2021

2122
```bash
2223
yarn start
@@ -26,7 +27,16 @@ yarn start
2627

2728
[x] Deploy functions with unique name
2829
[x] Update existing tests to use jest (v1 and v2)
29-
[] Add missing coverage for v1 and v2 (WIP)
30-
[] Ensure proper teardown of resources (only those for current test run)
30+
[x] Add missing coverage for v1 and v2 (WIP)
31+
[x] Ensure proper teardown of resources (only those for current test run)
32+
[] Check that we are properly tearing down all docs as side-effects
33+
[] Analytics: since you cannot directly trigger onLog events from Firebase Analytics in a CI environment, the primary strategy is to isolate and test the logic within the Cloud Functions by mocking Firebase services and the Analytics event data. This is done elsewhere via unit tests, so no additional coverage necessary.
34+
[] Alerts: same as analytics
35+
[] Auth blocking functions can only be deployed one at a time, half-way solution is to deploy v1 functions, run v1 tests, teardown, and repeat for v2. However, this still won't allow for multiple runs to happen in parallel. Solution needed before re-enabling auth/identity tests.
36+
[] Https tests were commented out previously, comments remain as before for same reasons
3137
[] Python runtime support
32-
[] Capture test outcome for use by CI
38+
39+
## Troubleshooting
40+
41+
- Sometimes I ran into this reported [issue](https://github.com/firebase/firebase-tools/issues/793), I had to give it some period of time and attempt deploy again. Probably an upstream issue but may affect our approach here. Seems to struggle with deploying the large amount of trigger functions...? Falls over on Firebase Storage functions (if you comment these out everything else deploys as expected).
42+
- Ensure service account has the necessary permissions for each service, and enable object versioning for the storage onArchive tests.
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,7 @@
1-
import * as admin from "firebase-admin";
21
import * as functions from "firebase-functions";
32
import { REGION } from "../region";
4-
import { sanitizeData } from "../utils";
53

64
export const analyticsEventTests: any = functions
75
.region(REGION)
86
.analytics.event("in_app_purchase")
9-
.onLog(async (event, context) => {
10-
const testId = event.params?.testId;
11-
try {
12-
await admin
13-
.firestore()
14-
.collection("analyticsEventTests")
15-
.doc(testId)
16-
.set(
17-
sanitizeData({
18-
...context,
19-
event: JSON.stringify(event),
20-
})
21-
);
22-
} catch (error) {
23-
console.error(`Error in Analytics event function for testId: ${testId}`, error);
24-
}
25-
});
7+
.onLog(async () => {});

integration_test/functions/src/v1/auth-tests.ts

+40-54
Original file line numberDiff line numberDiff line change
@@ -8,80 +8,66 @@ export const authUserOnCreateTests: any = functions
88
.auth.user()
99
.onCreate(async (user, context) => {
1010
const { email, displayName, uid } = user;
11-
try {
12-
const userProfile = {
13-
email,
14-
displayName,
15-
createdAt: admin.firestore.FieldValue.serverTimestamp(),
16-
};
17-
await admin.firestore().collection("userProfiles").doc(uid).set(userProfile);
11+
const userProfile = {
12+
email,
13+
displayName,
14+
createdAt: admin.firestore.FieldValue.serverTimestamp(),
15+
};
16+
await admin.firestore().collection("userProfiles").doc(uid).set(userProfile);
1817

19-
await admin
20-
.firestore()
21-
.collection("authUserOnCreateTests")
22-
.doc(uid)
23-
.set(
24-
sanitizeData({
25-
...context,
26-
metadata: JSON.stringify(user.metadata),
27-
})
28-
);
29-
} catch (error) {
30-
console.error(`Error in Auth user onCreate function for uid: ${uid}`, error);
31-
}
18+
await admin
19+
.firestore()
20+
.collection("authUserOnCreateTests")
21+
.doc(uid)
22+
.set(
23+
sanitizeData({
24+
...context,
25+
metadata: JSON.stringify(user.metadata),
26+
})
27+
);
3228
});
3329

3430
export const authUserOnDeleteTests: any = functions
3531
.region(REGION)
3632
.auth.user()
3733
.onDelete(async (user, context) => {
3834
const { uid } = user;
39-
try {
40-
await admin
41-
.firestore()
42-
.collection("authUserOnDeleteTests")
43-
.doc(uid)
44-
.set(
45-
sanitizeData({
46-
...context,
47-
metadata: JSON.stringify(user.metadata),
48-
})
49-
);
50-
} catch (error) {
51-
console.error(`Error in Auth user onDelete function for uid: ${uid}`, error);
52-
}
35+
await admin
36+
.firestore()
37+
.collection("authUserOnDeleteTests")
38+
.doc(uid)
39+
.set(
40+
sanitizeData({
41+
...context,
42+
metadata: JSON.stringify(user.metadata),
43+
})
44+
);
5345
});
5446

5547
export const authUserBeforeCreateTests: any = functions
5648
.region(REGION)
5749
.auth.user()
5850
.beforeCreate(async (user, context) => {
59-
const { uid } = user;
60-
try {
61-
await admin
62-
.firestore()
63-
.collection("authUserBeforeCreateTests")
64-
.doc(uid)
65-
.set(sanitizeData(context));
66-
} catch (error) {
67-
console.error(`Error in Auth user beforeCreate function for uid: ${uid}`, error);
68-
}
51+
await admin.firestore().collection("authBeforeCreateTests").doc(user.uid).set({
52+
eventId: context.eventId,
53+
eventType: context.eventType,
54+
timestamp: context.timestamp,
55+
resource: context.resource,
56+
});
57+
6958
return user;
7059
});
7160

7261
export const authUserBeforeSignInTests: any = functions
7362
.region(REGION)
7463
.auth.user()
7564
.beforeSignIn(async (user, context) => {
76-
const { uid } = user;
77-
try {
78-
await admin
79-
.firestore()
80-
.collection("authUserBeforeSignInTests")
81-
.doc(uid)
82-
.set(sanitizeData(context));
83-
} catch (error) {
84-
console.error(`Error in Auth user beforeSignIn function for uid: ${uid}`, error);
85-
}
65+
await admin.firestore().collection("authBeforeSignInTests").doc(user.uid).set({
66+
eventId: context.eventId,
67+
eventType: context.eventType,
68+
timestamp: context.timestamp,
69+
resource: context.resource,
70+
});
71+
8672
return user;
8773
});

integration_test/functions/src/v1/database-tests.ts

+42-56
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,16 @@ export const databaseRefOnCreateTests: any = functions
99
.onCreate(async (snapshot, context) => {
1010
const testId = context.params.testId;
1111

12-
try {
13-
await admin
14-
.firestore()
15-
.collection("databaseRefOnCreateTests")
16-
.doc(testId)
17-
.set(
18-
sanitizeData({
19-
...context,
20-
url: snapshot.ref.toString(),
21-
})
22-
);
23-
} catch (error) {
24-
console.error(`Error in Database ref onCreate function for testId: ${testId}`, error);
25-
}
12+
await admin
13+
.firestore()
14+
.collection("databaseRefOnCreateTests")
15+
.doc(testId)
16+
.set(
17+
sanitizeData({
18+
...context,
19+
url: snapshot.ref.toString(),
20+
})
21+
);
2622
});
2723

2824
export const databaseRefOnDeleteTests: any = functions
@@ -31,42 +27,36 @@ export const databaseRefOnDeleteTests: any = functions
3127
.onDelete(async (snapshot, context) => {
3228
const testId = context.params.testId;
3329

34-
try {
35-
await admin
36-
.firestore()
37-
.collection("databaseRefOnDeleteTests")
38-
.doc(testId)
39-
.set(
40-
sanitizeData({
41-
...context,
42-
url: snapshot.ref.toString(),
43-
})
44-
);
45-
} catch (error) {
46-
console.error(`Error in Database ref onDelete function for testId: ${testId}`, error);
47-
}
30+
await admin
31+
.firestore()
32+
.collection("databaseRefOnDeleteTests")
33+
.doc(testId)
34+
.set(
35+
sanitizeData({
36+
...context,
37+
url: snapshot.ref.toString(),
38+
})
39+
);
4840
});
4941

5042
export const databaseRefOnUpdateTests: any = functions
5143
.region(REGION)
5244
.database.ref("dbTests/{testId}/start")
5345
.onUpdate(async (change, context) => {
5446
const testId = context.params.testId;
47+
const data = change.after.val();
5548

56-
try {
57-
await admin
58-
.firestore()
59-
.collection("databaseRefOnUpdateTests")
60-
.doc(testId)
61-
.set(
62-
sanitizeData({
63-
...context,
64-
url: change.after.ref.toString(),
65-
})
66-
);
67-
} catch (error) {
68-
console.error(`Error in Database ref onUpdate function for testId: ${testId}`, error);
69-
}
49+
await admin
50+
.firestore()
51+
.collection("databaseRefOnUpdateTests")
52+
.doc(testId)
53+
.set(
54+
sanitizeData({
55+
...context,
56+
url: change.after.ref.toString(),
57+
data: data ? JSON.stringify(data) : null,
58+
})
59+
);
7060
});
7161

7262
export const databaseRefOnWriteTests: any = functions
@@ -79,18 +69,14 @@ export const databaseRefOnWriteTests: any = functions
7969
return;
8070
}
8171

82-
try {
83-
await admin
84-
.firestore()
85-
.collection("databaseRefOnWriteTests")
86-
.doc(testId)
87-
.set(
88-
sanitizeData({
89-
...context,
90-
url: change.after.ref.toString(),
91-
})
92-
);
93-
} catch (error) {
94-
console.error(`Error in Database ref onWrite function for testId: ${testId}`, error);
95-
}
72+
await admin
73+
.firestore()
74+
.collection("databaseRefOnWriteTests")
75+
.doc(testId)
76+
.set(
77+
sanitizeData({
78+
...context,
79+
url: change.after.ref.toString(),
80+
})
81+
);
9682
});

0 commit comments

Comments
 (0)