UNPKG

@keyv/test-suite

Version:

Test suite for Keyv API compliancy

496 lines (487 loc) 19.4 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { default: () => index_default, delay: () => delay, keyvApiTests: () => api_default, keyvCompresstionTests: () => compression_default, keyvIteratorTests: () => iterator_default, keyvNamespaceTest: () => namespace_default, keyvValueTests: () => values_default }); module.exports = __toCommonJS(index_exports); // src/api.ts var import_timekeeper = __toESM(require("timekeeper"), 1); var keyvApiTests = (test, Keyv2, store) => { test.beforeEach(async () => { const keyv = new Keyv2({ store: store() }); await keyv.clear(); }); test.it(".set(key, value) returns a Promise", (t) => { const keyv = new Keyv2({ store: store() }); t.expect(keyv.set("foo", "bar") instanceof Promise).toBeTruthy(); }); test.it(".set(key, value) resolves to true", async (t) => { const keyv = new Keyv2({ store: store() }); t.expect(await keyv.set("foo", "bar")).toBeTruthy(); }); test.it(".set(key, value) sets a value", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", "bar"); t.expect(await keyv.get("foo")).toBe("bar"); }); test.it(".set(key, value, ttl) sets a value that expires", async (t) => { const ttl = 1e3; const keyv = new Keyv2({ store: store() }); await keyv.set("foo", "bar", ttl); t.expect(await keyv.get("foo")).toBe("bar"); import_timekeeper.default.freeze(Date.now() + ttl + 1); t.expect(await keyv.get("foo")).toBeUndefined(); import_timekeeper.default.reset(); }); test.it(".get(key) returns a Promise", (t) => { const keyv = new Keyv2({ store: store() }); t.expect(keyv.get("foo") instanceof Promise).toBeTruthy(); }); test.it(".get(key) resolves to value", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", "bar"); t.expect(await keyv.get("foo")).toBe("bar"); }); test.it(".get(key) with nonexistent key resolves to undefined", async (t) => { const keyv = new Keyv2({ store: store() }); t.expect(await keyv.get("foo")).toBeUndefined(); }); test.it(".get([keys]) should return array values", async (t) => { const keyv = new Keyv2({ store: store() }); const ttl = 3e3; await keyv.set("foo", "bar", ttl); await keyv.set("foo1", "bar1", ttl); await keyv.set("foo2", "bar2", ttl); const values = await keyv.get(["foo", "foo1", "foo2"]); t.expect(Array.isArray(values)).toBeTruthy(); t.expect(values[0]).toBe("bar"); t.expect(values[1]).toBe("bar1"); t.expect(values[2]).toBe("bar2"); }); test.it(".get([keys]) should return array value undefined when expires", async (t) => { const keyv = new Keyv2(); await keyv.set("foo", "bar"); await keyv.set("foo1", "bar1", 1); await keyv.set("foo2", "bar2"); await new Promise((resolve) => { setTimeout(() => { resolve(); }, 30); }); const values = await keyv.get(["foo", "foo1", "foo2"]); t.expect(Array.isArray(values)).toBeTruthy(); t.expect(values[0]).toBe("bar"); t.expect(values[1]).toBeUndefined(); t.expect(values[2]).toBe("bar2"); }); test.it(".get([keys]) should return array values with undefined", async (t) => { const keyv = new Keyv2({ store: store() }); const ttl = 3e3; await keyv.set("foo", "bar", ttl); await keyv.set("foo2", "bar2", ttl); const values = await keyv.get(["foo", "foo1", "foo2"]); t.expect(Array.isArray(values)).toBeTruthy(); t.expect(values[0]).toBe("bar"); t.expect(values[1]).toBeUndefined(); t.expect(values[2]).toBe("bar2"); }); test.it(".get([keys]) should return undefined array for all no existent keys", async (t) => { const keyv = new Keyv2({ store: store() }); const values = await keyv.get(["foo", "foo1", "foo2"]); t.expect(Array.isArray(values)).toBeTruthy(); t.expect(values).toEqual([void 0, void 0, void 0]); }); test.it(".delete(key) returns a Promise", (t) => { const keyv = new Keyv2({ store: store() }); t.expect(keyv.delete("foo") instanceof Promise).toBeTruthy(); }); test.it(".delete([key]) returns a Promise", (t) => { const keyv = new Keyv2({ store: store() }); t.expect(keyv.delete(["foo"]) instanceof Promise).toBeTruthy(); }); test.it(".delete(key) resolves to true", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", "bar"); t.expect(await keyv.delete("foo")).toBeTruthy(); }); test.it(".delete(key) with nonexistent key resolves to false", async (t) => { const keyv = new Keyv2({ store: store() }); t.expect(await keyv.delete("foo")).toBeFalsy(); }); test.it(".delete(key) deletes a key", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", "bar"); t.expect(await keyv.delete("foo")).toBeTruthy(); t.expect(await keyv.get("foo")).toBeUndefined(); }); test.it(".deleteMany([keys]) should delete multiple key", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", "bar"); await keyv.set("foo1", "bar1"); await keyv.set("foo2", "bar2"); t.expect(await keyv.delete(["foo", "foo1", "foo2"])).toBeTruthy(); t.expect(await keyv.get("foo")).toBeUndefined(); t.expect(await keyv.get("foo1")).toBeUndefined(); t.expect(await keyv.get("foo2")).toBeUndefined(); }); test.it(".deleteMany([keys]) with nonexistent keys resolves to false", async (t) => { const keyv = new Keyv2({ store: store() }); t.expect(await keyv.delete(["foo", "foo1", "foo2"])).toBeFalsy(); }); test.it(".clear() returns a Promise", async (t) => { const keyv = new Keyv2({ store: store() }); const returnValue = keyv.clear(); t.expect(returnValue instanceof Promise).toBeTruthy(); await returnValue; }); test.it(".clear() resolves to undefined", async (t) => { const keyv = new Keyv2({ store: store() }); t.expect(await keyv.clear()).toBeUndefined(); await keyv.set("foo", "bar"); t.expect(await keyv.clear()).toBeUndefined(); }); test.it(".clear() deletes all key/value pairs", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", "bar"); await keyv.set("fizz", "buzz"); await keyv.clear(); t.expect(await keyv.get("foo")).toBeUndefined(); t.expect(await keyv.get("fizz")).toBeUndefined(); }); test.it(".has(key) where key is the key we are looking for", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", "bar"); t.expect(await keyv.has("foo")).toBeTruthy(); t.expect(await keyv.has("fizz")).toBeFalsy(); }); }; var api_default = keyvApiTests; // src/values.ts var import_buffer = require("buffer"); var import_json_bigint = __toESM(require("json-bigint"), 1); var import_bignumber = __toESM(require("bignumber.js"), 1); var keyvValueTests = (test, Keyv2, store) => { test.beforeEach(async () => { const keyv = new Keyv2({ store: store() }); await keyv.clear(); }); test.it("value can be false", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", false); t.expect(await keyv.get("foo")).toBeFalsy(); }); test.it("value can be null", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", null); t.expect(await keyv.get("foo")).toBeNull(); }); test.it("value can be undefined", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", void 0); t.expect(await keyv.get("foo")).toBeUndefined(); }); test.it("value can be a number", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", 0); t.expect(await keyv.get("foo")).toBe(0); }); test.it("value can be an object", async (t) => { const keyv = new Keyv2({ store: store() }); const value = { fizz: "buzz" }; await keyv.set("foo", value); t.expect(await keyv.get("foo")).toEqual(value); }); test.it("value can be a buffer", async (t) => { const keyv = new Keyv2({ store: store() }); const buf = import_buffer.Buffer.from("bar"); await keyv.set("foo", buf); t.expect(buf.equals(await keyv.get("foo"))).toBeTruthy(); }); test.it("value can be an object containing a buffer", async (t) => { const keyv = new Keyv2({ store: store() }); const value = { buff: import_buffer.Buffer.from("buzz") }; await keyv.set("foo", value); t.expect(await keyv.get("foo")).toEqual(value); }); test.it("value can contain quotes", async (t) => { const keyv = new Keyv2({ store: store() }); const value = '"'; await keyv.set("foo", value); t.expect(await keyv.get("foo")).toEqual(value); }); test.it("value can be a string", async (t) => { const keyv = new Keyv2({ store: store() }); await keyv.set("foo", "bar"); t.expect(await keyv.get("foo")).toBe("bar"); }); test.it("value can not be symbol", async (t) => { const keyv = new Keyv2({ store: store() }); const value = Symbol("value"); let errorObject; try { await keyv.set("foo", value); } catch (error) { errorObject = error; t.expect(error.message).toBe("symbol cannot be serialized"); } t.expect(errorObject.message).toBe("symbol cannot be serialized"); }); test.it("value can be BigInt using other serializer/deserializer", async (t) => { store().opts.deserialize = import_json_bigint.default.parse; const keyv = new Keyv2({ store: store(), serialize: import_json_bigint.default.stringify, deserialize: import_json_bigint.default.parse }); const value = BigInt("9223372036854775807"); await keyv.set("foo", value); const storedValue = await keyv.get("foo"); t.expect(import_json_bigint.default.stringify(storedValue)).toBe((0, import_bignumber.default)(value).toString()); }); test.it("single quotes value should be saved", async (t) => { const keyv = new Keyv2({ store: store() }); let value = "'"; await keyv.set("key", value); t.expect(await keyv.get("key")).toBe(value); value = "''"; await keyv.set("key1", value); t.expect(await keyv.get("key1")).toBe(value); value = '"'; await keyv.set("key2", value); t.expect(await keyv.get("key2")).toBe(value); }); test.it("single quotes key should be saved", async (t) => { const keyv = new Keyv2({ store: store() }); const value = "'"; const key = "'"; await keyv.set(key, value); t.expect(await keyv.get(key)).toBe(value); }); }; var values_default = keyvValueTests; // src/namespace.ts var keyvNamespaceTests = (test, Keyv2, store) => { test.beforeEach(async () => { const keyv1 = new Keyv2({ store: store(), namespace: "keyv1" }); const keyv2 = new Keyv2({ store: store(), namespace: "keyv2" }); await keyv1.clear(); await keyv2.clear(); }); test.it("namespaced set/get don't collide", async (t) => { const keyv1 = new Keyv2({ store: store(), namespace: "keyv1" }); const keyv2 = new Keyv2({ store: store(), namespace: "keyv2" }); await keyv1.set("foo", "keyv1"); await keyv2.set("foo", "keyv2"); t.expect(await keyv1.get("foo")).toBe("keyv1"); t.expect(await keyv2.get("foo")).toBe("keyv2"); }); test.it("namespaced delete only deletes from current namespace", async (t) => { const keyv1 = new Keyv2({ store: store(), namespace: "keyv1" }); const keyv2 = new Keyv2({ store: store(), namespace: "keyv2" }); await keyv1.set("foo", "keyv1"); await keyv2.set("foo", "keyv2"); t.expect(await keyv1.delete("foo")).toBe(true); t.expect(await keyv1.get("foo")).toBeUndefined(); t.expect(await keyv2.get("foo")).toBe("keyv2"); }); test.it("namespaced clear only clears current namespace", async (t) => { const keyv1 = new Keyv2({ store: store(), namespace: "keyv1" }); const keyv2 = new Keyv2({ store: store(), namespace: "keyv2" }); await keyv1.set("foo", "keyv1"); await keyv1.set("bar", "keyv1"); await keyv2.set("foo", "keyv2"); await keyv2.set("bar", "keyv2"); await keyv1.clear(); t.expect(await keyv1.get("foo")).toBeUndefined(); t.expect(await keyv1.get("bar")).toBeUndefined(); t.expect(await keyv2.get("foo")).toBe("keyv2"); t.expect(await keyv2.get("bar")).toBe("keyv2"); }); test.afterEach(async () => { const keyv1 = new Keyv2({ store: store(), namespace: "keyv1" }); const keyv2 = new Keyv2({ store: store(), namespace: "keyv2" }); await keyv1.clear(); await keyv2.clear(); }); }; var namespace_default = keyvNamespaceTests; // src/helper.ts async function delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } // src/iterator.ts var keyvIteratorTests = (test, Keyv2, store) => { test.beforeEach(async () => { const keyv = new Keyv2({ store: store() }); await keyv.clear(); }); test.it(".iterator() returns an asyncIterator", (t) => { const keyv = new Keyv2({ store: store() }); t.expect(typeof keyv.iterator()[Symbol.asyncIterator]).toBe("function"); }); test.it("iterator() iterates over all values", async (t) => { const keyv = new Keyv2({ store: store() }); const map = new Map(Array.from({ length: 5 }).fill(0).map((_x, i) => [String(i), String(i + 10)])); const toResolve = []; for (const [key, value] of map) { toResolve.push(keyv.set(key, value)); } await Promise.all(toResolve); t.expect.assertions(map.size); for await (const [key, value] of keyv.iterator()) { const doesKeyExist = map.has(key); const isValueSame = map.get(key) === value; t.expect(doesKeyExist && isValueSame).toBeTruthy(); } }); test.it( "iterator() doesn't yield values from other namespaces", async (t) => { const keyvStore = store(); const keyv1 = new Keyv2({ store: keyvStore, namespace: "keyv1" }); const map1 = new Map(Array.from({ length: 5 }).fill(0).map((_x, i) => [String(i), String(i + 10)])); const toResolve = []; for (const [key, value] of map1) { toResolve.push(keyv1.set(key, value)); } await Promise.all(toResolve); const keyv2 = new Keyv2({ store: keyvStore, namespace: "keyv2" }); const map2 = new Map(Array.from({ length: 5 }).fill(0).map((_x, i) => [String(i), String(i + 11)])); toResolve.length = 0; for (const [key, value] of map2) { toResolve.push(keyv2.set(key, value)); } await Promise.all(toResolve); t.expect.assertions(map2.size); for await (const [key, value] of keyv2.iterator()) { const doesKeyExist = map2.has(key); const isValueSame = map2.get(key) === value; t.expect(doesKeyExist && isValueSame).toBeTruthy(); } } ); test.it( "iterator() doesn't yield expired values, and deletes them", async (t) => { const keyv = new Keyv2({ store: store() }); const map = new Map(Array.from({ length: 5 }).fill(0).map((_x, i) => [String(i), String(i + 10)])); const toResolve = []; for (const [key, value] of map) { toResolve.push(keyv.set(key, value, 200)); } toResolve.push(keyv.set("foo", "bar")); await Promise.all(toResolve); await delay(250); const iterator = keyv.iterator(); let entry = await iterator.next(); const [k, v] = entry.value; t.expect(k).toBe("foo"); t.expect(v).toBe("bar"); entry = await iterator.next(); t.expect(entry.value).toBeUndefined(); } ); }; var iterator_default = keyvIteratorTests; // src/compression.ts var import_keyv = __toESM(require("keyv"), 1); var keyvCompressionTests = (test, compression) => { let keyv; test.beforeEach(async () => { keyv = new import_keyv.default({ store: /* @__PURE__ */ new Map(), compression }); await keyv.clear(); }); test.it("number array compression/decompression", async (t) => { const array = JSON.stringify([4, 5, 6, 7]); const compressed = await compression.compress(array); const decompressed = JSON.parse(await compression.decompress(compressed)); t.expect(decompressed).toEqual([4, 5, 6, 7]); }); test.it("compression/decompression using default options", async (t) => { const compressed = await compression.compress("whatever"); t.expect(compressed).not.toBe("whatever"); const decompressed = await compression.decompress(compressed); t.expect(decompressed).toBe("whatever"); }); test.it("compression/decompression with number", async (t) => { const number_ = JSON.stringify(5); const compressed = await compression.compress(number_); t.expect(compressed).not.toBe(5); const decompressed = JSON.parse(await compression.decompress(compressed)); t.expect(decompressed).toBe(5); }); test.it("serialize compression", async (t) => { const json = await compression.serialize({ value: "whatever", expires: void 0 }); t.expect(JSON.parse(json).value).not.toBe("whatever"); }); test.it("deserialize compression", async (t) => { const json = await compression.serialize({ value: "whatever", expires: void 0 }); const djson = await compression.deserialize(json); t.expect(djson).toEqual({ expires: void 0, value: "whatever" }); }); test.it("compress/decompress with main keyv", async (t) => { const keyv2 = new import_keyv.default({ compression }); await keyv2.set("foo", "bar"); t.expect(await keyv2.get("foo")).toBe("bar"); }); }; var compression_default = keyvCompressionTests; // src/index.ts var keyvTestSuite = (test, Keyv2, store) => { api_default(test, Keyv2, store); values_default(test, Keyv2, store); namespace_default(test, Keyv2, store); }; var index_default = keyvTestSuite; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { delay, keyvApiTests, keyvCompresstionTests, keyvIteratorTests, keyvNamespaceTest, keyvValueTests });