Skip to content

Commit

Permalink
fix: add play test for dialog, menubutton, select, tag, passwordfield
Browse files Browse the repository at this point in the history
  • Loading branch information
ganeshsomasundaram-okta committed Jul 6, 2023
1 parent a549d43 commit 2fb3d02
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 10 deletions.
3 changes: 3 additions & 0 deletions packages/odyssey-react-mui/src/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export type DialogProps = {
onClose: () => void;
isOpen: boolean;
title: string;
ariaLabel: string;
};

const Dialog = ({
Expand All @@ -46,6 +47,7 @@ const Dialog = ({
isOpen,
onClose,
title,
ariaLabel,
}: DialogProps) => {
const [isContentScrollable, setIsContentScrollable] = useState(false);
const dialogContentRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -87,6 +89,7 @@ const Dialog = ({
variant="floating"
onClick={onClose}
startIcon={<CloseIcon />}
ariaLabel={ariaLabel}
/>
</DialogTitle>
<DialogContent dividers={isContentScrollable} ref={dialogContentRef}>
Expand Down
2 changes: 2 additions & 0 deletions packages/odyssey-react-mui/src/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>(
ref={ref}
renderValue={isMultiSelect ? renderValue : undefined}
value={selectedValue}
labelId={label}
/>
),
[
Expand All @@ -201,6 +202,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>(
children,
renderValue,
selectedValue,
label,
]
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
DialogProps,
} from "@okta/odyssey-react-mui";
import { useState } from "react";
import { userEvent, waitFor, within } from "@storybook/testing-library";
import { axeRun } from "../../../axe-util";

import { MuiThemeDecorator } from "../../../../.storybook/components";

Expand Down Expand Up @@ -48,11 +50,15 @@ const storybookMeta: Meta<DialogProps> = {
title: {
control: "text",
},
ariaLabel: {
control: "text",
},
},
args: {
children:
"You are initiating this ship's self-destruct protocol. This ship, and its occupants, will be destroyed.",
title: "Initiate self-destruct protocol",
ariaLabel: "close",
},
decorators: [MuiThemeDecorator],
};
Expand Down Expand Up @@ -104,6 +110,16 @@ export const Default: StoryObj<DialogProps> = {
"You are initiating this ship's self-destruct protocol. This ship, and its occupants, will be destroyed.",
title: "Initiate self-destruct protocol",
},
play: async ({ canvasElement, step }) => {
const canvas = within(canvasElement);
await step("open Default Dialog", async () => {
const buttonElement = canvas.getByText("Open dialog");
userEvent.click(buttonElement);
await waitFor(() => {
axeRun("Default Dialog");
});
});
},
};

export const Long: StoryObj<DialogProps> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import {
MoreIcon,
} from "@okta/odyssey-react-mui";
import { MuiThemeDecorator } from "../../../../.storybook/components";
import { userEvent, waitFor, within } from "@storybook/testing-library";
import { axeRun } from "../../../axe-util";
import type { PlaywrightProps } from "../storybookTypes";

const storybookMeta: Meta<MenuButtonProps> = {
title: "MUI Components/Menu Button",
Expand Down Expand Up @@ -54,6 +57,19 @@ const storybookMeta: Meta<MenuButtonProps> = {

export default storybookMeta;

const clickMenuButton =
({ canvasElement, step }: PlaywrightProps<MenuButtonProps>) =>
async (args: MenuButtonProps, actionName: string) => {
const canvas = within(canvasElement);
await step("open menu button", async () => {
const buttonElement = canvas.getByText(args.buttonLabel || "");
userEvent.click(buttonElement);
await waitFor(() => {
axeRun(actionName);
});
});
};

export const Simple: StoryObj<MenuButtonProps> = {
args: {
buttonLabel: "More actions",
Expand All @@ -63,6 +79,9 @@ export const Simple: StoryObj<MenuButtonProps> = {
<MenuItem key="3">Launch</MenuItem>,
],
},
play: async ({ args, canvasElement, step }) => {
clickMenuButton({ canvasElement, step })(args, "Menu Button Simple");
},
};

export const ActionIcons: StoryObj<MenuButtonProps> = {
Expand All @@ -88,6 +107,9 @@ export const ActionIcons: StoryObj<MenuButtonProps> = {
</MenuItem>,
],
},
play: async ({ args, canvasElement, step }) => {
clickMenuButton({ canvasElement, step })(args, "Menu Button Action Icons");
},
};

export const ButtonVariant: StoryObj<MenuButtonProps> = {
Expand All @@ -106,13 +128,13 @@ export const Groupings: StoryObj<MenuButtonProps> = {
args: {
buttonLabel: "More actions",
children: [
<ListSubheader>Crew</ListSubheader>,
<ListSubheader key="sh1">Crew</ListSubheader>,
<MenuItem key="1">Assign captain</MenuItem>,
<MenuItem key="2">View roster</MenuItem>,
<ListSubheader>Ship</ListSubheader>,
<ListSubheader key="sh2">Ship</ListSubheader>,
<MenuItem key="3">Configure thrusters</MenuItem>,
<MenuItem key="4">View cargo</MenuItem>,
<Divider />,
<Divider key="div2" />,
<MenuItem key="5">Logout</MenuItem>,
],
},
Expand All @@ -129,6 +151,9 @@ export const WithDestructive: StoryObj<MenuButtonProps> = {
</MenuItem>,
],
},
play: async ({ args, canvasElement, step }) => {
clickMenuButton({ canvasElement, step })(args, "Menu Button Destructive");
},
};

export const IconButton: StoryObj<MenuButtonProps> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

import { Meta, StoryObj } from "@storybook/react";
import { PasswordField, PasswordFieldProps } from "@okta/odyssey-react-mui";
import { userEvent, waitFor } from "@storybook/testing-library";
import { expect } from "@storybook/jest";
import { axeRun } from "../../../axe-util";

import { MuiThemeDecorator } from "../../../../.storybook/components";

Expand Down Expand Up @@ -66,10 +69,39 @@ const storybookMeta: Meta<PasswordFieldProps> = {
autoCompleteType: "current-password",
label: "Password",
isOptional: false,
id: "password-input",
},
decorators: [MuiThemeDecorator],
};

export default storybookMeta;

export const Default: StoryObj<PasswordFieldProps> = {};
export const Default: StoryObj<PasswordFieldProps> = {
play: async ({ args, canvasElement, step }) => {
await step("toggle password", async () => {
const fieldElement = canvasElement.querySelector(
`#${args.id}`
) as HTMLInputElement;
expect(fieldElement.type).toBe("password");

const buttonElement = canvasElement.querySelector(
'[aria-label="toggle password visibility"]'
);
if (buttonElement) {
userEvent.type(fieldElement, "qwerty");
userEvent.click(buttonElement);
userEvent.tab();
await waitFor(() => {
expect(fieldElement.type).toBe("text");
});
userEvent.click(buttonElement);
await waitFor(() => {
expect(fieldElement.type).toBe("password");
});
}
await waitFor(() => {
axeRun("Password Field Default");
});
});
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
import { Meta, StoryObj } from "@storybook/react";
import { Select, SelectProps } from "@okta/odyssey-react-mui";
import { MuiThemeDecorator } from "../../../../.storybook/components";
import { userEvent, waitFor, screen } from "@storybook/testing-library";
import { axeRun } from "../../../axe-util";
import { expect } from "@storybook/jest";

const storybookMeta: Meta<SelectProps> = {
title: "MUI Components/Forms/Select",
Expand Down Expand Up @@ -181,6 +184,25 @@ const GroupTemplate: StoryObj<SelectProps> = {

export const Default: StoryObj<SelectProps> = {
...Template,
play: async ({ canvasElement, step }) => {
await step("Select Earth from the listbox", async () => {
const comboBoxElement = canvasElement.querySelector(
'[aria-haspopup="listbox"]'
);
if (comboBoxElement) {
userEvent.click(comboBoxElement);
const listboxElement = screen.getByRole("listbox");
expect(listboxElement).toBeInTheDocument();
const listItem = listboxElement.children[0];
userEvent.click(listItem);
userEvent.tab();
await waitFor(() => expect(listboxElement).not.toBeInTheDocument());
const inputElement = canvasElement.querySelector("input");
expect(inputElement?.value).toBe("Earth");
await waitFor(() => axeRun("Select Default"));
}
});
},
};
Default.args = {};

Expand All @@ -196,6 +218,11 @@ export const DefaultError: StoryObj<SelectProps> = {
args: {
errorMessage: "Select your destination.",
},
play: async ({ step }) => {
await step("Check for a11y errors on Select Error", async () => {
await waitFor(() => axeRun("Select Error"));
});
},
};

export const DefaultObject: StoryObj<SelectProps> = {
Expand All @@ -211,4 +238,25 @@ export const Multi: StoryObj<SelectProps> = {
args: {
isMultiSelect: true,
},
play: async ({ canvasElement, step }) => {
await step("Select Multiple items from the listbox", async () => {
const comboBoxElement = canvasElement.querySelector(
'[aria-haspopup="listbox"]'
);
if (comboBoxElement) {
userEvent.click(comboBoxElement);
const listboxElement = screen.getByRole("listbox");
expect(listboxElement).toBeInTheDocument();

userEvent.click(listboxElement.children[0]);
userEvent.click(listboxElement.children[1]);
userEvent.tab();
await waitFor(() => expect(listboxElement).not.toBeInTheDocument());
const inputElement = canvasElement.querySelector("input");
expect(inputElement?.value).toBe("Earth,Mars");
userEvent.click(canvasElement);
await waitFor(() => axeRun("Select Multiple"));
}
});
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { Meta, StoryObj } from "@storybook/react";
import { Tag, TagList, TagProps } from "@okta/odyssey-react-mui";
import { MuiThemeDecorator } from "../../../../.storybook/components";
import { GroupIcon } from "@okta/odyssey-react-mui";
import { userEvent } from "@storybook/testing-library";
import { expect } from "@storybook/jest";
import { axeRun } from "../../../axe-util";

const storybookMeta: Meta<TagProps> = {
title: "MUI Components/Tag",
Expand All @@ -40,8 +43,6 @@ const storybookMeta: Meta<TagProps> = {
},
args: {
label: "Starship",
onRemove: undefined,
onClick: undefined,
},
decorators: [MuiThemeDecorator],
};
Expand All @@ -58,7 +59,7 @@ export const List: StoryObj<TagProps> = {
render: function C(args) {
return (
<TagList>
<Tag {...args} />
<Tag label={args.label} />
<Tag label="Another tag" />
<Tag label="A third tag" />
</TagList>
Expand Down Expand Up @@ -88,9 +89,18 @@ export const Clickable: StoryObj<TagProps> = {
export const Removable: StoryObj<TagProps> = {
args: {
label: "Starship",
onRemove: function noRefCheck(event) {
event;
},
},
play: async ({ args, canvasElement, step }) => {
await step("remove the tag on click", async () => {
const tagElement = canvasElement.querySelector('[role="button"]');
const removeIcon = tagElement?.querySelector("svg");
if (removeIcon) {
userEvent.click(removeIcon);
userEvent.tab();
expect(args.onRemove).toHaveBeenCalled();
}
await axeRun("Removable Tag");
});
},
};

Expand Down

0 comments on commit 2fb3d02

Please sign in to comment.