Skip to content

Firestore: improve persistence parameter of integration tests to an object rather than a boolean #7404

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jul 4, 2023
134 changes: 69 additions & 65 deletions packages/firestore/test/integration/api/array_transforms.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,80 +160,84 @@ apiDescribe('Array Transforms:', persistence => {
* Unlike the withTestSetup() tests above, these tests intentionally avoid
* having any ongoing listeners so that we can test what gets stored in the
* offline cache based purely on the write acknowledgement (without receiving
* an updated document via watch). As such they also rely on persistence
* being enabled so documents remain in the cache after the write.
* an updated document via watch). As such they also rely on persistence with
* LRU garbage collection (rather than eager garbage collection) so documents
* remain in the cache after the write.
*/
// eslint-disable-next-line no-restricted-properties
(persistence ? describe : describe.skip)('Server Application: ', () => {
it('set() with no cached base doc', async () => {
await withTestDoc(persistence, async docRef => {
await setDoc(docRef, { array: arrayUnion(1, 2) });
const snapshot = await getDocFromCache(docRef);
expect(snapshot.data()).to.deep.equal({ array: [1, 2] });
});
});

it('update() with no cached base doc', async () => {
let path: string | null = null;
// Write an initial document in an isolated Firestore instance so it's not
// stored in our cache
await withTestDoc(persistence, async docRef => {
path = docRef.path;
await setDoc(docRef, { array: [42] });
(persistence.gc === 'lru' ? describe : describe.skip)(
'Server Application: ',
() => {
it('set() with no cached base doc', async () => {
await withTestDoc(persistence, async docRef => {
await setDoc(docRef, { array: arrayUnion(1, 2) });
const snapshot = await getDocFromCache(docRef);
expect(snapshot.data()).to.deep.equal({ array: [1, 2] });
});
});

await withTestDb(persistence, async db => {
const docRef = doc(db, path!);
await updateDoc(docRef, { array: arrayUnion(1, 2) });

// Nothing should be cached since it was an update and we had no base
// doc.
let errCaught = false;
try {
await getDocFromCache(docRef);
} catch (err) {
expect((err as FirestoreError).code).to.equal('unavailable');
errCaught = true;
}
expect(errCaught).to.be.true;
it('update() with no cached base doc', async () => {
let path: string | null = null;
// Write an initial document in an isolated Firestore instance so it's not
// stored in our cache
await withTestDoc(persistence, async docRef => {
path = docRef.path;
await setDoc(docRef, { array: [42] });
});

await withTestDb(persistence, async db => {
const docRef = doc(db, path!);
await updateDoc(docRef, { array: arrayUnion(1, 2) });

// Nothing should be cached since it was an update and we had no base
// doc.
let errCaught = false;
try {
await getDocFromCache(docRef);
} catch (err) {
expect((err as FirestoreError).code).to.equal('unavailable');
errCaught = true;
}
expect(errCaught).to.be.true;
});
});
});

it('set(..., {merge}) with no cached based doc', async () => {
let path: string | null = null;
// Write an initial document in an isolated Firestore instance so it's not
// stored in our cache
await withTestDoc(persistence, async docRef => {
path = docRef.path;
await setDoc(docRef, { array: [42] });
it('set(..., {merge}) with no cached based doc', async () => {
let path: string | null = null;
// Write an initial document in an isolated Firestore instance so it's not
// stored in our cache
await withTestDoc(persistence, async docRef => {
path = docRef.path;
await setDoc(docRef, { array: [42] });
});

await withTestDb(persistence, async db => {
const docRef = doc(db, path!);
await setDoc(docRef, { array: arrayUnion(1, 2) }, { merge: true });

// Document will be cached but we'll be missing 42.
const snapshot = await getDocFromCache(docRef);
expect(snapshot.data()).to.deep.equal({ array: [1, 2] });
});
});

await withTestDb(persistence, async db => {
const docRef = doc(db, path!);
await setDoc(docRef, { array: arrayUnion(1, 2) }, { merge: true });

// Document will be cached but we'll be missing 42.
const snapshot = await getDocFromCache(docRef);
expect(snapshot.data()).to.deep.equal({ array: [1, 2] });
it('update() with cached base doc using arrayUnion()', async () => {
await withTestDoc(persistence, async docRef => {
await setDoc(docRef, { array: [42] });
await updateDoc(docRef, { array: arrayUnion(1, 2) });
const snapshot = await getDocFromCache(docRef);
expect(snapshot.data()).to.deep.equal({ array: [42, 1, 2] });
});
});
});

it('update() with cached base doc using arrayUnion()', async () => {
await withTestDoc(persistence, async docRef => {
await setDoc(docRef, { array: [42] });
await updateDoc(docRef, { array: arrayUnion(1, 2) });
const snapshot = await getDocFromCache(docRef);
expect(snapshot.data()).to.deep.equal({ array: [42, 1, 2] });
it('update() with cached base doc using arrayRemove()', async () => {
await withTestDoc(persistence, async docRef => {
await setDoc(docRef, { array: [42, 1, 2] });
await updateDoc(docRef, { array: arrayRemove(1, 2) });
const snapshot = await getDocFromCache(docRef);
expect(snapshot.data()).to.deep.equal({ array: [42] });
});
});
});

it('update() with cached base doc using arrayRemove()', async () => {
await withTestDoc(persistence, async docRef => {
await setDoc(docRef, { array: [42, 1, 2] });
await updateDoc(docRef, { array: arrayRemove(1, 2) });
const snapshot = await getDocFromCache(docRef);
expect(snapshot.data()).to.deep.equal({ array: [42] });
});
});
});
}
);
});
110 changes: 57 additions & 53 deletions packages/firestore/test/integration/api/database.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,13 @@ import {
} from '../util/firebase_export';
import {
apiDescribe,
withEnsuredLruGcTestDb,
withTestCollection,
withTestDbsSettings,
withTestDb,
withTestDbs,
withTestDoc,
withTestDocAndInitialData,
withNamedTestDbsOrSkipUnlessUsingEmulator,
withEnsuredEagerGcTestDb
withNamedTestDbsOrSkipUnlessUsingEmulator
} from '../util/helpers';
import { DEFAULT_SETTINGS, DEFAULT_PROJECT_ID } from '../util/settings';

Expand Down Expand Up @@ -153,29 +151,32 @@ apiDescribe('Database', persistence => {
});

// eslint-disable-next-line no-restricted-properties
(persistence ? it : it.skip)('can update an unknown document', () => {
return withTestDbs(persistence, 2, async ([reader, writer]) => {
const writerRef = doc(collection(writer, 'collection'));
const readerRef = doc(collection(reader, 'collection'), writerRef.id);
await setDoc(writerRef, { a: 'a' });
await updateDoc(readerRef, { b: 'b' });
await getDocFromCache(writerRef).then(
doc => expect(doc.exists()).to.be.true
);
await getDocFromCache(readerRef).then(
() => {
expect.fail('Expected cache miss');
},
err => expect(err.code).to.be.equal('unavailable')
);
await getDoc(writerRef).then(doc =>
expect(doc.data()).to.deep.equal({ a: 'a', b: 'b' })
);
await getDoc(readerRef).then(doc =>
expect(doc.data()).to.deep.equal({ a: 'a', b: 'b' })
);
});
});
(persistence.gc === 'lru' ? it : it.skip)(
'can update an unknown document',
() => {
return withTestDbs(persistence, 2, async ([reader, writer]) => {
const writerRef = doc(collection(writer, 'collection'));
const readerRef = doc(collection(reader, 'collection'), writerRef.id);
await setDoc(writerRef, { a: 'a' });
await updateDoc(readerRef, { b: 'b' });
await getDocFromCache(writerRef).then(
doc => expect(doc.exists()).to.be.true
);
await getDocFromCache(readerRef).then(
() => {
expect.fail('Expected cache miss');
},
err => expect(err.code).to.be.equal('unavailable')
);
await getDoc(writerRef).then(doc =>
expect(doc.data()).to.deep.equal({ a: 'a', b: 'b' })
);
await getDoc(readerRef).then(doc =>
expect(doc.data()).to.deep.equal({ a: 'a', b: 'b' })
);
});
}
);

it('can merge data with an existing document using set', () => {
return withTestDoc(persistence, doc => {
Expand Down Expand Up @@ -1095,32 +1096,35 @@ apiDescribe('Database', persistence => {
});

// eslint-disable-next-line no-restricted-properties
(persistence ? it : it.skip)('offline writes are sent after restart', () => {
return withTestDoc(persistence, async (docRef, firestore) => {
const app = firestore.app;
const name = app.name;
const options = app.options;
(persistence.storage === 'indexeddb' ? it : it.skip)(
'offline writes are sent after restart',
() => {
return withTestDoc(persistence, async (docRef, firestore) => {
const app = firestore.app;
const name = app.name;
const options = app.options;

await disableNetwork(firestore);
await disableNetwork(firestore);

// We are merely adding to the cache.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setDoc(docRef, { foo: 'bar' });
// We are merely adding to the cache.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setDoc(docRef, { foo: 'bar' });

await deleteApp(app);
await deleteApp(app);

const firestore2 = newTestFirestore(
newTestApp(options.projectId!, name),
DEFAULT_SETTINGS
);
await enableIndexedDbPersistence(firestore2);
await waitForPendingWrites(firestore2);
const doc2 = await getDoc(doc(firestore2, docRef.path));
const firestore2 = newTestFirestore(
newTestApp(options.projectId!, name),
DEFAULT_SETTINGS
);
await enableIndexedDbPersistence(firestore2);
await waitForPendingWrites(firestore2);
const doc2 = await getDoc(doc(firestore2, docRef.path));

expect(doc2.exists()).to.be.true;
expect(doc2.metadata.hasPendingWrites).to.be.false;
});
});
expect(doc2.exists()).to.be.true;
expect(doc2.metadata.hasPendingWrites).to.be.false;
});
}
);

it('rejects subsequent method calls after terminate() is called', async () => {
return withTestDb(persistence, db => {
Expand All @@ -1141,7 +1145,7 @@ apiDescribe('Database', persistence => {
});

// eslint-disable-next-line no-restricted-properties
(persistence ? it : it.skip)(
(persistence.storage === 'indexeddb' ? it : it.skip)(
'maintains persistence after restarting app',
async () => {
await withTestDoc(persistence, async docRef => {
Expand All @@ -1164,7 +1168,7 @@ apiDescribe('Database', persistence => {
);

// eslint-disable-next-line no-restricted-properties
(persistence ? it : it.skip)(
(persistence.storage === 'indexeddb' ? it : it.skip)(
'can clear persistence if the client has been terminated',
async () => {
await withTestDoc(persistence, async (docRef, firestore) => {
Expand All @@ -1188,7 +1192,7 @@ apiDescribe('Database', persistence => {
);

// eslint-disable-next-line no-restricted-properties
(persistence ? it : it.skip)(
(persistence.storage === 'indexeddb' ? it : it.skip)(
'can clear persistence if the client has not been initialized',
async () => {
await withTestDoc(persistence, async docRef => {
Expand All @@ -1212,7 +1216,7 @@ apiDescribe('Database', persistence => {
);

// eslint-disable-next-line no-restricted-properties
(persistence ? it : it.skip)(
(persistence.storage === 'indexeddb' ? it : it.skip)(
'cannot clear persistence if the client has been initialized',
async () => {
await withTestDoc(persistence, async (docRef, firestore) => {
Expand Down Expand Up @@ -1757,7 +1761,7 @@ apiDescribe('Database', persistence => {

it('Cannot get document from cache with eager GC enabled.', () => {
const initialData = { key: 'value' };
return withEnsuredEagerGcTestDb(async db => {
return withTestDb(persistence.toEagerGc(), async db => {
const docRef = doc(collection(db, 'test-collection'));
await setDoc(docRef, initialData);
await expect(getDocFromCache(docRef)).to.be.rejectedWith('Failed to get');
Expand All @@ -1766,7 +1770,7 @@ apiDescribe('Database', persistence => {

it('Can get document from cache with Lru GC enabled.', () => {
const initialData = { key: 'value' };
return withEnsuredLruGcTestDb(persistence, async db => {
return withTestDb(persistence.toLruGc(), async db => {
const docRef = doc(collection(db, 'test-collection'));
await setDoc(docRef, initialData);
return getDocFromCache(docRef).then(doc => {
Expand Down
11 changes: 6 additions & 5 deletions packages/firestore/test/integration/api/get_options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {
apiDescribe,
withTestCollection,
withTestDocAndInitialData,
withEnsuredLruGcTestDb
withTestDb
} from '../util/helpers';

apiDescribe('GetOptions', persistence => {
Expand Down Expand Up @@ -70,8 +70,8 @@ apiDescribe('GetOptions', persistence => {

it('get document while offline with default get options', () => {
const initialData = { key: 'value' };
// Use an instance with Gc turned on.
return withEnsuredLruGcTestDb(persistence, async db => {
// Use an instance with LRU GC.
return withTestDb(persistence.toLruGc(), async db => {
const docRef = doc(collection(db, 'test-collection'));
await setDoc(docRef, initialData);
return getDoc(docRef)
Expand Down Expand Up @@ -496,9 +496,10 @@ apiDescribe('GetOptions', persistence => {
});
});

// We need the deleted doc to stay in cache, so only run this with persistence.
// We need the deleted doc to stay in cache, so only run this test when the
// local cache is configured with LRU GC (as opposed to eager GC).
// eslint-disable-next-line no-restricted-properties,
(persistence ? it : it.skip)(
(persistence.gc === 'lru' ? it : it.skip)(
'get deleted doc while offline with source=cache',
() => {
return withTestDocAndInitialData(persistence, null, (docRef, db) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ apiDescribe('Index Configuration:', persistence => {
it('bad JSON does not crash client', () => {
return withTestDb(persistence, async db => {
const action = (): Promise<void> => setIndexConfiguration(db, '{,}');
if (persistence) {
if (persistence.storage === 'indexeddb') {
expect(action).to.throw(/Failed to parse JSON/);
} else {
// Silently do nothing. Parsing is not done and therefore no error is thrown.
Expand Down
Loading