Skip to content

Commit

Permalink
test: add tooltip e2e
Browse files Browse the repository at this point in the history
  • Loading branch information
anuraghazra committed Jan 22, 2024
1 parent b496888 commit b4653ca
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 7 deletions.
9 changes: 2 additions & 7 deletions packages/blade/src/components/Tooltip/Tooltip.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,8 @@ const Tooltip = ({
open: isOpen,
strategy: 'fixed',
onOpenChange: (open) => {
if (open) {
setIsOpen(true);
onOpenChange?.({ isOpen: open });
} else {
setIsOpen(false);
onOpenChange?.({ isOpen: open });
}
setIsOpen(open);
onOpenChange?.({ isOpen: open });
},
middleware: [
shift({ crossAxis: false, padding: GAP }),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import type { StoryFn } from '@storybook/react';
import { within, userEvent } from '@storybook/testing-library';
import { expect, jest } from '@storybook/jest';
import React from 'react';
import { TooltipInteractiveWrapper, Tooltip as TooltipComponent } from '..';
import { Button } from '~components/Button';
import { Text } from '~components/Typography';
import { Badge } from '~components/Badge';
import BaseBox from '~components/Box/BaseBox';
import type { BladeCommonEvents } from '~components/types';

const sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));

const onOpenChange = jest.fn();

export const TestTooltipOpenClose: StoryFn<typeof TooltipComponent> = (
props,
): React.ReactElement => {
return (
<TooltipComponent {...props} onOpenChange={onOpenChange}>
<Button>Hover me</Button>
</TooltipComponent>
);
};

TestTooltipOpenClose.args = {
title: 'Hello World',
content: 'Some text',
};
TestTooltipOpenClose.play = async () => {
const { getByRole, queryByText } = within(document.body);
await expect(queryByText('Hello World')).not.toBeInTheDocument();
const showButton = getByRole('button', { name: 'Hover me' });
// open
await userEvent.hover(showButton);
await sleep(400);
await expect(onOpenChange).toBeCalledWith({ isOpen: true });
await expect(queryByText('Hello World')).toBeVisible();
// close
await userEvent.unhover(showButton);
await sleep(500);
await expect(onOpenChange).toBeCalledWith({ isOpen: false });
await expect(queryByText('Hello World')).not.toBeInTheDocument();
};

// TooltipInteractiveWrapper
export const TestTooltipInteractiveWrapper: StoryFn<typeof TooltipComponent> = (
props,
): React.ReactElement => {
onOpenChange.mockReset();
return (
<TooltipComponent {...props} onOpenChange={onOpenChange}>
<TooltipInteractiveWrapper>
<Badge>NEW</Badge>
</TooltipInteractiveWrapper>
</TooltipComponent>
);
};
TestTooltipInteractiveWrapper.args = {
content: 'Hello World',
};
TestTooltipInteractiveWrapper.play = async () => {
const { getByText, queryByText } = within(document.body);
const tooltipContent = 'Hello World';
await expect(queryByText(tooltipContent)).not.toBeInTheDocument();
const badge = getByText('NEW');
// open
await userEvent.hover(badge);
await sleep(400);
await expect(onOpenChange).toBeCalledWith({ isOpen: true });
await expect(queryByText(tooltipContent)).toBeVisible();
// close
await userEvent.unhover(badge);
await sleep(500);
await expect(onOpenChange).toBeCalledWith({ isOpen: false });
await expect(queryByText(tooltipContent)).not.toBeInTheDocument();
};

const CustomTrigger = React.forwardRef<
HTMLDivElement,
{ children: React.ReactNode } & BladeCommonEvents
>(
(
{
children,
onBlur,
onFocus,
onMouseLeave,
onMouseMove,
onPointerDown,
onPointerEnter,
onTouchEnd,
onTouchStart,
},
ref,
) => {
return (
<BaseBox
ref={ref}
tabIndex={0}
onBlur={onBlur}
onFocus={onFocus}
onMouseLeave={onMouseLeave}
onMouseMove={onMouseMove}
onPointerDown={onPointerDown}
onPointerEnter={onPointerEnter}
onTouchEnd={onTouchEnd}
onTouchStart={onTouchStart}
>
<Text contrast="low">{children}</Text>
</BaseBox>
);
},
);

// custom trigger
export const TestCustomTrigger: StoryFn<typeof TooltipComponent> = (props): React.ReactElement => {
onOpenChange.mockReset();
return (
<TooltipComponent {...props} onOpenChange={onOpenChange}>
<CustomTrigger>Custom Trigger</CustomTrigger>
</TooltipComponent>
);
};
TestCustomTrigger.args = {
content: 'Hello World',
};
TestCustomTrigger.play = async () => {
const { getByText, queryByText } = within(document.body);
const tooltipContent = 'Hello World';
await expect(queryByText(tooltipContent)).not.toBeInTheDocument();
const trigger = getByText('Custom Trigger');
// open
await userEvent.hover(trigger);
await sleep(400);
await expect(onOpenChange).toBeCalledWith({ isOpen: true });
await expect(queryByText(tooltipContent)).toBeVisible();
// close
await userEvent.unhover(trigger);
await sleep(500);
await expect(onOpenChange).toBeCalledWith({ isOpen: false });
await expect(queryByText(tooltipContent)).not.toBeInTheDocument();
};

// should open/close immediately on focus/blur without the default delay of 300ms
export const TestTooltipOpenCloseFocus: StoryFn<typeof TooltipComponent> = (
props,
): React.ReactElement => {
return (
<TooltipComponent {...props} onOpenChange={onOpenChange}>
<Button>Hover me</Button>
</TooltipComponent>
);
};

TestTooltipOpenCloseFocus.args = {
title: 'Hello World',
content: 'Some text',
};
TestTooltipOpenCloseFocus.play = async () => {
const { queryByText } = within(document.body);
await expect(queryByText('Hello World')).not.toBeInTheDocument();
// open
await userEvent.keyboard('{Tab}', {});
await sleep(200);
await expect(onOpenChange).toBeCalledWith({ isOpen: true });
await expect(queryByText('Hello World')).toBeVisible();
// close
await userEvent.keyboard('{Tab}', {});
await sleep(300);
await expect(onOpenChange).toBeCalledWith({ isOpen: false });
await expect(queryByText('Hello World')).not.toBeInTheDocument();
};

export default {
title: 'Components/Interaction Tests/Tooltip',
component: TooltipComponent,
parameters: {
controls: {
disable: true,
},
a11y: { disable: true },
essentials: { disable: true },
actions: { disable: true },
},
};

0 comments on commit b4653ca

Please sign in to comment.