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: `
currentModelValue = val" :initialTab="initialTabValue">
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');
});
});