UNPKG

@launchmenu/core

Version:

An environment for visual keyboard controlled applets

577 lines 66.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const model_react_1 = require("model-react"); const wait_helper_1 = require("../../../_tests/wait.helper"); const CoreSearchExecuter_1 = require("../CoreSearchExecuter"); const createSimpleResultMap_helper_1 = require("./createSimpleResultMap.helper"); const createSimpleSearch_helper_1 = require("./createSimpleSearch.helper"); const createSimpleResultMap = () => { const nodes = {}; const listener = new model_react_1.ManualSourceHelper(); return { onRemove: (ID) => { const contains = nodes[ID]; delete nodes[ID]; if (contains) listener.callListeners(); }, onUpdate: (ID, data) => { nodes[ID] = data; listener.callListeners(); }, getItems: (hook) => { listener.addListener(hook); return createSimpleResultMap_helper_1.s(Object.values(nodes) .map(({ item }) => item) .filter(Boolean)); }, getNodes: (hook) => { listener.addListener(hook); return Object.values(nodes); }, nodes, }; }; const createCoreExecuter = (searchable) => { const result = createSimpleResultMap(); return [new CoreSearchExecuter_1.CoreSearchExecuter({ searchable, ...result }), result]; }; describe("CoreSearchExecuter", () => { describe("new CoreSearchExecuter", () => { it("Can be constructed", () => { new CoreSearchExecuter_1.CoreSearchExecuter({ searchable: createSimpleSearch_helper_1.createSimpleSearch({ m: () => true }), onRemove: () => { }, onUpdate: () => { }, }); }); }); describe("CoreSearchExecuter.setQuery", () => { describe("Correctly obtains the items recursively", () => { it("Correctly obtains the items recursively", async () => { const search = createSimpleSearch_helper_1.createSimpleSearch({ m: s => s == "s" }); const [executer, result] = createCoreExecuter(search); await executer.setQuery("s"); expect(result.getItems()).toEqual([search.ID]); const [executer2, result2] = createCoreExecuter(search); await executer2.setQuery(""); expect(result2.getItems()).toEqual([]); }); it("Works on searchables returning children", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ m: s => s.substr(0, 1) == "s" }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ m: s => s.substr(0, 2) == "s2" }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ children: [search1, search2] }); const [executer, result] = createCoreExecuter(search3); await executer.setQuery("s"); expect(result.getItems()).toEqual([search1.ID]); const [executer2, result2] = createCoreExecuter(search3); await executer2.setQuery("s2"); expect(createSimpleResultMap_helper_1.s(result2.getItems())).toEqual(createSimpleResultMap_helper_1.s([search1.ID, search2.ID])); const [executer3, result3] = createCoreExecuter(search3); await executer3.setQuery("test"); expect(result3.getItems()).toEqual([]); }); it("Works on searchables returning children and items", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ m: s => s.substr(0, 1) == "s" }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ m: s => s.substr(0, 2) == "s2" }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ m: s => s.substr(0, 2) == "s3", children: [search1, search2], }); const [executer, result] = createCoreExecuter(search3); await executer.setQuery("s"); expect(result.getItems()).toEqual([search1.ID]); const [executer2, result2] = createCoreExecuter(search3); await executer2.setQuery("s2"); expect(result2.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID, search2.ID])); const [executer3, result3] = createCoreExecuter(search3); await executer3.setQuery("s3"); expect(result3.getItems()).toEqual(createSimpleResultMap_helper_1.s([search3.ID, search1.ID])); const [executer4, result4] = createCoreExecuter(search3); await executer4.setQuery("test"); expect(result4.getItems()).toEqual([]); }); }); describe("Correctly updates old items", () => { it("Works correctly when search indicates it no longer matches", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: s => s.substr(0, 1) == "s", }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: s => s.substr(0, 2) == "s2", }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: s => s.substr(0, 2) == "s3", children: [search1, search2], }); const [executer, result] = createCoreExecuter(search3); await executer.setQuery("s"); expect(result.getItems()).toEqual([search1.ID]); await executer.setQuery("s2"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID, search2.ID])); await executer.setQuery("s3"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID, search3.ID])); await executer.setQuery("test"); expect(result.getItems()).toEqual([]); }); it("Works correctly when search indicates children are no longer there", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: s => s.substr(s.length - 1) == "s", }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: s => s.substr(s.length - 1) == "t", }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: s => s.substr(0, 1) == "s", children: s => (s.substr(0, 1) == "s" ? [search1, search2] : []), }); const [executer, result] = createCoreExecuter(search3); await executer.setQuery("s"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search3.ID, search1.ID])); await executer.setQuery("s2"); expect(result.getItems()).toEqual([search3.ID]); await executer.setQuery("st"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search3.ID, search2.ID])); await executer.setQuery("t"); expect(result.getItems()).toEqual([]); await executer.setQuery("st"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search3.ID, search2.ID])); await executer.setQuery("s2"); expect(result.getItems()).toEqual([search3.ID]); }); describe("Multiple parents", () => { it("Doesn't duplicate results", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: s => s.substr(s.length - 1) == "s", }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: s => s.substr(s.length - 1) == "t", children: [search1], }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: s => s.substr(0, 1) == "s", children: [search1], }); const search4 = createSimpleSearch_helper_1.createSimpleSearch({ id: "4", m: s => s.substr(0, 1) == "s", children: [search2, search3], }); const updateCallback = jest.fn(); const executer = new CoreSearchExecuter_1.CoreSearchExecuter({ searchable: search4, onUpdate: updateCallback, onRemove: () => { }, }); await executer.setQuery("s"); expect(updateCallback.mock.calls.length).toBe(4); await executer.setQuery("t"); expect(updateCallback.mock.calls.length).toBe(8); }); it("Doesn't remove child results until all parents removed the child", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: s => s[0] == "s", }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: s => s[0] == "t", children: s => (s.includes("m") ? [] : [search1]), }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: s => s[0] == "s", children: s => (s.includes("i") ? [] : [search1]), }); const search4 = createSimpleSearch_helper_1.createSimpleSearch({ id: "4", m: s => s[0] == "s", children: [search2, search3], }); const [executer, result] = createCoreExecuter(search4); await executer.setQuery("s"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search4.ID, search3.ID, search1.ID])); await executer.setQuery("sm"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search4.ID, search3.ID, search1.ID])); await executer.setQuery("si"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search4.ID, search3.ID, search1.ID])); await executer.setQuery("sim"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search4.ID, search3.ID])); await executer.setQuery("si"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search4.ID, search3.ID, search1.ID])); }); }); }); describe("Correctly interrupts previous searches", () => { it("Correctly cancels previous searches", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: async (s) => { await wait_helper_1.wait(10); return s == "s"; }, }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: async (s) => { await wait_helper_1.wait(10); return s == "s"; }, }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: async (s) => { await wait_helper_1.wait(10); return s == "s"; }, }); const search4 = createSimpleSearch_helper_1.createSimpleSearch({ id: "4", m: async (s) => { await wait_helper_1.wait(10); return s == "s"; }, children: s => [search1, search2, search3], }); const [executer, result] = createCoreExecuter(search4); await executer.setQuery("s"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID, search2.ID, search3.ID, search4.ID])); const [executer2, result2] = createCoreExecuter(search3); executer2.setQuery("s"); await wait_helper_1.wait(20); // requires 40ms+ to complete expect(result2.getItems()).not.toEqual(createSimpleResultMap_helper_1.s([search1.ID, search2.ID, search3.ID, search4.ID])); let resolved = false; executer.setQuery("st").then(() => (resolved = true)); await wait_helper_1.wait(70); // Requires at most 10 ms to interrupt, + 40ms to complete expect(result.getItems()).toEqual([]); expect(resolved).toBe(true); }); it("Correctly removes items registered to be added", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: async (s) => { await wait_helper_1.wait(10); return s == "s"; }, }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: async (s) => { await wait_helper_1.wait(10); return s == "s"; }, }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: async (s) => { await wait_helper_1.wait(10); return s == "s" || s == "o"; }, }); const search4 = createSimpleSearch_helper_1.createSimpleSearch({ id: "4", m: async (s) => { await wait_helper_1.wait(10); return s == "s" || s == "o"; }, children: s => (s == "o" ? [] : [search1, search2, search3]), }); const [executer, result] = createCoreExecuter(search4); await executer.setQuery("t"); expect(result.getItems()).toEqual([]); // Update the query which should schedule all searches, but the first search should result in all searches being removed (despite being scheduled already) await executer.setQuery("o"); expect(result.getItems()).toEqual([search4.ID]); // Just a normal search to confirm nothing yanky is going on in the test in general await executer.setQuery("s"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search4.ID, search3.ID, search2.ID, search1.ID])); }); it("Correctly updates previously added items before finding new ones", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: async (s) => { await wait_helper_1.wait(50); return s == "s"; }, }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: async (s) => { await wait_helper_1.wait(50); return s == "s"; }, }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: async (s) => { await wait_helper_1.wait(50); return s == "o"; }, children: s => [search2, search1], }); const search4 = createSimpleSearch_helper_1.createSimpleSearch({ id: "4", m: async (s) => { await wait_helper_1.wait(50); return s == "o"; }, children: s => [search3], }); const sequence = []; const result = createSimpleResultMap(); let searchUpdated = false; const executer = new CoreSearchExecuter_1.CoreSearchExecuter({ searchable: search4, onUpdate: (ID, data) => { sequence.push({ type: "update", ID }); result.onUpdate(ID, data); // Update the query when node 3 is reached the first time if (!searchUpdated && ID == "3") { searchUpdated = true; sequence.push(null); executer.setQuery("s"); } }, onRemove: (ID, ...rest) => { sequence.push({ type: "remove", ID }); result.onRemove(ID); }, }); await executer.setQuery("o"); expect(sequence).toEqual([ { type: "update", ID: search4.ID }, { type: "update", ID: search3.ID }, null, { type: "update", ID: search3.ID }, { type: "update", ID: search4.ID }, { type: "update", ID: search2.ID }, { type: "update", ID: search1.ID }, ]); }); it("Correctly retains the latest result when results resolve out of order", async () => { let time = 0; let resolveOrder = []; const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: async (s) => { const d = ++time; // Add extra delay such that the first result resolves after the second if (d == 1) await wait_helper_1.wait(100); else await wait_helper_1.wait(20); resolveOrder.push(d); return s == "s"; }, }); const [executer, result] = createCoreExecuter(search1); executer.setQuery("s"); await wait_helper_1.wait(20); executer.setQuery("p"); await wait_helper_1.wait(110); expect(result.getItems()).toEqual([]); expect(resolveOrder).toEqual([2, 1]); }); }); describe("Refreshes searches when the searchable changes", () => { it("Correctly updates the resulting item of a search when requested", async () => { const field1 = new model_react_1.Field("o"); const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: (s, h) => s == field1.get(h), }); const field2 = new model_react_1.Field("s"); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: (s, h) => s == field2.get(h), }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: s => s == "o", children: s => [search1, search2], }); const [executer, result] = createCoreExecuter(search3); await executer.setQuery("s"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search2.ID])); await executer.setQuery("o"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID, search3.ID])); field2.set("o"); await wait_helper_1.wait(1); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID, search2.ID, search3.ID])); field1.set("s"); await wait_helper_1.wait(1); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search2.ID, search3.ID])); await executer.setQuery("s"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID])); }); it("Correctly updates the children of a search when requested", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: s => s == "s" || s == "p", }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: s => s == "o" || s == "p", }); const field = new model_react_1.Field("m"); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: s => s == "o" || s == "p", children: (s, h) => (s == field.get(h) ? [] : [search1, search2]), }); const [executer, result] = createCoreExecuter(search3); await executer.setQuery("s"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID])); await executer.setQuery("o"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search2.ID, search3.ID])); await executer.setQuery("p"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID, search2.ID, search3.ID])); field.set("p"); await wait_helper_1.wait(1); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search3.ID])); }); it("Doesn't update unaffected items", async () => { const field1 = new model_react_1.Field("o"); const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: (s, h) => s == field1.get(h), }); const field2 = new model_react_1.Field("s"); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: (s, h) => s == field2.get(h), }); let request = false; const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: s => { request = true; return s == "o"; }, children: s => [search1, search2], }); const [executer, result] = createCoreExecuter(search3); await executer.setQuery("s"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search2.ID])); request = false; await executer.setQuery("o"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID, search3.ID])); expect(request).toBe(true); request = false; field2.set("o"); await wait_helper_1.wait(1); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID, search2.ID, search3.ID])); expect(request).toBe(false); field1.set("s"); await wait_helper_1.wait(1); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search2.ID, search3.ID])); expect(request).toBe(false); await executer.setQuery("s"); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search1.ID])); expect(request).toBe(true); }); }); describe("Correctly executes searches in parallel", () => { it("Doesn't make one search block an other", async () => { const search1 = createSimpleSearch_helper_1.createSimpleSearch({ id: "1", m: async (s) => { await wait_helper_1.wait(10); return s == "s"; }, }); const search2 = createSimpleSearch_helper_1.createSimpleSearch({ id: "2", m: async (s) => { await wait_helper_1.wait(150); return s == "s"; }, }); const search3 = createSimpleSearch_helper_1.createSimpleSearch({ id: "3", m: async (s) => { await wait_helper_1.wait(10); return s == "s"; }, children: s => [search1], }); const search4 = createSimpleSearch_helper_1.createSimpleSearch({ id: "4", m: async (s) => { await wait_helper_1.wait(70); return s == "s"; }, }); const search5 = createSimpleSearch_helper_1.createSimpleSearch({ id: "5", m: async (s) => { await wait_helper_1.wait(10); return s == "s"; }, children: s => [search2, search3, search4], }); const [executer, result] = createCoreExecuter(search5); const searchPromise = executer.setQuery("s"); await wait_helper_1.wait(50); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search5.ID, search1.ID, search3.ID])); await wait_helper_1.wait(50); expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search5.ID, search1.ID, search3.ID, search4.ID])); await searchPromise; expect(result.getItems()).toEqual(createSimpleResultMap_helper_1.s([search5.ID, search1.ID, search3.ID, search4.ID, search2.ID])); }); }); }); describe("CoreSearchExecuter.getQuery", () => { it("Correctly reflects the latest query", () => { const search = createSimpleSearch_helper_1.createSimpleSearch({ m: s => s == "s" }); const [executer] = createCoreExecuter(search); executer.setQuery("hoi"); expect(executer.getQuery()).toEqual("hoi"); }); it("Can be subscribed to", async () => { const search = createSimpleSearch_helper_1.createSimpleSearch({ m: s => s == "s" }); const [executer] = createCoreExecuter(search); const listener = jest.fn(); new model_react_1.Observer(h => executer.getQuery(h)).listen(listener); executer.setQuery("hoi"); await wait_helper_1.wait(1); executer.setQuery("stuff"); await wait_helper_1.wait(1); expect(listener.mock.calls[0][0]).toEqual("hoi"); expect(listener.mock.calls[1][0]).toEqual("stuff"); }); }); describe("CoreSearchExecuter.isSearching", () => { it("Correctly reflects the search status", async () => { const search = createSimpleSearch_helper_1.createSimpleSearch({ m: async (s) => wait_helper_1.wait(20, s == "s") }); const [executer] = createCoreExecuter(search); expect(executer.isSearching()).toEqual(false); const promise = executer.setQuery("hoi"); await wait_helper_1.wait(1); expect(executer.isSearching()).toEqual(true); await promise; expect(executer.isSearching()).toEqual(false); }); it("Can be subscribed to", async () => { const search = createSimpleSearch_helper_1.createSimpleSearch({ m: async (s) => wait_helper_1.wait(20, s == "s") }); const [executer] = createCoreExecuter(search); const listener = jest.fn(); new model_react_1.Observer(h => executer.isSearching(h)).listen(listener); await executer.setQuery("hoi"); await wait_helper_1.wait(); expect(listener.mock.calls.length).toBe(2); expect(listener.mock.calls[0][0]).toEqual(true); expect(listener.mock.calls[1][0]).toEqual(false); }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29yZVNlYXJjaEV4ZWN1dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3NlYXJjaEV4ZWN1dGVyL190ZXN0cy9Db3JlU2VhcmNoRXhlY3V0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2Q0FBMkU7QUFDM0UsNkRBQWlEO0FBRWpELDhEQUF5RDtBQUd6RCxpRkFBaUQ7QUFDakQsMkVBQStEO0FBRS9ELE1BQU0scUJBQXFCLEdBQUcsR0FBTSxFQUFFO0lBQ2xDLE1BQU0sS0FBSyxHQUFHLEVBQXdELENBQUM7SUFDdkUsTUFBTSxRQUFRLEdBQUcsSUFBSSxnQ0FBa0IsRUFBRSxDQUFDO0lBQzFDLE9BQU87UUFDSCxRQUFRLEVBQUUsQ0FBQyxFQUFTLEVBQUUsRUFBRTtZQUNwQixNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDM0IsT0FBTyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDakIsSUFBSSxRQUFRO2dCQUFFLFFBQVEsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUMzQyxDQUFDO1FBQ0QsUUFBUSxFQUFFLENBQUMsRUFBUyxFQUFFLElBQXdDLEVBQUUsRUFBRTtZQUM5RCxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDO1lBQ2pCLFFBQVEsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUM3QixDQUFDO1FBQ0QsUUFBUSxFQUFFLENBQUMsSUFBZ0IsRUFBRSxFQUFFO1lBQzNCLFFBQVEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0IsT0FBTyxnQ0FBQyxDQUNKLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO2lCQUNmLEdBQUcsQ0FBQyxDQUFDLEVBQUMsSUFBSSxFQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQztpQkFDckIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUNoQixDQUFDO1FBQ2IsQ0FBQztRQUNELFFBQVEs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