mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-28 23:51:17 +08:00
363 lines
12 KiB
TypeScript
363 lines
12 KiB
TypeScript
import React from 'react';
|
|
import type { GetProps, SplitterProps } from 'antd';
|
|
import { ConfigProvider, Splitter } from 'antd';
|
|
|
|
import { fireEvent, render, waitFakeTimer } from '../../../tests/utils';
|
|
|
|
type PanelProps = GetProps<typeof Splitter.Panel>;
|
|
|
|
const SplitterDemo = ({ items = [{}, {}], ...props }: { items?: PanelProps[] } & SplitterProps) => (
|
|
<Splitter {...props}>
|
|
{items?.map((item, idx) => (
|
|
// eslint-disable-next-line react/no-array-index-key
|
|
<Splitter.Panel key={idx} {...item}>
|
|
{idx}
|
|
</Splitter.Panel>
|
|
))}
|
|
</Splitter>
|
|
);
|
|
|
|
describe('Splitter', () => {
|
|
beforeEach(() => {
|
|
// jsdom 不执行任何布局,因此不会计算值 https://github.com/jsdom/jsdom/issues/1590
|
|
global.HTMLElement.prototype.getBoundingClientRect = () =>
|
|
({
|
|
height: 400,
|
|
width: 400,
|
|
}) as DOMRect;
|
|
jest.useFakeTimers();
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllTimers();
|
|
jest.useRealTimers();
|
|
});
|
|
|
|
const doMove = async (
|
|
container: HTMLElement,
|
|
index: number,
|
|
options: { clientX?: number; clientY?: number },
|
|
) => {
|
|
fireEvent.mouseDown(container?.querySelectorAll('.ant-splitter-bar')[index]!, {
|
|
clientX: 0,
|
|
clientY: 0,
|
|
});
|
|
fireEvent.mouseMove(document.documentElement, options); // 40%
|
|
await waitFakeTimer();
|
|
fireEvent.mouseUp(document.documentElement);
|
|
};
|
|
|
|
it('should correct render', () => {
|
|
const { container } = render(<SplitterDemo />);
|
|
expect(container?.querySelector('.ant-splitter')).toBeTruthy();
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')?.length).toBe(2);
|
|
expect(container?.querySelector('.ant-splitter-bar')).toBeTruthy();
|
|
expect(container).toMatchSnapshot();
|
|
});
|
|
|
|
it('should correct render panel size', async () => {
|
|
// 修改 container 大小为添加操作杆后的大小 以便于测试
|
|
global.HTMLElement.prototype.getBoundingClientRect = () =>
|
|
({
|
|
height: 406,
|
|
width: 406,
|
|
}) as DOMRect;
|
|
jest.useFakeTimers();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo
|
|
items={[{ defaultSize: 20 }, { defaultSize: '45%' }, { defaultSize: '40px' }, {}]}
|
|
/>,
|
|
);
|
|
|
|
await waitFakeTimer();
|
|
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')?.[0]).toHaveStyle(
|
|
'flex-basis: calc(20% - 1.5px)',
|
|
);
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')?.[1]).toHaveStyle(
|
|
'flex-basis: calc(45% - 1.5px)',
|
|
);
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')?.[2]).toHaveStyle(
|
|
'flex-basis: calc(10% - 1.5px)',
|
|
);
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')?.[3]).toHaveStyle(
|
|
'flex-basis: calc(25% - 1.5px)',
|
|
);
|
|
});
|
|
|
|
it('The layout should work fine.', () => {
|
|
const { container, rerender } = render(<SplitterDemo />);
|
|
expect(container?.querySelector('.ant-splitter-horizontal')).toBeTruthy();
|
|
|
|
rerender(<SplitterDemo items={[{}, {}, {}]} layout="vertical" />);
|
|
expect(container?.querySelector('.ant-splitter-vertical')).toBeTruthy();
|
|
});
|
|
|
|
it('The resizable should work fine.', () => {
|
|
const { container } = render(
|
|
<SplitterDemo items={[{ defaultSize: 20 }, { resizable: false }, {}]} />,
|
|
);
|
|
|
|
expect(container?.querySelectorAll('.ant-splitter-bar-resizable')?.length).toBe(1);
|
|
});
|
|
|
|
it('The collapsible should work fine.', () => {
|
|
const { container, rerender } = render(
|
|
<SplitterDemo items={[{ defaultSize: 20, collapsible: true }, {}]} />,
|
|
);
|
|
|
|
expect(container?.querySelectorAll('.ant-splitter-bar-collapse-icon')?.length).toBe(2);
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-previous')).toBeTruthy();
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-next')).toBeTruthy();
|
|
|
|
// support collapsible is object
|
|
rerender(
|
|
<SplitterDemo
|
|
items={[
|
|
{
|
|
defaultSize: 20,
|
|
collapsible: {
|
|
prev: true,
|
|
},
|
|
},
|
|
{
|
|
collapsible: {
|
|
next: true,
|
|
},
|
|
},
|
|
{},
|
|
]}
|
|
/>,
|
|
);
|
|
const barNodes = container?.querySelectorAll('.ant-splitter-bar');
|
|
|
|
expect(barNodes?.[0]?.querySelector('.ant-splitter-bar-collapse-previous')).toBeTruthy();
|
|
expect(barNodes?.[0]?.querySelector('.ant-splitter-bar-collapse-next')).toBeFalsy();
|
|
|
|
expect(barNodes?.[1]?.querySelector('.ant-splitter-bar-collapse-previous')).toBeFalsy();
|
|
expect(barNodes?.[1]?.querySelector('.ant-splitter-bar-collapse-next')).toBeTruthy();
|
|
});
|
|
|
|
it('The collapsible click should work fine.', () => {
|
|
const { container, rerender } = render(
|
|
<SplitterDemo
|
|
items={[
|
|
{
|
|
size: 20,
|
|
collapsible: {
|
|
prev: true,
|
|
},
|
|
},
|
|
{},
|
|
]}
|
|
/>,
|
|
);
|
|
// previous click
|
|
fireEvent.click(container?.querySelector('.ant-splitter-bar-collapse-previous')!);
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-previous')).toBeFalsy();
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-next')).toBeTruthy();
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[0]).toHaveStyle(
|
|
'flex-basis: calc(0% - 1px)',
|
|
);
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[1]).toHaveStyle(
|
|
'flex-basis: calc(100% - 1px)',
|
|
);
|
|
|
|
rerender(
|
|
<SplitterDemo
|
|
items={[
|
|
{
|
|
size: 60,
|
|
collapsible: {
|
|
next: true,
|
|
},
|
|
},
|
|
{},
|
|
]}
|
|
/>,
|
|
);
|
|
// next click
|
|
fireEvent.click(container?.querySelector('.ant-splitter-bar-collapse-next')!);
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-previous')).toBeTruthy();
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-next')).toBeFalsy();
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[0]).toHaveStyle(
|
|
'flex-basis: calc(100% - 1px)',
|
|
);
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[1]).toHaveStyle(
|
|
'flex-basis: calc(0% - 1px)',
|
|
);
|
|
|
|
// collapsible is boolean
|
|
rerender(
|
|
<SplitterDemo
|
|
items={[
|
|
{
|
|
size: 10,
|
|
collapsible: true,
|
|
},
|
|
{},
|
|
]}
|
|
/>,
|
|
);
|
|
// mouseDown icon
|
|
fireEvent.mouseDown(container?.querySelector('.ant-splitter-bar-collapse-next')!);
|
|
expect(container?.querySelector('.ant-splitter-resizing')).toBeFalsy();
|
|
fireEvent.mouseDown(container?.querySelector('.ant-splitter-bar-collapse-previous')!);
|
|
expect(container?.querySelector('.ant-splitter-resizing')).toBeFalsy();
|
|
|
|
fireEvent.click(container?.querySelector('.ant-splitter-bar-collapse-next')!);
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-previous')).toBeTruthy();
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-next')).toBeFalsy();
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[0]).toHaveStyle(
|
|
'flex-basis: calc(100% - 1px)',
|
|
);
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[1]).toHaveStyle(
|
|
'flex-basis: calc(0% - 1px)',
|
|
);
|
|
|
|
fireEvent.click(container?.querySelector('.ant-splitter-bar-collapse-previous')!);
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-previous')).toBeTruthy();
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-next')).toBeTruthy();
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[0]).toHaveStyle(
|
|
'flex-basis: calc(10% - 1px)',
|
|
);
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[1]).toHaveStyle(
|
|
'flex-basis: calc(90% - 1px)',
|
|
);
|
|
|
|
fireEvent.click(container?.querySelector('.ant-splitter-bar-collapse-previous')!);
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-previous')).toBeFalsy();
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-next')).toBeTruthy();
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[0]).toHaveStyle(
|
|
'flex-basis: calc(0% - 1px)',
|
|
);
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[1]).toHaveStyle(
|
|
'flex-basis: calc(100% - 1px)',
|
|
);
|
|
|
|
fireEvent.click(container?.querySelector('.ant-splitter-bar-collapse-next')!);
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-previous')).toBeTruthy();
|
|
expect(container?.querySelector('.ant-splitter-bar-collapse-next')).toBeTruthy();
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[0]).toHaveStyle(
|
|
'flex-basis: calc(10% - 1px)',
|
|
);
|
|
expect(container?.querySelectorAll('.ant-splitter-panel')[1]).toHaveStyle(
|
|
'flex-basis: calc(90% - 1px)',
|
|
);
|
|
});
|
|
|
|
it('The mousemove should work fine.', async () => {
|
|
// 修改 container 大小为添加操作杆后的大小 以便于测试
|
|
global.HTMLElement.prototype.getBoundingClientRect = () =>
|
|
({
|
|
height: 402,
|
|
width: 402,
|
|
}) as DOMRect;
|
|
const mockStart = jest.fn();
|
|
const mockMoving = jest.fn();
|
|
const mockMovingVertical = jest.fn();
|
|
const mockEnd = jest.fn();
|
|
|
|
// previous click
|
|
const { container } = render(
|
|
<Splitter>
|
|
<Splitter.Panel>
|
|
<SplitterDemo
|
|
items={[{}, { min: 20 }]}
|
|
onResizeStart={mockStart}
|
|
onResize={mockMoving}
|
|
onResizeEnd={mockEnd}
|
|
/>
|
|
,
|
|
</Splitter.Panel>
|
|
|
|
<Splitter.Panel>
|
|
<SplitterDemo items={[{}, { max: 75 }]} layout="vertical" onResize={mockMovingVertical} />
|
|
</Splitter.Panel>
|
|
</Splitter>,
|
|
);
|
|
|
|
// layout horizontal
|
|
fireEvent.mouseDown(container?.querySelectorAll('.ant-splitter-bar')[0]!, {
|
|
clientX: 0,
|
|
clientY: 0,
|
|
});
|
|
expect(container?.querySelector('.ant-splitter-resizing')).toBeTruthy();
|
|
// 模拟鼠标移动事件
|
|
fireEvent.mouseMove(document.documentElement, { clientX: 40 });
|
|
await waitFakeTimer();
|
|
// 模拟鼠标释放结束拖动
|
|
fireEvent.mouseUp(document.documentElement);
|
|
expect(mockStart).toHaveBeenCalled();
|
|
expect(mockMoving).toHaveBeenCalledWith([60, 40], 0);
|
|
expect(mockEnd).toHaveBeenCalled();
|
|
|
|
// layout vertical
|
|
fireEvent.mouseDown(container?.querySelectorAll('.ant-splitter-bar')[2]!, {
|
|
clientX: 0,
|
|
clientY: 0,
|
|
});
|
|
expect(container?.querySelector('.ant-splitter-resizing')).toBeTruthy();
|
|
fireEvent.mouseMove(document.documentElement, { clientY: 80 });
|
|
await waitFakeTimer();
|
|
fireEvent.mouseUp(document.documentElement);
|
|
expect(mockMovingVertical).toHaveBeenCalledWith([70, 30], 0);
|
|
|
|
expect(container).toMatchSnapshot();
|
|
});
|
|
|
|
it('The min max should work fine.', async () => {
|
|
const mockMoving = jest.fn();
|
|
const { container, rerender } = render(
|
|
<SplitterDemo items={[{ min: 10 }, { max: 60 }, {}, { min: 12 }]} onResize={mockMoving} />,
|
|
);
|
|
|
|
await doMove(container, 0, { clientX: -160 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(1, [10, 40, 25, 25], 0);
|
|
|
|
await doMove(container, 1, { clientX: 160 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(2, [10, 60, 5, 25], 1);
|
|
|
|
await doMove(container, 0, { clientX: -120 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(2, [10, 60, 5, 25], 1);
|
|
|
|
await doMove(container, 2, { clientX: 60 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(3, [10, 60, 18, 12], 2);
|
|
|
|
rerender(<SplitterDemo items={[{ size: 20 }, {}]} onResize={mockMoving} />);
|
|
await doMove(container, 0, { clientX: -120 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(4, [0, 100], 0);
|
|
|
|
await doMove(container, 0, { clientX: -120 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(4, [0, 100], 0);
|
|
await doMove(container, 0, { clientX: 120 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(4, [0, 100], 0);
|
|
|
|
await doMove(container, 0, { clientX: 440 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(5, [100, 0], 0);
|
|
await doMove(container, 0, { clientX: 120 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(5, [100, 0], 0);
|
|
});
|
|
|
|
it('The RTL should work fine.', async () => {
|
|
global.HTMLElement.prototype.getBoundingClientRect = () =>
|
|
({
|
|
height: 402,
|
|
width: 402,
|
|
}) as DOMRect;
|
|
const mockMoving = jest.fn();
|
|
const { container } = render(
|
|
<ConfigProvider direction="rtl">
|
|
<SplitterDemo items={[{}, {}]} onResize={mockMoving} />
|
|
</ConfigProvider>,
|
|
);
|
|
|
|
await doMove(container, 0, { clientX: -80 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(1, [70, 30], 0);
|
|
|
|
await doMove(container, 0, { clientX: 40 });
|
|
expect(mockMoving).toHaveBeenNthCalledWith(2, [60, 40], 0);
|
|
});
|
|
});
|