import McadDataTableItems from '@/components/navigation/mcad/McadDataTableItems.vue'; import { useViewer3cr } from '@/composables/useViewer3cr'; import { useMcadStore } from '@/stores/mcad.store'; import { useToolStore } from '@/stores/tool.store'; import { DataOverlayMcadFaker } from '@test/fakers/data-overlay-mcad.faker'; import { beforeEach, describe } from '@vitest/runner'; import { flushPromises, mount } from '@vue/test-utils'; import interact from 'interactjs'; import { storeToRefs } from 'pinia'; import { VBtn, VDataTableRow, VDataTableVirtual, VTextField, } from 'vuetify/components'; vi.mock('interactjs', async (importOriginal) => ({ ...(await importOriginal()), default: vi.fn().mockReturnValue({ draggable: vi.fn().mockReturnValue({ dropzone: vi.fn(), }), }), })); describe('McadDataTableItems tests', () => { const viewer3cr = useViewer3cr(); const mcadsOriginal = [ DataOverlayMcadFaker.randomRaw(), DataOverlayMcadFaker.randomRaw(), DataOverlayMcadFaker.randomRaw(), ]; beforeEach(() => { const { state } = storeToRefs(useMcadStore()); state.value.Models.Models = mcadsOriginal as any; vi.mocked(interact('').draggable).mockClear(); vi.mocked(interact('').draggable({}).dropzone).mockClear(); }); it('should mount', () => { const props = {}; const wrapper = mount(McadDataTableItems, { props }); expect(wrapper).toBeTruthy(); }); describe('mcad loaded tests', () => { 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({}).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('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:modelValue', '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:modelValue', '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:modelValue', '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 }); const focusItem = wrapper.findComponent(VDataTableRow); expect(mcadSelectTool.selected.value?.Id).not.toBe(activeMcads[0].Id); await focusItem.trigger('click'); await flushPromises(); expect(mcadSelectTool.selected.value?.Id).toBe(activeMcads[0].Id); }); 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; }