import { afterEach, describe, expect, it, vi } from 'vitest'; import { defineComponent, h } from 'vue'; import { mount } from '@vue/test-utils'; import { Accordion } from '@42/core/accordion'; import { useC42 } from './useC42'; import AccordionWrapper from './components/Accordion'; /** Markup the headless `Accordion` controller enhances, built via render fns. */ const items = () => [ h('div', { 'data-c42-accordion-item': '', 'data-value': 'a' }, [ h('button', { 'data-c42-accordion-trigger': '' }, 'A'), h('div', { 'data-c42-accordion-panel': '' }, 'Panel A'), ]), h('div', { 'data-c42-accordion-item': '', 'data-value': 'b' }, [ h('button', { 'data-c42-accordion-trigger': '' }, 'B'), h('div', { 'data-c42-accordion-panel': '' }, 'Panel B'), ]), ]; /** Bare component exercising the composable directly with a real controller. */ const AccordionHarness = defineComponent({ name: 'AccordionHarness', setup() { const el = useC42(Accordion, () => ({})); return () => h('div', { ref: el, 'data-c42-accordion': '' }, items()); }, }); afterEach(() => { vi.restoreAllMocks(); }); describe('useC42', () => { it('instantiates the controller in onMounted and the markup responds', async () => { const wrapper = mount(AccordionHarness); const trigger = wrapper.get('[data-c42-accordion-trigger]'); // The controller enhanced the markup after mount. expect(trigger.attributes('aria-expanded')).toBe('false'); await trigger.trigger('click'); // The live instance is bound to the DOM and toggles state. expect(trigger.attributes('aria-expanded')).toBe('true'); wrapper.unmount(); }); it('calls destroy() on the controller in onUnmounted', () => { const destroySpy = vi.spyOn(Accordion.prototype, 'destroy'); const wrapper = mount(AccordionHarness); expect(destroySpy).not.toHaveBeenCalled(); wrapper.unmount(); expect(destroySpy).toHaveBeenCalledTimes(1); }); }); describe(' generated wrapper', () => { it('re-emits the accordion:change DOM event as a Vue emit', async () => { const wrapper = mount(AccordionWrapper, { slots: { default: () => items() }, }); await wrapper.get('[data-c42-accordion-trigger]').trigger('click'); const emitted = wrapper.emitted('accordion:change'); expect(emitted).toBeTruthy(); // The wrapper forwards the unwrapped CustomEvent detail. expect(emitted![0]![0]).toEqual({ value: ['a'] }); wrapper.unmount(); }); });