mirror of
https://github.com/hanzoai/firebase-js-sdk.git
synced 2026-09-24 16:59:10 +00:00
352 lines
11 KiB
TypeScript
352 lines
11 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2017 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import { expect } from 'chai';
|
|
|
|
import { User } from '../../../src/auth/user';
|
|
import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence';
|
|
import { Persistence } from '../../../src/local/persistence';
|
|
import { documentKeySet } from '../../../src/model/collections';
|
|
import { MutationBatch } from '../../../src/model/mutation_batch';
|
|
import { addEqualityMatcher } from '../../util/equality_matcher';
|
|
import {
|
|
expectEqualArrays,
|
|
key,
|
|
patchMutation,
|
|
query,
|
|
setMutation
|
|
} from '../../util/helpers';
|
|
|
|
import * as persistenceHelpers from './persistence_test_helpers';
|
|
import { TestMutationQueue } from './test_mutation_queue';
|
|
|
|
let persistence: Persistence;
|
|
let mutationQueue: TestMutationQueue;
|
|
describe('MemoryMutationQueue', () => {
|
|
beforeEach(() => {
|
|
return persistenceHelpers.testMemoryEagerPersistence().then(p => {
|
|
persistence = p;
|
|
});
|
|
});
|
|
|
|
genericMutationQueueTests();
|
|
});
|
|
|
|
describe('IndexedDbMutationQueue', () => {
|
|
if (!IndexedDbPersistence.isAvailable()) {
|
|
console.warn('No IndexedDB. Skipping IndexedDbMutationQueue tests.');
|
|
return;
|
|
}
|
|
|
|
beforeEach(() => {
|
|
return persistenceHelpers.testIndexedDbPersistence().then(p => {
|
|
persistence = p;
|
|
});
|
|
});
|
|
|
|
genericMutationQueueTests();
|
|
});
|
|
|
|
/**
|
|
* Defines the set of tests to run against both mutation queue
|
|
* implementations.
|
|
*/
|
|
function genericMutationQueueTests(): void {
|
|
addEqualityMatcher();
|
|
|
|
beforeEach(() => {
|
|
mutationQueue = new TestMutationQueue(
|
|
persistence,
|
|
persistence.getMutationQueue(
|
|
new User('user'),
|
|
persistence.getIndexManager(new User('user'))
|
|
)
|
|
);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await persistence.shutdown();
|
|
await persistenceHelpers.clearTestPersistence();
|
|
});
|
|
|
|
/**
|
|
* Creates a new MutationBatch with the next batch ID and a set of dummy
|
|
* mutations.
|
|
*/
|
|
function addMutationBatch(key?: string): Promise<MutationBatch> {
|
|
let keyStr = key;
|
|
if (keyStr === undefined) {
|
|
keyStr = 'foo/bar';
|
|
}
|
|
const mutation = setMutation(keyStr, { a: 1 });
|
|
return mutationQueue.addMutationBatch([mutation]);
|
|
}
|
|
|
|
/**
|
|
* Creates an array of batches containing count dummy MutationBatches. Each
|
|
* has a different batchID.
|
|
*/
|
|
async function createBatches(count: number): Promise<MutationBatch[]> {
|
|
const batches: MutationBatch[] = [];
|
|
for (let i = 0; i < count; i++) {
|
|
const batch = await addMutationBatch();
|
|
batches.push(batch);
|
|
}
|
|
return batches;
|
|
}
|
|
|
|
/**
|
|
* Removes the first n entries from the given batches and returns them.
|
|
*
|
|
* @param n - The number of batches to remove.
|
|
* @param batches - The array to mutate, removing entries from it.
|
|
* @returns A new array containing all the entries that were removed from
|
|
* batches.
|
|
*/
|
|
async function removeFirstBatches(
|
|
n: number,
|
|
batches: MutationBatch[]
|
|
): Promise<MutationBatch[]> {
|
|
const removed: MutationBatch[] = [];
|
|
for (let i = 0; i < n; i++) {
|
|
const batch = batches[0];
|
|
await mutationQueue.removeMutationBatch(batch);
|
|
batches.shift();
|
|
removed.push(batch);
|
|
}
|
|
return removed;
|
|
}
|
|
|
|
it('can count batches', async () => {
|
|
expect(await mutationQueue.countBatches()).to.equal(0);
|
|
expect(await mutationQueue.checkEmpty()).to.equal(true);
|
|
|
|
const batch1 = await addMutationBatch();
|
|
expect(await mutationQueue.countBatches()).to.equal(1);
|
|
expect(await mutationQueue.checkEmpty()).to.equal(false);
|
|
|
|
const batch2 = await addMutationBatch();
|
|
expect(await mutationQueue.countBatches()).to.equal(2);
|
|
|
|
await mutationQueue.removeMutationBatch(batch1);
|
|
expect(await mutationQueue.countBatches()).to.equal(1);
|
|
|
|
await mutationQueue.removeMutationBatch(batch2);
|
|
expect(await mutationQueue.countBatches()).to.equal(0);
|
|
});
|
|
|
|
it('can lookup mutation batch', async () => {
|
|
// Searching on an empty queue should not find a nonexistent batch
|
|
let notFound = await mutationQueue.lookupMutationBatch(42);
|
|
expect(notFound).to.be.null;
|
|
|
|
const batches = await createBatches(10);
|
|
const removed = await removeFirstBatches(3, batches);
|
|
|
|
// After removing, a batch should not be found
|
|
for (const batch of removed) {
|
|
const notFound = await mutationQueue.lookupMutationBatch(batch.batchId);
|
|
expect(notFound).to.be.null;
|
|
}
|
|
|
|
// Remaining entries should still be found
|
|
for (const batch of batches) {
|
|
const found = await mutationQueue.lookupMutationBatch(batch.batchId);
|
|
expect(found!.batchId).to.equal(batch.batchId);
|
|
}
|
|
|
|
// Even on a nonempty queue searching should not find a nonexistent batch
|
|
notFound = await mutationQueue.lookupMutationBatch(42);
|
|
expect(notFound).to.be.null;
|
|
});
|
|
|
|
it('can getNextMutationBatchAfterBatchId()', async () => {
|
|
const batches = await createBatches(10);
|
|
const removed = await removeFirstBatches(3, batches);
|
|
|
|
for (let i = 0; i < batches.length - 1; i++) {
|
|
const current = batches[i];
|
|
const next = batches[i + 1];
|
|
const found = await mutationQueue.getNextMutationBatchAfterBatchId(
|
|
current.batchId
|
|
);
|
|
expect(found!.batchId).to.equal(next.batchId);
|
|
}
|
|
|
|
for (let i = 0; i < removed.length; i++) {
|
|
const current = removed[i];
|
|
const next = batches[0];
|
|
const found = await mutationQueue.getNextMutationBatchAfterBatchId(
|
|
current.batchId
|
|
);
|
|
expect(found!.batchId).to.equal(next.batchId);
|
|
}
|
|
|
|
const first = batches[0];
|
|
const found = await mutationQueue.getNextMutationBatchAfterBatchId(
|
|
first.batchId - 42
|
|
);
|
|
expect(found!.batchId).to.equal(first.batchId);
|
|
|
|
const last = batches[batches.length - 1];
|
|
const notFound = await mutationQueue.getNextMutationBatchAfterBatchId(
|
|
last.batchId
|
|
);
|
|
expect(notFound).to.be.null;
|
|
});
|
|
|
|
it('can getAllMutationBatchesAffectingDocumentKey()', async () => {
|
|
const mutations = [
|
|
setMutation('fob/bar', { a: 1 }),
|
|
setMutation('foo/bar', { a: 1 }),
|
|
patchMutation('foo/bar', { b: 1 }),
|
|
setMutation('foo/bar/suffix/key', { a: 1 }),
|
|
setMutation('foo/baz', { a: 1 }),
|
|
setMutation('food/bar', { a: 1 })
|
|
];
|
|
// Store all the mutations.
|
|
const batches: MutationBatch[] = [];
|
|
for (const mutation of mutations) {
|
|
const batch = await mutationQueue.addMutationBatch([mutation]);
|
|
batches.push(batch);
|
|
}
|
|
const expected = [batches[1], batches[2]];
|
|
const matches =
|
|
await mutationQueue.getAllMutationBatchesAffectingDocumentKey(
|
|
key('foo/bar')
|
|
);
|
|
expectEqualArrays(matches, expected);
|
|
});
|
|
|
|
it('can getAllMutationBatchesAffectingDocumentKeys()', async () => {
|
|
const mutations = [
|
|
setMutation('fob/bar', { a: 1 }),
|
|
setMutation('foo/bar', { a: 1 }),
|
|
patchMutation('foo/bar', { b: 1 }),
|
|
setMutation('foo/bar/suffix/key', { a: 1 }),
|
|
setMutation('foo/baz', { a: 1 }),
|
|
setMutation('food/bar', { a: 1 })
|
|
];
|
|
// Store all the mutations.
|
|
const batches: MutationBatch[] = [];
|
|
for (const mutation of mutations) {
|
|
const batch = await mutationQueue.addMutationBatch([mutation]);
|
|
batches.push(batch);
|
|
}
|
|
const expected = [batches[1], batches[2], batches[4]];
|
|
const matches =
|
|
await mutationQueue.getAllMutationBatchesAffectingDocumentKeys(
|
|
documentKeySet().add(key('foo/bar')).add(key('foo/baz'))
|
|
);
|
|
expectEqualArrays(matches, expected);
|
|
});
|
|
|
|
it('can getAllMutationBatchesAffectingQuery()', async () => {
|
|
const mutations = [
|
|
setMutation('fob/bar', { a: 1 }),
|
|
setMutation('foo/bar', { a: 1 }),
|
|
patchMutation('foo/bar', { b: 1 }),
|
|
setMutation('foo/bar/suffix/key', { a: 1 }),
|
|
setMutation('foo/baz', { a: 1 }),
|
|
setMutation('food/bar', { a: 1 })
|
|
];
|
|
// Store all the mutations.
|
|
const batches: MutationBatch[] = [];
|
|
for (const mutation of mutations) {
|
|
const batch = await mutationQueue.addMutationBatch([mutation]);
|
|
batches.push(batch);
|
|
}
|
|
const expected = [batches[1], batches[2], batches[4]];
|
|
const query1 = query('foo');
|
|
const matches = await mutationQueue.getAllMutationBatchesAffectingQuery(
|
|
query1
|
|
);
|
|
expectEqualArrays(matches, expected);
|
|
});
|
|
|
|
it('can getAllMutationBatchesAffectingQuery() with compound batches', async () => {
|
|
const value = { a: 1 };
|
|
const batch1 = await mutationQueue.addMutationBatch([
|
|
setMutation('foo/bar', value),
|
|
setMutation('foo/bar/baz/quux', value)
|
|
]);
|
|
const batch2 = await mutationQueue.addMutationBatch([
|
|
setMutation('foo/bar', value),
|
|
setMutation('foo/baz', value)
|
|
]);
|
|
const expected = [batch1, batch2];
|
|
const query1 = query('foo');
|
|
const matches = await mutationQueue.getAllMutationBatchesAffectingQuery(
|
|
query1
|
|
);
|
|
expectEqualArrays(matches, expected);
|
|
});
|
|
|
|
it('can removeMutationBatch()', async () => {
|
|
const batches = await createBatches(10);
|
|
|
|
await mutationQueue.removeMutationBatch(batches[0]);
|
|
batches.splice(0, 1);
|
|
expect(await mutationQueue.countBatches()).to.equal(9);
|
|
|
|
let found;
|
|
|
|
found = await mutationQueue.getAllMutationBatches();
|
|
expectEqualArrays(found, batches);
|
|
expect(found.length).to.equal(9);
|
|
|
|
await mutationQueue.removeMutationBatch(batches[0]);
|
|
await mutationQueue.removeMutationBatch(batches[1]);
|
|
await mutationQueue.removeMutationBatch(batches[2]);
|
|
batches.splice(0, 3);
|
|
expect(await mutationQueue.countBatches()).to.equal(6);
|
|
|
|
found = await mutationQueue.getAllMutationBatches();
|
|
expectEqualArrays(found, batches);
|
|
expect(found.length).to.equal(6);
|
|
|
|
await mutationQueue.removeMutationBatch(batches[0]);
|
|
batches.shift();
|
|
expect(await mutationQueue.countBatches()).to.equal(5);
|
|
|
|
found = await mutationQueue.getAllMutationBatches();
|
|
expectEqualArrays(found, batches);
|
|
expect(found.length).to.equal(5);
|
|
|
|
await mutationQueue.removeMutationBatch(batches[0]);
|
|
batches.shift();
|
|
expect(await mutationQueue.countBatches()).to.equal(4);
|
|
|
|
await mutationQueue.removeMutationBatch(batches[0]);
|
|
batches.shift();
|
|
expect(await mutationQueue.countBatches()).to.equal(3);
|
|
|
|
found = await mutationQueue.getAllMutationBatches();
|
|
expectEqualArrays(found, batches);
|
|
expect(found.length).to.equal(3);
|
|
expect(await mutationQueue.checkEmpty()).to.equal(false);
|
|
|
|
for (const batch of batches) {
|
|
await mutationQueue.removeMutationBatch(batch);
|
|
}
|
|
found = await mutationQueue.getAllMutationBatches();
|
|
expectEqualArrays(found, []);
|
|
expect(found.length).to.equal(0);
|
|
expect(await mutationQueue.checkEmpty()).to.equal(true);
|
|
});
|
|
}
|