Update simple HTTP testing to explain emulator interactions
See: https://github.com/firebase/firebase-tools/issues/3098#issuecomment-771981685
@samtstern maybe you could help me out here -- I've accomplished setting up http testing:
const { expect } = require('chai');
const axios = require('axios');
const qs = require('qs');
const admin = require('firebase-admin');
const test = require('firebase-functions-test')({
projectId: process.env.GCLOUD_PROJECT,
});
const axiosConfig = (functionName, data) => {
return {
method: 'post',
url: `http://localhost:5001/${process.env.GCLOUD_PROJECT}/us-central1/${functionName}`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
data,
};
};
describe('Unit tests', () => {
after(() => {
test.cleanup();
});
it('tests a new deployment', async () => {
const data = qs.stringify({
payload:
'{"status": "started", "branch": "feature-fix", "env": "hotfix-2", "app": "enroll", "user_name": "kvootla", "org": "maine", "repo": "enroll", "commit_sha": "abc1234" }',
});
const config = axiosConfig('branchDeployment', data);
let responsePayload;
try {
// Make the http request
responsePayload = await axios(config);
} catch (e) {
console.log('ERROR:', e);
}
// Wait for the promise to be resolved and then check the sent text
expect(responsePayload.data).to.deep.eq({
status: 'started',
branch: 'feature-fix',
env: 'hotfix-2',
app: 'enroll',
user_name: 'kvootla',
org: 'maine',
repo: 'enroll',
commit_sha: 'abc1234',
});
}).timeout(5000);
});
This works when run with firebase emulators:exec --project=fakeproject \"npm run test\"
However, as soon as I also try to check that a value was set in Firestore, e.g. adding this just below the payload assertion:
const envSnap = await admin
.firestore()
.collection('orgs')
.doc('maine')
.collection('environments')
.doc('hotfix-2')
.get();
expect(envSnap.data()).to.eql({
status: 'started',
branch: 'feature-fix',
env: 'hotfix-2',
app: 'enroll',
user_name: 'kvootla',
org: 'maine',
repo: 'enroll',
commit_sha: 'abc1234',
});
I get the following error:
Error: The default Firebase app does not exist. Make sure you call initializeApp() before using any of the Firebase services.
at FirebaseAppError.FirebaseError [as constructor] (node_modules\firebase-admin\lib\utils\error.js:44:28)
at FirebaseAppError.PrefixedFirebaseError [as constructor] (node_modules\firebase-admin\lib\utils\error.js:90:28)
at new FirebaseAppError (node_modules\firebase-admin\lib\utils\error.js:125:28)
at FirebaseNamespaceInternals.app (node_modules\firebase-admin\lib\firebase-namespace.js:101:19)
at FirebaseNamespace.app (node_modules\firebase-admin\lib\firebase-namespace.js:430:30)
at FirebaseNamespace.ensureApp (node_modules\firebase-admin\lib\firebase-namespace.js:444:24)
at FirebaseNamespace.fn (node_modules\firebase-admin\lib\firebase-namespace.js:304:30)
at Context.<anonymous> (test\functions.spec.js:54:8)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
@markgoho that error message is correct, you have not called admin.initializeApp() anywhere so you can't use admin.firestore() to perform actions.
Also make sure you have FIRESTORE_EMULATOR_HOST set correctly in your environment or the Admin SDK will attempt to talk to prod. If you're running your tests through firebase emulators:exec this is handled for you.
thank you so much @samtstern that did solve this issue!
does your functions.spec.js file in this repo get the intializeApp() call from https://github.com/firebase/quickstart-testing/blob/master/unit-test-cloud-functions/functions/test/functions.spec.js#L15 where you require the index.js file?
it seems like I'll need two separate spec files:
- one where I'm manually calling initializeApp because I'm not importing my functions index
- one where I'm importing my functions index and letting it call initializeApp
@markgoho that's a great point and I hadn't thought about it! Yes we're somewhat accidentally inheriting the app initialization from the wrapped functions themselves since they're running inside the same process rather than being accessed over the network.