Skip to content

Commit 60e9f4a

Browse files
Make Serializer tests work in browser, remove test duplication (#2757)
1 parent a5d80d9 commit 60e9f4a

File tree

5 files changed

+91
-221
lines changed

5 files changed

+91
-221
lines changed

packages/firestore/src/util/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function isNullOrUndefined(value: unknown): boolean {
2828
}
2929

3030
/** Returns whether the value represents -0. */
31-
export function isNegativeZero(value: number) : boolean {
31+
export function isNegativeZero(value: number): boolean {
3232
// Detect if the value is -0.0. Based on polyfill from
3333
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
3434
return value === -0 && 1 / value === 1 / -0;

packages/firestore/test/unit/model/field_value.test.ts

Lines changed: 0 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -37,145 +37,6 @@ describe('FieldValue', () => {
3737
const date1 = new Date(2016, 4, 2, 1, 5);
3838
const date2 = new Date(2016, 5, 20, 10, 20, 30);
3939

40-
it('can parse integers', () => {
41-
const primitiveValues = [
42-
Number.MIN_SAFE_INTEGER,
43-
-1,
44-
0,
45-
1,
46-
2,
47-
Number.MAX_SAFE_INTEGER
48-
];
49-
const values = primitiveValues.map(v => wrap(v));
50-
51-
values.forEach(v => {
52-
expect(v).to.be.an.instanceof(fieldValue.IntegerValue);
53-
});
54-
55-
for (let i = 0; i < primitiveValues.length; i++) {
56-
const primitiveValue = primitiveValues[i];
57-
const value = values[i];
58-
expect(value.value()).to.equal(primitiveValue);
59-
}
60-
});
61-
62-
it('can parse doubles', () => {
63-
const primitiveValues = [
64-
Number.MIN_SAFE_INTEGER - 1,
65-
-1.1,
66-
0.1,
67-
Number.MAX_SAFE_INTEGER + 1,
68-
NaN,
69-
Infinity,
70-
-Infinity
71-
];
72-
const values = primitiveValues.map(v =>
73-
wrap(v)
74-
) as fieldValue.NumberValue[];
75-
76-
values.forEach(v => {
77-
expect(v).to.be.an.instanceof(fieldValue.DoubleValue);
78-
});
79-
80-
for (let i = 0; i < primitiveValues.length; i++) {
81-
const primitiveValue = primitiveValues[i];
82-
const value = values[i];
83-
if (isNaN(primitiveValue)) {
84-
expect(isNaN(value.value())).to.equal(isNaN(primitiveValue));
85-
} else {
86-
expect(value.value()).to.equal(primitiveValue);
87-
}
88-
}
89-
});
90-
91-
it('can parse null', () => {
92-
const nullValue = wrap(null);
93-
94-
expect(nullValue).to.be.an.instanceof(fieldValue.NullValue);
95-
expect(nullValue.value()).to.equal(null);
96-
97-
// check for identity for interning
98-
expect(nullValue).to.equal(wrap(null));
99-
});
100-
101-
it('can parse booleans', () => {
102-
const trueValue = wrap(true);
103-
const falseValue = wrap(false);
104-
105-
expect(trueValue).to.be.an.instanceof(fieldValue.BooleanValue);
106-
expect(falseValue).to.be.an.instanceof(fieldValue.BooleanValue);
107-
108-
expect(trueValue.value()).to.equal(true);
109-
expect(falseValue.value()).to.equal(false);
110-
111-
// check for identity for interning
112-
expect(trueValue).to.equal(wrap(true));
113-
expect(falseValue).to.equal(wrap(false));
114-
});
115-
116-
it('can parse dates', () => {
117-
const dateValue1 = wrap(date1);
118-
const dateValue2 = wrap(date2);
119-
120-
expect(dateValue1).to.be.an.instanceof(fieldValue.TimestampValue);
121-
expect(dateValue2).to.be.an.instanceof(fieldValue.TimestampValue);
122-
123-
expect(dateValue1.value()).to.deep.equal(Timestamp.fromDate(date1));
124-
expect(dateValue2.value()).to.deep.equal(Timestamp.fromDate(date2));
125-
});
126-
127-
it('can parse geo points', () => {
128-
const latLong1 = new GeoPoint(1.23, 4.56);
129-
const latLong2 = new GeoPoint(-20, 100);
130-
const value1 = wrap(latLong1) as fieldValue.GeoPointValue;
131-
const value2 = wrap(latLong2) as fieldValue.GeoPointValue;
132-
133-
expect(value1).to.be.an.instanceof(fieldValue.GeoPointValue);
134-
expect(value2).to.be.an.instanceof(fieldValue.GeoPointValue);
135-
136-
expect(value1.value().latitude).to.equal(1.23);
137-
expect(value1.value().longitude).to.equal(4.56);
138-
expect(value2.value().latitude).to.equal(-20);
139-
expect(value2.value().longitude).to.equal(100);
140-
});
141-
142-
it('can parse bytes', () => {
143-
const bytesValue = wrap(blob(0, 1, 2)) as fieldValue.BlobValue;
144-
145-
expect(bytesValue).to.be.an.instanceof(fieldValue.BlobValue);
146-
expect(bytesValue.value().toUint8Array()).to.deep.equal(
147-
new Uint8Array([0, 1, 2])
148-
);
149-
});
150-
151-
it('can parse simple objects', () => {
152-
const objValue = wrap({ a: 'foo', b: 1, c: true, d: null });
153-
154-
expect(objValue).to.be.an.instanceof(fieldValue.ObjectValue);
155-
expect(objValue.value()).to.deep.equal({
156-
a: 'foo',
157-
b: 1,
158-
c: true,
159-
d: null
160-
});
161-
});
162-
163-
it('can parse nested objects', () => {
164-
const objValue = wrap({ foo: { bar: 1, baz: [1, 2, { a: 'b' }] } });
165-
166-
expect(objValue).to.be.an.instanceof(fieldValue.ObjectValue);
167-
expect(objValue.value()).to.deep.equal({
168-
foo: { bar: 1, baz: [1, 2, { a: 'b' }] }
169-
});
170-
});
171-
172-
it('can parse empty objects', () => {
173-
const objValue = wrap({ foo: {} });
174-
175-
expect(objValue).to.be.an.instanceof(fieldValue.ObjectValue);
176-
expect(objValue.value()).to.deep.equal({ foo: {} });
177-
});
178-
17940
it('can extract fields', () => {
18041
const objValue = wrapObject({ foo: { a: 1, b: true, c: 'string' } });
18142

packages/firestore/test/unit/remote/node/serializer.test.ts renamed to packages/firestore/test/unit/remote/serializer.test.ts

Lines changed: 41 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,12 @@
1616
*/
1717

1818
import { expect } from 'chai';
19-
import * as Long from 'long';
20-
import * as ProtobufJS from 'protobufjs';
21-
22-
import { Blob } from '../../../../src/api/blob';
23-
import { PublicFieldValue as FieldValue } from '../../../../src/api/field_value';
24-
import { GeoPoint } from '../../../../src/api/geo_point';
25-
import { Timestamp } from '../../../../src/api/timestamp';
26-
import { DatabaseId } from '../../../../src/core/database_info';
19+
20+
import { Blob } from '../../../src/api/blob';
21+
import { PublicFieldValue as FieldValue } from '../../../src/api/field_value';
22+
import { GeoPoint } from '../../../src/api/geo_point';
23+
import { Timestamp } from '../../../src/api/timestamp';
24+
import { DatabaseId } from '../../../src/core/database_info';
2725
import {
2826
ArrayContainsAnyFilter,
2927
ArrayContainsFilter,
@@ -34,35 +32,30 @@ import {
3432
Operator,
3533
OrderBy,
3634
Query
37-
} from '../../../../src/core/query';
38-
import { SnapshotVersion } from '../../../../src/core/snapshot_version';
39-
import { Target } from '../../../../src/core/target';
40-
import { TargetData, TargetPurpose } from '../../../../src/local/target_data';
41-
import * as fieldValue from '../../../../src/model/field_value';
35+
} from '../../../src/core/query';
36+
import { SnapshotVersion } from '../../../src/core/snapshot_version';
37+
import { Target } from '../../../src/core/target';
38+
import { TargetData, TargetPurpose } from '../../../src/local/target_data';
39+
import * as fieldValue from '../../../src/model/field_value';
4240
import {
4341
DeleteMutation,
4442
FieldMask,
4543
Mutation,
4644
Precondition,
4745
SetMutation,
4846
VerifyMutation
49-
} from '../../../../src/model/mutation';
50-
import { DOCUMENT_KEY_NAME, FieldPath } from '../../../../src/model/path';
51-
import {
52-
loadRawProtos,
53-
protoLoaderOptions
54-
} from '../../../../src/platform_node/load_protos';
55-
import * as api from '../../../../src/protos/firestore_proto_api';
56-
import { JsonProtoSerializer } from '../../../../src/remote/serializer';
47+
} from '../../../src/model/mutation';
48+
import { DOCUMENT_KEY_NAME, FieldPath } from '../../../src/model/path';
49+
import * as api from '../../../src/protos/firestore_proto_api';
50+
import { JsonProtoSerializer } from '../../../src/remote/serializer';
5751
import {
5852
DocumentWatchChange,
5953
WatchTargetChange,
6054
WatchTargetChangeState
61-
} from '../../../../src/remote/watch_change';
62-
import { Code, FirestoreError } from '../../../../src/util/error';
63-
import { Indexable } from '../../../../src/util/misc';
64-
import * as obj from '../../../../src/util/obj';
65-
import { addEqualityMatcher } from '../../../util/equality_matcher';
55+
} from '../../../src/remote/watch_change';
56+
import { Code, FirestoreError } from '../../../src/util/error';
57+
import * as obj from '../../../src/util/obj';
58+
import { addEqualityMatcher } from '../../util/equality_matcher';
6659
import {
6760
bound,
6861
byteStringFromString,
@@ -82,24 +75,26 @@ import {
8275
version,
8376
wrap,
8477
wrapObject
85-
} from '../../../util/helpers';
86-
import { ByteString } from '../../../../src/util/byte_string';
78+
} from '../../util/helpers';
79+
import { ByteString } from '../../../src/util/byte_string';
80+
import { isNode } from '../../util/test_platform';
81+
82+
let verifyProtobufJsRoundTrip: (jsonValue: api.Value) => void = () => {};
83+
84+
if (isNode()) {
85+
// Note: We cannot use dynamic imports since our Node build uses CJS as its
86+
// module syntax.
87+
// eslint-disable-next-line @typescript-eslint/no-require-imports
88+
verifyProtobufJsRoundTrip = require('../../util/node_helpers')
89+
.verifyProtobufJsRoundTrip;
90+
}
8791

8892
describe('Serializer', () => {
8993
const partition = new DatabaseId('p', 'd');
9094
const s = new JsonProtoSerializer(partition, { useProto3Json: false });
9195
const proto3JsonSerializer = new JsonProtoSerializer(partition, {
9296
useProto3Json: true
9397
});
94-
const protos = loadRawProtos();
95-
96-
// tslint:disable:variable-name
97-
const ValueMessage = protos.lookupType('google.firestore.v1.Value');
98-
const LatLngMessage = protos.lookupType('google.type.LatLng');
99-
const TimestampMessage = protos.lookupType('google.protobuf.Timestamp');
100-
const ArrayValueMessage = protos.lookupType('google.firestore.v1.ArrayValue');
101-
const MapValueMessage = protos.lookupType('google.firestore.v1.MapValue');
102-
// tslint:enable:variable-name
10398

10499
/**
105100
* Wraps the given target in TargetData. This is useful because the APIs we're
@@ -126,24 +121,13 @@ describe('Serializer', () => {
126121
valueType: string;
127122
/** The expected JSON value for the field (e.g. 'NULL_VALUE') */
128123
jsonValue: unknown;
129-
/**
130-
* The expected protobufJs value for the field (e.g. `0`). This is
131-
* largely inconsequential (we only rely on the JSON representation), but
132-
* it can be useful for debugging issues. If omitted, it's assumed to be
133-
* the same as jsonValue.
134-
*/
135-
protobufJsValue?: unknown;
136124
/**
137125
* If true, uses the proto3Json serializer (and skips the round-trip
138126
* through protobufJs).
139127
*/
140128
useProto3Json?: boolean;
141129
}): void {
142130
const { value, valueType, jsonValue } = opts;
143-
const protobufJsValue =
144-
opts.protobufJsValue !== undefined
145-
? opts.protobufJsValue
146-
: opts.jsonValue;
147131
const serializer = opts.useProto3Json ? proto3JsonSerializer : s;
148132

149133
// Convert FieldValue to JSON and verify.
@@ -152,20 +136,7 @@ describe('Serializer', () => {
152136

153137
// If we're using protobufJs JSON (not Proto3Json), then round-trip through protobufjs.
154138
if (!opts.useProto3Json) {
155-
// Convert JSON to protobufjs and verify value.
156-
const actualProtobufjsProto: ProtobufJS.Message = ValueMessage.fromObject(
157-
actualJsonProto
158-
);
159-
expect(
160-
((actualProtobufjsProto as unknown) as Indexable)[valueType]
161-
).to.deep.equal(protobufJsValue);
162-
163-
// Convert protobufjs back to JSON.
164-
const returnJsonProto = ValueMessage.toObject(
165-
actualProtobufjsProto,
166-
protoLoaderOptions
167-
);
168-
expect(returnJsonProto).to.deep.equal(actualJsonProto);
139+
verifyProtobufJsRoundTrip(actualJsonProto);
169140
}
170141

171142
// Convert JSON back to FieldValue.
@@ -177,8 +148,7 @@ describe('Serializer', () => {
177148
verifyFieldValueRoundTrip({
178149
value: fieldValue.NullValue.INSTANCE,
179150
valueType: 'nullValue',
180-
jsonValue: 'NULL_VALUE',
181-
protobufJsValue: 0
151+
jsonValue: 'NULL_VALUE'
182152
});
183153
});
184154

@@ -207,11 +177,7 @@ describe('Serializer', () => {
207177
verifyFieldValueRoundTrip({
208178
value: new fieldValue.IntegerValue(example),
209179
valueType: 'integerValue',
210-
jsonValue: '' + example,
211-
protobufJsValue: Long.fromString(
212-
example.toString(),
213-
/*unsigned=*/ false
214-
)
180+
jsonValue: '' + example
215181
});
216182
}
217183
});
@@ -271,8 +237,7 @@ describe('Serializer', () => {
271237
verifyFieldValueRoundTrip({
272238
value: new fieldValue.TimestampValue(Timestamp.fromDate(examples[i])),
273239
valueType: 'timestampValue',
274-
jsonValue: expectedJson[i],
275-
protobufJsValue: TimestampMessage.fromObject(expectedJson[i])
240+
jsonValue: expectedJson[i]
276241
});
277242
}
278243
});
@@ -345,8 +310,7 @@ describe('Serializer', () => {
345310
verifyFieldValueRoundTrip({
346311
value: new fieldValue.GeoPointValue(example),
347312
valueType: 'geoPointValue',
348-
jsonValue: expected,
349-
protobufJsValue: LatLngMessage.fromObject(expected)
313+
jsonValue: expected
350314
});
351315
});
352316

@@ -380,26 +344,23 @@ describe('Serializer', () => {
380344
verifyFieldValueRoundTrip({
381345
value,
382346
valueType: 'arrayValue',
383-
jsonValue,
384-
protobufJsValue: ArrayValueMessage.fromObject(jsonValue)
347+
jsonValue
385348
});
386349
});
387350

388351
it('converts empty ArrayValue', () => {
389352
verifyFieldValueRoundTrip({
390353
value: wrap([]),
391354
valueType: 'arrayValue',
392-
jsonValue: { values: [] },
393-
protobufJsValue: ArrayValueMessage.fromObject({})
355+
jsonValue: { values: [] }
394356
});
395357
});
396358

397359
it('converts ObjectValue.EMPTY', () => {
398360
verifyFieldValueRoundTrip({
399361
value: wrap({}),
400362
valueType: 'mapValue',
401-
jsonValue: { fields: {} },
402-
protobufJsValue: MapValueMessage.fromObject({})
363+
jsonValue: { fields: {} }
403364
});
404365
});
405366

@@ -467,8 +428,7 @@ describe('Serializer', () => {
467428
verifyFieldValueRoundTrip({
468429
value: objValue,
469430
valueType: 'mapValue',
470-
jsonValue: expectedJson.mapValue,
471-
protobufJsValue: MapValueMessage.fromObject(expectedJson.mapValue!)
431+
jsonValue: expectedJson.mapValue
472432
});
473433
});
474434

0 commit comments

Comments
 (0)