Skip to content

Commit

Permalink
test: enhance test coverage for toast
Browse files Browse the repository at this point in the history
  • Loading branch information
cheton committed Nov 7, 2024
1 parent 7b55b87 commit 650a7cd
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 144 deletions.
139 changes: 137 additions & 2 deletions packages/react/src/toast/__tests__/Toast.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,43 @@
import { screen, waitForElementToBeRemoved } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render } from '@tonic-ui/react/test-utils/render';
import { Collapse, Toast } from '@tonic-ui/react/src';
import {
Button,
Collapse,
Flex,
Grid,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
Skeleton,
Stack,
Text,
Toast,
ToastCloseButton,
ToastController,
ToastTransition,
ToastTransitionGroup,
useColorStyle,
} from '@tonic-ui/react/src';
import { useToggle } from '@tonic-ui/react-hooks/src';
import { callEventHandlers, transitionDuration } from '@tonic-ui/utils/src';
import React from 'react';
import React, { useState } from 'react';

const InlineToastContainer = (props) => (
<Flex
flexDirection="column"
alignItems="center"
position="absolute"
top="12x"
left="50%"
transform="translateX(-50%)"
width="max-content"
maxWidth="80%" // up to 80% of the drawer width
zIndex="toast"
{...props}
/>
);

describe('Toast', () => {
it('should render correctly', async () => {
Expand Down Expand Up @@ -42,4 +75,106 @@ describe('Toast', () => {
timeout: transitionDuration.standard + 100, // see "transitions/Collapse.js"
});
});

test('should display a toast within a modal', async () => {
const user = userEvent.setup();

const TestComponent = ({ onClose }) => {
const [colorStyle] = useColorStyle();
const [toasts, setToasts] = useState([
{
id: 1,
appearance: 'success',
content: 'This is a success message.',
duration: 5000,
},
]);
const closeToast = (id) => {
setToasts(toasts => toasts.filter(x => x.id !== id));
};
const createCloseToastHandler = (id) => () => {
closeToast(id);
};

return (
<ModalContent
margin={0}
minHeight={400}
minWidth={320}
width="50%"
>
<InlineToastContainer>
<ToastTransitionGroup>
{toasts.map(toast => {
const onClose = createCloseToastHandler(toast.id);
return (
<ToastTransition
key={toast.id}
in
unmountOnExit
>
<ToastController
duration={toast.duration}
onClose={onClose}
>
<Toast
appearance={toast.appearance}
isClosable={true}
onClose={onClose}
sx={{
mb: '2x',
minWidth: 280, // The toast has a minimum width of 280 pixels
width: 'fit-content',
boxShadow: colorStyle.shadow.thin,
}}
data-testid="toast"
>
<Text pr="10x">{toast.content}</Text>
<ToastCloseButton top={10} right={8} position="absolute" data-testid="toast-close-button" />

Check warning on line 133 in packages/react/src/toast/__tests__/Toast.test.js

View workflow job for this annotation

GitHub Actions / build

Prop `data-testid` must be placed on a new line
</Toast>
</ToastController>
</ToastTransition>
);
})}
</ToastTransitionGroup>
</InlineToastContainer>
<ModalHeader>
Modal
</ModalHeader>
<ModalBody>
<Stack direction="column" spacing="4x">
<Skeleton width={160} />
<Skeleton width={240} />
<Skeleton width={240} />
</Stack>
</ModalBody>
<ModalFooter>
<Grid templateColumns="repeat(2, 1fr)" columnGap="2x">
<Button variant="primary">
OK
</Button>
<Button>
Cancel
</Button>
</Grid>
</ModalFooter>
</ModalContent>
);
};

render(
<TestComponent />
);

// Verify the toast is displayed
expect(screen.getByText('This is a success message.')).toBeInTheDocument();

// Simulate closing the toast
const toastCloseButton = screen.getByTestId('toast-close-button');
await user.click(toastCloseButton);

await waitForElementToBeRemoved(() => screen.getByTestId('toast'), {
timeout: transitionDuration.standard + 100, // see "transitions/Collapse.js"
});
});
});
45 changes: 45 additions & 0 deletions packages/react/src/toast/__tests__/ToastController.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render } from '@tonic-ui/react/test-utils/render';
import { Toast, ToastController } from '@tonic-ui/react/src';

jest.useFakeTimers();

describe('ToastController', () => {
test('pauses timeout on mouse enter and resumes on mouse leave', async () => {
const user = userEvent.setup({
// Disable action delay to allow `await user.hover(element)` to complete immediately
// Reference: https://github.com/testing-library/user-event/issues/833
delay: null,
});
const onClose = jest.fn();
const duration = 5000;

render(
<ToastController
duration={duration}
onClose={onClose}
>
<Toast data-testid="toast">
This is a toast
</Toast>
</ToastController>
);

const toast = screen.getByTestId('toast');

// Simulate mouse enter, which should pause the timeout
await user.hover(toast);

// Timeout should be paused
jest.advanceTimersByTime(duration);
expect(onClose).not.toHaveBeenCalled();

// Simulate mouse leave, which should resume the timeout
await user.unhover(toast);

// Timeout should be resumed
jest.advanceTimersByTime(duration);
expect(onClose).toHaveBeenCalled();
});
});
142 changes: 0 additions & 142 deletions packages/react/src/toast/__tests__/ToastTransitionGroup.js

This file was deleted.

0 comments on commit 650a7cd

Please sign in to comment.