forked from mystiq/hydrogen-web
add unit tests for findExistingKeys
This commit is contained in:
parent
edc3a1d33c
commit
ec2f1b9833
2 changed files with 112 additions and 7 deletions
|
@ -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");
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue