fix(frontend): prevent RangeError in TimeAdjuster and add validation to SleepButton
Build Frontend / build (push) Failing after 3m15s
Build Frontend / build (push) Failing after 3m15s
This commit is contained in:
@@ -10,6 +10,10 @@ const SleepButton: React.FC<SleepButtonProps> = ({ time }) => {
|
||||
const isSleeping = !!activeSession;
|
||||
|
||||
const handleClick = async () => {
|
||||
if (!time) {
|
||||
alert('Please select a valid time.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (isSleeping && activeSession?.id) {
|
||||
await endSession({ sessionId: activeSession.id, endTime: time });
|
||||
|
||||
@@ -90,6 +90,9 @@ export function formatDateTime(date: Date | string): string {
|
||||
*/
|
||||
export function toUTCFromLocalInput(inputValue: string): string {
|
||||
const d = new Date(inputValue);
|
||||
if (isNaN(d.getTime())) {
|
||||
return "";
|
||||
}
|
||||
return d.toISOString();
|
||||
}
|
||||
|
||||
|
||||
@@ -70,4 +70,20 @@ describe('SleepButton', () => {
|
||||
|
||||
await waitFor(() => expect(endSessionMock).toHaveBeenCalled());
|
||||
});
|
||||
|
||||
it('shows alert when time is invalid', async () => {
|
||||
const alertSpy = vi.spyOn(window, 'alert').mockImplementation(() => {});
|
||||
(useSleepSession as any).mockReturnValue({
|
||||
activeSession: null,
|
||||
isCreating: false,
|
||||
isEnding: false,
|
||||
});
|
||||
|
||||
renderWithProviders(<SleepButton time="" />);
|
||||
const button = screen.getByRole('button', { name: /Start Sleep/i });
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(alertSpy).toHaveBeenCalledWith('Please select a valid time.');
|
||||
alertSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,4 +29,18 @@ describe('TimeAdjuster', () => {
|
||||
fireEvent.click(resetButton);
|
||||
expect(handleChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles invalid date input gracefully (returns empty string)', async () => {
|
||||
// Since we changed the implementation, it should no longer throw.
|
||||
// We can't easily test the useEffect error anymore because it doesn't throw,
|
||||
// but we can check if onTimeChange is called with "" for invalid input.
|
||||
const handleChange = vi.fn();
|
||||
const { container } = render(<TimeAdjuster onTimeChange={handleChange} />);
|
||||
const input = container.querySelector('input');
|
||||
|
||||
fireEvent.change(input!, { target: { value: '2026-06-0' } });
|
||||
// We might need to wait for the effect
|
||||
await new Promise((r) => setTimeout(r, 0));
|
||||
expect(handleChange).toHaveBeenCalledWith("");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
adjustForTimezone,
|
||||
getLocalOffsetFromReference,
|
||||
formatDateTime,
|
||||
toUTCFromLocalInput,
|
||||
} from '../../src/utils/time';
|
||||
|
||||
describe('formatMinutesAfter', () => {
|
||||
@@ -152,3 +153,18 @@ describe('getLocalOffsetFromReference', () => {
|
||||
expect(offset).toBe(localMins - refMins);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toUTCFromLocalInput', () => {
|
||||
it('converts valid datetime-local string to ISO UTC string', () => {
|
||||
const input = '2024-01-15T10:00';
|
||||
// This is tricky because it depends on local timezone.
|
||||
// But we just want to see if it works for a valid input.
|
||||
const result = toUTCFromLocalInput(input);
|
||||
expect(result).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/);
|
||||
});
|
||||
|
||||
it('returns empty string on invalid datetime-local string', () => {
|
||||
expect(toUTCFromLocalInput('2026-06-0')).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user