@launchmenu/core
Version:
An environment for visual keyboard controlled applets
917 lines • 90.7 kB
JavaScript
"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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