import { vi, describe, expect, it, beforeAll, afterEach, beforeEach } from 'vitest'; import { default as axios } from 'axios'; import { createWrapper } from 'app/test/vitest/helper'; import LeftMenu from 'components/LeftMenu.vue'; import * as vueRouter from 'vue-router'; import { useNavigationStore } from 'src/stores/useNavigationStore'; let vm; let navigation; vi.mock('src/router/modules', () => ({ default: [ { path: '/customer', name: 'Customer', meta: { title: 'customers', icon: 'vn:client', menu: ['CustomerList', 'CustomerCreate'], }, children: [ { path: '', name: 'CustomerMain', meta: { menu: 'Customer', menuChildren: [ { name: 'CustomerCreditContracts', title: 'creditContracts', icon: 'vn:solunion', }, ], }, children: [ { path: 'list', name: 'CustomerList', meta: { title: 'list', icon: 'view_list', menuChildren: [ { name: 'CustomerCreditContracts', title: 'creditContracts', icon: 'vn:solunion', }, ], }, }, ], }, ], }, ], })); vi.spyOn(vueRouter, 'useRoute').mockReturnValue({ matched: [ { path: '/', redirect: { name: 'Dashboard', }, name: 'Main', meta: {}, props: { default: false, }, children: [ { path: '/dashboard', name: 'Dashboard', meta: { title: 'dashboard', icon: 'dashboard', }, }, ], }, { path: '/customer', redirect: { name: 'CustomerMain', }, name: 'Customer', meta: { title: 'customers', icon: 'vn:client', moduleName: 'Customer', keyBinding: 'c', menu: ['customer'], }, }, ], query: {}, params: {}, meta: { moduleName: 'mockName' }, path: 'mockName/1', name: 'Customer', }); function mount(source = 'main') { vi.spyOn(axios, 'get').mockResolvedValue({ data: [], }); const wrapper = createWrapper(LeftMenu, { propsData: { source, }, }); navigation = useNavigationStore(); navigation.fetchPinned = vi.fn().mockReturnValue(Promise.resolve(true)); navigation.getModules = vi.fn().mockReturnValue({ value: [ { name: 'customer', title: 'customer.pageTitles.customers', icon: 'vn:customer', module: 'customer', }, ], }); return wrapper; } describe('getRoutes', () => { afterEach(() => vi.clearAllMocks()); const getRoutes = vi.fn().mockImplementation((props, getMethodA, getMethodB) => { const handleRoutes = { methodA: getMethodA, methodB: getMethodB, }; try { handleRoutes[props.source](); } catch (error) { throw Error('Method not defined'); } }); const getMethodA = vi.fn(); const getMethodB = vi.fn(); const fn = (props) => getRoutes(props, getMethodA, getMethodB); it('should call getMethodB when source is card', () => { let props = { source: 'methodB' }; fn(props); expect(getMethodB).toHaveBeenCalled(); expect(getMethodA).not.toHaveBeenCalled(); }); it('should call getMethodA when source is main', () => { let props = { source: 'methodA' }; fn(props); expect(getMethodA).toHaveBeenCalled(); expect(getMethodB).not.toHaveBeenCalled(); }); it('should call getMethodA when source is not exists or undefined', () => { let props = { source: 'methodC' }; expect(() => fn(props)).toThrowError('Method not defined'); expect(getMethodA).not.toHaveBeenCalled(); expect(getMethodB).not.toHaveBeenCalled(); }); }); describe('LeftMenu as card', () => { beforeAll(() => { vm = mount('card').vm; }); it('should get routes for card source', () => { vm.getRoutes(); }); }); describe('LeftMenu as main', () => { beforeEach(() => { vm = mount().vm; }); it('should initialize with default props', () => { expect(vm.source).toBe('main'); }); it('should filter items based on search input', async () => { vm.search = 'cust'; await vm.$nextTick(); expect(vm.filteredItems[0].name).toEqual('customer'); expect(vm.filteredItems[0].module).toEqual('customer'); }); it('should filter items based on search input', async () => { vm.search = 'Rou'; await vm.$nextTick(); expect(vm.filteredItems).toEqual([]); }); it('should return pinned items', () => { vm.items = [ { name: 'Item 1', isPinned: false }, { name: 'Item 2', isPinned: true }, ]; expect(vm.pinnedModules).toEqual( new Map([['Item 2', { name: 'Item 2', isPinned: true }]]), ); }); it('should find matches in routes', () => { const search = 'child1'; const item = { children: [ { name: 'child1', children: [] }, { name: 'child2', children: [] }, ], }; const matches = vm.findMatches(search, item); expect(matches).toEqual([{ name: 'child1', children: [] }]); }); it('should not proceed if event is already prevented', async () => { const item = { module: 'testModule', isPinned: false }; const event = { preventDefault: vi.fn(), stopPropagation: vi.fn(), defaultPrevented: true, }; await vm.togglePinned(item, event); expect(event.preventDefault).not.toHaveBeenCalled(); expect(event.stopPropagation).not.toHaveBeenCalled(); }); it('should call quasar.notify with success message', async () => { const item = { module: 'testModule', isPinned: false }; const event = { preventDefault: vi.fn(), stopPropagation: vi.fn(), defaultPrevented: false, }; const response = { data: { id: 1 } }; vi.spyOn(axios, 'post').mockResolvedValue(response); vi.spyOn(vm.quasar, 'notify'); await vm.togglePinned(item, event); expect(vm.quasar.notify).toHaveBeenCalledWith({ message: 'Data saved', type: 'positive', }); }); it('should get routes for main source', () => { vm.getRoutes(); expect(navigation.getModules).toHaveBeenCalled(); }); it('should find direct child matches', () => { const search = 'child1'; const item = { children: [{ name: 'child1' }, { name: 'child2' }], }; const result = vm.findMatches(search, item); expect(result).toEqual([{ name: 'child1' }]); }); it('should find nested child matches', () => { const search = 'child3'; const item = { children: [ { name: 'child1' }, { name: 'child2', children: [{ name: 'child3' }], }, ], }; const result = vm.findMatches(search, item); expect(result).toEqual([{ name: 'child3' }]); }); }); describe('normalize', () => { beforeAll(() => { vm = mount('card').vm; }); it('should normalize and lowercase text', () => { const input = 'ÁÉÍÓÚáéíóú'; const expected = 'aeiouaeiou'; expect(vm.normalize(input)).toBe(expected); }); it('should handle empty string', () => { const input = ''; const expected = ''; expect(vm.normalize(input)).toBe(expected); }); it('should handle text without diacritics', () => { const input = 'hello'; const expected = 'hello'; expect(vm.normalize(input)).toBe(expected); }); it('should handle mixed text', () => { const input = 'Héllo Wórld!'; const expected = 'hello world!'; expect(vm.normalize(input)).toBe(expected); }); }); describe('addChildren', () => { const module = 'testModule'; beforeEach(() => { vm = mount().vm; vi.clearAllMocks(); }); it('should add menu items to parent if matches are found', () => { const parent = 'testParent'; const route = { meta: { menu: 'testMenu', }, children: [{ name: 'child1' }, { name: 'child2' }], }; vm.addChildren(module, route, parent); expect(navigation.addMenuItem).toHaveBeenCalled(); }); it('should handle routes with no meta menu', () => { const route = { meta: { menu: [], }, }; const parent = []; vm.addChildren(module, route, parent); expect(navigation.addMenuItem).toHaveBeenCalled(); }); it('should handle empty parent array', () => { const parent = []; const route = { meta: { menu: 'child11', }, children: [ { name: 'child1', meta: { menuChildren: [ { name: 'CustomerCreditContracts', title: 'creditContracts', icon: 'vn:solunion', }, ], }, }, ], }; vm.addChildren(module, route, parent); expect(navigation.addMenuItem).toHaveBeenCalled(); }); });