From 1dce89c97e5424c14bdf31f2662b7d68887968e9 Mon Sep 17 00:00:00 2001 From: Rajat Dabade Date: Mon, 4 Aug 2025 19:22:35 +0530 Subject: [PATCH] Reschedule time picker should open with post's scheduled date time (#9035) --- .../data_time_selector/index.test.tsx | 58 +++++++++++++++++++ app/components/data_time_selector/index.tsx | 7 ++- .../reschedule_draft.test.tsx | 47 +++++++++++++++ .../reschedule_draft/reschedule_draft.tsx | 3 +- 4 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 app/components/data_time_selector/index.test.tsx diff --git a/app/components/data_time_selector/index.test.tsx b/app/components/data_time_selector/index.test.tsx new file mode 100644 index 000000000..fb0935e5d --- /dev/null +++ b/app/components/data_time_selector/index.test.tsx @@ -0,0 +1,58 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {fireEvent} from '@testing-library/react-native'; +import moment from 'moment-timezone'; +import React from 'react'; + +import Preferences from '@constants/preferences'; +import {renderWithEverything} from '@test/intl-test-helper'; +import TestHelper from '@test/test_helper'; + +import DateTimeSelector from './index'; + +import type Database from '@nozbe/watermelondb/Database'; + +describe('DateTimeSelector', () => { + let database: Database; + const mockHandleChange = jest.fn(); + const timezone = 'America/New_York'; + const theme = Preferences.THEMES.denim; + + const baseProps = { + timezone, + theme, + handleChange: mockHandleChange, + showInitially: 'date' as const, + }; + + beforeAll(async () => { + const server = await TestHelper.setupServerDatabase(); + database = server.database; + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders with initialDate and uses it when date is selected', () => { + const initialDate = moment().add(2, 'days').hour(14).minute(30); + const {getByTestId, getByText} = renderWithEverything( + , + {database}, + ); + + const picker = getByTestId('custom_date_time_picker'); + expect(picker).toBeTruthy(); + + const selectDateButton = getByText('Select Date'); + fireEvent.press(selectDateButton); + + expect(mockHandleChange).toHaveBeenCalledWith(expect.objectContaining({ + _d: initialDate.toDate(), + })); + }); +}); diff --git a/app/components/data_time_selector/index.tsx b/app/components/data_time_selector/index.tsx index aa8a27d7d..0a196538d 100644 --- a/app/components/data_time_selector/index.tsx +++ b/app/components/data_time_selector/index.tsx @@ -24,6 +24,7 @@ type Props = { theme: Theme; handleChange: (currentDate: Moment) => void; showInitially?: AndroidMode; + initialDate?: Moment; } type AndroidMode = 'date' | 'time'; @@ -43,12 +44,14 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { }; }); -const DateTimeSelector = ({timezone, handleChange, isMilitaryTime, theme, showInitially}: Props) => { +const DateTimeSelector = ({timezone, handleChange, isMilitaryTime, theme, showInitially, initialDate}: Props) => { const styles = getStyleSheet(theme); const currentTime = getCurrentMomentForTimezone(timezone); const timezoneOffSetInMinutes = timezone ? getUtcOffsetForTimeZone(timezone) : undefined; const minimumDate = getRoundedTime(currentTime); - const [date, setDate] = useState(minimumDate); + + const defaultDate = initialDate && initialDate.isAfter(minimumDate) ? initialDate : minimumDate; + const [date, setDate] = useState(defaultDate); const [mode, setMode] = useState(showInitially || 'date'); const [show, setShow] = useState(Boolean(showInitially)); diff --git a/app/screens/reschedule_draft/reschedule_draft.test.tsx b/app/screens/reschedule_draft/reschedule_draft.test.tsx index 1e08db168..77885f101 100644 --- a/app/screens/reschedule_draft/reschedule_draft.test.tsx +++ b/app/screens/reschedule_draft/reschedule_draft.test.tsx @@ -259,4 +259,51 @@ describe('RescheduledDraft', () => { expect(updateScheduledPost).not.toHaveBeenCalled(); }); + + it('should pass the draft scheduledAt time as initialDate to DateTimeSelector', () => { + const scheduledTime = moment().add(3, 'days').valueOf(); + const draftWithScheduledTime = { + ...mockDraft, + scheduledAt: scheduledTime, + } as unknown as ScheduledPostModel; + + const propsWithScheduledDraft = { + ...baseProps, + draft: draftWithScheduledTime, + }; + + const {getByTestId} = renderWithEverything( + , + {database}, + ); + + const dateTimeSelector = getByTestId('custom_date_time_picker'); + expect(dateTimeSelector).toBeTruthy(); + }); + + it('should initialize with draft scheduledAt time for different timezone', () => { + const scheduledTime = moment.tz('2024-12-25 14:30', 'Asia/Tokyo').valueOf(); + const draftWithScheduledTime = { + ...mockDraft, + scheduledAt: scheduledTime, + } as unknown as ScheduledPostModel; + + const propsWithTimezone = { + ...baseProps, + draft: draftWithScheduledTime, + currentUserTimezone: { + useAutomaticTimezone: true, + automaticTimezone: 'Asia/Tokyo', + manualTimezone: '', + }, + }; + + const {getByTestId} = renderWithEverything( + , + {database}, + ); + + const dateTimeSelector = getByTestId('custom_date_time_picker'); + expect(dateTimeSelector).toBeTruthy(); + }); }); diff --git a/app/screens/reschedule_draft/reschedule_draft.tsx b/app/screens/reschedule_draft/reschedule_draft.tsx index e7850bbe3..9a6556bae 100644 --- a/app/screens/reschedule_draft/reschedule_draft.tsx +++ b/app/screens/reschedule_draft/reschedule_draft.tsx @@ -1,6 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. +import moment, {type Moment} from 'moment-timezone'; import React, {useCallback, useRef, useState} from 'react'; import {useIntl} from 'react-intl'; import {Keyboard, SafeAreaView, StyleSheet, View} from 'react-native'; @@ -22,7 +23,6 @@ import {getTimezone} from '@utils/user'; import type ScheduledPostModel from '@typings/database/models/servers/scheduled_post'; import type {AvailableScreens} from '@typings/screens/navigation'; -import type {Moment} from 'moment-timezone'; type Props = { currentUserTimezone?: UserTimezone | null; @@ -139,6 +139,7 @@ const RescheduledDraft: React.FC = ({ theme={theme} timezone={userTimezone} showInitially='date' + initialDate={moment(draft.scheduledAt)} />