Open PedroReyes opened 1 year ago
😊
😬
@PedroReyes - I am expecting the same behaviour. Did you managed to solve this issue?
Hello @lpotapczuk ,
I gave up trying to use this firebase suite.
What I did as a solution:
I will show here one of my "subtests" of a test suite for the user profile updates test so you can take it directly. Once you understand this one you can simply expand it to your needs.
// https://firebase.google.com/docs/firestore/security/test-rules-emulator
import "mocha";
import assert = require("assert");
import admin = require("firebase-admin");
import { initAdminApp } from "../../utils/setup";
import { createRandomFirestoreUser, wait } from "../../utils/utils";
import { FIRESTORE, STORAGE } from "../../../src/shared/utils/setup";
import { StorageMetadata } from "../../../src/shared/types/storage";
import { FirebaseUser } from "../../../src/shared/types/users";
initAdminApp();
/**
* 📘 This test mainly checks that firestore document timestamp is updated whenever
* an update happens in the storage document. This is very helpful to know when
* the storage document was updated for the last time and for updating in real time
* the frontend. We "monitor" the firestore document that matches the storage document
* and we can react to changes in real time in the frontend.
*/
describe(`📖 Firestore user updates`, () => {
let userForDeletion: FirebaseUser;
let userForUpdates: FirebaseUser;
const WAITING_TIME = 5000;
before(async () => {
// Create user in firestore to be able to trigger the function for deletion
userForDeletion = await createRandomFirestoreUser(admin);
// Create user in firestore to be able to trigger the function for updates
userForUpdates = await createRandomFirestoreUser(admin);
// Wait for trigger function to complete
await wait(WAITING_TIME);
});
it(`should create ${STORAGE.USERS_DOC_PATH} 🟩 if it doesn't exist`, async () => {
try {
// Get current date in firestore
(
await admin.firestore().doc(FIRESTORE.STORAGE(STORAGE.USERS_DOC_PATH)).get()
).data() as StorageMetadata;
assert.fail("Should not be any document");
} catch (e) {
assert.ok(true);
}
// Create random number
await createRandomFirestoreUser(admin);
// Wait for trigger function to complete
await wait(WAITING_TIME);
// Get current date in firestore
const metadataFileAfter: StorageMetadata = (
await admin.firestore().doc(FIRESTORE.STORAGE(STORAGE.USERS_DOC_PATH)).get()
).data() as StorageMetadata;
assert.ok(metadataFileAfter?.generation !== undefined);
});
});
As you can see I init the admin firebase with a function:
/**
* Initializes the admin app and sets environment variables for
* development environment.
*
* You will have to set this at the beginning of the test in case of having problems with
* environment credentials to setup the admin app.
*/
export async function initAdminApp() {
// Using admin SDK to connect to firestore emulator in local tests - https://github.com/firebase/firebase-admin-node/issues/776#issuecomment-1129048690
// Set this environment variables if we are in a development environment
process.env["FUNCTIONS_EMULATOR"] = "true";
process.env["FIRESTORE_EMULATOR_HOST"] = "localhost:8080";
process.env["FIREBASE_STORAGE_EMULATOR_HOST"] = "localhost:9199";
if (admin.apps.length === 0) {
logInfo("🤖 Initializing admin app 🔁");
admin.initializeApp({
projectId: `${PROJECT_ID}`,
storageBucket: `${STORAGE_BUCKET_NAME}`,
});
logInfo("🤖 Admin app initialized ✅");
} else {
logInfo("🤖 Admin app already initialized 🆗");
}
}
My "wait" time function is something simple:
/**
* The `wait` function is an asynchronous function that waits for a specified delay before resolving.
* @param [delay=1000] - The `delay` parameter is the amount of time in milliseconds that the function
* should wait before resolving the promise. By default, it is set to 1000 milliseconds (1 second).
*/
export async function wait(delay = 1000) {
await new Promise((resolve: any) => setTimeout(resolve, delay));
}
And here are the function for creating random users:
/**
* The function creates a random Firebase user object with a unique ID, display name, email, and
* default user role.
* @returns a new FirebaseUser object with randomly generated values for uid, displayName, email, and
* roles.
*/
export function createRandomFirebaseUser(): FirebaseUser {
const randomNumber: number = Math.floor(Math.random() * 1000000000000000);
// Create new FirebaseUser object
const newUser: FirebaseUser = {
uid: `${randomNumber}_Uid`,
displayName: `${randomNumber}_DisplayName`,
email: `${randomNumber}_Email`,
photoURL: `${randomNumber}_PhotoURL`,
};
return newUser;
}
/**
* The function creates a random user and saves it to a Firestore database.
* @returns a `FirebaseUser` object.
*/
export async function createRandomFirestoreUser(firebaseAdmin: any) {
const newUser: FirebaseUser = createRandomFirebaseUser();
// Create new user
if (newUser) {
await firebaseAdmin.firestore().doc(FIRESTORE.USERS(newUser.uid)).set(newUser);
}
return newUser;
}
This is my command script from package json to run the triggers in my CI/CD for example:
- run: npm ci && npm run build && firebase emulators:exec 'npm run test:triggers'
The command npm run test:triggers
is a package.json script command, the next one:
"test:triggers": "node --experimental-vm-modules --dns-result-order=ipv4first node_modules/mocha/bin/_mocha --timeout 40000 --reporter spec --require ts-node/register ./test/triggers/**/*.test.ts",
I'd say that's all you need to make my code yours.
Best regards, Pedro Reyes.
@PedroReyes thank you!
Moment after I've posted the message, I've found the solution to our problem in another thread:
https://github.com/firebase/firebase-functions-test/issues/205
Basically, the solution was to modify:
await wrapped(change);
to
await wrapped({ data: change, params: {...} });
@lpotapczuk thank you!
I'll give it a try as soon as I can ✌️
Hello
Version info
Test case
I have a trigger function that updates the storage. I simplified the function to this:
❌ Problem 1: In the console I get always the same random data that I don't know where is coming from instead of the data I provided. This is the result:
❌ Problem 2: I don't find the way to wait for the function to update the storage (either using firebase emulator preferably or a new "testing project" in Firebase)
Steps to reproduce
This is the code for the testing file:
Expected behavior
I would expect to receive in my firebase function the data I have passed which is:
Actual behavior
I am getting this random data coming from nowhere when calling
makeDocumentSnapshot
,makeChange
,wrap
methods from firebase-function-testing:Right now I am using
mocha
for the testing and directly a firebase project instead of the emulator so I am running the test either with:or this:
Thanks in advance for your help, Pedro Reyes.