From ea9b8124d8978da3b7adfa785fc11d75786087ea Mon Sep 17 00:00:00 2001 From: sam Date: Thu, 22 Sep 2022 11:06:32 +0800 Subject: [PATCH] test(collapse): add unit test for collapse and support content api (#1536) --- src/collapse/__tests__/index.test.js | 440 +++++++++++++++++++++++++++ src/collapse/collapse-panel.tsx | 6 +- 2 files changed, 443 insertions(+), 3 deletions(-) create mode 100644 src/collapse/__tests__/index.test.js diff --git a/src/collapse/__tests__/index.test.js b/src/collapse/__tests__/index.test.js new file mode 100644 index 000000000..0799bd5bc --- /dev/null +++ b/src/collapse/__tests__/index.test.js @@ -0,0 +1,440 @@ +import { mount } from '@vue/test-utils'; +import Vue from 'vue'; +import { Collapse, CollapsePanel } from '../index'; + +describe('Collapse', () => { + describe(':props', () => { + test(':borderless', async () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + data() { + return { borderless: false }; + }, + template: ` + + + + `, + }), + ); + + expect(wrapper.classes()).not.toContain('t--border-less'); + + await wrapper.setData({ borderless: true }); + expect(wrapper.classes()).toContain('t--border-less'); + }); + + test(':defaultExpandAll', async () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + template: ` + + + + + `, + }), + ); + + const panel1 = wrapper.findComponent({ ref: '1' }); + const panel2 = wrapper.findComponent({ ref: '2' }); + + expect(panel1.find('.t-collapse-panel__body').attributes().style).toBeUndefined(); + expect(panel2.find('.t-collapse-panel__body').attributes().style).toBeUndefined(); + }); + + test(':disabled', async () => { + const mockFn = jest.fn(); + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + data() { + return { disabled: false }; + }, + methods: { + handleChange: mockFn, + }, + template: ` + + + + `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + await panel.find('.t-collapse-panel__header').trigger('click'); + + expect(mockFn).toHaveBeenCalled(); + + await wrapper.setData({ disabled: true }); + await panel.find('.t-collapse-panel__header').trigger('click'); + + expect(mockFn).toHaveBeenCalledTimes(1); + }); + + test(':expandIcon', async () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + data() { + return { expandIcon: true }; + }, + template: ` + + + + `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + expect(panel.find('.t-collapse-panel__header svg').exists()).toBeTruthy(); + + await wrapper.setData({ expandIcon: false }); + expect(panel.find('.t-collapse-panel__header svg').exists()).toBeFalsy(); + }); + + test(':expandIconPlacement', async () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + data() { + return { expandIconPlacement: 'left' }; + }, + template: ` + + + + `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + expect(panel.find('.t-collapse-panel__header svg').classes()).toContain('t-collapse-panel__icon--left'); + + await wrapper.setData({ expandIconPlacement: 'right' }); + expect(panel.find('.t-collapse-panel__header svg').classes()).toContain('t-collapse-panel__icon--right'); + }); + + test(':expandMutex', async () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + data() { + return { value: [] }; + }, + template: ` + + + + + `, + }), + ); + + const panel1 = wrapper.findComponent({ ref: '1' }); + const panel2 = wrapper.findComponent({ ref: '2' }); + await panel1.find('.t-collapse-panel__header').trigger('click'); + + expect(wrapper.vm.value).toHaveLength(1); + expect(wrapper.vm.value).toContain('1'); + + await panel2.find('.t-collapse-panel__header').trigger('click'); + + expect(wrapper.vm.value).toHaveLength(1); + expect(wrapper.vm.value).toContain('2'); + }); + + test(':expandOnRowClick', async () => { + const mockFn = jest.fn(); + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + data() { + return { expandOnRowClick: true }; + }, + methods: { + handleChange: mockFn, + }, + template: ` + + + + `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + await panel.find('.t-collapse-panel__header').trigger('click'); + expect(mockFn).toHaveBeenCalled(); + + await wrapper.setData({ expandOnRowClick: false }); + + await panel.find('.t-collapse-panel__header').trigger('click'); + expect(mockFn).toHaveBeenCalledTimes(1); + + await panel.find('.t-collapse-panel__header svg').trigger('click'); + expect(mockFn).toHaveBeenCalledTimes(2); + }); + + test(':defaultValue', async () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + template: ` + + + + + `, + }), + ); + + const panel1 = wrapper.findComponent({ ref: '1' }); + const panel2 = wrapper.findComponent({ ref: '2' }); + + expect(panel1.find('.t-collapse-panel__body').attributes().style).toBeUndefined(); + expect(panel2.find('.t-collapse-panel__body').attributes().style).toBe('display: none;'); + }); + }); + + describe('@event', () => { + test('change', async () => { + const mockFn = jest.fn(); + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + methods: { + handleChange: mockFn, + }, + template: ` + + + + `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + await panel.find('.t-collapse-panel__header').trigger('click'); + expect(mockFn).toHaveBeenCalled(); + }); + }); +}); + +describe('CollapsePanel', () => { + describe(':props', () => { + test(':default、content、header、headerRightContent', async () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + template: ` + + + + + `, + }), + ); + + const panel1 = wrapper.findComponent({ ref: '1' }); + const panel2 = wrapper.findComponent({ ref: '2' }); + expect(panel1.find('.t-collapse-panel__content').text()).toBe('内容1'); + expect(panel1.find('.t-collapse-panel__header').text()).toBe('标题右侧'); + expect(panel2.find('.t-collapse-panel__content').text()).toBe('内容2'); + }); + + test(':destroyOnCollapse', async () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + data() { + return { + destroyOnCollapse: false, + }; + }, + template: ` + + + + `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + await panel.find('.t-collapse-panel__header').trigger('click'); + expect(panel.find('.t-collapse-panel__content').exists()).toBeTruthy(); + + await wrapper.setData({ destroyOnCollapse: true }); + await panel.find('.t-collapse-panel__header').trigger('click'); + await panel.find('.t-collapse-panel__header').trigger('click'); + expect(panel.find('.t-collapse-panel__content').exists()).toBeFalsy(); + }); + + test(':disabled', async () => { + const mockFn = jest.fn(); + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + data() { + return { disabled: false }; + }, + methods: { + handleChange: mockFn, + }, + template: ` + + + + `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + await panel.find('.t-collapse-panel__header').trigger('click'); + + expect(mockFn).toHaveBeenCalled(); + + await wrapper.setData({ disabled: true }); + await panel.find('.t-collapse-panel__header').trigger('click'); + + expect(mockFn).toHaveBeenCalledTimes(1); + }); + + test(':expandIcon', async () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + data() { + return { expandIcon: true }; + }, + template: ` + + + + `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + expect(panel.find('.t-collapse-panel__header svg').exists()).toBeTruthy(); + + await wrapper.setData({ expandIcon: false }); + expect(panel.find('.t-collapse-panel__header svg').exists()).toBeFalsy(); + }); + + test(':value', async () => { + const mockFn = jest.fn(); + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + methods: { + handleChange: mockFn, + }, + template: ` + + + + `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + await panel.find('.t-collapse-panel__header').trigger('click'); + expect(mockFn).toHaveBeenCalledWith(['abc']); + }); + }); + + describe('', () => { + test('default、header、headerRightContent', () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + template: ` + + +

标题

+ 操作 +
内容
+
+
+ `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + expect(panel.find('.t-collapse-panel__content > div').html()).toBe('
内容
'); + expect(panel.find('.t-collapse-panel__header > h4').html()).toBe('

标题

'); + expect(panel.find('.t-collapse-panel__header > span').html()).toBe('操作'); + }); + + test('content', () => { + const wrapper = mount( + Vue.extend({ + components: { + 't-collapse': Collapse, + 't-collapse-panel': CollapsePanel, + }, + template: ` + + +
内容
+
+
+ `, + }), + ); + + const panel = wrapper.findComponent({ ref: '1' }); + expect(panel.find('.t-collapse-panel__content > div').html()).toBe('
内容
'); + }); + }); +}); diff --git a/src/collapse/collapse-panel.tsx b/src/collapse/collapse-panel.tsx index f900b0261..37458a884 100644 --- a/src/collapse/collapse-panel.tsx +++ b/src/collapse/collapse-panel.tsx @@ -6,7 +6,7 @@ import FakeArrow from '../common-components/fake-arrow'; import { CollapseValue, TdCollapsePanelProps } from './type'; import { usePrefixClass } from '../hooks/useConfig'; import useCollapseAnimation from './useCollapseAnimation'; -import { renderTNodeJSX } from '../utils/render-tnode'; +import { renderTNodeJSX, renderContent } from '../utils/render-tnode'; export default defineComponent({ name: 'TCollapsePanel', @@ -95,14 +95,14 @@ export default defineComponent({ renderBodyByNormal() { return (
-
{renderTNodeJSX(this, 'default')}
+
{renderContent(this, 'default', 'content')}
); }, renderBodyDestroyOnCollapse() { return this.isActive ? (
-
{renderTNodeJSX(this, 'default')}
+
{renderContent(this, 'default', 'content')}
) : null; },