diff --git a/packages/react-component-library/src/components/Toast/Toast.stories.tsx b/packages/react-component-library/src/components/Toast/Toast.stories.tsx index 822369f6d..5cada79a8 100644 --- a/packages/react-component-library/src/components/Toast/Toast.stories.tsx +++ b/packages/react-component-library/src/components/Toast/Toast.stories.tsx @@ -1,8 +1,9 @@ import React, { useEffect } from 'react' import { Meta, StoryFn } from '@storybook/react' -import { TOAST_APPEARANCE, Toast, ToastProps, showToast } from '.' +import { TOAST_APPEARANCE, Toast, ToastProps, showToast, dismissToast } from '.' import { Button } from '../Button' +import { Group } from '../Group' export default { component: Toast, @@ -31,13 +32,22 @@ const ToastButton = (props: ToastProps) => { return (
- + + + +
) } diff --git a/packages/react-component-library/src/components/Toast/Toast.test.tsx b/packages/react-component-library/src/components/Toast/Toast.test.tsx index f9690d693..a4b16df6a 100644 --- a/packages/react-component-library/src/components/Toast/Toast.test.tsx +++ b/packages/react-component-library/src/components/Toast/Toast.test.tsx @@ -1,8 +1,8 @@ import React from 'react' import { color } from '@royalnavy/design-tokens' -import { render, screen, waitFor, within } from '@testing-library/react' +import { render, screen, within, waitFor } from '@testing-library/react' -import { TOAST_APPEARANCE, Toast, showToast } from '.' +import { TOAST_APPEARANCE, Toast, dismissToast, showToast } from '.' const LABEL = 'Example label' const MESSAGE = 'This is an example toast message' @@ -19,12 +19,20 @@ function setup() { /* Added this function to resolve an issue when running tests for * the whole of this file and more than one toast is shown */ -async function getLastToast(lastToastLabel: string) { - await waitFor(() => { - expect(screen.getByText(lastToastLabel)).toBeInTheDocument() - }) - - return screen.getAllByRole('status')[0] +async function getLastToast(label?: string) { + try { + const toasts = await screen.findAllByRole('status', { + name: label ? new RegExp(label, 'i') : undefined, + }) + + return toasts[0] + } catch (error) { + if (error instanceof Error && error.message.includes('Unable to find')) { + return null + } + + throw error + } } it('renders the toast', async () => { @@ -41,11 +49,11 @@ it('renders the toast', async () => { const contentId = screen.getByText(MESSAGE).getAttribute('id') expect(lastToast).toHaveAttribute('aria-describedby', contentId) - expect(within(lastToast).getByTestId('icon')).toHaveAttribute( + expect(within(lastToast!).getByTestId('icon')).toHaveAttribute( 'aria-hidden', 'true' ) - expect(within(lastToast).getByTestId('icon')).toHaveStyle({ + expect(within(lastToast!).getByTestId('icon')).toHaveStyle({ color: color('action', '500'), }) @@ -66,9 +74,9 @@ it('sets new props when `showToast` is called with new props', async () => { const lastToast = await getLastToast(expectedNewLabel) - expect(within(lastToast).getByText(expectedNewLabel)).toBeInTheDocument() - expect(within(lastToast).getByText(expectedNewMessage)).toBeInTheDocument() - expect(within(lastToast).getByTestId('icon')).toHaveStyle({ + expect(within(lastToast!).getByText(expectedNewLabel)).toBeInTheDocument() + expect(within(lastToast!).getByText(expectedNewMessage)).toBeInTheDocument() + expect(within(lastToast!).getByTestId('icon')).toHaveStyle({ color: color('danger', '500'), }) }) @@ -91,8 +99,8 @@ it('sets the message when the message is JSX', async () => { const lastToast = await getLastToast(expectedNewLabel) - expect(within(lastToast).getByText(expectedNewLabel)).toBeInTheDocument() - expect(within(lastToast).getAllByRole('paragraph')).toHaveLength(2) + expect(within(lastToast!).getByText(expectedNewLabel)).toBeInTheDocument() + expect(within(lastToast!).getAllByRole('paragraph')).toHaveLength(2) }) it('sets unique IDs when there are multiple toasts', async () => { @@ -121,3 +129,18 @@ it('sets an accessible name when there is no message', async () => { expect(toast).toHaveAccessibleName(new RegExp(label)) }) + +it('dismisses all toasts when `dismissToast` is called', async () => { + setup() + + showToast(MESSAGE) + showToast(MESSAGE) + + expect(screen.queryAllByRole('status').length).toBeGreaterThan(0) + + dismissToast() + + await waitFor(() => { + expect(screen.queryAllByRole('status')).toHaveLength(0) + }) +}) diff --git a/packages/react-component-library/src/components/Toast/Toast.tsx b/packages/react-component-library/src/components/Toast/Toast.tsx index 2ff6cbc60..7b9c39d2d 100644 --- a/packages/react-component-library/src/components/Toast/Toast.tsx +++ b/packages/react-component-library/src/components/Toast/Toast.tsx @@ -183,3 +183,7 @@ export const showToast = ( }) } } + +export const dismissToast = (id?: string) => { + toast.dismiss(id) +}