import ViewerNavigationDrawer from '@/components/modal/ViewerNavigationDrawer.vue'; import { defaultHotkeys, Hotkeys } from '@/functions/HotkeyScope'; import { useDrawerStore } from '@/stores/drawer.store'; import { useViewerStore } from '@/stores/viewer.store'; import { ViewerNavigationOptions } from '@3cr/viewer-types-ts/types/viewer-navigation-options'; import { ViewerOptions } from '@3cr/viewer-types-ts/types/viewer-options'; import { MockInstance } from '@vitest/spy'; import { flushPromises, mount, VueWrapper } from '@vue/test-utils'; import { storeToRefs } from 'pinia'; import { h } from 'vue'; import { VApp } from 'vuetify/components'; function factory(component: any, props?: Record): VueWrapper { return mount(VApp, { slots: { default: h(component, props) }, }); } type DefHot = { [key in Hotkeys]?: string; }; const def: DefHot = { [Hotkeys.ALT_D]: 'display', [Hotkeys.ALT_H]: 'home', [Hotkeys.ALT_A]: 'annotation', [Hotkeys.ALT_M]: 'measure', [Hotkeys.ALT_E]: 'design', }; vi.mock('@/functions/HotkeyScope', async (importOriginal) => { return { ...(await importOriginal()), defaultHotkeys: vi.fn(), defineHotkeys: vi.fn(), resetScope: vi.fn(), }; }); vi.mock('interactjs', async (importOriginal) => { return { ...(await importOriginal()), default: vi.fn().mockReturnValue({ draggable: vi.fn().mockReturnValue({ dropzone: vi.fn(), }), resizable: vi.fn().mockReturnValue({ dropzone: vi.fn(), }), }), }; }); describe('ViewerNavigationDrawer tests', () => { it('should mount', async () => { const wrapper = factory(ViewerNavigationDrawer); await flushPromises(); expect(wrapper).toBeTruthy(); }); it('should hover show back', async () => { const wrapper = factory(ViewerNavigationDrawer); await flushPromises(); const btn = wrapper.findComponentByTestId('nav-btn'); await btn.trigger('mouseleave'); expect(btn.html()).toContain('colour_single'); }); it('should close', async () => { const { options } = storeToRefs(useViewerStore()); options.value.onExit = undefined; const wrapper = factory(ViewerNavigationDrawer); await flushPromises(); const btn = wrapper.findComponentByTestId('nav-btn'); await flushPromises(); await btn.trigger('mouseenter'); await flushPromises(); requestAnimationFrame(async () => { await btn.trigger('click'); await flushPromises(); }); }); it('should close with onExit', async () => { const wrapper = factory(ViewerNavigationDrawer); const { options } = storeToRefs(useViewerStore()); options.value.onExit = vi.fn(); await flushPromises(); const btn = wrapper.findComponentByTestId('nav-btn'); await flushPromises(); await btn.trigger('mouseenter'); await flushPromises(); requestAnimationFrame(async () => { await btn.trigger('click'); await flushPromises(); expect(options.value.onExit).toHaveBeenCalled(); }); }); it('should hover show back', async () => { const wrapper = factory(ViewerNavigationDrawer); await flushPromises(); const btn = wrapper.findComponentByTestId('nav-btn'); await btn.trigger('mouseenter'); await flushPromises(); requestAnimationFrame(() => { expect(btn.html()).toContain('west'); }); }); it('should update vlist on change', async () => { const wrapper = factory(ViewerNavigationDrawer); await flushPromises(); const list = wrapper.findComponentByTestId('nav-list'); await list.vm.$emit('update:selected', [1]); await flushPromises(); expect((list.vm as any).selected).toStrictEqual([1]); }); it('should update vlist on change mcad', async () => { const wrapper = factory(ViewerNavigationDrawer); await flushPromises(); const list = wrapper.findComponentByTestId('nav-list'); await list.vm.$emit('update:selected', ['mcad']); await flushPromises(); expect((list.vm as any).selected).toStrictEqual(['mcad']); }); it('should call all hotkey scopes', async () => { const { activeDrawer } = storeToRefs(useDrawerStore()); const defineHotkeysMock = defaultHotkeys as unknown as MockInstance; defineHotkeysMock.mockImplementation((definition: any) => { for (const x of Object.keys(definition)) { definition[x](); expect(activeDrawer.value).toBe(def[x as Hotkeys] as string); } }); factory(ViewerNavigationDrawer); expect(defaultHotkeys).toHaveBeenCalledWith(expect.anything()); }); it('should call hotkey scopes on drawer', async () => { const { activeDrawer } = storeToRefs(useDrawerStore()); const defaultHotkeysMock = defaultHotkeys as unknown as MockInstance; defaultHotkeysMock.mockImplementation((definition: any) => {}); factory(ViewerNavigationDrawer); activeDrawer.value = 'mcad'; await flushPromises(); activeDrawer.value = 'home'; await flushPromises(); expect(defaultHotkeys).toHaveBeenCalledWith(expect.anything()); }); vi.stubGlobal('open', vi.fn()); vi.spyOn(window, 'open'); for (const def of ['home', 'display', 'annotations', 'measure', 'design']) { it(`should display different ${def} icon`, async () => { const wrapper = factory(ViewerNavigationDrawer); const { options } = storeToRefs(useViewerStore()); const { activeDrawer } = storeToRefs(useDrawerStore()); const item = { icon: 'hello', title: '123', visible: true }; const fn = vi.fn(); options.value.onRecentDropdown = fn; (options.value[def as keyof ViewerOptions] as any) = item as ViewerNavigationOptions; const definition = def.endsWith('s') ? def.slice(0, def.length - 1) : def; activeDrawer.value = definition; await flushPromises(); expect(wrapper.html()).toContain(item.title); expect(wrapper.html()).toContain(item.icon); }); it(`should display default ${def}`, async () => { const wrapper = factory(ViewerNavigationDrawer); const { options } = storeToRefs(useViewerStore()); const { activeDrawer } = storeToRefs(useDrawerStore()); const fn = vi.fn(); (options.value[def as keyof ViewerOptions] as any) = { visible: true, } as ViewerNavigationOptions; options.value.onRecentDropdown = fn; const definition = def.endsWith('s') ? def.slice(0, def.length - 1) : def; activeDrawer.value = definition; await flushPromises(); expect(wrapper.html()).toContain(`labels.${definition}`); }); } });