import { cleanUpSeparators, MenuInstance } from "../MenuInstance" import { MenuItem } from "../MenuItem" const visibleItem: MenuItem = { type: "normal", label: "hello" } const invisibleItem: MenuItem = { type: "normal", label: "Hiding", visible: false } const visibleSeparator: MenuItem = { type: "separator" } const invisibleSeparator: MenuItem = { type: "separator", visible: false } describe("MenuInstance.ts", () => { describe("cleanUpSeparators()", () => { it("doesn't alter correct menus", () => { const menuItems = [visibleItem, visibleSeparator, visibleItem, visibleSeparator, visibleItem] const filteredItems = cleanUpSeparators(menuItems) expect(filteredItems).toEqual(menuItems) }) it("hides separators in the first or last position", () => { const menuItems = [visibleSeparator, visibleItem, visibleItem, visibleSeparator] const expectedResult = [invisibleSeparator, visibleItem, visibleItem, invisibleSeparator] const filteredItems = cleanUpSeparators(menuItems) expect(filteredItems).toEqual(expectedResult) }) it("hides separators in the first or last visible position", () => { const menuItems = [invisibleItem, visibleSeparator, visibleItem, visibleSeparator, invisibleItem] const expectedResult = [invisibleItem, invisibleSeparator, visibleItem, invisibleSeparator, invisibleItem] const filteredItems = cleanUpSeparators(menuItems) expect(filteredItems).toEqual(expectedResult) }) it("only displays one separator when there are two consecutive menu items of type separator", () => { const menuItems = [visibleItem, visibleSeparator, invisibleItem, visibleSeparator, visibleItem] const expectedResult = [visibleItem, visibleSeparator, invisibleItem, invisibleSeparator, visibleItem] const filteredItems = cleanUpSeparators(menuItems) expect(filteredItems).toEqual(expectedResult) }) it("only hides separators when there are no visible menu items in a section", () => { const menuItems = [ invisibleItem, visibleSeparator, invisibleItem, visibleItem, invisibleItem, visibleSeparator, visibleItem, ] const expectedResult = [ invisibleItem, invisibleSeparator, invisibleItem, visibleItem, invisibleItem, visibleSeparator, visibleItem, ] const filteredItems = cleanUpSeparators(menuItems) expect(filteredItems).toEqual(expectedResult) }) it("handles multiple continuous sections of hidden menu items correctly", () => { const menuItems = [ visibleItem, visibleSeparator, invisibleItem, visibleSeparator, invisibleItem, visibleSeparator, invisibleItem, visibleSeparator, invisibleItem, visibleSeparator, visibleItem, ] const expectedResult = [ visibleItem, visibleSeparator, invisibleItem, invisibleSeparator, invisibleItem, invisibleSeparator, invisibleItem, invisibleSeparator, invisibleItem, invisibleSeparator, visibleItem, ] const filteredItems = cleanUpSeparators(menuItems) expect(filteredItems).toEqual(expectedResult) }) describe("handles submenus correctly", () => { it("doesn't alter correct menus", () => { const menuItems: MenuItem[] = [ { type: "normal", label: "submenu", submenu: [visibleItem, visibleSeparator, visibleItem, visibleSeparator, visibleItem], }, ] const filteredItems = cleanUpSeparators(menuItems) expect(filteredItems).toEqual(menuItems) }) it("hides separators in the first or last position", () => { const menuItems: MenuItem[] = [ { type: "normal", label: "submenu", submenu: [visibleSeparator, visibleItem, visibleItem, visibleSeparator], }, ] const expectedResult = [ { type: "normal", label: "submenu", submenu: [invisibleSeparator, visibleItem, visibleItem, invisibleSeparator], }, ] const filteredItems = cleanUpSeparators(menuItems) expect(filteredItems).toEqual(expectedResult) }) it("hides separators in the first or last visible position", () => { const menuItems: MenuItem[] = [ { type: "normal", label: "submenu", submenu: [invisibleItem, visibleSeparator, visibleItem, visibleSeparator, invisibleItem], }, ] const expectedResult = [ { type: "normal", label: "submenu", submenu: [invisibleItem, invisibleSeparator, visibleItem, invisibleSeparator, invisibleItem], }, ] const filteredItems = cleanUpSeparators(menuItems) expect(filteredItems).toEqual(expectedResult) }) it("only displays one separator when there are two consecutive menu items of type separator", () => { const menuItems: MenuItem[] = [ { type: "normal", label: "submenu", submenu: [visibleItem, visibleSeparator, invisibleItem, visibleSeparator, visibleItem], }, ] const expectedResult = [ { type: "normal", label: "submenu", submenu: [visibleItem, visibleSeparator, invisibleItem, invisibleSeparator, visibleItem], }, ] const filteredItems = cleanUpSeparators(menuItems) expect(filteredItems).toEqual(expectedResult) }) }) }) describe("handleEvent", () => { it("does NOT close the menu onmouseup when it was just opened", () => { const menu = new MenuInstance( [visibleItem, visibleSeparator, visibleItem, visibleSeparator, visibleItem], {} ) const animationendEvent = createEvent("animationend") const mouseoverEvent = createEvent("mouseover") const mouseupEvent = createEvent("mouseup") const spy = jest.spyOn(menu, "close") // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore menu.showTime = Date.now() // ❗️ Sequence matters! menu.handleEvent(mouseoverEvent) menu.handleEvent(animationendEvent) menu.handleEvent(mouseupEvent) expect(spy).not.toBeCalled() }) }) }) function createEvent( type: string, { eventInitDict, target, currentTarget = target, }: Partial<{ eventInitDict: EventInit target: Record currentTarget: Record }> = { eventInitDict: { bubbles: true, cancelable: true, composed: true }, } ) { const event = new Event(type, eventInitDict) const targetDef = { value: target || { classList: new Set(), nodeName: "" }, writable: false, } const currentTargetDef = { value: currentTarget || { classList: new Set(), nodeName: "" }, writable: false, } return Object.defineProperties(event, { currentTargetDef, targetDef, }) }