import { mount } from '@vue/test-utils'; import VTabs from './VTabs.vue'; import VTab from './VTab.vue'; import VTabList from './VTabList.vue'; import VTabPanel from './VTabPanel.vue'; import VTabPanels from './VTabPanels.vue'; import { TabsProviderKey } from './types'; import { nextTick, h } from 'vue'; // Helper to create a minimal tabs structure for testing VTabs logic const createBasicTabsStructure = (activeTabId: string | null = 'tab1') => { return { components: { VTabs, VTabList, VTab, VTabPanels, VTabPanel }, template: `

Content 1

Content 2

`, data() { return { currentModelValue: activeTabId, initialTabValue: activeTabId, // Can be overridden in test }; }, }; }; describe('VTabs.vue', () => { it('initializes activeTabId with modelValue', () => { const wrapper = mount(VTabs, { props: { modelValue: 'second' }, slots: { default: '' }, global: { components: { VTabList, VTab, VTabPanels, VTabPanel } } // Stubbing children }); const context = wrapper.vm.$.provides[TabsProviderKey as any]; expect(context.activeTabId.value).toBe('second'); }); it('initializes activeTabId with initialTab if modelValue is not provided', () => { const wrapper = mount(VTabs, { props: { initialTab: 'third' }, slots: { default: '' }, global: { components: { VTabList, VTab, VTabPanels, VTabPanel } } }); const context = wrapper.vm.$.provides[TabsProviderKey as any]; expect(context.activeTabId.value).toBe('third'); }); it('updates activeTabId when modelValue prop changes', async () => { const wrapper = mount(VTabs, { props: { modelValue: 'one' }, slots: { default: '' }, global: { components: { VTabList, VTab, VTabPanels, VTabPanel } } }); const context = wrapper.vm.$.provides[TabsProviderKey as any]; expect(context.activeTabId.value).toBe('one'); await wrapper.setProps({ modelValue: 'two' }); expect(context.activeTabId.value).toBe('two'); }); it('emits update:modelValue when selectTab is called', async () => { const wrapper = mount(VTabs, { props: { modelValue: 'alpha' }, slots: { default: '' }, global: { components: { VTabList, VTab, VTabPanels, VTabPanel } } }); const context = wrapper.vm.$.provides[TabsProviderKey as any]; context.selectTab('beta'); await nextTick(); expect(wrapper.emitted()['update:modelValue']).toBeTruthy(); expect(wrapper.emitted()['update:modelValue'][0]).toEqual(['beta']); expect(context.activeTabId.value).toBe('beta'); }); it('selects the first tab if no modelValue or initialTab is provided on mount', async () => { // This test is more involved as it requires inspecting slot children // We need to ensure VTab components are actually rendered within the slots const TestComponent = { components: { VTabs, VTabList, VTab, VTabPanels, VTabPanel }, template: ` Content First Content Second `, }; const wrapper = mount(TestComponent); await nextTick(); // Wait for onMounted hook in VTabs // Access VTabs instance to check its internal activeTabId via provided context const vTabsInstance = wrapper.findComponent(VTabs); const context = vTabsInstance.vm.$.provides[TabsProviderKey as any]; expect(context.activeTabId.value).toBe('firstMounted'); }); it('does not change activeTabId if modelValue is explicitly null and no initialTab', async () => { const TestComponent = { components: { VTabs, VTabList, VTab, VTabPanels, VTabPanel }, template: ` `, }; const wrapper = mount(TestComponent); await nextTick(); const vTabsInstance = wrapper.findComponent(VTabs); const context = vTabsInstance.vm.$.provides[TabsProviderKey as any]; expect(context.activeTabId.value).toBeNull(); // Should remain null, not default to first tab }); it('renders its default slot content', () => { const wrapper = mount(VTabs, { slots: { default: '
Hello
' }, }); expect(wrapper.find('.test-slot-content').exists()).toBe(true); expect(wrapper.text()).toContain('Hello'); }); });