Skip to content

Commit 4b55572

Browse files
authored
Firestore: Add isEqual() and port DocumentReference array test. (#222)
* Ports the test for the fix I made for Android for DocumentReference objects in arrays (bug not present in Web). * Implements isEqual() on Query and DocumentReference
1 parent 646dbb2 commit 4b55572

File tree

7 files changed

+123
-15
lines changed

7 files changed

+123
-15
lines changed

packages/firebase/app/index.d.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,14 @@ declare namespace firebase.firestore {
969969
*/
970970
collection(collectionPath: string): CollectionReference;
971971

972+
/**
973+
* Returns true if this `DocumentReference` is equal to the provided one.
974+
*
975+
* @param other The `DocumentReference` to compare against.
976+
* @return true if this `DocumentReference` is equal to the provided one.
977+
*/
978+
isEqual(other: DocumentReference): boolean;
979+
972980
/**
973981
* Writes to the document referred to by this `DocumentReference`. If the
974982
* document does not yet exist, it will be created. If you pass
@@ -1308,6 +1316,14 @@ declare namespace firebase.firestore {
13081316
*/
13091317
endAt(...fieldValues: any[]): Query;
13101318

1319+
/**
1320+
* Returns true if this `Query` is equal to the provided one.
1321+
*
1322+
* @param other The `Query` to compare against.
1323+
* @return true if this `Query` is equal to the provided one.
1324+
*/
1325+
isEqual(other: Query): boolean;
1326+
13111327
/**
13121328
* Executes the query and returns the results as a QuerySnapshot.
13131329
*

packages/firebase/index.d.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,14 @@ declare namespace firebase.firestore {
969969
*/
970970
collection(collectionPath: string): CollectionReference;
971971

972+
/**
973+
* Returns true if this `DocumentReference` is equal to the provided one.
974+
*
975+
* @param other The `DocumentReference` to compare against.
976+
* @return true if this `DocumentReference` is equal to the provided one.
977+
*/
978+
isEqual(other: DocumentReference): boolean;
979+
972980
/**
973981
* Writes to the document referred to by this `DocumentReference`. If the
974982
* document does not yet exist, it will be created. If you pass
@@ -1308,6 +1316,14 @@ declare namespace firebase.firestore {
13081316
*/
13091317
endAt(...fieldValues: any[]): Query;
13101318

1319+
/**
1320+
* Returns true if this `Query` is equal to the provided one.
1321+
*
1322+
* @param other The `Query` to compare against.
1323+
* @return true if this `Query` is equal to the provided one.
1324+
*/
1325+
isEqual(other: Query): boolean;
1326+
13111327
/**
13121328
* Executes the query and returns the results as a QuerySnapshot.
13131329
*

packages/firestore/src/api/database.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,13 @@ export class DocumentReference implements firestore.DocumentReference {
742742
return new CollectionReference(this._key.path.child(path), this.firestore);
743743
}
744744

745+
isEqual(other: firestore.DocumentReference): boolean {
746+
if (!(other instanceof DocumentReference)) {
747+
throw invalidClassError('isEqual', 'DocumentReference', 1, other);
748+
}
749+
return this.firestore === other.firestore && this._key.equals(other._key);
750+
}
751+
745752
set(
746753
value: firestore.DocumentData,
747754
options?: firestore.SetOptions
@@ -1240,6 +1247,15 @@ export class Query implements firestore.Query {
12401247
return new Query(this._query.withEndAt(bound), this.firestore);
12411248
}
12421249

1250+
isEqual(other: firestore.Query): boolean {
1251+
if (!(other instanceof Query)) {
1252+
throw invalidClassError('isEqual', 'Query', 1, other);
1253+
}
1254+
return (
1255+
this.firestore === other.firestore && this._query.equals(other._query)
1256+
);
1257+
}
1258+
12431259
/** Helper function to create a bound from a document or fields */
12441260
private boundFromDocOrFields(
12451261
methodName: string,

packages/firestore/src/typings/firestore.d.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,14 @@ declare namespace firestore {
403403
*/
404404
collection(collectionPath: string): CollectionReference;
405405

406+
/**
407+
* Returns true if this `DocumentReference` is equal to the provided one.
408+
*
409+
* @param other The `DocumentReference` to compare against.
410+
* @return true if this `DocumentReference` is equal to the provided one.
411+
*/
412+
isEqual(other: DocumentReference): boolean;
413+
406414
/**
407415
* Writes to the document referred to by this `DocumentReference`. If the
408416
* document does not yet exist, it will be created. If you pass
@@ -742,6 +750,14 @@ declare namespace firestore {
742750
*/
743751
endAt(...fieldValues: any[]): Query;
744752

753+
/**
754+
* Returns true if this `Query` is equal to the provided one.
755+
*
756+
* @param other The `Query` to compare against.
757+
* @return true if this `Query` is equal to the provided one.
758+
*/
759+
isEqual(other: Query): boolean;
760+
745761
/**
746762
* Executes the query and returns the results as a QuerySnapshot.
747763
*

packages/firestore/test/integration/api/database.test.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,20 +468,66 @@ apiDescribe('Database', persistence => {
468468
});
469469
});
470470

471-
asyncIt('exposes "database" on document references.', () => {
471+
asyncIt('exposes "firestore" on document references.', () => {
472472
return withTestDb(persistence, db => {
473473
expect(db.doc('foo/bar').firestore).to.equal(db);
474474
return Promise.resolve();
475475
});
476476
});
477477

478-
asyncIt('exposes "database" on query references.', () => {
478+
asyncIt('exposes "firestore" on query references.', () => {
479479
return withTestDb(persistence, db => {
480480
expect(db.collection('foo').limit(5).firestore).to.equal(db);
481481
return Promise.resolve();
482482
});
483483
});
484484

485+
asyncIt('can compare DocumentReference instances with isEqual().', () => {
486+
return withTestDb(persistence, firestore => {
487+
return withTestDb(persistence, otherFirestore => {
488+
const docRef = firestore.doc('foo/bar');
489+
expect(docRef.isEqual(firestore.doc('foo/bar'))).to.be.true;
490+
expect(docRef.collection('baz').parent.isEqual(docRef)).to.be.true;
491+
492+
expect(firestore.doc('foo/BAR').isEqual(docRef)).to.be.false;
493+
494+
expect(otherFirestore.doc('foo/bar').isEqual(docRef)).to.be.false;
495+
496+
return Promise.resolve();
497+
});
498+
});
499+
});
500+
501+
asyncIt('can compare Query instances with isEqual().', () => {
502+
return withTestDb(persistence, firestore => {
503+
return withTestDb(persistence, otherFirestore => {
504+
const query = firestore
505+
.collection('foo')
506+
.orderBy('bar')
507+
.where('baz', '==', 42);
508+
const query2 = firestore
509+
.collection('foo')
510+
.orderBy('bar')
511+
.where('baz', '==', 42);
512+
expect(query.isEqual(query2)).to.be.true;
513+
514+
const query3 = firestore
515+
.collection('foo')
516+
.orderBy('BAR')
517+
.where('baz', '==', 42);
518+
expect(query.isEqual(query3)).to.be.false;
519+
520+
const query4 = otherFirestore
521+
.collection('foo')
522+
.orderBy('bar')
523+
.where('baz', '==', 42);
524+
expect(query4.isEqual(query)).to.be.false;
525+
526+
return Promise.resolve();
527+
});
528+
});
529+
});
530+
485531
asyncIt('can traverse collections and documents.', () => {
486532
return withTestDb(persistence, db => {
487533
const expected = 'a/b/c/d';

packages/firestore/test/integration/api/type.test.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,20 +93,14 @@ apiDescribe('Firestore', persistence => {
9393
});
9494

9595
asyncIt('can read and write document references', () => {
96-
// TODO(b/62143881): Implement DocumentReference.equals() so we can use
97-
// expectRoundtrip()
9896
return withTestDoc(persistence, doc => {
99-
return doc
100-
.set({ a: 42, ref: doc })
101-
.then(() => {
102-
return doc.get();
103-
})
104-
.then(docSnap => {
105-
expect(docSnap.exists).to.equal(true);
106-
expect(docSnap.get('a')).to.equal(42);
107-
const readDocRef = docSnap.get('ref') as firestore.DocumentReference;
108-
expect(readDocRef.path).to.equal(doc.path);
109-
});
97+
return expectRoundtrip(doc.firestore, { a: 42, ref: doc });
98+
});
99+
});
100+
101+
asyncIt('can read and write document references in an array', () => {
102+
return withTestDoc(persistence, doc => {
103+
return expectRoundtrip(doc.firestore, { a: 42, refs: [doc] });
110104
});
111105
});
112106
});

packages/firestore/test/util/equality_matcher.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ function customDeepEqual(left, right) {
2727
/**
2828
* START: Custom compare logic
2929
*/
30+
// Internally we use .equals(), but our public API uses .isEqual() so
31+
// we handle both.
3032
if (left && typeof left.equals === 'function') return left.equals(right);
33+
if (left && typeof left.isEqual === 'function') return left.isEqual(right);
3134
if (right && typeof right.equals === 'function') return right.equals(left);
35+
if (right && typeof right.isEqual === 'function') return right.isEqual(left);
3236
/**
3337
* END: Custom compare logic
3438
*/

0 commit comments

Comments
 (0)