I'm attempting to connect to the firebase emulator within an integration test, using the new AngularFire API (>v7)
import {
TestBed
} from '@angular/core/testing';
import {
initializeApp,
provideFirebaseApp
} from '@angular/fire/app';
import {
doc,
enableIndexedDbPersistence,
Firestore,
getFirestore,
provideFirestore,
setDoc
} from '@angular/fire/firestore';
import {
connectFirestoreEmulator
} from "firebase/firestore";
describe('FirestoreEmulatorSmoketest', () => {
let projectId: string;
let firestore: Firestore;
beforeAll(() => {
const testConfig = {
projectId,
auth: ...
};
TestBed.configureTestingModule({
imports: [
provideFirebaseApp(() => initializeApp(testConfig)),
provideFirestore(() => {
const firestore = getFirestore();
connectFirestoreEmulator(firestore, 'localhost', 8080);
enableIndexedDbPersistence(firestore);
return firestore;
}),
],
})
});
beforeEach(() => {})
afterAll(() => {})
it('should connect', () => {
const fooDoc = doc(firestore, "foo/12345");
return setDoc(fooDoc, {
updated: new Date()
})
})
});
This code produces the following error "AngularFireModule has not been provided"
I can only assume I'm not initialising angular fire somehow?
First of all, my native language is not English, so if I write like a fool you know why.
Try this.
environment.ts
export const environment = {
production: false,
useEmulators: true,
firebaseConfig: {
apiKey: 'YOUR-API-KEY',
authDomain: 'YOUR-AUTH-DOMAIN',
projectId: 'YOUR-PROJECT-ID',
storageBucket: 'YPUR-STORAGE-BUCKET',
messagingSenderId: 'YOUR-MESSAGING-SENDER-ID',
appId: 'YOUR-APP-ID',
measurementId: 'YOUR-MEASUREMENT-ID',
},
};
Important: As you can see I have the variable useEmulators, which in the following lines I will explain what it is going to be used for.
app.module.ts
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { getAuth, provideAuth, connectAuthEmulator } from '@angular/fire/auth';
import { getFirestore, provideFirestore, connectFirestoreEmulator, enableIndexedDbPersistence } from '@angular/fire/firestore';
import { getStorage, provideStorage, connectStorageEmulator } from '@angular/fire/storage';
import { getAnalytics, provideAnalytics } from '@angular/fire/analytics';
import { getFunctions, provideFunctions, connectFunctionsEmulator} from '@angular/fire/functions';
import { environment } from 'environments/environment'; // <--- Environment variables.
imports: [
// Firebase
provideFirebaseApp(() => initializeApp(environment.firebaseConfig)),
provideFirestore(() => {
if (environment.useEmulators) {
const firestore = getFirestore();
connectFirestoreEmulator(firestore, 'localhost', 8080);
enableIndexedDbPersistence(firestore);
return firestore;
} else {
getFirestore();
}
}),
provideAuth(() => {
if (environment.useEmulators) {
const fireauth = getAuth();
connectAuthEmulator(fireauth, 'http://localhost:9099'); // <---FireAuth Port
return fireauth;
} else {
getAuth();
}
}),
provideStorage(() => {
if (environment.useEmulators) {
const firestorage = getStorage();
connectStorageEmulator(firestorage, 'localhost', 9199); // <---- Firestorage Port
return firestorage;
} else {
getStorage();
}
}),
provideFunctions(() => {
if (environment.useEmulators) {
const firefunctions = getFunctions();
connectFunctionsEmulator(firefunctions, 'localhost', 5001); // <--- FireFunctions Port
return firefunctions;
} else {
getFunctions();
}
}),
provideAnalytics(() => getAnalytics()),
],
Important (Environment Path): Change the environment path of the variables in case you don't have them in the default location.
Important (Local Ports): In case you use different local ports than the default ones, change them.
As you can see I have added code to the initializations to be able to switch between the emulated project and the online project, in a simple way:
useEmulators: true // We load the emulator environment
useEmulators: false // We load the production environment
_fireAuth.service.ts
import { Auth } from '@angular/fire/auth';
constructor(private _fireAuth: Auth) {}
_fireStorage.service.ts
import { Storage } from '@angular/fire/storage';
constructor(private _fireStorage: Storage) {}
_fireStore.service.ts
import { Firestore } from '@angular/fire/firestore';
constructor(private _fireStore: Firestore) {}
It only remains to import the functions you are going to use, e.g. { doc, Collection, etc... }.
Use the documentation provided by Google to see how they changed the functions: https://firebase.google.com/docs/build and use the code found in the "Web version 9 (modular)" tab.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With