#7058 LeftMenu vitest #1153
|
@ -1,9 +1,11 @@
|
||||||
import { vi, describe, expect, it, beforeAll, beforeEach } from 'vitest';
|
import { vi, describe, expect, it, beforeAll, beforeEach } from 'vitest';
|
||||||
import { createWrapper, axios } from 'app/test/vitest/helper';
|
import { createWrapper, axios } from 'app/test/vitest/helper';
|
||||||
import Leftmenu from 'components/LeftMenu.vue';
|
import Leftmenu from 'components/LeftMenu.vue';
|
||||||
|
import * as vueRouter from 'vue-router';
|
||||||
|
|
||||||
import { useNavigationStore } from 'src/stores/useNavigationStore';
|
import { useNavigationStore } from 'src/stores/useNavigationStore';
|
||||||
|
let vm;
|
||||||
|
let navigation;
|
||||||
vi.mock('src/router/modules', () => ({
|
vi.mock('src/router/modules', () => ({
|
||||||
default: [
|
default: [
|
||||||
{
|
{
|
||||||
|
@ -44,126 +46,330 @@ vi.mock('src/router/modules', () => ({
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function mount(source) {
|
function mount(source) {
|
||||||
return createWrapper(Leftmenu, {
|
vi.spyOn(axios, 'get').mockResolvedValue({
|
||||||
|
data: [],
|
||||||
|
});
|
||||||
|
const wrapper = createWrapper(Leftmenu, {
|
||||||
propsData: {
|
propsData: {
|
||||||
source,
|
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('Leftmenu', () => {
|
describe('Leftmenu as card', () => {
|
||||||
let vm;
|
|
||||||
let navigation;
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
vi.spyOn(axios, 'get').mockResolvedValue({
|
vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
|
||||||
data: [],
|
matched: [
|
||||||
});
|
|
||||||
vm = mount('main').vm;
|
|
||||||
vi.spyOn(vm, 'getCardRoutes');
|
|
||||||
|
|
||||||
navigation = useNavigationStore();
|
|
||||||
navigation.fetchPinned = vi.fn().mockReturnValue(Promise.resolve(true));
|
|
||||||
navigation.getModules = vi.fn().mockReturnValue({
|
|
||||||
value: [
|
|
||||||
{
|
{
|
||||||
name: 'customer',
|
path: '/',
|
||||||
title: 'customer.pageTitles.customers',
|
redirect: {
|
||||||
icon: 'vn:customer',
|
name: 'Dashboard',
|
||||||
module: 'customer',
|
},
|
||||||
|
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',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
query: {},
|
||||||
|
params: {},
|
||||||
|
meta: { moduleName: 'mockName' },
|
||||||
|
path: 'mockName/1',
|
||||||
|
name: 'Customer',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
vm = mount('card').vm;
|
||||||
|
vm.getCardRoutes = vi.fn().mockReturnValue(() => vi.fn);
|
||||||
});
|
});
|
||||||
describe.only(' its card', () => {
|
|
||||||
it('getRoutes', () => {
|
|
||||||
vm.props.source = 'card';
|
|
||||||
|
|
||||||
vm.getRoutes();
|
it('should get routes for card source', () => {
|
||||||
expect(useNavigationStore().getModules).toHaveBeenCalled();
|
const spyGetCardRoutes = vi.spyOn(vm, 'getCardRoutes');
|
||||||
});
|
vm.getCardRoutes();
|
||||||
});
|
console.log('spyGetCardRoutes', spyGetCardRoutes.mock.calls);
|
||||||
describe(' its main', () => {
|
expect(spyGetCardRoutes.mock.calls).toHaveLength(1);
|
||||||
beforeAll(() => {
|
});
|
||||||
vm = mount('main').vm;
|
});
|
||||||
});
|
describe('Leftmenu as main', () => {
|
||||||
|
beforeAll(() => {
|
||||||
it('should return a proper formated object with two child items', async () => {
|
vm = mount('main').vm;
|
||||||
const expectedMenuItem = [
|
});
|
||||||
{
|
|
||||||
children: null,
|
it('should return a proper formated object with two child items', async () => {
|
||||||
name: 'CustomerList',
|
const expectedMenuItem = [
|
||||||
title: 'globals.pageTitles.list',
|
{
|
||||||
icon: 'view_list',
|
children: null,
|
||||||
},
|
name: 'CustomerList',
|
||||||
{
|
title: 'globals.pageTitles.list',
|
||||||
children: null,
|
icon: 'view_list',
|
||||||
name: 'CustomerCreate',
|
},
|
||||||
title: 'globals.pageTitles.createCustomer',
|
{
|
||||||
icon: 'vn:addperson',
|
children: null,
|
||||||
},
|
name: 'CustomerCreate',
|
||||||
];
|
title: 'globals.pageTitles.createCustomer',
|
||||||
const firstMenuItem = vm.items[0];
|
icon: 'vn:addperson',
|
||||||
expect(firstMenuItem.children).toEqual(
|
},
|
||||||
expect.arrayContaining(expectedMenuItem)
|
];
|
||||||
);
|
const firstMenuItem = vm.items[0];
|
||||||
});
|
expect(firstMenuItem.children).toEqual(expect.arrayContaining(expectedMenuItem));
|
||||||
|
});
|
||||||
it('should initialize with default props', () => {
|
|
||||||
expect(vm.source).toBe('main');
|
it('should initialize with default props', () => {
|
||||||
});
|
expect(vm.source).toBe('main');
|
||||||
|
});
|
||||||
it('should filter items based on search input', async () => {
|
|
||||||
vm.search = 'Rou';
|
it('should filter items based on search input', async () => {
|
||||||
await vm.$nextTick();
|
vm.search = 'Rou';
|
||||||
// expect(vm.filterItems).toHaveBeenCalled();
|
await vm.$nextTick();
|
||||||
expect(vm.filterItems()).toEqual([]);
|
// expect(vm.filterItems).toHaveBeenCalled();
|
||||||
});
|
expect(vm.filterItems()).toEqual([]);
|
||||||
|
});
|
||||||
it('should return pinned items', () => {
|
|
||||||
vm.items = [
|
it('should return pinned items', () => {
|
||||||
{ name: 'Item 1', isPinned: false },
|
vm.items = [
|
||||||
{ name: 'Item 2', isPinned: true },
|
{ name: 'Item 1', isPinned: false },
|
||||||
|
|||||||
];
|
{ name: 'Item 2', isPinned: true },
|
||||||
expect(vm.pinnedModules).toEqual(
|
];
|
||||||
new Map([['Item 2', { 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';
|
it('should find matches in routes', () => {
|
||||||
const item = {
|
const search = 'child1';
|
||||||
children: [
|
const item = {
|
||||||
{ name: 'child1', children: [] },
|
children: [
|
||||||
{ name: 'child2', children: [] },
|
{ name: 'child1', children: [] },
|
||||||
],
|
{ name: 'child2', children: [] },
|
||||||
};
|
],
|
||||||
const matches = vm.findMatches(search, item);
|
};
|
||||||
expect(matches).toEqual([{ name: 'child1', children: [] }]);
|
const matches = vm.findMatches(search, item);
|
||||||
});
|
expect(matches).toEqual([{ name: 'child1', children: [] }]);
|
||||||
|
});
|
||||||
it.skip('should add children to navigation', () => {
|
it('should not proceed if event is already prevented', async () => {
|
||||||
const module = 'module1';
|
const item = { module: 'testModule', isPinned: false };
|
||||||
const route = {
|
const event = {
|
||||||
meta: { menu: 'child1' },
|
preventDefault: vi.fn(),
|
||||||
children: [
|
stopPropagation: vi.fn(),
|
||||||
{ name: 'child1', children: [] },
|
defaultPrevented: true,
|
||||||
{ name: 'child2', children: [] },
|
};
|
||||||
],
|
|
||||||
};
|
await vm.togglePinned(item, event);
|
||||||
const parent = 'parent1';
|
|
||||||
jorgep
commented
Estaría bien crear un test que devuelva algún resultado, mockea otra para comprobar que solo te va a devolver esa. Estaría bien crear un test que devuelva algún resultado, mockea otra para comprobar que solo te va a devolver esa.
|
|||||||
vm.addChildren(module, route, parent);
|
expect(event.preventDefault).not.toHaveBeenCalled();
|
||||||
expect(useNavigationStore().addMenuItem).toHaveBeenCalledWith(
|
expect(event.stopPropagation).not.toHaveBeenCalled();
|
||||||
module,
|
});
|
||||||
{ name: 'child1', children: [] },
|
|
||||||
parent
|
it('should call quasar.notify with success message', async () => {
|
||||||
);
|
const item = { module: 'testModule', isPinned: false };
|
||||||
});
|
const event = {
|
||||||
|
preventDefault: vi.fn(),
|
||||||
it('should get routes for main source', () => {
|
stopPropagation: vi.fn(),
|
||||||
vm.props.source = 'main';
|
defaultPrevented: false,
|
||||||
vm.getRoutes();
|
};
|
||||||
expect(useNavigationStore().getModules).toHaveBeenCalled();
|
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 handle an empty matched array', () => {
|
||||||
|
const result = vm.betaGetRoutes();
|
||||||
|
|
||||||
|
expect(result).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('should handle a single matched route with a menu', () => {
|
||||||
|
const route = {
|
||||||
|
matched: [{ meta: { menu: 'menu1' } }],
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = vm.betaGetRoutes();
|
||||||
|
|
||||||
|
expect(result).toEqual(route.matched[0]);
|
||||||
|
});
|
||||||
|
it('should get routes for main source', () => {
|
||||||
|
vm.props.source = 'main';
|
||||||
|
vm.getRoutes();
|
||||||
|
expect(useNavigationStore().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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// WIP
|
||||||
|
describe.skip('addChildren', () => {
|
||||||
|
it('should add menu items to parent if matches are found', () => {
|
||||||
|
const module = 'testModule';
|
||||||
|
const route = {
|
||||||
|
meta: { menu: 'child1' },
|
||||||
|
children: [{ name: 'child1' }, { name: 'child2' }],
|
||||||
|
};
|
||||||
|
const parent = [];
|
||||||
|
|
||||||
|
vm.addChildren(module, route, parent);
|
||||||
|
|
||||||
|
expect(useNavigationStore().addMenuItem).toHaveBeenCalledWith(
|
||||||
|
module,
|
||||||
|
{ name: 'child1' },
|
||||||
|
parent
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('should not add menu items if no matches are found', () => {
|
||||||
|
const module = 'testModule';
|
||||||
|
const route = {
|
||||||
|
meta: { menu: 'child3' },
|
||||||
|
children: [{ name: 'child1' }, { name: 'child2' }],
|
||||||
|
};
|
||||||
|
const parent = [];
|
||||||
|
|
||||||
|
vm.addChildren(module, route, parent);
|
||||||
|
|
||||||
|
expect(useNavigationStore().addMenuItem).not.toHaveBeenCalled();
|
||||||
jorgep
commented
En estos tests, solo veo que compruebes que la función haya sido llamada, no se debería comprobar si navigation ha cambiado? En estos tests, solo veo que compruebes que la función haya sido llamada, no se debería comprobar si navigation ha cambiado?
|
|||||||
|
});
|
||||||
|
|
||||||
|
it.skip('should handle routes with no meta menu', () => {
|
||||||
|
const module = 'testModule';
|
||||||
|
const route = {
|
||||||
|
menus: { main: 'child1' },
|
||||||
|
children: [{ name: 'child1' }, { name: 'child2' }],
|
||||||
|
};
|
||||||
|
const parent = [];
|
||||||
|
|
||||||
|
vm.addChildren(module, route, parent);
|
||||||
|
|
||||||
|
expect(useNavigationStore().addMenuItem).toHaveBeenCalledWith(
|
||||||
|
module,
|
||||||
|
{ name: 'child1' },
|
||||||
|
parent
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('should handle routes with no matches', () => {
|
||||||
|
const module = 'testModule';
|
||||||
|
const route = {
|
||||||
|
meta: { menu: 'child3' },
|
||||||
|
children: [{ name: 'child1' }, { name: 'child2' }],
|
||||||
|
};
|
||||||
jorgep
commented
Aquí habría que comprobar que el módulo ha sido añadido no? Aquí habría que comprobar que el módulo ha sido añadido no?
jsegarra
commented
Eso correspondería al test de useNavigationStore, no? No podríamos ni deberíamos testear funcionalidad de otros archivos Eso correspondería al test de useNavigationStore, no? No podríamos ni deberíamos testear funcionalidad de otros archivos
jorgep
commented
En el título del archivo pone should add menu items. Como sabes que ha funcionado? solo sabes que se ha llamado a la función. Los 3 tests son exactamente iguales, con diferente título. Veo tu punto, si no crees que sea el lugar de testearlo, cambia el título del test por uno que compruebe realmente lo que hace esa función, llamar a otra función. En el título del archivo pone should add menu items. Como sabes que ha funcionado? solo sabes que se ha llamado a la función. Los 3 tests son exactamente iguales, con diferente título. Veo tu punto, si no crees que sea el lugar de testearlo, cambia el título del test por uno que compruebe realmente lo que hace esa función, llamar a otra función.
jsegarra
commented
Mmm...WTF. Mmm...WTF.
Lo reviso, pero si 3 iguales
jorgep
commented
Hacer solo 1 test que compruebe que la función ha sido llamada. Estos tests hay hacerlos en navigationStore según lo que hablamos en persona. Hacer solo 1 test que compruebe que la función ha sido llamada. Estos tests hay hacerlos en navigationStore según lo que hablamos en persona.
|
|||||||
|
const parent = [];
|
||||||
|
|
||||||
|
vm.addChildren(module, route, parent);
|
||||||
|
|
||||||
|
expect(useNavigationStore().addMenuItem).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip('should handle empty parent array', () => {
|
||||||
|
const module = 'testModule';
|
||||||
|
const route = {
|
||||||
|
meta: { menu: 'child1' },
|
||||||
|
children: [{ name: 'child1' }, { name: 'child2' }],
|
||||||
|
};
|
||||||
|
const parent = [];
|
||||||
|
|
||||||
|
vm.addChildren(module, route, parent);
|
||||||
|
|
||||||
|
expect(useNavigationStore().addMenuItem).toHaveBeenCalledWith(
|
||||||
|
module,
|
||||||
|
{ name: 'child1' },
|
||||||
|
parent
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Poner otro nombre, está repetido.
oh vaya
should not call getMethodA when method is undefined por ej.