Skip to content

Commit 436c724

Browse files
committed
feat: Add Integration tests CI
1 parent 1ed8fee commit 436c724

19 files changed

+174
-1419
lines changed

Diff for: .github/workflows/ci.yaml

+23
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ on:
77
- main
88

99
jobs:
10+
integration-tests:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
fail-fast: false
14+
matrix:
15+
python: ["3.10", "3.12"]
16+
steps:
17+
- uses: actions/checkout@v3
18+
- name: Set up Python ${{ matrix.python }}
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: ${{ matrix.python }}
22+
- name: Setup Node 18
23+
uses: actions/setup-node@v3
24+
with:
25+
node-version: 18
26+
- name: Install Node dependencies
27+
run: |
28+
cd integration_tests && npm install
29+
- name: Run Integration Tests
30+
run: |
31+
cd integration_tests && npm start
32+
1033
test:
1134
runs-on: ubuntu-latest
1235
strategy:

Diff for: .gitignore

-3
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,3 @@ doc/dist
139139
.idea
140140
.vscode/*
141141
!.vscode/settings.json
142-
integration_tests/serviceAccount.json
143-
integration_tests/functions/firebase_functions_*.tar.gz
144-
integration_tests/functions/requirements.txt

Diff for: integration_tests/.env.example

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ REGION=us-central1
22
PROJECT_ID=
33
DATABASE_URL=
44
STORAGE_BUCKET=
5-
NODE_VERSION=18
6-
FIREBASE_ADMIN=^10.0.0
5+
FIREBASE_ADMIN=6.5.0
76
FIREBASE_APP_ID=
87
FIREBASE_MEASUREMENT_ID=
98
FIREBASE_AUTH_DOMAIN=

Diff for: integration_tests/.gitignore

+5-1
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,8 @@ node_modules/
6363
.yarn-integrity
6464

6565
# dotenv environment variables file
66-
.env
66+
.env
67+
/functions/functions.yaml
68+
/serviceAccount.json
69+
/functions/requirements.txt
70+
/functions/firebase_functions.tar.gz

Diff for: integration_tests/functions/main.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
# Welcome to Cloud Functions for Firebase for Python!
2-
# To get started, simply uncomment the below code or create your own.
3-
# Deploy with `firebase deploy`
4-
51
from firebase_admin import initialize_app
2+
from v2.firestore_tests import *
63

74
initialize_app()

Diff for: integration_tests/functions/v2/firestore_tests.py

+49-37
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,67 @@
11
from firebase_admin import firestore
22
from firebase_functions import firestore_fn, logger
3-
from integration_tests.functions.region import REGION
3+
from region import REGION
44

55

6-
@firestore_fn.on_document_created(document='tests/{documentId}', region=REGION, timeout_sec=540)
7-
def firestoreOnDocumentCreatedTests(event: firestore_fn.Event[firestore_fn.DocumentSnapshot]):
8-
logger.debug(event=event)
6+
@firestore_fn.on_document_created(document='tests/{documentId}',
7+
region=REGION,
8+
timeout_sec=540)
9+
def firestoreOnDocumentCreatedTests(
10+
event: firestore_fn.Event[firestore_fn.DocumentSnapshot]):
911
documentId = event.params['documentId']
1012

11-
firestore.client().collection('firestoreOnDocumentCreatedTests').document(documentId).set({
12-
'time': event.time,
13-
'id': event.id,
14-
'type': event.type,
15-
'source': event.source,
16-
})
13+
firestore.client().collection('firestoreOnDocumentCreatedTests').document(
14+
documentId).set({
15+
'time': event.time,
16+
'id': event.id,
17+
'type': event.type,
18+
'source': event.source,
19+
})
1720

1821

19-
@firestore_fn.on_document_deleted(document='tests/{documentId}', region=REGION, timeout_sec=540)
20-
def firestoreOnDocumentDeletedTests(event: firestore_fn.Event[firestore_fn.DocumentSnapshot]):
21-
logger.debug(event=event)
22+
@firestore_fn.on_document_deleted(document='tests/{documentId}',
23+
region=REGION,
24+
timeout_sec=540)
25+
def firestoreOnDocumentDeletedTests(
26+
event: firestore_fn.Event[firestore_fn.DocumentSnapshot]):
2227
documentId = event.params['documentId']
2328

24-
firestore.client().collection('firestoreOnDocumentDeletedTests').document(documentId).set({
25-
'time': event.time,
26-
'id': event.id,
27-
'type': event.type,
28-
'source': event.source,
29-
})
29+
firestore.client().collection('firestoreOnDocumentDeletedTests').document(
30+
documentId).set({
31+
'time': event.time,
32+
'id': event.id,
33+
'type': event.type,
34+
'source': event.source,
35+
})
3036

3137

32-
@firestore_fn.on_document_updated(document='tests/{documentId}', region=REGION, timeout_sec=540)
33-
def firestoreOnDocumentUpdatedTests(event: firestore_fn.Event[firestore_fn.DocumentSnapshot]):
34-
logger.debug(event=event)
38+
@firestore_fn.on_document_updated(document='tests/{documentId}',
39+
region=REGION,
40+
timeout_sec=540)
41+
def firestoreOnDocumentUpdatedTests(
42+
event: firestore_fn.Event[firestore_fn.DocumentSnapshot]):
3543
documentId = event.params['documentId']
3644

37-
firestore.client().collection('firestoreOnDocumentUpdatedTests').document(documentId).set({
38-
'time': event.time,
39-
'id': event.id,
40-
'type': event.type,
41-
'source': event.source,
42-
})
45+
firestore.client().collection('firestoreOnDocumentUpdatedTests').document(
46+
documentId).set({
47+
'time': event.time,
48+
'id': event.id,
49+
'type': event.type,
50+
'source': event.source,
51+
})
4352

4453

45-
@firestore_fn.on_document_written(document='tests/{documentId}', region=REGION, timeout_sec=540)
46-
def firestoreOnDocumentWrittenTests(event: firestore_fn.Event[firestore_fn.DocumentSnapshot]):
47-
logger.debug(event=event)
54+
@firestore_fn.on_document_written(document='tests/{documentId}',
55+
region=REGION,
56+
timeout_sec=540)
57+
def firestoreOnDocumentWrittenTests(
58+
event: firestore_fn.Event[firestore_fn.DocumentSnapshot]):
4859
documentId = event.params['documentId']
4960

50-
firestore.client().collection('firestoreOnDocumentWrittenTests').document(documentId).set({
51-
'time': event.time,
52-
'id': event.id,
53-
'type': event.type,
54-
'source': event.source,
55-
})
61+
firestore.client().collection('firestoreOnDocumentWrittenTests').document(
62+
documentId).set({
63+
'time': event.time,
64+
'id': event.id,
65+
'type': event.type,
66+
'source': event.source,
67+
})

Diff for: integration_tests/package-lock.json

+20-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: integration_tests/package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@
1414
"scripts": {
1515
"copyfiles": "cp ./serviceAccount.json ./dist/serviceAccount.json",
1616
"build": "tsc && npm run copyfiles",
17-
"test": "jest --detectOpenHandles",
17+
"test": "jest --detectOpenHandles tests/v2/firestore.test.ts",
1818
"start": "npm run build && node dist/run.js"
1919
},
2020
"devDependencies": {
2121
"@types/firebase": "^3.2.1",
22-
"@types/jest": "^29.5.11",
22+
"@types/jest": "^29.5.12",
2323
"@types/js-yaml": "^4.0.9",
2424
"@types/node-fetch": "2",
2525
"jest": "^29.7.0",
26+
"prettier": "^3.3.3",
2627
"ts-jest": "^29.1.1"
2728
}
2829
}

Diff for: integration_tests/run.ts

+23-6
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,12 @@ async function discoverAndModifyEndpoints() {
9999
const killServer = await delegate.serveAdmin(port.toString(), {}, env);
100100

101101
console.log("Started on port", port);
102-
const originalYaml = await detectFromPort(port, config.projectId, config.runtime, 10000);
102+
const originalYaml = await detectFromPort(
103+
port,
104+
config.projectId,
105+
config.runtime,
106+
10000
107+
);
103108

104109
modifiedYaml = {
105110
...originalYaml,
@@ -206,7 +211,11 @@ function cleanFiles(): void {
206211
process.chdir("../"); // go back to integration_test
207212
}
208213

209-
const spawnAsync = (command: string, args: string[], options: any): Promise<string> => {
214+
const spawnAsync = (
215+
command: string,
216+
args: string[],
217+
options: any
218+
): Promise<string> => {
210219
return new Promise((resolve, reject) => {
211220
const child = spawn(command, args, options);
212221

@@ -231,19 +240,23 @@ const spawnAsync = (command: string, args: string[], options: any): Promise<stri
231240

232241
async function runTests(): Promise<void> {
233242
try {
234-
console.log("Starting Node.js Tests...");
243+
console.log("Starting Python Tests...");
235244
const output = await spawnAsync("npm", ["test"], {
236245
env: {
237246
...process.env,
238-
GOOGLE_APPLICATION_CREDENTIALS: path.join(__dirname, "serviceAccount.json"),
247+
GOOGLE_APPLICATION_CREDENTIALS: path.join(
248+
__dirname,
249+
"serviceAccount.json"
250+
),
239251
TEST_RUN_ID,
240252
},
241253
stdio: "inherit",
242254
});
243255
console.log(output);
244-
console.log("Node.js Tests Completed.");
256+
console.log("Python Tests Completed.");
245257
} catch (error) {
246258
console.error("Error during testing:", error);
259+
throw error;
247260
}
248261
}
249262

@@ -272,6 +285,7 @@ async function runIntegrationTests(): Promise<void> {
272285
await runTests();
273286
} catch (err) {
274287
console.error("Error occurred during integration tests", err);
288+
throw new Error("Integration tests failed");
275289
} finally {
276290
await handleCleanUp();
277291
}
@@ -282,4 +296,7 @@ runIntegrationTests()
282296
console.log("Integration tests completed");
283297
process.exit(0);
284298
})
285-
.catch((error) => console.error("An error occurred during integration tests", error));
299+
.catch((error) => {
300+
console.error("An error occurred during integration tests", error);
301+
process.exit(1);
302+
});

Diff for: integration_tests/setup.ts

+17-8
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,21 @@ function buildSdk(testRunId: string) {
1818
process.chdir(path.join(DIR, "..")); // go up to root
1919

2020
// remove existing build
21-
fs.rmdirSync("dist", { recursive: true });
21+
fs.rmSync("dist", { recursive: true, force: true });
22+
// remove existing venv
23+
fs.rmSync("venv", { recursive: true, force: true });
24+
25+
// make virtual environment for building
26+
execSync("python3 -m venv venv", { stdio: "inherit" });
2227

2328
// build the package
24-
execSync("python -m pip install --upgrade build", { stdio: "inherit" });
25-
execSync("python -m build -s", { stdio: "inherit" });
29+
execSync(
30+
"source venv/bin/activate && python -m pip install --upgrade build",
31+
{ stdio: "inherit" },
32+
);
33+
execSync("source venv/bin/activate && python -m build -s", {
34+
stdio: "inherit",
35+
});
2636

2737
// move the generated tarball package to functions
2838
const generatedFile = fs
@@ -33,7 +43,7 @@ function buildSdk(testRunId: string) {
3343
const targetPath = path.join(
3444
"integration_tests",
3545
"functions",
36-
`firebase_functions_${testRunId}.tar.gz`
46+
`firebase_functions.tar.gz`,
3747
);
3848
fs.renameSync(path.join("dist", generatedFile), targetPath);
3949
console.log("SDK moved to", targetPath);
@@ -52,11 +62,11 @@ function createRequirementsTxt(testRunId: string, firebaseAdmin: string) {
5262
let requirementsContent = fs.readFileSync(requirementsPath, "utf8");
5363
requirementsContent = requirementsContent.replace(
5464
/__LOCAL_FIREBASE_FUNCTIONS__/g,
55-
`firebase_functions_${testRunId}.tar.gz`
65+
`firebase_functions.tar.gz`,
5666
);
5767
requirementsContent = requirementsContent.replace(
5868
/__FIREBASE_ADMIN__/g,
59-
firebaseAdmin
69+
firebaseAdmin,
6070
);
6171

6272
fs.writeFileSync(requirementsPath, requirementsContent);
@@ -73,7 +83,6 @@ function installDependencies() {
7383
}
7484

7585
execSync("python3 -m venv venv", { stdio: "inherit" });
76-
execSync("source venv/bin/activate", { stdio: "inherit" });
77-
execSync("python3 -m pip install -r requirements.txt", { stdio: "inherit" });
86+
execSync("source venv/bin/activate && python3 -m pip install -r requirements.txt", { stdio: "inherit" });
7887
process.chdir("../"); // go back to integration_test
7988
}

0 commit comments

Comments
 (0)