import { describe, test, expect, vi, beforeEach } from 'vitest' import type { RuntimeConfig } from '@nuxt/schema' import type { AnyAbility } from '@casl/ability' import type { Router } from 'vue-router' import AbstractMenuBuilder from '~/services/layout/menuBuilder/abstractMenuBuilder' import type { IconItem, MenuGroup, MenuItem, MenuItems } from '~/types/layout' import { MENU_LINK_TYPE } from '~/types/enum/layout' import type { AccessProfile, organizationState } from '~/types/interfaces' class TestableAbstractMenuBuilder extends AbstractMenuBuilder { static readonly menuName = 'TestableMenu' public build(): MenuItem | MenuGroup | null { return { label: 'my_menu' } } public createGroup( label: string, icon?: IconItem, children: MenuItems = [], actions: Array = [], ): MenuGroup { return super.createGroup(label, icon, children, actions) } public createItem( label: string, icon?: IconItem, to: string = '', type: MENU_LINK_TYPE = MENU_LINK_TYPE.INTERNAL, ): MenuItem { return super.createItem(label, icon, to, type) } public buildSubmenu(menuBuilder: typeof AbstractMenuBuilder) { return super.buildSubmenu(menuBuilder) } public makeChildren(items: Array<{ pageName: string; icon?: string }>) { return super.makeChildren(items) } } let runtimeConfig: RuntimeConfig let ability: AnyAbility let organizationProfile: organizationState let accessProfile: AccessProfile let menuBuilder: TestableAbstractMenuBuilder let router: Router beforeEach(() => { runtimeConfig = vi.fn() as any as RuntimeConfig ability = vi.fn() as any as AnyAbility organizationProfile = vi.fn() as any as organizationState accessProfile = vi.fn() as any as AccessProfile // @ts-ignore router = vi.fn() as Router menuBuilder = new TestableAbstractMenuBuilder( runtimeConfig, ability, organizationProfile, accessProfile, router, ) }) describe('getMenuName', () => { test('get name', () => { expect(menuBuilder.getMenuName()).toEqual('TestableMenu') }) }) describe('createGroup', () => { test('simple group', () => { const label = 'my_menu' const icon = { name: 'my_icon' } const children = [ { label: 'submenu', type: MENU_LINK_TYPE.INTERNAL, active: true }, ] const actions = [ { label: 'action', type: MENU_LINK_TYPE.INTERNAL, active: true }, ] const result = menuBuilder.createGroup(label, icon, children, actions) expect(result).toEqual({ label, icon, children, actions }) }) test('default values', () => { const result = menuBuilder.createGroup('my_menu') expect(result).toEqual({ label: 'my_menu', icon: undefined, children: [], actions: [], }) }) }) describe('createItem', () => { test('simple item', () => { const label = 'my_menu' const icon = { name: 'my_icon' } const to = 'https://domain.com/foo/bar' const type = MENU_LINK_TYPE.EXTERNAL const result = menuBuilder.createItem(label, icon, to, type) expect(result).toEqual({ icon, label, to, type, active: false }) }) test('default values', () => { const result = menuBuilder.createItem('my_menu') expect(result).toEqual({ label: 'my_menu', icon: undefined, to: '', type: MENU_LINK_TYPE.INTERNAL, active: false, }) }) test('prepend https on external url', () => { const item = menuBuilder.createItem( 'my_menu', undefined, 'domain.com', MENU_LINK_TYPE.EXTERNAL, ) expect(item.to).toEqual('https://domain.com') }) test('complete V1 links (server side)', () => { runtimeConfig.baseUrlAdminLegacy = 'https://admin.opentalent.fr' const item = menuBuilder.createItem( 'my_menu', undefined, '/my_page', MENU_LINK_TYPE.V1, ) expect(item.to).toEqual('https://admin.opentalent.fr/#/my_page') }) test('complete V1 links (client side)', () => { runtimeConfig.baseUrlAdminLegacy = '' // @ts-ignore runtimeConfig.public = { baseUrlAdminLegacy: 'https://admin.opentalent.fr' } const item = menuBuilder.createItem( 'my_menu', undefined, '/my_page', MENU_LINK_TYPE.V1, ) expect(item.to).toEqual('https://admin.opentalent.fr/#/my_page') }) }) describe('buildSubmenu', () => { test('should call given menu build method', () => { expect(menuBuilder.buildSubmenu(TestableAbstractMenuBuilder)).toEqual({ label: 'my_menu', }) }) }) describe('makeChildren', () => { test('simple call', () => { ability.can = vi.fn(() => true) // @ts-ignore router.resolve = vi.fn(() => { return { href: 'foo' } }) const children: MenuItems = menuBuilder.makeChildren([ { pageName: 'foo_page', icon: 'fas fa-dog' }, ]) expect(children).toEqual([ { label: 'foo_page', icon: { name: 'fas fa-dog' }, to: 'foo', type: 0, active: false, }, ]) }) test('no icon', () => { ability.can = vi.fn(() => true) // @ts-ignore router.resolve = vi.fn(() => { return { href: 'foo' } }) const children: MenuItems = menuBuilder.makeChildren([ { pageName: 'foo_page' }, ]) expect(children).toEqual([ { label: 'foo_page', icon: undefined, to: 'foo', type: 0, active: false }, ]) }) test('not allowed', () => { ability.can = vi.fn(() => false) const children: MenuItems = menuBuilder.makeChildren([ { pageName: 'foo_page' }, ]) expect(children).toEqual([]) }) test('unknown page name', () => { ability.can = vi.fn(() => true) // @ts-ignore router.resolve = vi.fn(() => { return null }) expect(() => menuBuilder.makeChildren([{ pageName: 'foo_page' }]), ).toThrowError() }) })