import { describe, it, expect, vi } from 'vitest'; import { ComponentPublicInstance, nextTick, ref } from 'vue'; import { mount, VueWrapper } from '@vue/test-utils'; import Tabs from '../Tabs.vue'; import TabPanel from '../TabPanel.vue'; const _mount = () => { return mount({ components: { 'co-tabs': Tabs, 'co-tab-panel': TabPanel, }, template: ` 内容1 内容2 `, setup() { const selected = ref('tab1'); return { selected }; }, }); }; const expectActiveTabCorrectly = ( wrapper: VueWrapper, activatedIndex: number, ) => { const anotherIndex = activatedIndex ? 0 : 1; const tabsWrapper = wrapper.findComponent(Tabs); const panelsWrapper = wrapper.findComponent(TabPanel); const tabsNavItemList = tabsWrapper.findAll('.coast-tabs-nav-item'); const activatedTab = tabsWrapper.find('.selected'); expect(activatedTab.text()).toBe(`tab${activatedIndex + 1}`); expect(tabsNavItemList[anotherIndex].text()).toBe(`tab${anotherIndex + 1}`); expect(tabsNavItemList[anotherIndex].classes()).not.toContain('selected'); expect(panelsWrapper.text()).toBe(`内容${activatedIndex + 1}`); }; describe('Tabs', () => { it('create', async () => { const wrapper = _mount(); const tabsWrapper = wrapper.findComponent(Tabs); const panelsWrapper = wrapper.findComponent(TabPanel); expect(tabsWrapper.classes()).toContain('coast-tabs'); expect(panelsWrapper.classes()).toContain('coast-tabs-content'); const tabsNavWrapper = tabsWrapper.find('.coast-tabs-nav'); const tabsNavItemList = tabsNavWrapper.findAll('.coast-tabs-nav-item'); expect(tabsNavItemList.length).toBe(2); expect(tabsNavItemList[0].text()).toBe('tab1'); expect(tabsNavItemList[1].text()).toBe('tab2'); expectActiveTabCorrectly(wrapper, 0); tabsNavItemList[1].trigger('click'); await nextTick(); expectActiveTabCorrectly(wrapper, 1); }); it('watch selected tabPanel change', async () => { const wrapper = mount({ components: { 'co-tabs': Tabs, 'co-tab-panel': TabPanel, }, template: ` 内容1 内容2 `, setup() { const selected = ref('tab1'); const onChange = vi.fn(); return { selected, onChange }; }, }); const vm = wrapper.vm; const tabsWrapper = wrapper.findComponent(Tabs); const tabsNavItemList = tabsWrapper.findAll('.coast-tabs-nav-item'); tabsNavItemList[0].trigger('click'); await nextTick(); expect(vm.onChange).not.toHaveBeenCalled(); tabsNavItemList[1].trigger('click'); await nextTick(); expect(vm.onChange).toHaveBeenCalled(); }); it('TabPanel disabled', () => { const wrapper = mount({ components: { 'co-tabs': Tabs, 'co-tab-panel': TabPanel, }, template: ` 内容1 内容2 内容3 `, setup() { const selected = ref('tab1'); const onChange = vi.fn(); return { selected, onChange }; }, }); const vm = wrapper.vm; const tabsWrapper = wrapper.findComponent(Tabs); const tabsNavItemList = tabsWrapper.findAll('.coast-tabs-nav-item'); for (let i = 1; i < 3; i++) { tabsNavItemList[i].trigger('click'); expect(tabsNavItemList[i].classes()).toContain('disabled'); expect(vm.onChange).not.toHaveBeenCalled(); expectActiveTabCorrectly(wrapper, 0); } }); }); describe('TabPanel', () => { it('TabPanel must in Tabs', () => { const errorMsg = 'CoTabPanel must use width CoTabs'; expect(() => { mount({ components: { 'co-tab-panel': TabPanel }, template: `
内容1 内容2
`, }); }).toThrowError(errorMsg); }); });