import React from 'react'; import { fireEvent, render } from '@testing-library/react-native'; import DatePickerRangeView from '../date-picker-range-view'; jest.mock('@xrnjs/ui', () => ({ Button: ({ children, onPress }: any) => { const React = require('react'); const { Text } = require('react-native'); return React.createElement(Text, { onPress }, children); }, Fill: { weak: 'weak', outline: 'outline', }, })); jest.mock('../../date-picker-view', () => { return function MockDatePickerView() { return null; }; }); jest.mock('../../date-picker-view/helper', () => ({ formatDate: (_mode: string, day: Date) => `${day.getFullYear()}-${day.getMonth() + 1}-${day.getDate()}`, })); jest.mock('../../../components/Locale/locale', () => ({ useLocale: () => ({ DatePickerRangeView: { labelStartTime: '开始时间', labelEndTime: '结束时间', placeholder: ['请选择开始时间', '请选择结束时间'], resetButtonText: '重置', confirmButtonText: '确认', clearButtonText: '清空', }, }), useLangType: () => 'zh_CN', })); jest.mock('../../picker/style', () => ({ varCreator: () => ({ picker_action_gap: 0, }), styleCreator: () => ({ data_range: {}, data_range_item: {}, data_range_text: {}, data_range_day: {}, data_range_day_active: {}, }), })); jest.mock('../../button/style', () => ({ varCreator: () => ({ button_active_opacity: 1, }), })); jest.mock('../../row', () => { return function MockRow({ children }: any) { const React = require('react'); const { View } = require('react-native'); return {children}; }; }); jest.mock('../../col', () => { return function MockCol({ children }: any) { const React = require('react'); const { View } = require('react-native'); return {children}; }; }); jest.mock('../../theme', () => ({ __esModule: true, default: { useThemeTokens: () => ({}), createVar: (_tokens: any, creator: any) => creator(), createStyle: (_vars: any, creator: any) => creator(), }, })); jest.mock('../../hooks', () => ({ usePersistFn: (fn: any) => { const React = require('react'); return React.useCallback(fn, []); }, })); describe('DatePickerRangeView', () => { test('does not auto emit partial range on mount', () => { const onChange = jest.fn(); render( ); expect(onChange).not.toHaveBeenCalled(); }); test('reset keeps empty range instead of auto filling start date', () => { const onChange = jest.fn(); const { getByText } = render( ); fireEvent.press(getByText('重置')); expect(onChange).toHaveBeenLastCalledWith([null, null]); }); test('invalid end date falls back to placeholder instead of NaN text', () => { const { queryByText, getByText } = render( ); expect(queryByText('NaN-NaN')).toBeNull(); expect(getByText('请选择结束时间')).toBeTruthy(); }); test('switching to end date does not auto fill end value', () => { const onChange = jest.fn(); const { getByText } = render( ); fireEvent.press(getByText('结束时间')); expect(onChange).not.toHaveBeenCalled(); }); test('reset then switch to end date shows correct placeholders', () => { const onChange = jest.fn(); const Wrapper = () => { const [val, setVal] = React.useState<[Date | null, Date | null]>([ new Date('2026-03-27'), new Date('2026-03-28'), ]); return ( { setVal(v); onChange(v); }} /> ); }; const { getByText } = render(); // Reset to initialValue [null, null] fireEvent.press(getByText('重置')); expect(onChange).toHaveBeenLastCalledWith([null, null]); // Switch to end date tab — should not crash or auto-fill fireEvent.press(getByText('结束时间')); // Both placeholders should appear since value is [null, null] expect(getByText('请选择开始时间')).toBeTruthy(); expect(getByText('请选择结束时间')).toBeTruthy(); }); test('reset with non-null initialValue restores original dates', () => { const initStart = new Date('2025-06-01'); const initEnd = new Date('2025-06-15'); const onChange = jest.fn(); const { getByText } = render( ); fireEvent.press(getByText('重置')); const lastCall = onChange.mock.calls[onChange.mock.calls.length - 1][0]; expect(lastCall[0].getTime()).toBe(initStart.getTime()); expect(lastCall[1].getTime()).toBe(initEnd.getTime()); }); test('confirm fills both values when only start is set', () => { const onConfirm = jest.fn(); const onChange = jest.fn(); const start = new Date('2026-05-10'); const { getByText } = render( ); fireEvent.press(getByText('确认')); // ensureCompleteRangeValue should fill end = start when end is null if (onConfirm.mock.calls.length > 0) { const confirmed = onConfirm.mock.calls[0][0]; expect(confirmed[0]).toBeInstanceOf(Date); expect(confirmed[1]).toBeInstanceOf(Date); // end should be >= start expect(confirmed[1].getTime()).toBeGreaterThanOrEqual( confirmed[0].getTime() ); } }); test('switching start→end→start does not lose dates', () => { const onChange = jest.fn(); const start = new Date('2026-04-01'); const end = new Date('2026-04-15'); const { getByText } = render( ); fireEvent.press(getByText('结束时间')); fireEvent.press(getByText('开始时间')); // Dates should still be displayed, not replaced by placeholders expect(getByText('2026-4-1')).toBeTruthy(); expect(getByText('2026-4-15')).toBeTruthy(); }); });