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 isSleeping = !!activeSession;
|
||||||
|
|
||||||
const handleClick = async () => {
|
const handleClick = async () => {
|
||||||
|
if (!time) {
|
||||||
|
alert('Please select a valid time.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (isSleeping && activeSession?.id) {
|
if (isSleeping && activeSession?.id) {
|
||||||
await endSession({ sessionId: activeSession.id, endTime: time });
|
await endSession({ sessionId: activeSession.id, endTime: time });
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ export function formatDateTime(date: Date | string): string {
|
|||||||
*/
|
*/
|
||||||
export function toUTCFromLocalInput(inputValue: string): string {
|
export function toUTCFromLocalInput(inputValue: string): string {
|
||||||
const d = new Date(inputValue);
|
const d = new Date(inputValue);
|
||||||
|
if (isNaN(d.getTime())) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
return d.toISOString();
|
return d.toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,4 +70,20 @@ describe('SleepButton', () => {
|
|||||||
|
|
||||||
await waitFor(() => expect(endSessionMock).toHaveBeenCalled());
|
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);
|
fireEvent.click(resetButton);
|
||||||
expect(handleChange).toHaveBeenCalled();
|
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,
|
adjustForTimezone,
|
||||||
getLocalOffsetFromReference,
|
getLocalOffsetFromReference,
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
|
toUTCFromLocalInput,
|
||||||
} from '../../src/utils/time';
|
} from '../../src/utils/time';
|
||||||
|
|
||||||
describe('formatMinutesAfter', () => {
|
describe('formatMinutesAfter', () => {
|
||||||
@@ -152,3 +153,18 @@ describe('getLocalOffsetFromReference', () => {
|
|||||||
expect(offset).toBe(localMins - refMins);
|
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