Skip to content

Commit

Permalink
fix: provide custom error for FieldValue subclasses (#771)
Browse files Browse the repository at this point in the history
This PR extends the custom errors for instances of FieldValue classes that do not match the expected prototype to the FieldValue sentinel classes FieldTransform, ServerTimestampTransform, ArrayUnionTransform, ArrayRemoveTransform and NumericIncrementTransform.

Fixes #760
  • Loading branch information
schmidt-sebastian committed Oct 3, 2019
1 parent 39adabb commit 29c3e9b
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
21 changes: 20 additions & 1 deletion dev/src/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ export interface NumericRangeOptions {
maxValue?: number;
}

/**
* Returns the name of the base class (ignoring Object).
*
* @private
* @param value The object whose base class name to extract.
* @returns The name of the base class constructor or "Object" if value does not
* extend a custom class.
*/
function extractBaseClassName(value: object): string {
let constructorName = 'Object';
while (Object.getPrototypeOf(value) !== Object.prototype) {
value = Object.getPrototypeOf(value);
constructorName = value.constructor.name;
}
return constructorName;
}
/**
* Generates an error message to use with custom objects that cannot be
* serialized.
Expand All @@ -54,7 +70,10 @@ export function customObjectMessage(
const fieldPathMessage = path ? ` (found in field ${path})` : '';

if (isObject(value)) {
const typeName = value.constructor.name;
// We use the base class name as the type name as the sentinel classes
// returned by the public FieldValue API are subclasses of FieldValue. By
// using the base name, we reduce the number of special cases below.
const typeName = extractBaseClassName(value);
switch (typeName) {
case 'DocumentReference':
case 'FieldPath':
Expand Down
23 changes: 23 additions & 0 deletions dev/test/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,29 @@ describe('serialize document', () => {
);
});

it('provides custom error for objects from different Firestore instance', () => {
class FieldPath {}
class CustomFieldPath extends FieldPath {}
class VeryCustomFieldPath extends CustomFieldPath {}

const customClasses = [
new FieldPath(),
new CustomFieldPath(),
new VeryCustomFieldPath(),
];

for (const customClass of customClasses) {
expect(() => {
firestore
.doc('collectionId/documentId')
.set(customClass as InvalidApiUsage);
}).to.throw(
'Value for argument "data" is not a valid Firestore document. ' +
'Detected an object of type "FieldPath" that doesn\'t match the expected instance.'
);
}
});

it('serializes large numbers into doubles', () => {
const overrides: ApiOverride = {
commit: (request, options, callback) => {
Expand Down

0 comments on commit 29c3e9b

Please sign in to comment.