Skip to content

[Multi-Tab] Using WebStorage Mock with all IndexedDB tests #1034

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 3 commits into from
Jul 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
OnlineState,
TargetId
} from '../../../src/core/types';
import { BrowserPlatform } from '../../../src/platform_browser/browser_platform';
import { AsyncQueue } from '../../../src/util/async_queue';
import { User } from '../../../src/auth/user';
import {
Expand Down Expand Up @@ -122,7 +121,7 @@ export async function populateWebStorage(
// NOTE: We don't call shutdown() on it because that would delete the data.
const secondaryClientState = new WebStorageSharedClientState(
new AsyncQueue(),
new BrowserPlatform(),
PlatformSupport.getPlatform(),
TEST_PERSISTENCE_PREFIX,
existingClientId,
user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import {
clearWebStorage,
TEST_PERSISTENCE_PREFIX
} from './persistence_test_helpers';
import { BrowserPlatform } from '../../../src/platform_browser/browser_platform';
import { PlatformSupport } from '../../../src/platform/platform';
import * as objUtils from '../../../src/util/obj';
import { targetIdSet } from '../../../src/model/collections';
Expand Down Expand Up @@ -174,6 +173,7 @@ describe('WebStorageSharedClientState', () => {
let clientSyncer: TestSharedClientSyncer;

let previousAddEventListener;
let previousRemoveEventListener;

let localStorageCallbacks = [];

Expand All @@ -192,6 +192,7 @@ describe('WebStorageSharedClientState', () => {
localStorageCallbacks = [];

previousAddEventListener = window.addEventListener;
previousRemoveEventListener = window.removeEventListener;

// We capture the listener here so that we can invoke it from the local
// client. If we directly relied on LocalStorage listeners, we would not
Expand All @@ -200,12 +201,13 @@ describe('WebStorageSharedClientState', () => {
expect(type).to.equal('storage');
localStorageCallbacks.push(callback);
};
window.removeEventListener = () => {};

primaryClientId = AutoId.newId();
queue = new AsyncQueue();
sharedClientState = new WebStorageSharedClientState(
queue,
new BrowserPlatform(),
PlatformSupport.getPlatform(),
TEST_PERSISTENCE_PREFIX,
primaryClientId,
AUTHENTICATED_USER
Expand All @@ -220,6 +222,7 @@ describe('WebStorageSharedClientState', () => {
afterEach(() => {
sharedClientState.shutdown();
window.addEventListener = previousAddEventListener;
window.removeEventListener = previousRemoveEventListener;
});

function assertClientState(
Expand Down
12 changes: 9 additions & 3 deletions packages/firestore/test/util/node_persistence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import * as registerIndexedDBShim from 'indexeddbshim';
import * as fs from 'fs';
import * as os from 'os';

import { FakeWindow, SharedFakeWebStorage } from './test_platform';

// WARNING: The `indexeddbshim` installed via this module should only ever be
// used during initial development. Always validate your changes via
// `yarn test:browser` (which uses a browser-based IndexedDB implementation)
Expand All @@ -36,9 +38,13 @@ if (process.env.USE_MOCK_PERSISTENCE === 'YES') {
databaseBasePath: dbDir,
deleteDatabaseFiles: true
});
globalAny.window = Object.assign(globalAny.window || {}, {
indexedDB: globalAny.indexedDB
});

const fakeWindow = new FakeWindow(
new SharedFakeWebStorage(),
globalAny.indexedDB
);

globalAny.window = fakeWindow;

// We need to define the `Event` type as it is used in Node to send events to
// WebStorage when using both the IndexedDB mock and the WebStorage mock.
Expand Down
40 changes: 27 additions & 13 deletions packages/firestore/test/util/test_platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,36 @@ import { assert, fail } from '../../src/util/assert';
* Firestore.
*/
export class FakeWindow {
private readonly storageArea: Storage;
private storageListener: EventListener = () => {};
private readonly fakeStorageArea: Storage;
private readonly fakeIndexedDb: IDBFactory;

constructor(sharedMockStorage: SharedFakeWebStorage) {
this.storageArea = sharedMockStorage.getStorageArea(event =>
this.storageListener(event)
);
private storageListeners: EventListener[] = [];

constructor(
sharedFakeStorage: SharedFakeWebStorage,
fakeIndexedDb?: IDBFactory
) {
this.fakeStorageArea = sharedFakeStorage.getStorageArea(event => {
for (const listener of this.storageListeners) {
listener(event);
}
});
this.fakeIndexedDb =
fakeIndexedDb || (typeof window !== 'undefined' && window.indexedDB);
}

get localStorage(): Storage {
return this.storageArea;
return this.fakeStorageArea;
}

get indexedDB(): IDBFactory {
return window.indexedDB;
return this.fakeIndexedDb;
}

addEventListener(type: string, listener: EventListener): void {
switch (type) {
case 'storage':
this.storageListener = listener;
this.storageListeners.push(listener);
break;
case 'unload':
// The spec tests currently do not rely on 'unload' listeners.
Expand All @@ -59,11 +68,15 @@ export class FakeWindow {

removeEventListener(type: string, listener: EventListener): void {
if (type === 'storage') {
const oldCount = this.storageListeners.length;
this.storageListeners = this.storageListeners.filter(
registeredListener => listener !== registeredListener
);
const newCount = this.storageListeners.length;
assert(
this.storageListener === listener,
"Listener passed to 'removeEventListener' doesn't match the current listener."
newCount === oldCount - 1,
"Listener passed to 'removeEventListener' doesn't match any registered listener."
);
this.storageListener = () => {};
}
}
}
Expand Down Expand Up @@ -150,7 +163,8 @@ export class SharedFakeWebStorage {
}

private key(index: number): string | null {
return Array.from(this.data.keys())[index];
const key = Array.from(this.data.keys())[index];
return key !== undefined ? key : null;
}

private removeItem(key: string): void {
Expand Down