Skip to content

Commit 9844cfd

Browse files
committed
scheduler & tasks tests
1 parent 2da70db commit 9844cfd

28 files changed

+743
-152
lines changed

integration_test/functions/package-lock.json

Lines changed: 410 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

integration_test/functions/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
"main": "lib/index.js",
1616
"dependencies": {
1717
"@google-cloud/pubsub": "^5.2.0",
18+
"@google-cloud/scheduler": "^5.3.1",
19+
"@google-cloud/tasks": "^6.2.1",
1820
"firebase": "^12.6.0",
1921
"firebase-admin": "^12.6.0",
2022
"firebase-functions": "file:firebase-functions-local.tgz",
File renamed without changes.

integration_test/functions/src/assertions/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@ export function expectCloudEvent(data: any) {
88
expect(data.source).toBeDefined();
99
assertType<string>(data.source);
1010
expect(data.source.length).toBeGreaterThan(0);
11-
expect(data.subject).toBeDefined();
12-
assertType<string>(data.subject);
13-
expect(data.subject.length).toBeGreaterThan(0);
11+
12+
// Subject is optional (e.g. pubsub)
13+
if ("subject" in data) {
14+
expect(data.subject).toBeDefined();
15+
assertType<string>(data.subject);
16+
expect(data.subject.length).toBeGreaterThan(0);
17+
}
18+
1419
expect(data.type).toBeDefined();
1520
assertType<string>(data.type);
1621
expect(data.type.length).toBeGreaterThan(0);
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
import { initializeApp } from "firebase/app";
2-
import { getAuth } from "firebase/auth";
3-
import { getFunctions } from "firebase/functions";
4-
5-
export const app = initializeApp({
1+
export const config = {
62
apiKey: "AIzaSyBBt77mpu6TV0IA2tcNSyf4OltsVu_Z1Zw",
73
authDomain: "cf3-integration-tests-v2-qa.firebaseapp.com",
84
databaseURL: "https://cf3-integration-tests-v2-qa-default-rtdb.firebaseio.com",
95
projectId: "cf3-integration-tests-v2-qa",
106
storageBucket: "cf3-integration-tests-v2-qa.firebasestorage.app",
117
messagingSenderId: "576826020291",
12-
appId: "1:576826020291:web:488d568c5d4109df12ed76",
13-
});
14-
15-
export const auth = getAuth(app);
16-
export const functions = getFunctions(app);
8+
appId: "1:576826020291:web:488d568c5d4109df12ed76"
9+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { initializeApp } from "firebase/app";
2+
import { getAuth } from "firebase/auth";
3+
import { getFunctions } from "firebase/functions";
4+
import { config } from "./config";
5+
6+
export const app = initializeApp(config);
7+
export const auth = getAuth(app);
8+
export const functions = getFunctions(app);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import admin from "firebase-admin";
2+
import { GoogleAuth } from "google-auth-library";
3+
import { applicationDefault } from "firebase-admin/app";
4+
import { getFunctions } from "firebase-admin/functions";
5+
import { getDatabase } from "firebase-admin/database";
6+
import { getAuth } from "firebase-admin/auth";
7+
import { getRemoteConfig } from "firebase-admin/remote-config";
8+
import { getFirestore } from "firebase-admin/firestore";
9+
import { config } from "./config";
10+
11+
export const app = admin.initializeApp({
12+
credential: applicationDefault(),
13+
projectId: config.projectId,
14+
databaseURL: config.databaseURL,
15+
});
16+
17+
export const firestore = getFirestore(app);
18+
firestore.settings({ ignoreUndefinedProperties: true });
19+
export const database = getDatabase(app);
20+
export const auth = getAuth(app);
21+
export const remoteConfig = getRemoteConfig(app);
22+
export const functions = getFunctions(app);
23+
24+
// See https://github.com/firebase/functions-samples/blob/a6ae4cbd3cf2fff3e2b97538081140ad9befd5d8/Node/taskqueues-backup-images/functions/index.js#L111-L128
25+
export async function getFunctionUrl(name: string) {
26+
const auth = new GoogleAuth({
27+
projectId: config.projectId,
28+
});
29+
30+
const url = `https://cloudfunctions.googleapis.com/v2beta/projects/${config.projectId}/locations/us-central1/functions/${name}`;
31+
const client = await auth.getClient();
32+
const res: any = await client.request({ url });
33+
const uri = res.data?.serviceConfig?.uri;
34+
35+
if (!uri) {
36+
throw new Error(`Function ${name} not found`);
37+
}
38+
39+
return uri;
40+
}
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
export * from "./firestore.v2";
2-
export * from "./database.v2";
3-
export * from "./eventarc.v2";
4-
export * from "./auth.v2";
5-
export * from "./https.v2";
1+
export * from "./v2/database.v2";
2+
export * from "./v2/eventarc.v2";
3+
export * from "./v2/firestore.v2";
4+
export * from "./v2/https.v2";
5+
export * from "./v2/identity.v2";
6+
export * from "./v2/pubsub.v2";
7+
export * from "./v2/remoteConfig.v2";
8+
export * from "./v2/scheduler.v2";
9+
export * from "./v2/tasks.v2";
File renamed without changes.
Lines changed: 1 addition & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,4 @@
1-
import admin from "firebase-admin";
2-
import { GeoPoint } from "firebase-admin/firestore";
3-
import { logger } from "firebase-functions";
4-
5-
const adminApp = admin.initializeApp({
6-
projectId: "cf3-integration-tests-v2-qa",
7-
databaseURL: "https://cf3-integration-tests-v2-qa-default-rtdb.firebaseio.com",
8-
9-
});
10-
export const firestore = adminApp.firestore();
11-
firestore.settings({ ignoreUndefinedProperties: true });
12-
export const database = adminApp.database();
13-
export const auth = adminApp.auth();
1+
import { firestore } from "./firebase.server";
142

153
export const RUN_ID = String(process.env.RUN_ID);
164

@@ -60,98 +48,3 @@ export function waitForEvent<T = unknown>(
6048
.catch(reject);
6149
});
6250
}
63-
64-
export function serializeData(data: any): any {
65-
if (data === null || data === undefined) {
66-
return null;
67-
}
68-
69-
if (typeof data === "function") {
70-
logger.debug("serializeData function", data);
71-
const result = serializeData(data());
72-
logger.debug("serializeData function result", result);
73-
return result;
74-
}
75-
76-
// Handle Date objects
77-
if (data instanceof Date) {
78-
return data.toISOString();
79-
}
80-
81-
if (data instanceof GeoPoint) {
82-
return {
83-
_type: "geopoint",
84-
latitude: data.latitude,
85-
longitude: data.longitude,
86-
};
87-
}
88-
89-
// Handle Firestore DocumentReference (check for path, id, and firestore properties)
90-
if (
91-
data &&
92-
typeof data === "object" &&
93-
"path" in data &&
94-
"id" in data &&
95-
"firestore" in data &&
96-
typeof (data as any).path === "string"
97-
) {
98-
const ref = data as { path: string; id: string };
99-
// Only serialize if path is non-empty to avoid the error
100-
if (ref.path) {
101-
return {
102-
_type: "reference",
103-
path: ref.path,
104-
id: ref.id,
105-
};
106-
} else {
107-
// If path is empty, return a safe representation
108-
logger.warn("DocumentReference with empty path detected", { id: ref.id });
109-
return {
110-
_type: "reference",
111-
path: "",
112-
id: ref.id || "",
113-
};
114-
}
115-
}
116-
117-
// Handle Firestore Timestamp (check for toDate method and seconds property)
118-
if (
119-
data &&
120-
typeof data === "object" &&
121-
"toDate" in data &&
122-
typeof (data as any).toDate === "function"
123-
) {
124-
const timestamp = data as { toDate: () => Date; seconds?: number; nanoseconds?: number };
125-
return {
126-
_type: "timestamp",
127-
seconds: timestamp.seconds,
128-
nanoseconds: timestamp.nanoseconds,
129-
iso: timestamp.toDate().toISOString(),
130-
};
131-
}
132-
133-
// Handle Firestore GeoPoint (check for latitude and longitude properties)
134-
if (data && typeof data === "object" && "latitude" in data && "longitude" in data) {
135-
const geoPoint = data as { latitude: number; longitude: number };
136-
return {
137-
_type: "geopoint",
138-
latitude: geoPoint.latitude,
139-
longitude: geoPoint.longitude,
140-
};
141-
}
142-
143-
// Handle arrays (must check before plain objects since arrays are objects)
144-
if (Array.isArray(data)) {
145-
return data.map(serializeData);
146-
}
147-
148-
if (typeof data === "object") {
149-
const result: Record<string, unknown> = {};
150-
for (const [key, value] of Object.entries(data)) {
151-
result[key] = serializeData(value);
152-
}
153-
return result;
154-
}
155-
156-
return data;
157-
}

0 commit comments

Comments
 (0)