From ac26a80f14510c151e2cbdfdfc6dfd521ed59bed Mon Sep 17 00:00:00 2001 From: cheton Date: Fri, 8 Nov 2024 18:02:30 +0800 Subject: [PATCH] test: improve test coverage for ToastManager --- packages/react/src/toast/ToastManager.js | 8 +- .../src/toast/__tests__/ToastManager.test.js | 163 ++++++++++++++++++ 2 files changed, 165 insertions(+), 6 deletions(-) diff --git a/packages/react/src/toast/ToastManager.js b/packages/react/src/toast/ToastManager.js index fcbbf7d1f7..cc4f82042a 100644 --- a/packages/react/src/toast/ToastManager.js +++ b/packages/react/src/toast/ToastManager.js @@ -222,7 +222,7 @@ const ToastManager = (inProps) => { containerRef={containerRef} > {Object.keys(state).map((placement) => { - const toasts = ensureArray(state[placement]); + const toasts = ensureArray(state[placement]).filter(toast => !isNullish(toast)); return ( { {...ToastContainerProps} > - {ensureArray(toasts).map((toast) => { - if (!toast || isNullish(toast.id)) { - // TODO: log an error if the toast id is missing - return null; - } + {toasts.map((toast) => { const onClose = createCloseToastHandler(toast.id, placement); return ( { }); expect(updateSuccess).toBe(true); }, [toast]); + const handleClickUpdateInvalidToast = useCallback(() => { + const updateSuccess = toast.update(null, {}); + expect(updateSuccess).toBe(false); + }, [toast]); return ( <> @@ -525,6 +529,9 @@ describe('ToastManager', () => { + ); }; @@ -540,9 +547,165 @@ describe('ToastManager', () => { // Update the toast await user.click(screen.getByText('Update Toast')); + await user.click(screen.getByText('Update Invalid Toast')); // Check if the content has been updated const toastElement = screen.getByTestId(toastId); expect(toastElement).toHaveTextContent(updatedMessage); }); + + it('should not create a toast and return false for invalid placement', async () => { + const user = userEvent.setup(); + const toastId = 'toast-id'; + const placement = 'center'; // "center" is not a supported placement + const message = 'This is a toast message'; + + // Spy on console.error to capture and check the error message + const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + + const WrapperComponent = (props) => ( + + ); + + const TestComponent = () => { + const toast = useToastManager(); + const handleClick = useCallback(() => { + const result = toast(({ onClose }) => ( + + {message} + + ), { placement }); + expect(result).toBe(false); + }, [toast]); + + return ( + + ); + }; + + render( + + + + ); + + const button = await screen.findByText('Add Toast'); + await user.click(button); + + // Check that console.error was called with the expected error message + const placements = [ + 'bottom', + 'bottom-right', + 'bottom-left', + 'top', + 'top-left', + 'top-right', + ]; + const expectedErrorMessage = `[ToastManager] Error: Invalid toast placement "${placement}". Please provide a valid placement from the following options: ${placements.join(', ')}.`; + expect(consoleErrorSpy).toHaveBeenCalledWith(expectedErrorMessage); + + // Assert that no toast element with the invalid placement was created + const toastElement = screen.queryByTestId(toastId); + expect(toastElement).not.toBeInTheDocument(); + + // Restore console.error to its original implementation + consoleErrorSpy.mockRestore(); + }); + + it('should create toasts in the correct order for top and bottom placements in the state', async () => { + const user = userEvent.setup(); + const topPlacement = 'top'; + const bottomPlacement = 'bottom'; + const message = 'This is a toast message'; + + const WrapperComponent = (props) => ( + + ); + + const TestComponent = () => { + const toast = useToastManager(); + const handleClickAddToasts = useCallback(() => { + // Add toast for top-right placement + toast(({ onClose }) => ( + + {message} + + ), { placement: topPlacement }); + + // Add toast for bottom-right placement + toast(({ onClose }) => ( + + {message} + + ), { placement: bottomPlacement }); + }, [toast]); + + return ( + <> + + {/* Access toast.state here to check order */} + {toast.state && ( +
{JSON.stringify(toast.state, null, 2)}
+ )} + + ); + }; + + render( + + + + ); + + const button = await screen.findByText('Add Toasts'); + await user.click(button); + await user.click(button); + + // Wait for the state to be updated with toasts + await screen.findByTestId('toast-state'); + + // Get the state of the toasts + const toastState = JSON.parse(screen.getByTestId('toast-state').textContent); + + // Check that toasts with top-right and bottom-right placements exist in the state + const topToasts = toastState[topPlacement]; + const bottomToasts = toastState[bottomPlacement]; + + // top-right + // + // ```js + // [ + // { id: '3', placement: 'top-right' }, + // { id: '1', placement: 'top-right' }, + // ] + // ``` + expect(topToasts).toHaveLength(2); + expect(topToasts[0].id > topToasts[1].id).toBeTruthy(); + + // bottom-right + // + // ```js + // [ + // { id: '2', placement: 'bottom-right' }, + // { id: '4', placement: 'bottom-right' }, + // ] + // ``` + expect(bottomToasts).toHaveLength(2); + expect(bottomToasts[0].id < bottomToasts[1].id).toBeTruthy(); + }); });