UNPKG

@launchmenu/core

Version:

An environment for visual keyboard controlled applets

917 lines 90.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const MenuItem_helper_1 = require("./MenuItem.helper"); const Menu_1 = require("../Menu"); const wait_helper_1 = require("../../../_tests/wait.helper"); const context_helper_1 = require("../../../_tests/context.helper"); const model_react_1 = require("model-react"); const onMenuChangAction_1 = require("../../../actions/types/onMenuChange/onMenuChangAction"); const onSelectAction_1 = require("../../../actions/types/onSelect/onSelectAction"); const onCursorAction_1 = require("../../../actions/types/onCursor/onCursorAction"); const getCategoryAction_1 = require("../../../actions/types/category/getCategoryAction"); describe("Menu", () => { describe("new Menu", () => { it("Properly creates a new menu", () => { new Menu_1.Menu(context_helper_1.dummyContext); }); it("Can be initialized with an item array", () => { const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; const menu = new Menu_1.Menu(context_helper_1.dummyContext, items); expect(menu.getItems().length).toBe(3); expect(menu.getItems()).toEqual(items); }); }); describe("Menu.addItem / Menu.getItems", () => { let menu; const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; beforeEach(() => { menu = new Menu_1.Menu(context_helper_1.dummyContext, items); }); it("Can add an item", () => { const item = MenuItem_helper_1.createTestDummyMenuItem(); menu.addItem(item); expect(menu.getItems()).toEqual([...items, item]); }); it("Can add an item at the specified index", () => { const item = MenuItem_helper_1.createTestDummyMenuItem(); menu.addItem(item, 1); expect(menu.getItems()).toEqual([items[0], item, items[1], items[2]]); }); describe("Uses categories", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const someCategory2 = { name: "John", description: "some category for John", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory2 }), ]; it("Inserts the correct category in the menu", () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext); menu.addItem(items[0]); menu.addItem(items[1]); menu.addItem(items[2]); expect(menu.getItems()).toEqual([ items[0], items[1], someCategory.item, items[2], ]); const menu2 = new Menu_1.Menu(context_helper_1.dummyContext); menu2.addItem(items[2]); menu2.addItem(items[1]); menu2.addItem(items[0]); expect(menu2.getItems()).toEqual([ items[1], items[0], someCategory.item, items[2], ]); }); it("Adds categories in the order items of said categories were added", () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext); menu.addItem(items[0]); menu.addItem(items[1]); menu.addItem(items[2]); menu.addItem(items[3]); expect(menu.getItems()).toEqual([ items[0], items[1], someCategory.item, items[2], someCategory2.item, items[3], ]); const menu2 = new Menu_1.Menu(context_helper_1.dummyContext); menu2.addItem(items[1]); menu2.addItem(items[3]); menu2.addItem(items[2]); menu2.addItem(items[0]); expect(menu2.getItems()).toEqual([ items[1], items[0], someCategory2.item, items[3], someCategory.item, items[2], ]); }); }); it("Calls onMenuChange actions", () => { const onMenuChange = jest.fn(); const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [onMenuChangAction_1.onMenuChangeAction.createBinding(onMenuChange)], }); const menu = new Menu_1.Menu(context_helper_1.dummyContext, items); menu.addItem(item); expect(onMenuChange.mock.calls.length).toBe(1); expect(onMenuChange.mock.calls[0]).toEqual([menu, true]); const onMenuChange2 = jest.fn(); const item2 = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [onMenuChangAction_1.onMenuChangeAction.createBinding(onMenuChange2)], }); const menu2 = new Menu_1.Menu(context_helper_1.dummyContext, [...items, item2]); expect(onMenuChange2.mock.calls.length).toBe(1); expect(onMenuChange2.mock.calls[0]).toEqual([menu2, true]); }); }); describe("Menu.getCategories", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const someCategory2 = { name: "John", description: "some category for John", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory2 }), ]; it("Correctly retrieves the categories", () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext); menu.addItem(items[0]); menu.addItem(items[1]); menu.addItem(items[2]); menu.addItem(items[3]); expect(menu.getCategories()).toEqual([ { category: undefined, items: [items[0], items[1]] }, { category: someCategory, items: [items[2]] }, { category: someCategory2, items: [items[3]] }, ]); }); it("Can be subscribed to", async () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext); menu.addItem(items[0]); menu.addItem(items[1]); menu.addItem(items[2]); menu.addItem(items[3]); const cb = jest.fn(); new model_react_1.Observer(h => menu.getCategories(h)).listen(cb); const newItem = MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory2 }); menu.addItem(newItem); await wait_helper_1.wait(0); expect(cb.mock.calls.length).toBe(1); expect(cb.mock.calls[0][0]).toEqual([ { category: undefined, items: [items[0], items[1]] }, { category: someCategory, items: [items[2]] }, { category: someCategory2, items: [items[3], newItem] }, ]); }); }); describe("Menu.addItems", () => { it("Can add items", () => { const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; const menu = new Menu_1.Menu(context_helper_1.dummyContext, items); const item = MenuItem_helper_1.createTestDummyMenuItem(); const item2 = MenuItem_helper_1.createTestDummyMenuItem(); menu.addItems([item, item2]); expect(menu.getItems()).toEqual([...items, item, item2]); }); describe("Considers categories", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const someCategory2 = { name: "John", description: "some category for John", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory2 }), ]; it("Inserts the correct category in the menu", () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext); menu.addItems(items.slice(0, 3)); expect(menu.getItems()).toEqual([ items[0], items[1], someCategory.item, items[2], ]); const menu2 = new Menu_1.Menu(context_helper_1.dummyContext); menu2.addItems(items.slice(0, 3).reverse()); expect(menu2.getItems()).toEqual([ items[1], items[0], someCategory.item, items[2], ]); }); it("Adds categories in the order items of said categories were added", () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext); menu.addItems(items); expect(menu.getItems()).toEqual([ items[0], items[1], someCategory.item, items[2], someCategory2.item, items[3], ]); const menu2 = new Menu_1.Menu(context_helper_1.dummyContext); menu2.addItems([...items].reverse()); expect(menu2.getItems()).toEqual([ items[1], items[0], someCategory2.item, items[3], someCategory.item, items[2], ]); }); it("Moves items to their new category when its category changes", async () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext); const category = new model_react_1.Field(someCategory); const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: h => [ getCategoryAction_1.getCategoryAction.createBinding(category.get(h)), ], }); menu.addItems([...items, item]); expect(menu.getItems()).toEqual([ items[0], items[1], someCategory.item, items[2], item, someCategory2.item, items[3], ]); category.set(someCategory2); await wait_helper_1.wait(); expect(menu.getItems()).toEqual([ items[0], items[1], someCategory.item, items[2], someCategory2.item, items[3], item, ]); category.set(someCategory); await wait_helper_1.wait(); expect(menu.getItems()).toEqual([ items[0], items[1], someCategory.item, items[2], item, someCategory2.item, items[3], ]); }); }); it("Calls onMenuChange actions", () => { const onMenuChange = jest.fn(); const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [onMenuChangAction_1.onMenuChangeAction.createBinding(onMenuChange)], }); const onMenuChange2 = jest.fn(); const item2 = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [onMenuChangAction_1.onMenuChangeAction.createBinding(onMenuChange2)], }); const menu = new Menu_1.Menu(context_helper_1.dummyContext); menu.addItems([item, item2]); expect(onMenuChange.mock.calls.length).toBe(1); expect(onMenuChange.mock.calls[0]).toEqual([menu, true]); expect(onMenuChange2.mock.calls.length).toBe(1); expect(onMenuChange2.mock.calls[0]).toEqual([menu, true]); }); }); describe("Menu.removeItem", () => { const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; let menu; beforeEach(() => { menu = new Menu_1.Menu(context_helper_1.dummyContext, items); }); it("Can remove items", () => { menu.removeItem(items[1]); expect(menu.getItems()).toEqual([items[0], items[2]]); }); it("Correctly informs whether the item was removed", () => { expect(menu.removeItem(items[1])).toBeTruthy(); expect(menu.removeItem(MenuItem_helper_1.createTestDummyMenuItem())).toBeFalsy(); expect(menu.getItems()).toEqual([items[0], items[2]]); }); describe("Considers categories", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const someCategory2 = { name: "John", description: "some category for John", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const item = MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }); const item2 = MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory2 }); const item3 = MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory2 }); it("Removes items from their category", () => { menu.addItems([item, item3, item2]); expect(menu.getItems()).toEqual([ ...items, someCategory.item, item, someCategory2.item, item3, item2, ]); menu.removeItem(item3); expect(menu.getItems()).toEqual([ ...items, someCategory.item, item, someCategory2.item, item2, ]); }); it("Removes empty categories", () => { menu.addItems([item3, item2, item]); expect(menu.getItems()).toEqual([ ...items, someCategory2.item, item3, item2, someCategory.item, item, ]); menu.removeItem(item3); menu.removeItem(item2); expect(menu.getItems()).toEqual([...items, someCategory.item, item]); }); }); it("Calls onMenuChange actions", () => { const onMenuChange = jest.fn(); const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [onMenuChangAction_1.onMenuChangeAction.createBinding(onMenuChange)], }); const menu = new Menu_1.Menu(context_helper_1.dummyContext, [...items, item]); expect(onMenuChange.mock.calls.length).toBe(1); menu.removeItem(item); expect(onMenuChange.mock.calls.length).toBe(2); expect(onMenuChange.mock.calls[0]).toEqual([menu, true]); expect(onMenuChange.mock.calls[1]).toEqual([menu, false]); }); }); describe("Menu.removeItems", () => { const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; let menu; beforeEach(() => { menu = new Menu_1.Menu(context_helper_1.dummyContext, items); }); it("Can remove items", () => { menu.removeItems([items[1], items[0]]); expect(menu.getItems()).toEqual([items[2]]); }); it("Correctly informs whether any of the items were removed", () => { expect(menu.removeItems([items[1], MenuItem_helper_1.createTestDummyMenuItem()])).toBeTruthy(); expect(menu.removeItems([MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem()])).toBeFalsy(); expect(menu.getItems()).toEqual([items[0], items[2]]); }); describe("Considers categories", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const someCategory2 = { name: "John", description: "some category for John", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const item = MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }); const item2 = MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory2 }); const item3 = MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory2 }); it("Removes items from their category", () => { menu.addItems([item, item3, item2]); expect(menu.getItems()).toEqual([ ...items, someCategory.item, item, someCategory2.item, item3, item2, ]); menu.removeItems([item3, item]); expect(menu.getItems()).toEqual([...items, someCategory2.item, item2]); }); it("Removes empty categories", () => { menu.addItems([item, item3, item2]); expect(menu.getItems()).toEqual([ ...items, someCategory.item, item, someCategory2.item, item3, item2, ]); menu.removeItems([item2, item3]); expect(menu.getItems()).toEqual([...items, someCategory.item, item]); }); }); it("Calls onMenuChange actions", () => { const onMenuChange = jest.fn(); const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [onMenuChangAction_1.onMenuChangeAction.createBinding(onMenuChange)], }); const item2 = MenuItem_helper_1.createTestDummyMenuItem(); const menu = new Menu_1.Menu(context_helper_1.dummyContext, [...items, item, item2]); expect(onMenuChange.mock.calls.length).toBe(1); menu.removeItems([item, item2]); expect(onMenuChange.mock.calls.length).toBe(2); expect(onMenuChange.mock.calls[0]).toEqual([menu, true]); expect(onMenuChange.mock.calls[1]).toEqual([menu, false]); }); }); describe("Menu.setSelected / Menu.getSelected", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const someCategory2 = { name: "John", description: "some category for John", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory2 }), ]; it("Can select items", () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext, items); menu.setSelected(items[0], true); expect(menu.getSelected()).toEqual([items[0]]); menu.setSelected(items[3], true); expect(menu.getSelected()).toEqual([items[0], items[3]]); }); it("Can deselect items", () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext, items); menu.setSelected(items[0], true); menu.setSelected(items[3], true); expect(menu.getSelected()).toEqual([items[0], items[3]]); menu.setSelected(items[3], false); expect(menu.getSelected()).toEqual([items[0]]); menu.setSelected(items[0], false); expect(menu.getSelected()).toEqual([]); }); it("Calls onSelect actions", () => { let selectCount = 0; let deselectCount = 0; const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [ onSelectAction_1.onSelectAction.createBinding(selected => { if (selected) selectCount++; else deselectCount++; }), ], }); const menu = new Menu_1.Menu(context_helper_1.dummyContext, [...items, item]); expect(selectCount).toBe(0); expect(deselectCount).toBe(0); menu.setSelected(item, true); expect(selectCount).toBe(1); expect(deselectCount).toBe(0); menu.setSelected(item, false); expect(selectCount).toBe(1); expect(deselectCount).toBe(1); }); it("Can't select items that aren't in the menu", () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext, items); const item = MenuItem_helper_1.createTestDummyMenuItem(); menu.setSelected(item, true); expect(menu.getSelected()).toEqual([]); }); it("Automatically deselects items when removed", () => { const item = MenuItem_helper_1.createTestDummyMenuItem(); const menu = new Menu_1.Menu(context_helper_1.dummyContext, [...items, item]); menu.setSelected(item, true); expect(menu.getSelected()).toEqual([item]); menu.removeItem(item); expect(menu.getSelected()).toEqual([]); }); }); describe("Menu.setCursor / Menu.getCursor", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const items = [ MenuItem_helper_1.createTestDummyMenuItem({ noSelect: true }), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), ]; it("Has the correct initial cursor", () => { expect(new Menu_1.Menu(context_helper_1.dummyContext).getCursor()).toEqual(null); // It won't select unselectable items expect(new Menu_1.Menu(context_helper_1.dummyContext, items).getCursor()).toEqual(items[1]); }); it("Properly updates the cursor", () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext, items); menu.setCursor(items[2]); expect(menu.getCursor()).toEqual(items[2]); }); it("Calls onCursor actions", () => { let selectCount = 0; let deselectCount = 0; const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [ onCursorAction_1.onCursorAction.createBinding((selected, m) => { if (selected) selectCount++; else deselectCount++; expect(m).toEqual(menu); }), ], }); const menu = new Menu_1.Menu(context_helper_1.dummyContext, [...items, item]); expect(selectCount).toBe(0); expect(deselectCount).toBe(0); menu.setCursor(item); expect(selectCount).toBe(1); expect(deselectCount).toBe(0); menu.setCursor(null); expect(selectCount).toBe(1); expect(deselectCount).toBe(1); }); it("Can't set item as cursor if not in the menu", () => { const menu = new Menu_1.Menu(context_helper_1.dummyContext, items); const item = MenuItem_helper_1.createTestDummyMenuItem(); menu.setCursor(item); expect(menu.getCursor()).not.toEqual(item); }); it("Automatically selects another cursor when cursor is removed", () => { const item = MenuItem_helper_1.createTestDummyMenuItem(); const menu = new Menu_1.Menu(context_helper_1.dummyContext, [...items, item]); menu.setCursor(item); expect(menu.getCursor()).toEqual(item); menu.removeItem(item); expect(menu.getCursor()).not.toEqual(item); expect(menu.getCursor()).not.toEqual(null); menu.removeItems(items); expect(menu.getCursor()).toEqual(null); }); }); describe("Menu.getAllSelected", () => { const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; it("Combines the selection and cursor if present", () => { const item = MenuItem_helper_1.createTestDummyMenuItem(); const item2 = MenuItem_helper_1.createTestDummyMenuItem(); const menu = new Menu_1.Menu(context_helper_1.dummyContext, [...items, item, item2]); menu.setCursor(item); expect(menu.getAllSelected()).toEqual([item]); menu.setSelected(item2); expect(menu.getAllSelected()).toEqual([item2, item]); }); it("Returns the selection if no cursor is present", () => { const item = MenuItem_helper_1.createTestDummyMenuItem(); const item2 = MenuItem_helper_1.createTestDummyMenuItem(); const menu = new Menu_1.Menu(context_helper_1.dummyContext, [...items, item, item2]); menu.setCursor(null); menu.setSelected(item2); expect(menu.getAllSelected()).toEqual([item2]); }); it("Only includes items once", () => { const item = MenuItem_helper_1.createTestDummyMenuItem(); const item2 = MenuItem_helper_1.createTestDummyMenuItem(); const menu = new Menu_1.Menu(context_helper_1.dummyContext, [...items, item, item2]); menu.setCursor(item); expect(menu.getAllSelected()).toEqual([item]); menu.setSelected(item); expect(menu.getAllSelected()).toEqual([item]); }); }); describe("Menu.destroy", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), ]; let menu; beforeEach(() => { menu = new Menu_1.Menu(context_helper_1.dummyContext, items); }); it("Deselects all items", () => { let deselectCount = 0; const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [ onSelectAction_1.onSelectAction.createBinding((selected, m) => { if (!selected) deselectCount++; expect(m).toEqual(menu); }), ], }); menu.addItem(item); menu.setSelected(item, true); expect(menu.getSelected()).toEqual([item]); expect(deselectCount).toBe(0); menu.destroy(); expect(menu.getSelected()).toEqual([]); expect(deselectCount).toBe(1); }); it("Deselects the cursor", () => { let deselectCount = 0; const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [ onCursorAction_1.onCursorAction.createBinding((selected, m) => { if (!selected) deselectCount++; expect(m).toEqual(menu); }), ], }); menu.addItem(item); menu.setCursor(item); expect(menu.getCursor()).toEqual(item); expect(deselectCount).toBe(0); menu.destroy(); expect(menu.getCursor()).toEqual(null); expect(deselectCount).toBe(1); }); it("Removes all items", () => { // Logically the items are removed, but for rendering purposes they are still obtainable // One shouldn't logically rely on these items if the menu indicates it has been destroyed however const ci = [items[0], items[1], someCategory.item, items[2]]; expect(menu.getItems()).toEqual(ci); menu.destroy(); expect(menu.getItems()).toEqual(ci); }); it("Blocks changing the cursor", () => { let selectCount = 0; const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [ onCursorAction_1.onCursorAction.createBinding((selected, m) => { if (selected) selectCount++; expect(m).toEqual(menu); }), ], }); menu.addItem(item); expect(menu.getCursor()).not.toEqual(null); menu.destroy(); menu.setCursor(items[0]); expect(menu.getCursor()).toEqual(null); expect(selectCount).toBe(0); }); it("Blocks selecting of items", () => { let selectCount = 0; const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [ onSelectAction_1.onSelectAction.createBinding((selected, m) => { if (selected) selectCount++; expect(m).toEqual(menu); }), ], }); menu.addItem(item); menu.destroy(); menu.setSelected(items[0], true); expect(menu.getSelected()).toEqual([]); expect(selectCount).toBe(0); }); }); describe("Getters can be subscribed to", () => { let menu; const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; beforeEach(() => { menu = new Menu_1.Menu(context_helper_1.dummyContext, items); }); describe("Menu.getItems", () => { it("Correctly subscribes to changes", () => { const item = MenuItem_helper_1.createTestDummyMenuItem(); const item2 = MenuItem_helper_1.createTestDummyMenuItem(); const callback = jest.fn(() => { }); expect(menu.getItems({ call: callback, registerRemover: () => { } })).toEqual(items); expect(callback.mock.calls.length).toBe(0); menu.addItems([item, item2]); expect(callback.mock.calls.length).toBe(1); }); }); describe("Menu.getSelected", () => { it("Correctly subscribes to changes", () => { const callback = jest.fn(() => { }); expect(menu.getSelected({ call: callback, registerRemover: () => { } })).toEqual([]); expect(callback.mock.calls.length).toBe(0); menu.setSelected(items[2], true); expect(callback.mock.calls.length).toBe(1); }); }); describe("Menu.getCursor", () => { it("Correctly subscribes to changes", () => { const callback = jest.fn(() => { }); expect(menu.getCursor({ call: callback, registerRemover: () => { } })).toEqual(items[0]); expect(callback.mock.calls.length).toBe(0); menu.setCursor(items[2]); expect(callback.mock.calls.length).toBe(1); }); }); describe("Menu.getAllSelected", () => { it("Correctly subscribes to changes", () => { const callback = jest.fn(() => { }); expect(menu.getAllSelected({ call: callback, registerRemover: () => { } })).toEqual([items[0]]); expect(callback.mock.calls.length).toBe(0); menu.setCursor(items[2]); expect(callback.mock.calls.length).toBe(1); menu.setSelected(items[1], true); expect(callback.mock.calls.length).toBe(2); }); }); }); describe("categoryConfig", () => { describe("categoryConfig.maxCategoryItemCount", () => { let menu; const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; beforeEach(() => { menu = new Menu_1.Menu(context_helper_1.dummyContext, { maxCategoryItemCount: 2 }); }); it("Allows the number of items for each category to be limited", () => { menu.addItems(items); expect(menu.getItems()).toEqual(items.slice(0, 2)); }); it("Considers separate categories", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const items2 = [ MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), ]; menu.addItems(items); menu.addItems(items2); expect(menu.getItems()).toEqual([ ...items.slice(0, 2), someCategory.item, ...items2.slice(0, 2), ]); }); it("Doesn't call onMenuChange if the item wasn't added", () => { menu.addItems(items); const onMenuChange = jest.fn(); const item = MenuItem_helper_1.createTestDummyMenuItem({ actionBindings: [onMenuChangAction_1.onMenuChangeAction.createBinding(onMenuChange)], }); menu.addItem(item); expect(onMenuChange.mock.calls.length).toBe(0); }); }); describe("categoryConfig.getCategory", () => { it("Allows categories to be ignored", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const menu = new Menu_1.Menu(context_helper_1.dummyContext, { getCategory: () => undefined }); const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; const items2 = [ MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), ]; menu.addItems(items); menu.addItems(items2); expect(menu.getItems()).toEqual([...items, ...items2]); }); it("Allows categories to be altered", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const menu = new Menu_1.Menu(context_helper_1.dummyContext, { getCategory: () => someCategory }); const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; const items2 = [ MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), ]; menu.addItems(items); menu.addItems(items2); expect(menu.getItems()).toEqual([someCategory.item, ...items, ...items2]); }); }); describe("categoryConfig.sortCategories", () => { it("Allows category orders to be changed", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const menu = new Menu_1.Menu(context_helper_1.dummyContext, { sortCategories: categories => categories.map(({ category }) => category).reverse(), }); const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; const items2 = [ MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), ]; menu.addItems(items); menu.addItems(items2); expect(menu.getItems()).toEqual([someCategory.item, ...items2, ...items]); }); it("Allows categories to be left out", () => { const someCategory = { name: "Bob", description: "some category for Bob", item: MenuItem_helper_1.createTestDummyMenuItem(), }; const menu = new Menu_1.Menu(context_helper_1.dummyContext, { sortCategories: () => [undefined] }); const items = [ MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), MenuItem_helper_1.createTestDummyMenuItem(), ]; const items2 = [ MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), MenuItem_helper_1.createTestDummyMenuItem({ category: someCategory }), ]; menu.addItems(items); menu.addItems(items2); expect(menu.getItems()).toEqual(items); }); }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWVudS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9tZW51cy9tZW51L190ZXN0cy9NZW51LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsdURBQTBEO0FBQzFELGtDQUE2QjtBQUM3Qiw2REFBaUQ7QUFDakQsbUVBQTREO0FBQzVELDZDQUE0QztBQUM1Qyw2RkFBeUY7QUFDekYsbUZBQThFO0FBQzlFLG1GQUE4RTtBQUM5RSx5RkFBb0Y7QUFHcEYsUUFBUSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUU7SUFDbEIsUUFBUSxDQUFDLFVBQVUsRUFBRSxHQUFHLEVBQUU7UUFDdEIsRUFBRSxDQUFDLDZCQUE2QixFQUFFLEdBQUcsRUFBRTtZQUNuQyxJQUFJLFdBQUksQ0FBQyw2QkFBWSxDQUFDLENBQUM7UUFDM0IsQ0FBQyxDQUFDLENBQUM7UUFDSCxFQUFFLENBQUMsdUNBQXVDLEVBQUUsR0FBRyxFQUFFO1lBQzdDLE1BQU0sS0FBSyxHQUFHO2dCQUNWLHlDQUF1QixFQUFFO2dCQUN6Qix5Q0FBdUIsRUFBRTtnQkFDekIseUNBQXVCLEVBQUU7YUFDNUIsQ0FBQztZQUNGLE1BQU0sSUFBSSxHQUFHLElBQUksV0FBSSxDQUFDLDZCQUFZLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDM0MsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMzQyxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLDhCQUE4QixFQUFFLEdBQUcsRUFBRTtRQUMxQyxJQUFJLElBQVUsQ0FBQztRQUNmLE1BQU0sS0FBSyxHQUFHO1lBQ1YseUNBQXVCLEVBQUU7WUFDekIseUNBQXVCLEVB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