@mozaic-ds/vue
Version:
Mozaic-Vue is the Vue.js implementation of ADEO Design system
164 lines (136 loc) • 5.12 kB
text/typescript
import { mount } from '@vue/test-utils';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { ref, nextTick } from 'vue';
const onTriggerKeydown = vi.fn();
const onListboxKeydown = vi.fn();
const hideFloatingItem = vi.fn();
vi.mock('../sidebar/use-floating-item.composable', () => {
return {
useFloatingItem: () => {
const floatingItemIsDisplayed = ref(false);
return {
floatingItemIsDisplayed,
showFloatingItem: () => (floatingItemIsDisplayed.value = true),
hideFloatingItem: () => {
floatingItemIsDisplayed.value = false;
hideFloatingItem();
},
onTriggerKeydown,
onListboxKeydown,
};
},
};
});
import MSidebarExpandableItem from './MSidebarExpandableItem.vue';
import { EXPANDED_SIDEBAR_KEY } from '../sidebar/MSidebar.const';
describe('MSidebarExpandableItem', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('renders expanded details when expanded is true', async () => {
const wrapper = mount(MSidebarExpandableItem, {
props: { label: 'My Label', menuLabel: 'Menu' },
global: {
provide: { [EXPANDED_SIDEBAR_KEY]: true },
},
slots: {
default: '<li>Child item</li>',
},
});
expect(wrapper.find('li.mc-sidebar__item').exists()).toBe(true);
expect(
wrapper.find('summary.mc-sidebar__link').attributes('aria-label'),
).toBe('My Label');
expect(wrapper.text()).toContain('My Label');
expect(wrapper.find('ul.mc-sidebar__sublist').html()).toContain(
'Child item',
);
});
it('renders trigger and toggles listbox when not expanded', async () => {
const wrapper = mount(MSidebarExpandableItem, {
props: { label: 'My Label', menuLabel: 'Overlay Menu' },
global: {
provide: { [EXPANDED_SIDEBAR_KEY]: false },
},
slots: {
default: '<li>Overlay item</li>',
},
});
const button = wrapper.find('button.mc-sidebar__trigger');
expect(button.exists()).toBe(true);
expect(button.attributes('aria-haspopup')).toBe('listbox');
expect(button.attributes('aria-expanded')).toBe('false');
await button.trigger('mouseenter');
await nextTick();
expect(button.attributes('aria-expanded')).toBe('true');
const floating = wrapper.find('.mc-sidebar__floating-item');
expect(floating!.text()).toContain('Overlay Menu');
expect(floating!.text()).toContain('Overlay item');
await button.trigger('mouseleave');
await nextTick();
expect(button.attributes('aria-expanded')).toBe('false');
expect(floating.classes()).toContain('mc-sidebar__floating-item--hidden');
});
it('handles listbox trigger with keyboard accessibility', async () => {
const wrapper = mount(MSidebarExpandableItem, {
props: { label: 'My Label', menuLabel: 'Overlay Menu' },
global: {
provide: { [EXPANDED_SIDEBAR_KEY]: false },
},
slots: {
default: `
<li>Overlay item</li>
<li>Overlay item 2</li>
`,
},
});
const button = wrapper.find('button.mc-sidebar__trigger');
expect(button.exists()).toBe(true);
await button.trigger('focus');
await nextTick();
expect(button.attributes('aria-expanded')).toBe('true');
await button.trigger('keydown', { key: 'ArrowDown' });
expect(onTriggerKeydown).toHaveBeenCalled();
const listboxEl = wrapper.find('.mc-sidebar__floating-item');
await listboxEl.trigger('keydown', { key: 'Escape' });
await button.trigger('blur');
await nextTick();
expect(button.attributes('aria-expanded')).toBe('false');
});
it('calls onListboxKeydown when keydown is emitted on the listbox', async () => {
const wrapper = mount(MSidebarExpandableItem, {
props: { label: 'Item', menuLabel: 'Menu' },
global: {
provide: { [EXPANDED_SIDEBAR_KEY]: false },
},
});
const listbox = wrapper.find('.mc-sidebar__floating-item');
expect(listbox.exists()).toBe(true);
await listbox.trigger('keydown');
expect(onListboxKeydown).toHaveBeenCalled();
});
it('collapsed trigger button has aria-label equal to label prop', () => {
const wrapper = mount(MSidebarExpandableItem, {
props: { label: 'Products', menuLabel: 'Products menu' },
global: {
provide: { [EXPANDED_SIDEBAR_KEY]: false },
},
});
const button = wrapper.find('button.mc-sidebar__trigger');
expect(button.attributes('aria-label')).toBe('Products');
});
it('calls hideFloatingItem on mouseleave and blur on the listbox', async () => {
const wrapper = mount(MSidebarExpandableItem, {
props: { label: 'Item', menuLabel: 'Menu' },
global: {
provide: { [EXPANDED_SIDEBAR_KEY]: false },
},
});
const listbox = wrapper.find('.mc-sidebar__floating-item');
expect(listbox.exists()).toBe(true);
await listbox.trigger('mouseleave');
expect(hideFloatingItem).toHaveBeenCalledTimes(1);
await listbox.trigger('blur');
expect(hideFloatingItem).toHaveBeenCalledTimes(2);
});
});