add unit tests for findExistingKeys

This commit is contained in:
Bruno Windels 2021-09-28 14:20:21 +02:00
parent edc3a1d33c
commit ec2f1b9833
2 changed files with 112 additions and 7 deletions

View file

@ -15,7 +15,15 @@ limitations under the License.
*/ */
import {iterateCursor, DONE, NOT_DONE, reqAsPromise} from "./utils"; import {iterateCursor, DONE, NOT_DONE, reqAsPromise} from "./utils";
import {Transaction} from "./Transaction"; import {StorageError} from "../common";
import {LogItem} from "../../../logging/LogItem.js";
import {IDBKey} from "./Transaction";
export interface ITransaction {
idbFactory: IDBFactory;
IDBKeyRange: typeof IDBKeyRange;
addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, keys: IDBKey[] | undefined);
}
type Reducer<A,B> = (acc: B, val: A) => B type Reducer<A,B> = (acc: B, val: A) => B
@ -32,9 +40,9 @@ interface QueryTargetInterface<T> {
export class QueryTarget<T> { export class QueryTarget<T> {
protected _target: QueryTargetInterface<T>; protected _target: QueryTargetInterface<T>;
protected _transaction: Transaction; protected _transaction: ITransaction;
constructor(target: QueryTargetInterface<T>, transaction: Transaction) { constructor(target: QueryTargetInterface<T>, transaction: ITransaction) {
this._target = target; this._target = target;
this._transaction = transaction; this._transaction = transaction;
} }
@ -167,7 +175,6 @@ export class QueryTarget<T> {
const sortedKeys = keys.slice().sort(compareKeys); const sortedKeys = keys.slice().sort(compareKeys);
const firstKey = sortedKeys[0]; const firstKey = sortedKeys[0];
const lastKey = sortedKeys[sortedKeys.length - 1]; const lastKey = sortedKeys[sortedKeys.length - 1];
console.log(firstKey, lastKey, sortedKeys);
const direction = backwards ? "prev" : "next"; const direction = backwards ? "prev" : "next";
const cursor = this._target.openKeyCursor(this.IDBKeyRange.bound(firstKey, lastKey), direction); const cursor = this._target.openKeyCursor(this.IDBKeyRange.bound(firstKey, lastKey), direction);
let index = 0; let index = 0;
@ -254,3 +261,101 @@ export class QueryTarget<T> {
} }
} }
} }
import {createMockDatabase, MockIDBImpl} from "../../../mocks/Storage";
import {txnAsPromise} from "./utils";
import {QueryTargetWrapper, Store} from "./Store";
export function tests() {
class MockTransaction extends MockIDBImpl {
addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, keys: IDBKey[] | undefined) {}
}
interface TestEntry {
key: string
}
async function createTestStore(): Promise<Store<TestEntry>> {
const mockImpl = new MockTransaction();
const db = await createMockDatabase("findExistingKeys", (db: IDBDatabase) => {
db.createObjectStore("test", {keyPath: "key"});
}, mockImpl);
const txn = db.transaction(["test"], "readwrite");
return new Store<TestEntry>(txn.objectStore("test"), mockImpl);
}
return {
"findExistingKeys should not match on empty store": async assert => {
const store = await createTestStore();
await store.findExistingKeys(["2db1a709-d8f1-4c40-a835-f312badd277a", "fe7aa5c2-d4ed-4278-b3b0-f49d48d11df2"], false, () => {
assert.fail("no key should match");
return false;
});
},
"findExistingKeys should not match any existing keys (in between sorting order)": async assert => {
const store = await createTestStore();
store.add({key: "43cd16eb-a6b4-4b9d-ab36-ab87d1b038c3"});
store.add({key: "b655e7c5-e02d-4823-a7af-4202b12de659"});
await store.findExistingKeys(["2db1a709-d8f1-4c40-a835-f312badd277a", "fe7aa5c2-d4ed-4278-b3b0-f49d48d11df2"], false, () => {
assert.fail("no key should match");
return false;
});
},
"findExistingKeys should match only existing keys": async assert => {
const store = await createTestStore();
store.add({key: "2db1a709-d8f1-4c40-a835-f312badd277a"});
store.add({key: "43cd16eb-a6b4-4b9d-ab36-ab87d1b038c3"});
store.add({key: "fe7aa5c2-d4ed-4278-b3b0-f49d48d11df2"});
const found: string[] = [];
await store.findExistingKeys([
"2db1a709-d8f1-4c40-a835-f312badd277a",
"eac3ef5c-a48f-4e19-b41d-ebd1d84c53f2",
"fe7aa5c2-d4ed-4278-b3b0-f49d48d11df2"
], false, (key: IDBValidKey) => {
found.push(key as string);
return false;
});
assert.equal(found.length, 2);
assert.equal(found[0], "2db1a709-d8f1-4c40-a835-f312badd277a");
assert.equal(found[1], "fe7aa5c2-d4ed-4278-b3b0-f49d48d11df2");
},
"findExistingKeys should match all if all exist": async assert => {
const store = await createTestStore();
store.add({key: "2db1a709-d8f1-4c40-a835-f312badd277a"});
store.add({key: "fe7aa5c2-d4ed-4278-b3b0-f49d48d11df2"});
store.add({key: "b655e7c5-e02d-4823-a7af-4202b12de659"});
const found: string[] = [];
await store.findExistingKeys([
"2db1a709-d8f1-4c40-a835-f312badd277a",
"b655e7c5-e02d-4823-a7af-4202b12de659",
"fe7aa5c2-d4ed-4278-b3b0-f49d48d11df2"
], false, (key: IDBValidKey) => {
found.push(key as string);
return false;
});
assert.equal(found.length, 3);
assert.equal(found[0], "2db1a709-d8f1-4c40-a835-f312badd277a");
assert.equal(found[1], "b655e7c5-e02d-4823-a7af-4202b12de659");
assert.equal(found[2], "fe7aa5c2-d4ed-4278-b3b0-f49d48d11df2");
},
"findExistingKeys should stop matching when callback returns true": async assert => {
const store = await createTestStore();
store.add({key: "2db1a709-d8f1-4c40-a835-f312badd277a"});
store.add({key: "fe7aa5c2-d4ed-4278-b3b0-f49d48d11df2"});
store.add({key: "b655e7c5-e02d-4823-a7af-4202b12de659"});
const found: string[] = [];
await store.findExistingKeys([
"2db1a709-d8f1-4c40-a835-f312badd277a",
"b655e7c5-e02d-4823-a7af-4202b12de659",
"fe7aa5c2-d4ed-4278-b3b0-f49d48d11df2"
], false, (key: IDBValidKey) => {
found.push(key as string);
return true;
});
assert.equal(found.length, 1);
assert.equal(found[0], "2db1a709-d8f1-4c40-a835-f312badd277a");
},
}
}

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {QueryTarget, IDBQuery} from "./QueryTarget"; import {QueryTarget, IDBQuery, ITransaction} from "./QueryTarget";
import {IDBRequestError, IDBRequestAttemptError} from "./error"; import {IDBRequestError, IDBRequestAttemptError} from "./error";
import {reqAsPromise} from "./utils"; import {reqAsPromise} from "./utils";
import {Transaction, IDBKey} from "./Transaction"; import {Transaction, IDBKey} from "./Transaction";
@ -28,7 +28,7 @@ function logRequest(method: string, params: any[], source: any): void {
console.info(`${databaseName}.${storeName}.${method}(${params.map(p => JSON.stringify(p)).join(", ")})`); console.info(`${databaseName}.${storeName}.${method}(${params.map(p => JSON.stringify(p)).join(", ")})`);
} }
class QueryTargetWrapper<T> { export class QueryTargetWrapper<T> {
private _qt: IDBIndex | IDBObjectStore; private _qt: IDBIndex | IDBObjectStore;
constructor(qt: IDBIndex | IDBObjectStore) { constructor(qt: IDBIndex | IDBObjectStore) {
@ -133,7 +133,7 @@ class QueryTargetWrapper<T> {
} }
export class Store<T> extends QueryTarget<T> { export class Store<T> extends QueryTarget<T> {
constructor(idbStore: IDBObjectStore, transaction: Transaction) { constructor(idbStore: IDBObjectStore, transaction: ITransaction) {
super(new QueryTargetWrapper<T>(idbStore), transaction); super(new QueryTargetWrapper<T>(idbStore), transaction);
} }