Skip to content

Commit f7030a4

Browse files
committed
Add spec test
1 parent 765def8 commit f7030a4

13 files changed

+162
-32
lines changed

packages/firestore/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,11 @@
9797
"@firebase/auth": "0.20.4",
9898
"@rollup/plugin-alias": "3.1.9",
9999
"@rollup/plugin-json": "4.1.0",
100+
"@types/chai": "^4.3.1",
100101
"@types/eslint": "7.29.0",
101102
"@types/json-stable-stringify": "1.0.34",
103+
"chai": "^4.3.6",
104+
"chai-exclude": "^2.1.0",
102105
"json-stable-stringify": "1.0.1",
103106
"protobufjs": "6.11.3",
104107
"rollup": "2.72.1",

packages/firestore/src/api/database.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import { AsyncQueue } from '../util/async_queue';
5656
import { newAsyncQueue } from '../util/async_queue_impl';
5757
import { Code, FirestoreError } from '../util/error';
5858
import { cast } from '../util/input_validation';
59+
import { logWarn } from '../util/log';
5960
import { Deferred } from '../util/promise';
6061

6162
import { LoadBundleTask } from './bundle';
@@ -332,7 +333,7 @@ function setPersistenceProviders(
332333
if (!canFallbackFromIndexedDbError(error)) {
333334
throw error;
334335
}
335-
console.warn(
336+
logWarn(
336337
'Error enabling offline persistence. Falling back to ' +
337338
'persistence disabled: ' +
338339
error

packages/firestore/src/api/index_configuration.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
} from '../model/field_index';
2727
import { Code, FirestoreError } from '../util/error';
2828
import { cast } from '../util/input_validation';
29+
import { logWarn } from '../util/log';
2930

3031
import { ensureFirestoreConfigured, Firestore } from './database';
3132

@@ -147,7 +148,7 @@ export function setIndexConfiguration(
147148
firestore: Firestore,
148149
json: string
149150
): Promise<void>;
150-
export async function setIndexConfiguration(
151+
export function setIndexConfiguration(
151152
firestore: Firestore,
152153
jsonOrConfiguration: string | IndexConfiguration
153154
): Promise<void> {
@@ -157,10 +158,18 @@ export async function setIndexConfiguration(
157158
// PORTING NOTE: We don't return an error if the user has not enabled
158159
// persistence since `enableIndexeddbPersistence()` can fail on the Web.
159160
if (!client.offlineComponents?.indexBackfillerScheduler) {
160-
console.warn('Cannot enable indexes when persistence is disabled');
161-
return;
161+
logWarn('Cannot enable indexes when persistence is disabled');
162+
return Promise.resolve();
162163
}
164+
const parsedIndexes = parseIndexes(jsonOrConfiguration);
165+
return getLocalStore(client).then(localStore =>
166+
localStoreConfigureFieldIndexes(localStore, parsedIndexes)
167+
);
168+
}
163169

170+
export function parseIndexes(
171+
jsonOrConfiguration: string | IndexConfiguration
172+
): FieldIndex[] {
164173
const indexConfiguration =
165174
typeof jsonOrConfiguration === 'string'
166175
? (tryParseJson(jsonOrConfiguration) as IndexConfiguration)
@@ -200,9 +209,7 @@ export async function setIndexConfiguration(
200209
);
201210
}
202211
}
203-
204-
const localStore = await getLocalStore(client);
205-
await localStoreConfigureFieldIndexes(localStore, parsedIndexes);
212+
return parsedIndexes;
206213
}
207214

208215
function tryParseJson(json: string): Record<string, unknown> {

packages/firestore/src/local/indexeddb_schema.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ import {
2828
import { EncodedResourcePath } from './encoded_resource_path';
2929
import { DbTimestampKey } from './indexeddb_sentinels';
3030

31-
export const INDEXING_SCHEMA_VERSION = 15;
32-
3331
/**
3432
* Schema Version for the Web client:
3533
* 1. Initial version including Mutation Queue, Query Cache, and Remote
@@ -55,7 +53,7 @@ export const INDEXING_SCHEMA_VERSION = 15;
5553
* 15. Add indexing support.
5654
*/
5755

58-
export const SCHEMA_VERSION = INDEXING_SCHEMA_VERSION;
56+
export const SCHEMA_VERSION = 15;
5957

6058
/**
6159
* Wrapper class to store timestamps (seconds and nanos) in IndexedDb objects.

packages/firestore/src/local/indexeddb_schema_converter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import {
4545
DbTarget,
4646
DbTargetDocument,
4747
DbTargetGlobal,
48-
INDEXING_SCHEMA_VERSION
48+
SCHEMA_VERSION
4949
} from './indexeddb_schema';
5050
import {
5151
DbRemoteDocument as DbRemoteDocumentLegacy,
@@ -146,7 +146,7 @@ export class SchemaConverter implements SimpleDbSchemaConverter {
146146
debugAssert(
147147
fromVersion < toVersion &&
148148
fromVersion >= 0 &&
149-
toVersion <= INDEXING_SCHEMA_VERSION,
149+
toVersion <= SCHEMA_VERSION,
150150
`Unexpected schema upgrade from v${fromVersion} to v${toVersion}.`
151151
);
152152

packages/firestore/src/local/local_store_impl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1496,7 +1496,7 @@ export async function localStoreConfigureFieldIndexes(
14961496
const promises: Array<PersistencePromise<void>> = [];
14971497
return localStoreImpl.persistence.runTransaction(
14981498
'Configure indexes',
1499-
'readwrite-primary',
1499+
'readwrite',
15001500
transaction =>
15011501
indexManager
15021502
.getFieldIndexes(transaction)

packages/firestore/src/util/async_observer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import { Observer } from '../core/event_manager';
1919

2020
import { FirestoreError } from './error';
21+
import { logError } from './log';
2122
import { EventHandler } from './misc';
2223

2324
/*
@@ -44,7 +45,7 @@ export class AsyncObserver<T> implements Observer<T> {
4445
if (this.observer.error) {
4546
this.scheduleEvent(this.observer.error, error);
4647
} else {
47-
console.error('Uncaught Error in snapshot listener:', error);
48+
logError('Uncaught Error in snapshot listener:', error);
4849
}
4950
}
5051

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

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,11 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { expect, use } from 'chai';
19-
import chaiAsPromised from 'chai-as-promised';
18+
import { expect } from 'chai';
2019

2120
import { _setIndexConfiguration as setIndexConfiguration } from '../util/firebase_export';
2221
import { apiDescribe, withTestDb } from '../util/helpers';
2322

24-
use(chaiAsPromised);
25-
2623
apiDescribe('Index Configuration:', (persistence: boolean) => {
2724
it('supports JSON', () => {
2825
return withTestDb(persistence, async db => {
@@ -82,14 +79,12 @@ apiDescribe('Index Configuration:', (persistence: boolean) => {
8279

8380
it('bad JSON does not crash client', () => {
8481
return withTestDb(persistence, async db => {
85-
const action: Promise<void> = setIndexConfiguration(db, '{,}');
82+
const action = (): Promise<void> => setIndexConfiguration(db, '{,}');
8683
if (persistence) {
87-
await expect(action).to.eventually.be.rejectedWith(
88-
/Failed to parse JSON/
89-
);
84+
expect(action).to.throw(/Failed to parse JSON/);
9085
} else {
9186
// Silently do nothing. Parsing is not done and therefore no error is thrown.
92-
await action;
87+
await action();
9388
}
9489
});
9590
});

packages/firestore/test/unit/local/index_manager.test.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {
3232
import { FieldFilter } from '../../../src/core/target';
3333
import { IndexType } from '../../../src/local/index_manager';
3434
import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence';
35-
import { INDEXING_SCHEMA_VERSION } from '../../../src/local/indexeddb_schema';
3635
import { Persistence } from '../../../src/local/persistence';
3736
import { documentMap } from '../../../src/model/collections';
3837
import { Document } from '../../../src/model/document';
@@ -73,9 +72,7 @@ describe('IndexedDbIndexManager', async () => {
7372

7473
let persistencePromise: Promise<Persistence>;
7574
beforeEach(async () => {
76-
persistencePromise = persistenceHelpers.testIndexedDbPersistence({
77-
schemaVersion: INDEXING_SCHEMA_VERSION
78-
});
75+
persistencePromise = persistenceHelpers.testIndexedDbPersistence();
7976
});
8077

8178
async function getIndexManager(

packages/firestore/test/unit/local/query_engine.test.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import { SnapshotVersion } from '../../../src/core/snapshot_version';
3030
import { View } from '../../../src/core/view';
3131
import { DocumentOverlayCache } from '../../../src/local/document_overlay_cache';
3232
import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence';
33-
import { INDEXING_SCHEMA_VERSION } from '../../../src/local/indexeddb_schema';
3433
import { LocalDocumentsView } from '../../../src/local/local_documents_view';
3534
import { MutationQueue } from '../../../src/local/mutation_queue';
3635
import { Persistence } from '../../../src/local/persistence';
@@ -122,9 +121,7 @@ describe('IndexedDbQueryEngine', async () => {
122121

123122
let persistencePromise: Promise<Persistence>;
124123
beforeEach(async () => {
125-
persistencePromise = persistenceHelpers.testIndexedDbPersistence({
126-
schemaVersion: INDEXING_SCHEMA_VERSION
127-
});
124+
persistencePromise = persistenceHelpers.testIndexedDbPersistence();
128125
});
129126

130127
genericQueryEngineTest(/* durable= */ true, () => persistencePromise);
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* @license
3+
* Copyright 2022 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { IndexConfiguration } from '../../../src/api/index_configuration';
19+
import { IndexKind } from '../../../src/model/field_index';
20+
import * as Helpers from '../../util/helpers';
21+
22+
import { describeSpec, specTest } from './describe_spec';
23+
import { client } from './spec_builder';
24+
25+
describeSpec('Client Side Index', [], () => {
26+
const config: IndexConfiguration = {
27+
indexes: [
28+
{
29+
collectionGroup: 'restaurants',
30+
queryScope: 'COLLECTION',
31+
fields: [
32+
{
33+
fieldPath: 'price',
34+
order: 'ASCENDING'
35+
}
36+
]
37+
}
38+
]
39+
};
40+
const expectedIndexes = [
41+
Helpers.fieldIndex('restaurants', {
42+
fields: [['price', IndexKind.ASCENDING]]
43+
})
44+
];
45+
specTest('Index Creation visible on all clients', ['multi-client'], () => {
46+
return client(0)
47+
.expectPrimaryState(true)
48+
.setIndexConfiguration(config)
49+
.expectIndexes(expectedIndexes)
50+
.client(1)
51+
.expectPrimaryState(false)
52+
.expectIndexes(expectedIndexes);
53+
});
54+
specTest(
55+
'Index Creation succeeds even if not primary',
56+
['multi-client'],
57+
() => {
58+
return client(0)
59+
.expectPrimaryState(true)
60+
.client(1)
61+
.expectPrimaryState(false)
62+
.setIndexConfiguration(config)
63+
.expectIndexes(expectedIndexes)
64+
.client(0)
65+
.expectIndexes(expectedIndexes);
66+
}
67+
);
68+
});

packages/firestore/test/unit/specs/spec_builder.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { IndexConfiguration } from '../../../src/api/index_configuration';
1819
import { ExpUserDataWriter } from '../../../src/api/reference_impl';
1920
import {
2021
LimitType,
@@ -34,6 +35,7 @@ import { TargetIdGenerator } from '../../../src/core/target_id_generator';
3435
import { TargetId } from '../../../src/core/types';
3536
import { Document } from '../../../src/model/document';
3637
import { DocumentKey } from '../../../src/model/document_key';
38+
import { FieldIndex } from '../../../src/model/field_index';
3739
import { JsonObject } from '../../../src/model/object_value';
3840
import { ResourcePath } from '../../../src/model/path';
3941
import {
@@ -386,6 +388,16 @@ export class SpecBuilder {
386388
return this;
387389
}
388390

391+
setIndexConfiguration(
392+
jsonOrConfiguration: string | IndexConfiguration
393+
): this {
394+
this.nextStep();
395+
this.currentStep = {
396+
setIndexConfiguration: jsonOrConfiguration
397+
};
398+
return this;
399+
}
400+
389401
// PORTING NOTE: Only used by web multi-tab tests.
390402
becomeHidden(): this {
391403
this.nextStep();
@@ -508,6 +520,15 @@ export class SpecBuilder {
508520
return this;
509521
}
510522

523+
/** Expects indexes to exist (in any order) */
524+
expectIndexes(indexes: FieldIndex[]): this {
525+
this.assertStep('Indexes expectation requires previous step');
526+
const currentStep = this.currentStep!;
527+
currentStep.expectedState = currentStep.expectedState || {};
528+
currentStep.expectedState.indexes = indexes;
529+
return this;
530+
}
531+
511532
/** Overrides the currently expected set of active targets. */
512533
expectActiveTargets(
513534
...targets: Array<{

0 commit comments

Comments
 (0)