// Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ import { h } from 'vue' import { renderComponent } from '#tests/support/components/index.ts' import CommonPopover from '../CommonPopover.vue' import CommonPopoverMenu from '../CommonPopoverMenu.vue' import { usePopover } from '../usePopover.ts' import type { MenuItem } from '../types.ts' const html = String.raw const fn = vi.fn() describe('rendering section', () => { it('no output without default slot and items', () => { const view = renderComponent(CommonPopoverMenu, { props: { popover: null, headerLabel: 'Test Header', }, router: true, }) expect(view.queryByText('Test Header')).not.toBeInTheDocument() }) it('if have header prop, renders header', () => { const view = renderComponent(CommonPopoverMenu, { props: { popover: null, headerLabel: 'Test Header', items: [ { label: 'Example', }, ], }, router: true, store: true, }) expect(view.getByText('Test Header')).toBeInTheDocument() }) it('if have header slot, renders header', () => { const view = renderComponent(CommonPopoverMenu, { props: { popover: null, }, slots: { header: '
Test Header
', default: 'Example', }, router: true, }) expect(view.getByText('Test Header')).toBeInTheDocument() }) it('rendering items', () => { const items: MenuItem[] = [ { key: 'login', link: '/login', label: 'Login' }, { key: 'dashboard', link: '/', label: 'Link' }, ] const view = renderComponent(CommonPopoverMenu, { shallow: false, props: { popover: null, items, }, router: true, }) expect(view.getByText('Login')).toBeInTheDocument() expect(view.getByText('Link')).toBeInTheDocument() }) it('rendering only items with permission', () => { const items: MenuItem[] = [ { key: 'login', link: '/login', label: 'Login' }, { key: 'dashboard', link: '/', label: 'Link', permission: ['example'] }, ] const view = renderComponent(CommonPopoverMenu, { shallow: false, props: { popover: null, items, }, router: true, }) expect(view.getByText('Login')).toBeInTheDocument() expect(view.queryByText('Link')).not.toBeInTheDocument() }) it('support click handler on item', async () => { const clickHandler = vi.fn() const items: MenuItem[] = [ { key: 'example', onClick: clickHandler, label: 'Example' }, ] const view = renderComponent(CommonPopoverMenu, { shallow: false, props: { popover: null, items, }, router: true, }) await view.events.click(view.getByText('Example')) expect(clickHandler).toHaveBeenCalledOnce() }) it('close popover on click on item or avoid closing', async () => { const clickHandlerExample = vi.fn() const clickHandlerOther = vi.fn() const view = renderComponent({ components: { CommonPopover, CommonPopoverMenu }, template: html` `, setup() { const { popover, popoverTarget, toggle } = usePopover() const items: MenuItem[] = [ { key: 'example', onClick: clickHandlerExample, label: 'Example' }, { key: 'other', onClick: clickHandlerOther, label: 'Other', noCloseOnClick: true, }, ] return { items, toggle, popover, popoverTarget, } }, }) await view.events.click(view.getByText('Click me')) expect(view.queryByText('Example')).toBeInTheDocument() await view.events.click(view.getByText('Example')) expect(clickHandlerExample).toHaveBeenCalledOnce() expect(view.queryByText('Example')).not.toBeInTheDocument() await view.events.click(view.getByText('Click me')) await view.events.click(view.getByText('Other')) expect(clickHandlerOther).toHaveBeenCalledOnce() expect(view.queryByText('Other')).toBeInTheDocument() }) it('can use an own component for item rendering', async () => { const CustomComponent = (props: any) => { return h('div', `Example ${props.label}`) } CustomComponent.props = ['label'] const items: MenuItem[] = [ { key: 'menu-item', component: CustomComponent, label: 'Menu item' }, ] const view = renderComponent(CommonPopoverMenu, { shallow: false, props: { popover: null, items, }, router: true, }) expect(view.getByText('Example Menu item')).toBeInTheDocument() }) it('yields entity data on show if prop is passed', async () => { renderComponent(CommonPopoverMenu, { props: { popover: null, headerLabel: 'Test Header', entity: { id: 'example', name: 'vitest', }, items: [ { label: 'Example', show: (event: { id: string; name: string }) => { fn(event) return true }, }, ], }, router: true, store: true, }) expect(fn).toBeCalledWith({ id: 'example', name: 'vitest' }) }) })