mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-15 17:19:11 +08:00
742ce37887
* feat: SplitPanel init
* feat: SplitPanel update
* feat: SplitPanel update
* feat: splitPanel update useResize
* feat: SplitPanel update
* feat: splitPanel update useResize
* feat: SplitPanel update
* feat: splitPanel demo
* feat: splitPanel update
* feat: splitPanel support complicated combination
* feat: SplitPanel rename to Splitter
* feat: Splitter support onRize
* feat: support collapsible
* feat: support token and collapsible
* feat: update docs
* feat: size defaultSize support string
* feat: min max support string
* feat: update
* feat: support DOM structure
* feat: Optimize UI
* feat: Optimize Code
* fix: Add a default size during initialization to prevent failure to obtain container size
* feat: optimized code
* feat: optimized code
* feat: Optimize Code
* Update components/splitter/demo/layout.tsx
Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: Wanpan <wanpan96@163.com>
* Update components/splitter/demo/multiple.tsx
Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: Wanpan <wanpan96@163.com>
* docs: update
* feat: Modify the style and optimize the interface
* feat: use PropsWithChildren
* feat: support rtl
* feat: collapsible supports object types
* fix: when collapsible is boolean not work
* feat: Splitter add test
* feat: update
* test: update snapshots
* docs: update
* test: update snapshots
* test: update
* test: update
* test: update
* test: update
* fix: Removed invalid min and max restrictions when collapsible exists
* test: update
* test: update
* test: update
* test: test coverage
* Revert "test: test coverage"
This reverts commit d247193722
.
* test: test coverage
* feat: rename
* feat: optimized code
* ci: lint
* feat: optimized code
* feat: add useag tips
* feat: optimized code
* feat: Modify splitbar layout
* feat: optimized code
* feat: numerical precision
* feat: optimized code
* feat: Optimized trigger region
* feat: Support configuration animation
* fix: Fix Collapsible exception when using multiple panels
* fix: Fixed the issue of drag area overlapping when multiple panels are folded
* feat: optimized code
* feat: annotation
* feAt: optimized code
* fix: bgcolor
* fix: Modify the initial value calculation method
* test: update
* feat: add cover image
* chore: adjust logic
* chore: use items size
* chore: rtl
* chore: limit
* chore: controlled
* docs: update demo
* docs: adjust style
* chore: add split style
* chore: hor collapisble style
* chore: collapse icon
* chore: update warning
* chore: clean up
* chore: collapse logic
* chore: adjust demo
* chore: clean up
* test: adjust logic
* docs: update demo
* docs: rm useless demo
* docs: demo
* test: add demo test
* test: test of them
* test: 100% coverage
* chore: fix lint
* docs: update demo
* refactor: unique resize config
* docs: add demo
* fix: support virtual resiable
* chore: add cursor mask
* test: update snapshot
* test: add test case
* test: update snapshot
* chore: use px base
* chore: rm useless code
---------
Signed-off-by: Wanpan <wanpan96@163.com>
Co-authored-by: lijianan <574980606@qq.com>
Co-authored-by: 二货机器人 <smith3816@gmail.com>
Co-authored-by: ice <49827327+coding-ice@users.noreply.github.com>
453 lines
14 KiB
TypeScript
453 lines
14 KiB
TypeScript
import React from 'react';
|
|
import type { GetProps, SplitterProps } from 'antd';
|
|
import { ConfigProvider, Splitter } from 'antd';
|
|
import { spyElementPrototypes } from 'rc-util/lib/test/domHook';
|
|
|
|
import { resetWarned } from '../../_util/warning';
|
|
import {
|
|
act,
|
|
createEvent,
|
|
fireEvent,
|
|
render,
|
|
triggerResize,
|
|
waitFakeTimer,
|
|
} from '../../../tests/utils';
|
|
|
|
type PanelProps = GetProps<typeof Splitter.Panel>;
|
|
|
|
const SplitterDemo = ({ items = [{}, {}], ...props }: { items?: PanelProps[] } & SplitterProps) => (
|
|
<Splitter {...props}>
|
|
{items?.map((item, idx) => {
|
|
const key = `panel-${idx}`;
|
|
return <Splitter.Panel key={key} {...item} />;
|
|
})}
|
|
</Splitter>
|
|
);
|
|
|
|
describe('Splitter', () => {
|
|
const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
|
|
let containerSize = 100;
|
|
|
|
beforeAll(() => {
|
|
spyElementPrototypes(HTMLElement, {
|
|
offsetWidth: {
|
|
get: () => containerSize,
|
|
},
|
|
offsetHeight: {
|
|
get: () => containerSize,
|
|
},
|
|
});
|
|
});
|
|
|
|
beforeEach(() => {
|
|
containerSize = 100;
|
|
errSpy.mockReset();
|
|
resetWarned();
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllTimers();
|
|
jest.useRealTimers();
|
|
});
|
|
|
|
it('should correct render', () => {
|
|
const { container } = render(<SplitterDemo />);
|
|
expect(container.querySelector('.ant-splitter')).toBeTruthy();
|
|
expect(container.querySelectorAll('.ant-splitter-panel')).toHaveLength(2);
|
|
expect(container.querySelector('.ant-splitter-bar')).toBeTruthy();
|
|
});
|
|
|
|
it('should correct render panel size', async () => {
|
|
const { container } = render(<SplitterDemo items={[{ size: 20 }, { size: '45%' }, {}]} />);
|
|
|
|
const panels = container.querySelectorAll('.ant-splitter-panel');
|
|
|
|
expect(panels?.[0]).toHaveStyle('flex-basis: 20px');
|
|
expect(panels?.[1]).toHaveStyle('flex-basis: 45px');
|
|
expect(panels?.[2]).toHaveStyle('flex-basis: 35px');
|
|
});
|
|
|
|
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, rerender } = render(
|
|
<SplitterDemo items={[{ size: 20 }, { resizable: false }, {}]} />,
|
|
);
|
|
expect(container.querySelectorAll('.ant-splitter-bar-dragger')).toHaveLength(2);
|
|
expect(container.querySelectorAll('.ant-splitter-bar-dragger-disabled')).toHaveLength(2);
|
|
|
|
rerender(<SplitterDemo items={[{ size: 20 }, {}, { resizable: false }]} />);
|
|
expect(container.querySelectorAll('.ant-splitter-bar-dragger')).toHaveLength(2);
|
|
expect(container.querySelectorAll('.ant-splitter-bar-dragger-disabled')).toHaveLength(1);
|
|
});
|
|
|
|
it('Splitter.Panel is syntactic sugar', () => {
|
|
const { container } = render(<Splitter.Panel />);
|
|
expect(container.innerHTML).toEqual('');
|
|
});
|
|
|
|
// ============================== Resizable ==============================
|
|
describe('drag', () => {
|
|
function mockDrag(draggerEle: HTMLElement, offset: number) {
|
|
// Down
|
|
const downEvent = createEvent.mouseDown(draggerEle);
|
|
(downEvent as any).pageX = 0;
|
|
(downEvent as any).pageY = 0;
|
|
|
|
fireEvent(draggerEle, downEvent);
|
|
|
|
// Move
|
|
const moveEvent = createEvent.mouseMove(draggerEle);
|
|
(moveEvent as any).pageX = offset;
|
|
(moveEvent as any).pageY = offset;
|
|
fireEvent(draggerEle, moveEvent);
|
|
|
|
// Up
|
|
fireEvent.mouseUp(draggerEle);
|
|
}
|
|
|
|
it('The mousemove should work fine', async () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo items={[{}, {}]} onResize={onResize} onResizeEnd={onResizeEnd} />,
|
|
);
|
|
|
|
// Right
|
|
mockDrag(container.querySelector('.ant-splitter-bar-dragger')!, 40);
|
|
expect(onResize).toHaveBeenCalledWith([90, 10]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([90, 10]);
|
|
|
|
// Left
|
|
mockDrag(container.querySelector('.ant-splitter-bar-dragger')!, -200);
|
|
expect(onResize).toHaveBeenCalledWith([0, 100]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([0, 100]);
|
|
});
|
|
|
|
it('with min', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo items={[{ min: 10 }, {}]} onResize={onResize} onResizeEnd={onResizeEnd} />,
|
|
);
|
|
|
|
mockDrag(container.querySelector('.ant-splitter-bar-dragger')!, -100);
|
|
expect(onResize).toHaveBeenCalledWith([10, 90]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([10, 90]);
|
|
});
|
|
|
|
it('with max', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo items={[{ max: 90 }, {}]} onResize={onResize} onResizeEnd={onResizeEnd} />,
|
|
);
|
|
|
|
mockDrag(container.querySelector('.ant-splitter-bar-dragger')!, 100);
|
|
expect(onResize).toHaveBeenCalledWith([90, 10]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([90, 10]);
|
|
});
|
|
|
|
it('both panel has min and max', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo
|
|
items={[
|
|
{ min: 10, max: 80 },
|
|
{ min: 10, max: 80 },
|
|
]}
|
|
onResize={onResize}
|
|
onResizeEnd={onResizeEnd}
|
|
/>,
|
|
);
|
|
|
|
mockDrag(container.querySelector('.ant-splitter-bar-dragger')!, -100);
|
|
expect(onResize).toHaveBeenCalledWith([20, 80]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([20, 80]);
|
|
|
|
mockDrag(container.querySelector('.ant-splitter-bar-dragger')!, 100);
|
|
expect(onResize).toHaveBeenCalledWith([80, 20]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([80, 20]);
|
|
});
|
|
|
|
it('rtl', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<ConfigProvider direction="rtl">
|
|
<SplitterDemo items={[{}, {}]} onResize={onResize} onResizeEnd={onResizeEnd} />
|
|
</ConfigProvider>,
|
|
);
|
|
|
|
mockDrag(container.querySelector('.ant-splitter-bar-dragger')!, -40);
|
|
expect(onResize).toHaveBeenCalledWith([90, 10]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([90, 10]);
|
|
});
|
|
|
|
it('[true, 0, true] can be move left', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo
|
|
items={[{}, { defaultSize: 0 }, {}]}
|
|
onResize={onResize}
|
|
onResizeEnd={onResizeEnd}
|
|
/>,
|
|
);
|
|
|
|
mockDrag(container.querySelectorAll<HTMLDivElement>('.ant-splitter-bar-dragger')[1], -100);
|
|
expect(onResize).toHaveBeenCalledWith([0, 50, 50]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([0, 50, 50]);
|
|
});
|
|
|
|
it('[false, 0, true] can not be move left', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo
|
|
items={[{ resizable: false }, { defaultSize: 0 }, {}]}
|
|
onResize={onResize}
|
|
onResizeEnd={onResizeEnd}
|
|
/>,
|
|
);
|
|
|
|
mockDrag(container.querySelectorAll<HTMLDivElement>('.ant-splitter-bar-dragger')[1], -100);
|
|
expect(onResize).toHaveBeenCalledWith([50, 0, 50]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([50, 0, 50]);
|
|
});
|
|
});
|
|
|
|
// ============================= Collapsible =============================
|
|
describe('collapsible', () => {
|
|
it('Basic', () => {
|
|
const { container, rerender } = render(
|
|
<SplitterDemo items={[{ size: 20, collapsible: true }, { collapsible: true }]} />,
|
|
);
|
|
|
|
expect(container.querySelectorAll('.ant-splitter-bar-collapse-icon')).toHaveLength(2);
|
|
expect(container.querySelector('.ant-splitter-bar-collapse-start')).toBeTruthy();
|
|
expect(container.querySelector('.ant-splitter-bar-collapse-end')).toBeTruthy();
|
|
|
|
// support collapsible is object
|
|
rerender(
|
|
<SplitterDemo
|
|
items={[
|
|
{
|
|
size: 20,
|
|
collapsible: true,
|
|
},
|
|
{
|
|
collapsible: true,
|
|
},
|
|
{},
|
|
]}
|
|
/>,
|
|
);
|
|
|
|
expect(container.querySelectorAll('.ant-splitter-bar-collapse-start')).toHaveLength(2);
|
|
expect(container.querySelectorAll('.ant-splitter-bar-collapse-end')).toHaveLength(1);
|
|
});
|
|
|
|
it('collapsible - true', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo
|
|
items={[
|
|
{
|
|
size: 20,
|
|
collapsible: true,
|
|
},
|
|
{},
|
|
]}
|
|
onResize={onResize}
|
|
onResizeEnd={onResizeEnd}
|
|
/>,
|
|
);
|
|
|
|
fireEvent.click(container.querySelector('.ant-splitter-bar-collapse-start')!);
|
|
expect(onResize).toHaveBeenCalledWith([0, 100]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([0, 100]);
|
|
});
|
|
|
|
it('collapsible - start:true', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo
|
|
items={[
|
|
{},
|
|
{
|
|
size: 20,
|
|
collapsible: {
|
|
start: true,
|
|
},
|
|
},
|
|
{},
|
|
]}
|
|
onResize={onResize}
|
|
onResizeEnd={onResizeEnd}
|
|
/>,
|
|
);
|
|
|
|
expect(container.querySelector('.ant-splitter-bar-collapse-start')).toBeFalsy();
|
|
expect(container.querySelector('.ant-splitter-bar-collapse-end')).toBeTruthy();
|
|
|
|
fireEvent.click(container.querySelector('.ant-splitter-bar-collapse-end')!);
|
|
expect(onResize).toHaveBeenCalledWith([60, 0, 40]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([60, 0, 40]);
|
|
});
|
|
|
|
it('collapsible - end:true', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo
|
|
items={[
|
|
{},
|
|
{
|
|
size: 20,
|
|
collapsible: {
|
|
end: true,
|
|
},
|
|
},
|
|
{},
|
|
]}
|
|
onResize={onResize}
|
|
onResizeEnd={onResizeEnd}
|
|
/>,
|
|
);
|
|
|
|
expect(container.querySelector('.ant-splitter-bar-collapse-start')).toBeTruthy();
|
|
expect(container.querySelector('.ant-splitter-bar-collapse-end')).toBeFalsy();
|
|
|
|
fireEvent.click(container.querySelector('.ant-splitter-bar-collapse-start')!);
|
|
expect(onResize).toHaveBeenCalledWith([40, 0, 60]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([40, 0, 60]);
|
|
});
|
|
|
|
it('both collapsible', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo
|
|
items={[
|
|
{
|
|
collapsible: true,
|
|
},
|
|
{
|
|
collapsible: true,
|
|
},
|
|
]}
|
|
onResize={onResize}
|
|
onResizeEnd={onResizeEnd}
|
|
/>,
|
|
);
|
|
|
|
function expectClick(element: HTMLElement, size: number[]) {
|
|
onResize.mockReset();
|
|
onResizeEnd.mockReset();
|
|
|
|
fireEvent.click(element);
|
|
expect(onResize).toHaveBeenCalledWith(size);
|
|
expect(onResizeEnd).toHaveBeenCalledWith(size);
|
|
}
|
|
|
|
expectClick(container.querySelector('.ant-splitter-bar-collapse-start')!, [0, 100]);
|
|
expectClick(container.querySelector('.ant-splitter-bar-collapse-end')!, [50, 50]);
|
|
expectClick(container.querySelector('.ant-splitter-bar-collapse-end')!, [100, 0]);
|
|
expectClick(container.querySelector('.ant-splitter-bar-collapse-start')!, [50, 50]);
|
|
});
|
|
|
|
it('collapsible with min', () => {
|
|
const onResize = jest.fn();
|
|
const onResizeEnd = jest.fn();
|
|
|
|
const { container } = render(
|
|
<SplitterDemo
|
|
items={[
|
|
{
|
|
defaultSize: 20,
|
|
collapsible: true,
|
|
min: 10,
|
|
},
|
|
{
|
|
collapsible: true,
|
|
min: '80%',
|
|
},
|
|
]}
|
|
onResize={onResize}
|
|
onResizeEnd={onResizeEnd}
|
|
/>,
|
|
);
|
|
|
|
// Collapse left
|
|
fireEvent.click(container.querySelector('.ant-splitter-bar-collapse-start')!);
|
|
expect(onResize).toHaveBeenCalledWith([0, 100]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([0, 100]);
|
|
expect(container.querySelector('.ant-splitter-bar-dragger-disabled')).toBeTruthy();
|
|
|
|
// Collapse back
|
|
onResize.mockReset();
|
|
onResizeEnd.mockReset();
|
|
fireEvent.click(container.querySelector('.ant-splitter-bar-collapse-end')!);
|
|
expect(onResize).toHaveBeenCalledWith([5, 95]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([5, 95]);
|
|
expect(container.querySelector('.ant-splitter-bar-dragger-disabled')).toBeFalsy();
|
|
|
|
// Collapse right
|
|
onResize.mockReset();
|
|
onResizeEnd.mockReset();
|
|
fireEvent.click(container.querySelector('.ant-splitter-bar-collapse-end')!);
|
|
expect(onResize).toHaveBeenCalledWith([100, 0]);
|
|
expect(onResizeEnd).toHaveBeenCalledWith([100, 0]);
|
|
expect(container.querySelector('.ant-splitter-bar-dragger-disabled')).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
it('auto resize', async () => {
|
|
containerSize = 200;
|
|
|
|
const onResize = jest.fn();
|
|
const { container } = render(
|
|
<SplitterDemo
|
|
items={[
|
|
{
|
|
collapsible: true,
|
|
},
|
|
{},
|
|
]}
|
|
onResize={onResize}
|
|
/>,
|
|
);
|
|
|
|
triggerResize(container.querySelector('.ant-splitter')!);
|
|
|
|
await act(async () => {
|
|
await waitFakeTimer();
|
|
});
|
|
|
|
fireEvent.click(container.querySelector('.ant-splitter-bar-collapse-start')!);
|
|
expect(onResize).toHaveBeenCalledWith([0, 200]);
|
|
});
|
|
});
|