import { flushPromises, mount } from '@vue/test-utils'; import McadDataTableItems from '@/components/navigation/mcad/McadDataTableItems.vue'; import { createPinia, setActivePinia, storeToRefs } from 'pinia'; import { useMcadStore } from '@/stores/mcad.store'; import { DataOverlayMcadFaker } from '@test/fakers/data-overlay-mcad.faker'; import { beforeEach, describe } from '@vitest/runner'; import interact from 'interactjs'; import { useViewer3cr } from '@/composables/useViewer3cr'; import { deepClone } from '@vitest/utils'; import { VBtn, VDataTableRow, VDataTableVirtual, VTextField } from 'vuetify/components'; import { useToolStore } from '@/stores/tool.store'; import { createTestingPinia } from '@pinia/testing'; vi.mock('interactjs', async (importOriginal) => ({ ...(await importOriginal()), default: vi.fn().mockReturnValue({ draggable: vi.fn().mockReturnValue({ dropzone: vi.fn() }) }) })); describe('McadDataTableItems tests', () => { setActivePinia(createPinia()); const viewer3cr = useViewer3cr(); it('should mount', () => { const props = {}; const wrapper = mount(McadDataTableItems, { props }); expect(wrapper).toBeTruthy(); }); describe('mcad loaded tests', () => { const mcadsOriginal = [DataOverlayMcadFaker.random(), DataOverlayMcadFaker.random(), DataOverlayMcadFaker.random()]; beforeEach(() => { vi.clearAllMocks(); const { mcads } = storeToRefs(useMcadStore()); vi.spyOn(mcads, 'value', 'get').mockReturnValue(mcadsOriginal); }); it('should contain item from store', async () => { const activeMcads = mcadsOriginal.slice(0, 1); const props = { items: activeMcads.map((x) => x.Key), isPrimary: false }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); expect(wrapper.html()).toContain(activeMcads[0].Title); }); it('should check custom filter', () => { const activeMcads = mcadsOriginal.slice(0, 1); const props = { items: activeMcads.map((x) => x.Key), isPrimary: false }; const wrapper = mount(McadDataTableItems, { props }); expect(wrapper.vm.customFilter('123', '123', { value: '123' })).toBeFalsy(); }); it('should check custom filter found', async () => { const activeMcads = mcadsOriginal.slice(0, 1); const props = { items: activeMcads.map((x) => x.Key), isPrimary: false }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); expect( wrapper.vm.customFilter(activeMcads[0].Title, activeMcads[0].Title, { value: activeMcads[0].Key }) ).toBeTruthy(); }); it('should contain item from store with children', async () => { const activeMcads = mcadsOriginal.slice(0, 2); activeMcads[0].Children = [mcadsOriginal[2].Id]; const props = { items: activeMcads.map((x) => x.Key), isPrimary: false }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); expect(wrapper.html()).toContain(activeMcads[0].Title); const focusItem = wrapper.findComponentByTestId('expand-btn'); expect(focusItem.html()).toContain('chevron_forward'); await focusItem.trigger('click'); await flushPromises(); expect(focusItem.html()).toContain('mdi-chevron-down'); }); it('should primary contain .drag-drop and call interact', async () => { const props = { items: mcadsOriginal.slice(0, 1).map((x) => x.Key), isPrimary: true }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); const dragger = wrapper.find('.drag-drop'); expect(dragger.exists()).toBeTruthy(); expect(interact('').draggable).toHaveBeenCalled(); expect(interact('').draggable({}).dropzone).toHaveBeenCalled(); }); it('should not primary contain .drag-drop and not call interact', async () => { const props = { items: mcadsOriginal.slice(0, 1).map((x) => x.Key), isPrimary: false }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); const dragger = wrapper.find('.drag-drop'); expect(dragger.exists()).toBeTruthy(); expect(interact('').draggable).not.toHaveBeenCalled(); expect(interact('').draggable({}).dropzone).not.toHaveBeenCalled(); }); it('should dragStart', async () => { const props = { items: mcadsOriginal.slice(0, 1).map((x) => x.Key), isPrimary: true }; const rect = { left: 100, top: 1000 }; const dataset = { originalX: 0, originalY: 0 }; const mockEvent = { target: { getBoundingClientRect: vi.fn().mockReturnValue(rect), dataset: dataset } }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); await wrapper.vm.onDragStart(mockEvent); expect(dataset.originalX).toBe(rect.left); expect(dataset.originalY).toBe(rect.top); }); it('should onDragMove', async () => { const props = { items: mcadsOriginal.slice(0, 1).map((x) => x.Key), isPrimary: true }; const x = 10; const y = 100; const dx = 9; const dy = 90; const mockEvent = { target: { getAttribute: vi.fn().mockReturnValueOnce(x).mockReturnValueOnce(y), setAttribute: vi.fn(), style: { transform: 'nothing' } }, delta: { x: dx, y: dy } }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); wrapper.vm.onDragMove(mockEvent); expect(mockEvent.target.style.transform).not.toBe('nothing'); expect(mockEvent.target.setAttribute).toHaveBeenNthCalledWith(1, 'data-x', x + dx); expect(mockEvent.target.setAttribute).toHaveBeenNthCalledWith(2, 'data-y', y + dy); }); it('should onDragMove default values', async () => { const props = { items: mcadsOriginal.slice(0, 1).map((x) => x.Key), isPrimary: true }; const x = null; const y = null; const dx = 9; const dy = 90; const mockEvent = { target: { getAttribute: vi.fn().mockReturnValueOnce(x).mockReturnValueOnce(y), setAttribute: vi.fn(), style: { transform: 'nothing' } }, delta: { x: dx, y: dy } }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); wrapper.vm.onDragMove(mockEvent); expect(mockEvent.target.style.transform).not.toBe('nothing'); expect(mockEvent.target.setAttribute).toHaveBeenNthCalledWith(1, 'data-x', dx); expect(mockEvent.target.setAttribute).toHaveBeenNthCalledWith(2, 'data-y', dy); }); it('should onDragEnd', async () => { const props = { items: mcadsOriginal.slice(0, 1).map((x) => x.Key), isPrimary: true }; const mockEvent = { target: { removeAttribute: vi.fn(), style: { transform: 'nothing' } }, relatedTarget: true, dropzone: true }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); wrapper.vm.onDragEnd(mockEvent); expect(mockEvent.target.style.transform).not.toBe(''); expect(mockEvent.target.removeAttribute).not.toHaveBeenNthCalledWith(1, 'data-x'); expect(mockEvent.target.removeAttribute).not.toHaveBeenNthCalledWith(2, 'data-y'); }); it('should onDragEnd and reset', async () => { const props = { items: mcadsOriginal.slice(0, 1).map((x) => x.Key), isPrimary: true }; const mockEvent = { target: { removeAttribute: vi.fn(), style: { transform: 'nothing' } }, relatedTarget: false, dropzone: false }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); wrapper.vm.onDragEnd(mockEvent); expect(mockEvent.target.style.transform).toBe(''); expect(mockEvent.target.removeAttribute).toHaveBeenNthCalledWith(1, 'data-x'); expect(mockEvent.target.removeAttribute).toHaveBeenNthCalledWith(2, 'data-y'); }); it('should onDrop', async () => { const props = { items: mcadsOriginal.slice(0, 1).map((x) => x.Key), isPrimary: true }; const spy = vi.spyOn(viewer3cr, 'groupMcad'); const mockEvent = { target: { id: 'item-123', classList: newDOMTokenList(['nothing-important']) }, relatedTarget: { id: 'item-1234' } }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); wrapper.vm.onDrop(mockEvent); expect(spy).toHaveBeenCalledWith({ message: { Version: '0.0.0', Parent: '', Children: ['1234', '123'] } }); }); describe('ondrop group tests', () => { let localMcads = deepClone(mcadsOriginal); const ungroupMcadSpy = vi.spyOn(viewer3cr, 'ungroupMcad'); const removeMcadObjectSpy = vi.spyOn(viewer3cr, 'removeMcadObject'); const groupMcadSpy = vi.spyOn(viewer3cr, 'groupMcad'); const setMcadObjectTitleSpy = vi.spyOn(viewer3cr, 'setMcadObjectTitle'); let mockEvent = { target: { id: `item-${mcadsOriginal[0].Key}`, classList: newDOMTokenList(['group-container']) }, relatedTarget: { id: 'item-1234' } }; beforeEach(() => { localMcads = deepClone(mcadsOriginal); localMcads[0].Children = [localMcads[1].Key]; const { mcads } = storeToRefs(useMcadStore()); vi.spyOn(mcads, 'value', 'get').mockReturnValue(localMcads); ungroupMcadSpy.mockClear(); removeMcadObjectSpy.mockClear(); groupMcadSpy.mockClear(); setMcadObjectTitleSpy.mockClear(); mockEvent = { target: { id: `item-${mcadsOriginal[0].Key}`, classList: newDOMTokenList(['group-container']) }, relatedTarget: { id: 'item-1234' } }; }); function construct() { return mount(McadDataTableItems, { props: { items: localMcads.slice(0, 1).map((x) => x.Key), isPrimary: true } }); } it('should onDrop as group not exist', async () => { localMcads[0].Children = []; const wrapper = construct(); await flushPromises(); wrapper.vm.onDrop(mockEvent); await flushPromises(); expect(groupMcadSpy).not.toHaveBeenCalled(); expect(removeMcadObjectSpy).not.toHaveBeenCalled(); expect(ungroupMcadSpy).not.toHaveBeenCalled(); expect(setMcadObjectTitleSpy).not.toHaveBeenCalled(); }); it('should onDrop as already includes', async () => { localMcads[0].Children = ['1234']; const wrapper = construct(); await flushPromises(); wrapper.vm.onDrop(mockEvent); await flushPromises(); expect(groupMcadSpy).not.toHaveBeenCalled(); expect(removeMcadObjectSpy).not.toHaveBeenCalled(); expect(ungroupMcadSpy).not.toHaveBeenCalled(); expect(setMcadObjectTitleSpy).not.toHaveBeenCalled(); }); it('should onDrop as group', async () => { const wrapper = construct(); await flushPromises(); wrapper.vm.onDrop(mockEvent); await flushPromises(); await flushPromises(); await flushPromises(); expect(groupMcadSpy).toHaveBeenCalled(); expect(removeMcadObjectSpy).toHaveBeenCalled(); expect(ungroupMcadSpy).toHaveBeenCalled(); expect(setMcadObjectTitleSpy).toHaveBeenCalled(); }); it('should onDrop as not newGroup', async () => { const targetGroup = localMcads[0]; console.log(targetGroup.Id); targetGroup.Children = ['123123123']; const wrapper = construct(); groupMcadSpy.mockImplementationOnce(async () => { const newbie = DataOverlayMcadFaker.random(); newbie.Children = ['123123123']; localMcads[0].Children = []; localMcads.push(newbie); const { mcads } = storeToRefs(useMcadStore()); vi.spyOn(mcads, 'value', 'get').mockReturnValue([]); await flushPromises(); }); await flushPromises(); wrapper.vm.onDrop(mockEvent); await flushPromises(); expect(groupMcadSpy).toHaveBeenCalled(); expect(removeMcadObjectSpy).toHaveBeenCalled(); expect(ungroupMcadSpy).toHaveBeenCalled(); expect(setMcadObjectTitleSpy).not.toHaveBeenCalled(); }); it('should onDrop as group with previous title', async () => { const wrapper = construct(); await flushPromises(); wrapper.vm.onDrop(mockEvent); await flushPromises(); await flushPromises(); expect(groupMcadSpy).toHaveBeenCalled(); expect(removeMcadObjectSpy).toHaveBeenCalled(); expect(ungroupMcadSpy).toHaveBeenCalled(); expect(setMcadObjectTitleSpy).toHaveBeenCalled(); await flushPromises(); wrapper.vm.onDrop(mockEvent); await flushPromises(); expect(groupMcadSpy).toHaveBeenCalled(); expect(removeMcadObjectSpy).toHaveBeenCalled(); expect(ungroupMcadSpy).toHaveBeenCalled(); expect(setMcadObjectTitleSpy).toHaveBeenCalled(); }); }); describe('focus tests', () => { const activeMcads = mcadsOriginal.slice(0, 1); activeMcads[0].Children = ['123']; const wrapper = mount(McadDataTableItems); let focusItem = wrapper.findComponentByTestId('focus-item'); const setMcadObjectTitleSpy = vi.spyOn(viewer3cr, 'setMcadObjectTitle'); beforeEach(async () => { const props = { items: activeMcads.map((x) => x.Key), isPrimary: true }; const wrapper = mount(McadDataTableItems, { props }); await flushPromises(); focusItem = wrapper.findComponentByTestId('focus-item'); setMcadObjectTitleSpy.mockClear(); }); it('should be focusable', async () => { expect(focusItem.exists()).toBe(true); }); it('should handleFocus when clicked', async () => { await focusItem.trigger('focus'); expect(focusItem.vm.modelValue).toBe(activeMcads[0].Title); }); it('should update title when event triggered', async () => { await focusItem.trigger('focus'); expect(focusItem.vm.modelValue).toBe(activeMcads[0].Title); focusItem.vm.$emit('update:model-value', 'some new title'); await flushPromises(); expect(focusItem.vm.modelValue).not.toBe(activeMcads[0].Title); expect(focusItem.vm.modelValue).toBe('some new title'); }); it('should not save title when blurred same title', async () => { await focusItem.trigger('focus'); expect(focusItem.vm.modelValue).toBe(activeMcads[0].Title); expect(setMcadObjectTitleSpy).not.toHaveBeenCalled(); await focusItem.trigger('blur'); expect(setMcadObjectTitleSpy).not.toHaveBeenCalledWith({ message: { Version: '0.0.0', Id: activeMcads[0].Id, Value: activeMcads[0].Title } }); }); it('should save title when blurred', async () => { await focusItem.trigger('focus'); expect(focusItem.vm.modelValue).toBe(activeMcads[0].Title); focusItem.vm.$emit('update:model-value', 'some new title'); await flushPromises(); expect(focusItem.vm.modelValue).not.toBe(activeMcads[0].Title); expect(focusItem.vm.modelValue).toBe('some new title'); expect(setMcadObjectTitleSpy).not.toHaveBeenCalled(); await focusItem.trigger('blur'); expect(setMcadObjectTitleSpy).toHaveBeenCalledWith({ message: { Version: '0.0.0', Id: activeMcads[0].Id, Value: 'some new title' } }); }); it('should save title when keydown:enter', async () => { await focusItem.trigger('focus'); expect(focusItem.vm.modelValue).toBe(activeMcads[0].Title); focusItem.vm.$emit('update:model-value', 'some new title'); await flushPromises(); expect(focusItem.vm.modelValue).not.toBe(activeMcads[0].Title); expect(focusItem.vm.modelValue).toBe('some new title'); expect(setMcadObjectTitleSpy).not.toHaveBeenCalled(); await focusItem.trigger('keydown.enter'); expect(setMcadObjectTitleSpy).toHaveBeenCalledWith({ message: { Version: '0.0.0', Id: activeMcads[0].Id, Value: 'some new title' } }); }); it('should not update title when not group', async () => { expect(setMcadObjectTitleSpy).not.toHaveBeenCalled(); await wrapper.vm.updateMcadTitle(mcadsOriginal[1].Id, '123'); expect(setMcadObjectTitleSpy).not.toHaveBeenCalledWith({ message: { Version: '0.0.0', Id: mcadsOriginal[1].Id, Value: '123' } }); }); }); describe('select tests', () => { it('should not update title when not group', async () => { const { mcadSelectTool } = useToolStore(); const selectSpy = vi.spyOn(mcadSelectTool, 'toggle'); const activeMcads = mcadsOriginal.slice(0, 1); activeMcads[0].Children = ['123']; const props = { items: activeMcads.map((x) => x.Key), isPrimary: true }; const wrapper = mount(McadDataTableItems, { props }); const focusItem = wrapper.findComponent(VDataTableRow); expect(selectSpy).not.toHaveBeenCalled(); await focusItem.trigger('click'); await flushPromises(); expect(selectSpy).toHaveBeenCalled(); }); it('should not update title when not group from store', async () => { const { mcadSelectTool } = useToolStore(); const activeMcads = mcadsOriginal.slice(0, 1); activeMcads[0].Children = ['123']; const props = { items: activeMcads.map((x) => x.Key), isPrimary: true }; const wrapper = mount(McadDataTableItems, { props, plugins: [createTestingPinia({ createSpy: vi.fn })] }); const focusItem = wrapper.findComponent(VDataTableRow); expect(mcadSelectTool.selected.value).not.toBe(activeMcads[0]); await focusItem.trigger('click'); await flushPromises(); expect(mcadSelectTool.selected.value).toStrictEqual(activeMcads[0]); }); it('should not update title when not group', async () => { const activeMcads = mcadsOriginal.slice(0, 1); activeMcads[0].Children = ['123']; const props = { items: activeMcads.map((x) => x.Key), isPrimary: true }; const wrapper = mount(McadDataTableItems, { props }); const focusItem = wrapper.findComponent(VDataTableVirtual); await focusItem.setValue([activeMcads[0].Key]); await flushPromises(); expect(focusItem.exists()).toBe(true); }); it('should expand item', async () => { const activeMcads = mcadsOriginal.slice(0, 1); activeMcads[0].Children = ['123']; const props = { items: activeMcads.map((x) => x.Key), isPrimary: true }; const wrapper = mount(McadDataTableItems, { props }); const focusItem = wrapper.findComponentByTestId('expand-btn'); expect(focusItem.html()).toContain('chevron_forward'); await focusItem.trigger('click'); await flushPromises(); expect(focusItem.html()).toContain('mdi-chevron-down'); }); }); }); }); function newDOMTokenList(initialTokens: Array): DOMTokenList { const tmp = document.createElement(`div`); const classList = tmp.classList; if (initialTokens) { initialTokens.forEach((token: string) => { classList.add(token); }); } return classList; }