From be8c8baf6f4ceaf0267f21dec6fda711c2087a14 Mon Sep 17 00:00:00 2001 From: Hugo Kiyodi Oshiro Date: Thu, 26 Sep 2024 15:56:25 +0200 Subject: [PATCH] ConfirmModal: Allow button disable to be externally managed (#93446) --- .../ConfirmModal/ConfirmContent.tsx | 8 ++- .../ConfirmModal/ConfirmModal.test.tsx | 57 ++++++++++++++++++- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/packages/grafana-ui/src/components/ConfirmModal/ConfirmContent.tsx b/packages/grafana-ui/src/components/ConfirmModal/ConfirmContent.tsx index b63f2ffe7ad..27b94d395c0 100644 --- a/packages/grafana-ui/src/components/ConfirmModal/ConfirmContent.tsx +++ b/packages/grafana-ui/src/components/ConfirmModal/ConfirmContent.tsx @@ -77,11 +77,15 @@ export const ConfirmContent = ({ }, [confirmPromptText, disabled]); const onConfirmClick = async () => { - setIsDisabled(true); + if (disabled === undefined) { + setIsDisabled(true); + } try { await onConfirm(); } finally { - setIsDisabled(false); + if (disabled === undefined) { + setIsDisabled(false); + } } }; diff --git a/packages/grafana-ui/src/components/ConfirmModal/ConfirmModal.test.tsx b/packages/grafana-ui/src/components/ConfirmModal/ConfirmModal.test.tsx index 53ac68e20ad..a667bc2ee80 100644 --- a/packages/grafana-ui/src/components/ConfirmModal/ConfirmModal.test.tsx +++ b/packages/grafana-ui/src/components/ConfirmModal/ConfirmModal.test.tsx @@ -1,8 +1,11 @@ -import { render, screen, waitFor } from '@testing-library/react'; +import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { useState } from 'react'; import { ConfirmModal } from './ConfirmModal'; +jest.useFakeTimers(); + describe('ConfirmModal', () => { const mockOnConfirm = jest.fn(); @@ -170,4 +173,56 @@ describe('ConfirmModal', () => { return expect(screen.getByRole('button', { name: 'Please Confirm' })).toBeEnabled(); }); }); + + it('should disable the confirm button when disabled prop changes from false to true', async () => { + const TestComponent = () => { + const [disabled, setDisabled] = useState(false); + + const handleConfirm = async () => { + act(() => { + setDisabled(true); + setTimeout(() => { + setDisabled(false); + }, 4000); + }); + }; + + return ( + {}} + onAlternative={() => {}} + disabled={disabled} + /> + ); + }; + + render(); + + const confirmButton = screen.getByRole('button', { name: 'Please Confirm' }); + + expect(confirmButton).toBeEnabled(); + + fireEvent.click(confirmButton); + + // Ensure React processes the state update and calls useEffect in ConfirmModal + await act(() => { + jest.advanceTimersByTime(0); + }); + + expect(confirmButton).toBeDisabled(); + + // Fast-forward time by 4 seconds + await act(() => { + jest.advanceTimersByTime(4000); + }); + + await waitFor(() => { + expect(confirmButton).toBeEnabled(); + }); + }); });