Skip to content

Commit

Permalink
Implement useEmulator for Firestore (#3909)
Browse files Browse the repository at this point in the history
  • Loading branch information
samtstern authored Oct 16, 2020
1 parent 8939aec commit 79b0493
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 3 deletions.
7 changes: 7 additions & 0 deletions .changeset/short-icons-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'firebase': minor
'@firebase/firestore': minor
'@firebase/firestore-types': minor
---

Add a useEmulator(host, port) method to Firestore
10 changes: 10 additions & 0 deletions packages/firebase/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8030,6 +8030,16 @@ declare namespace firebase.firestore {
*/
settings(settings: Settings): void;

/**
* Modify this instance to communicate with the Cloud Firestore emulator.
*
* <p>Note: this must be called before this instance has been used to do any operations.
*
* @param host the emulator host (ex: localhost).
* @param port the emulator port (ex: 9000).
*/
useEmulator(host: string, port: number): void;

/**
* Attempts to enable persistent storage, if possible.
*
Expand Down
2 changes: 2 additions & 0 deletions packages/firestore-types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export class FirebaseFirestore {

settings(settings: Settings): void;

useEmulator(host: string, port: number): void;

enablePersistence(settings?: PersistenceSettings): Promise<void>;

collection(collectionPath: string): CollectionReference<DocumentData>;
Expand Down
4 changes: 4 additions & 0 deletions packages/firestore/exp/test/shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ export class FirebaseFirestore
initializeFirestore(this.app._delegate, settings);
}

useEmulator(host: string, port: number): void {
this.settings({ host: `${host}:${port}`, ssl: false, merge: true });
}

enablePersistence(settings?: legacy.PersistenceSettings): Promise<void> {
return settings?.synchronizeTabs
? enableMultiTabIndexedDbPersistence(this._delegate)
Expand Down
25 changes: 23 additions & 2 deletions packages/firestore/src/api/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ import {
valueDescription,
validateIsNotUsedTogether
} from '../util/input_validation';
import { logError, setLogLevel as setClientLogLevel } from '../util/log';
import {
setLogLevel as setClientLogLevel,
logWarn
} from '../util/log';
import { AutoId } from '../util/misc';
import { Deferred } from '../util/promise';
import { FieldPath as ExternalFieldPath } from './field_path';
Expand Down Expand Up @@ -503,7 +506,7 @@ export class Firestore implements PublicFirestore, FirebaseService {
throw new FirestoreError(
Code.FAILED_PRECONDITION,
'Firestore has already been started and its settings can no longer ' +
'be changed. You can only call settings() before calling any other ' +
'be changed. You can only modify settings before calling any other ' +
'methods on a Firestore object.'
);
}
Expand All @@ -514,6 +517,24 @@ export class Firestore implements PublicFirestore, FirebaseService {
}
}

useEmulator(host: string, port: number): void {
validateExactNumberOfArgs('Firestore.useEmulator', arguments, 2);
validateArgType('Firestore.useEmulator', 'string', 1, host);
validateArgType('Firestore.useEmulator', 'number', 2, port);

if (this._settings.host !== DEFAULT_HOST) {
logWarn(
'Host has been set in both settings() and useEmulator(), emulator host will be used'
);
}

this.settings({
host: `${host}:${port}`,
ssl: false,
merge: true
});
}

enableNetwork(): Promise<void> {
this.ensureClientConfigured();
return this._firestoreClient!.enableNetwork();
Expand Down
20 changes: 19 additions & 1 deletion packages/firestore/test/integration/api/validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ apiDescribe('Validation:', (persistence: boolean) => {
'getFirestore()';
} else {
errorMsg +=
'You can only call settings() before calling any other ' +
'You can only modify settings before calling any other ' +
'methods on a Firestore object.';
}

Expand All @@ -182,6 +182,24 @@ apiDescribe('Validation:', (persistence: boolean) => {
// Verify that this doesn't throw.
db.settings({ cacheSizeBytes: /* CACHE_SIZE_UNLIMITED= */ -1 });
});

validationIt(persistence, 'useEmulator can set host and port', () => {
const db = newTestFirestore('test-project');
// Verify that this doesn't throw.
db.useEmulator('localhost', 9000);
});

validationIt(
persistence,
'disallows calling useEmulator after use',
async db => {
const errorMsg =
'Firestore has already been started and its settings can no longer be changed.';

await db.doc('foo/bar').set({});
expect(() => db.useEmulator('localhost', 9000)).to.throw(errorMsg);
}
);
});

describe('Firestore', () => {
Expand Down
19 changes: 19 additions & 0 deletions packages/firestore/test/unit/api/database.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,23 @@ describe('Settings', () => {
expect(firestoreClient._getSettings().ignoreUndefinedProperties).to.be.true;
expect(firestoreClient._getSettings().host).to.equal('other.host');
});

it('gets settings from useEmulator', () => {
// Use a new instance of Firestore in order to configure settings.
const firestoreClient = newTestFirestore();
firestoreClient.useEmulator('localhost', 9000);

expect(firestoreClient._getSettings().host).to.equal('localhost:9000');
expect(firestoreClient._getSettings().ssl).to.be.false;
});

it('prefers host from useEmulator to host from settings', () => {
// Use a new instance of Firestore in order to configure settings.
const firestoreClient = newTestFirestore();
firestoreClient.settings({ host: 'other.host' });
firestoreClient.useEmulator('localhost', 9000);

expect(firestoreClient._getSettings().host).to.equal('localhost:9000');
expect(firestoreClient._getSettings().ssl).to.be.false;
});
});

0 comments on commit 79b0493

Please sign in to comment.