fix(ui): close date-range Apply dropdown in Safari

handleApply() called setIsOpen(false) after requestIdleCallback(),
which Safari has never implemented. There the call threw a
ReferenceError that silently skipped the close, leaving the dropdown
stuck open on every Apply click. Moved the close before the scheduling
call and added a setTimeout fallback so the background date
adjustment still runs there too.
This commit is contained in:
spions 2026-08-07 17:15:22 +03:00
parent 809b63b9f3
commit d1c3e7bcc5
2 changed files with 53 additions and 9 deletions

View file

@ -180,4 +180,43 @@ describe("AdvancedDatePicker", () => {
expect(applyButton).toBeDisabled();
});
});
it("should close dropdown when Apply is clicked", async () => {
const { container } = render(<AdvancedDatePicker value={defaultValue} onValueChange={mockOnValueChange} />);
openDropdown(container);
expect(screen.getByText("Today")).toBeInTheDocument();
fireEvent.click(screen.getByText("Apply"));
await waitFor(() => {
expect(screen.queryByText("Today")).not.toBeInTheDocument();
});
});
it("should close dropdown on Apply even without requestIdleCallback (Safari)", async () => {
// Safari has never implemented requestIdleCallback. Simulate that by
// removing the polyfill installed in the beforeAll above for this one
// test, so a regression that puts setIsOpen(false) after the
// requestIdleCallback call (and lets its ReferenceError swallow it)
// fails here instead of only in real Safari.
const original = window.requestIdleCallback;
// @ts-expect-error - deleting a browser API to emulate Safari's absence of it
delete window.requestIdleCallback;
try {
const { container } = render(<AdvancedDatePicker value={defaultValue} onValueChange={mockOnValueChange} />);
openDropdown(container);
expect(screen.getByText("Today")).toBeInTheDocument();
fireEvent.click(screen.getByText("Apply"));
await waitFor(() => {
expect(screen.queryByText("Today")).not.toBeInTheDocument();
});
} finally {
window.requestIdleCallback = original;
}
});
});

View file

@ -179,16 +179,21 @@ const AdvancedDatePicker: React.FC<AdvancedDatePickerProps> = ({
// First call with immediate value for UI responsiveness
onValueChange(tempValue);
// Then do the same background adjustment logic as the original component
requestIdleCallback(
() => {
const adjustedValue = adjustDateRange(tempValue);
onValueChange(adjustedValue);
},
{ timeout: 100 },
);
// Close immediately - Safari has no requestIdleCallback, and scheduling
// the close after it (as before) meant the thrown ReferenceError there
// silently skipped this line, leaving the dropdown stuck open.
setIsOpen(false);
// Then do the same background adjustment logic as the original component.
// Safari doesn't implement requestIdleCallback, so fall back to setTimeout.
const scheduleIdle: (callback: () => void) => void =
typeof requestIdleCallback === "function"
? (callback) => requestIdleCallback(callback, { timeout: 100 })
: (callback) => setTimeout(callback, 0);
scheduleIdle(() => {
const adjustedValue = adjustDateRange(tempValue);
onValueChange(adjustedValue);
});
}
};