Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/date-picker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export default defineComponent({
time,
inputRef,
onChange,
closePopup,
} = useSingle(props, { emit });

const formatRef = computed(() => getDefaultFormat({
Expand Down Expand Up @@ -103,7 +104,7 @@ export default defineComponent({
}

// 日期点击
function onCellClick(date: Date) {
function onCellClick(date: Date, { e }: { e: MouseEvent }) {
isHoverCell.value = false;
// date 模式自动切换年月
if (props.mode === 'date') {
Expand Down Expand Up @@ -133,7 +134,7 @@ export default defineComponent({
trigger: 'pick',
},
);
popupVisible.value = false;
closePopup({ e });
}

props.onPick?.(date);
Expand Down Expand Up @@ -219,7 +220,7 @@ export default defineComponent({
format: formatRef.value.format,
});
}
popupVisible.value = false;
closePopup({ e });
}

// 预设
Expand All @@ -237,7 +238,7 @@ export default defineComponent({
);
props.onPresetClick?.(context);
emit('preset-click', context);
popupVisible.value = false;
closePopup({ e: context?.e });
}

function onYearChange(nextYear: number) {
Expand Down Expand Up @@ -290,7 +291,7 @@ export default defineComponent({

const onTagClearClick = ({ e }: { e: MouseEvent }) => {
e.stopPropagation();
popupVisible.value = false;
closePopup({ e });
onChange?.([], { dayjsValue: dayjs(), trigger: 'clear' });
};

Expand Down
7 changes: 4 additions & 3 deletions src/date-picker/DateRangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export default defineComponent({
isHoverCell,
isFirstValueSelected,
onChange,
closePopup,
} = useRange(props, { emit });

const formatRef = computed(() => getDefaultFormat({
Expand Down Expand Up @@ -189,7 +190,7 @@ export default defineComponent({
activeIndex.value = nextIndex;
isFirstValueSelected.value = true;
} else {
popupVisible.value = false;
closePopup({ e });
}
}

Expand Down Expand Up @@ -307,7 +308,7 @@ export default defineComponent({
activeIndex.value = nextIndex;
isFirstValueSelected.value = true;
} else if (nextValue.length === 2) {
popupVisible.value = false;
closePopup({ e });
}
}

Expand All @@ -331,7 +332,7 @@ export default defineComponent({
trigger: 'preset',
},
);
popupVisible.value = false;
closePopup({ e: context?.e });
props.onPresetClick?.(context);
emit('preset-click', context);
}
Expand Down
133 changes: 133 additions & 0 deletions src/date-picker/__tests__/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,4 +238,137 @@ describe('DatePicker', () => {
expect(blurFn).toBeCalledTimes(1);
});
});

// test popupProps.onVisibleChange
describe('popupProps.onVisibleChange', () => {
afterEach(() => {
document.querySelectorAll('.t-popup').forEach((node) => node?.remove());
});

const getLatestPanel = () => {
const panels = document.querySelectorAll('.t-date-picker__panel-container');
return panels[panels.length - 1];
};

it('点击清除按钮关闭面板时触发 onVisibleChange,visible=false 且 trigger=trigger-element-close', async () => {
const onVisibleChange = vi.fn();
const wrapper = mount(
{
render() {
return <DatePicker defaultValue={'2022-09-14'} clearable popupProps={{ onVisibleChange }} />;
},
},
{ attachTo: document.body },
);
// 打开面板
wrapper.find('.t-input').trigger('click');
await nextTick();
// hover 输入框以显示清除按钮
wrapper.find('.t-input').trigger('mouseenter');
await nextTick();
// 触发清除
wrapper.find('.t-input__suffix-clear').trigger('click');
await nextTick();
// 验证 onVisibleChange 被调用过:visible=false, trigger=trigger-element-close, 且带事件对象
expect(onVisibleChange).toHaveBeenCalledWith(
false,
expect.objectContaining({
trigger: 'trigger-element-close',
e: expect.anything(),
}),
);
});

it('选日期后关闭面板时触发 onVisibleChange,visible=false 且 trigger=trigger-element-close', async () => {
const onVisibleChange = vi.fn();
const wrapper = mount(
{
render() {
return <DatePicker popupProps={{ onVisibleChange }} />;
},
},
{ attachTo: document.body },
);
// 打开面板
wrapper.find('.t-input').trigger('click');
await nextTick();
await nextTick();
await nextTick(); // 等待面板完全打开
onVisibleChange.mockClear();
// 点击日期
const cell = getLatestPanel()?.querySelector(
'.t-date-picker__panel-date .t-date-picker__cell:not(.t-is-disabled)',
);
if (cell) {
cell.click();
}
await nextTick();
await nextTick(); // 等待面板关闭动画完成
// 验证 onVisibleChange 被调用过:visible=false, trigger=trigger-element-close
expect(onVisibleChange).toHaveBeenCalledWith(
false,
expect.objectContaining({
trigger: 'trigger-element-close',
e: expect.anything(),
}),
);
});

it('点击预设按钮关闭面板时触发 onVisibleChange,visible=false 且 trigger=trigger-element-close', async () => {
const onVisibleChange = vi.fn();
const presets = {
昨天: dayjs().subtract(1, 'day').format('YYYY-MM-DD'),
};
const wrapper = mount(
{
render() {
return <DatePicker presets={presets} popupProps={{ onVisibleChange }} />;
},
},
{ attachTo: document.body },
);
// 打开面板
wrapper.find('.t-input').trigger('click');
await nextTick();
await nextTick();
onVisibleChange.mockClear();
// 点击预设按钮
const presetButton = getLatestPanel()?.querySelector('.t-date-picker__presets .t-button');
if (presetButton) {
presetButton.click();
}
await nextTick();
// 验证 onVisibleChange 被调用过:visible=false, trigger=trigger-element-close
expect(onVisibleChange).toHaveBeenCalledWith(
false,
expect.objectContaining({
trigger: 'trigger-element-close',
e: expect.anything(),
}),
);
});

it('readonly 状态下不触发关闭事件', async () => {
const onVisibleChange = vi.fn();
const wrapper = mount(
{
render() {
return <DatePicker readonly defaultValue={'2022-09-14'} clearable popupProps={{ onVisibleChange }} />;
},
},
{ attachTo: document.body },
);
// 打开面板
wrapper.find('.t-input').trigger('click');
await nextTick();
// hover 输入框以显示清除按钮
wrapper.find('.t-input').trigger('mouseenter');
await nextTick();
// 触发清除
wrapper.find('.t-input__suffix-clear').trigger('click');
await nextTick();
// 验证 onVisibleChange 没有被调用(readonly 状态)
expect(onVisibleChange).not.toHaveBeenCalled();
});
});
});
124 changes: 123 additions & 1 deletion src/date-picker/__tests__/rangepicker.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import MockDate from 'mockdate';
import { nextTick } from 'vue';
import { BrowseIcon, LockOnIcon } from 'tdesign-icons-vue';
import dayjs from 'dayjs';
import DateRangePicker from '@/src/date-picker/index.ts';
import DateRangePicker, { DateRangePicker as RealDateRangePicker } from '@/src/date-picker/index.ts';
import DateRangePickerPanel from '@/src/date-picker/DateRangePickerPanel';

// 固定时间,当使用 new Date() 时,返回固定时间,防止“当前时间”的副作用影响,导致 snapshot 变更,mockdate 插件见 https://github.com/boblauer/MockDate
Expand Down Expand Up @@ -276,4 +276,126 @@ describe('DateRangePicker', () => {
expect(panels.length).toBe(2);
});
});

// test popupProps.onVisibleChange
describe('popupProps.onVisibleChange', () => {
afterEach(() => {
document.querySelectorAll('.t-popup').forEach((node) => node?.remove());
});

const getLatestPanel = () => {
const panels = document.querySelectorAll('.t-date-picker__panel-container, .t-date-range-picker__panel');
return panels[panels.length - 1];
};

it('点击清除按钮关闭面板时触发 onVisibleChange,visible=false 且 trigger=trigger-element-close', async () => {
const onVisibleChange = vi.fn();
const wrapper = mount(
{
render() {
return (
<RealDateRangePicker
defaultValue={['2022-09-14', '2022-09-15']}
clearable
popupProps={{ onVisibleChange }}
/>
);
},
},
{ attachTo: document.body },
);
// 打开面板
wrapper.find('.t-range-input').trigger('click');
await nextTick();
// hover 输入框以显示清除按钮
wrapper.find('.t-range-input').trigger('mouseenter');
await nextTick();
// 触发清除
wrapper.find('.t-range-input__suffix-clear').trigger('click');
await nextTick();
// 验证 onVisibleChange 被调用过:visible=false, trigger=trigger-element-close, 且带事件对象
expect(onVisibleChange).toHaveBeenCalledWith(
false,
expect.objectContaining({
trigger: 'trigger-element-close',
e: expect.anything(),
}),
);
});

it('选完日期范围后关闭面板时触发 onVisibleChange,visible=false 且 trigger=trigger-element-close', async () => {
const onVisibleChange = vi.fn();
const wrapper = mount(
{
render() {
return <RealDateRangePicker popupProps={{ onVisibleChange }} />;
},
},
{ attachTo: document.body },
);
// 打开面板
wrapper.find('.t-range-input').trigger('click');
await nextTick();
await nextTick();
await nextTick(); // 等待面板完全打开
onVisibleChange.mockClear();
// 点击第一个日期
const panel = getLatestPanel();
expect(panel).toBeTruthy();
let cells = panel.querySelectorAll('.t-date-picker__panel-date .t-date-picker__cell:not(.t-is-disabled)');
if (cells.length >= 2) {
cells[5].click(); // 选择第一个日期
await nextTick();
await nextTick(); // 等待第一个日期选择完成
cells = panel.querySelectorAll('.t-date-picker__panel-date .t-date-picker__cell:not(.t-is-disabled)');
cells[12].click(); // 选择第二个日期
await nextTick();
await nextTick(); // 等待面板关闭动画完成
}
// 验证 onVisibleChange 被调用过:visible=false, trigger=trigger-element-close
expect(onVisibleChange).toHaveBeenCalledWith(
false,
expect.objectContaining({
trigger: 'trigger-element-close',
e: expect.anything(),
}),
);
});

it('点击预设按钮关闭面板时触发 onVisibleChange,visible=false 且 trigger=trigger-element-close', async () => {
const onVisibleChange = vi.fn();
const presets = {
昨天: [dayjs().subtract(7, 'day').format('YYYY-MM-DD'), dayjs().subtract(1, 'day').format('YYYY-MM-DD')],
};
const wrapper = mount(
{
render() {
return <RealDateRangePicker presets={presets} popupProps={{ onVisibleChange }} />;
},
},
{ attachTo: document.body },
);
// 打开面板
wrapper.find('.t-range-input').trigger('click');
await nextTick();
await nextTick();
await nextTick(); // 等待面板完全打开
onVisibleChange.mockClear();
// 点击预设按钮
const presetButton = getLatestPanel()?.querySelector('.t-date-picker__presets .t-button');
if (presetButton) {
presetButton.click();
await nextTick();
await nextTick(); // 等待面板关闭动画完成
}
// 验证 onVisibleChange 被调用过:visible=false, trigger=trigger-element-close
expect(onVisibleChange).toHaveBeenCalledWith(
false,
expect.objectContaining({
trigger: 'trigger-element-close',
e: expect.anything(),
}),
);
});
});
});
Loading
Loading