Skip to content

Commit

Permalink
Add data-testid, aria-label to general buttons, dialogs (#3299)
Browse files Browse the repository at this point in the history
  • Loading branch information
imnasnainaec authored Aug 27, 2024
1 parent bfc9230 commit ff4350f
Show file tree
Hide file tree
Showing 21 changed files with 125 additions and 26 deletions.
1 change: 1 addition & 0 deletions src/components/AppBar/NavigationButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ function NavButton(props: NavButtonProps): ReactElement {

return (
<Button
data-testid={props.buttonId}
id={props.buttonId}
onClick={() => navigate(props.targetPath)}
color="inherit"
Expand Down
6 changes: 5 additions & 1 deletion src/components/Buttons/CloseButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { IconButton } from "@mui/material";
import { CSSProperties, ReactElement } from "react";

interface CloseButtonProps {
buttonId?: string;
buttonLabel?: string;
close: () => void;
}

Expand All @@ -15,7 +17,9 @@ export default function CloseButton(props: CloseButtonProps): ReactElement {

return (
<IconButton
aria-label="close"
aria-label={props.buttonLabel ?? "Close"}
data-testid={props.buttonId}
id={props.buttonId}
onClick={props.close}
style={closeButtonStyle}
>
Expand Down
2 changes: 2 additions & 0 deletions src/components/Buttons/DeleteButtonWithDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface DeleteButtonWithDialogProps {
buttonId: string;
buttonIdCancel?: string;
buttonIdConfirm?: string;
buttonLabel?: string;
delete: () => void | Promise<void>;
disabled?: boolean;
textId: string;
Expand All @@ -28,6 +29,7 @@ export default function DeleteButtonWithDialog(
<>
<IconButtonWithTooltip
buttonId={props.buttonId}
buttonLabel={props.buttonLabel ?? "Delete"}
icon={<Delete />}
onClick={props.disabled ? undefined : () => setOpen(true)}
textId={props.tooltipTextId || props.textId}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Buttons/FileInputButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { ReactElement, ReactNode } from "react";
interface BrowseProps {
updateFile: (file: File) => void;
accept?: string;
buttonProps?: ButtonProps & { "data-testid"?: string };
children?: ReactNode;
buttonProps?: ButtonProps;
}

// This button links to a set of functions
Expand Down
8 changes: 6 additions & 2 deletions src/components/Buttons/FlagButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import { IconButtonWithTooltip } from "components/Buttons";
import { DeleteEditTextDialog } from "components/Dialogs";

interface FlagButtonProps {
flag: Flag;
buttonId?: string;
buttonLabel?: string;
flag: Flag;
updateFlag?: (flag: Flag) => void;
}

Expand Down Expand Up @@ -41,6 +42,8 @@ export default function FlagButton(props: FlagButtonProps): ReactElement {
return (
<>
<IconButtonWithTooltip
buttonId={props.buttonId}
buttonLabel={props.buttonLabel ?? "Flag"}
icon={
active ? (
<FlagFilled sx={{ color: (t) => t.palette.error.main }} />
Expand All @@ -54,7 +57,6 @@ export default function FlagButton(props: FlagButtonProps): ReactElement {
textId={active ? "flags.edit" : "flags.add"}
size="small"
onClick={props.updateFlag ? () => setOpen(true) : undefined}
buttonId={props.buttonId ?? "flag-button"}
side="top"
/>
{props.updateFlag && (
Expand All @@ -65,6 +67,8 @@ export default function FlagButton(props: FlagButtonProps): ReactElement {
close={() => setOpen(false)}
updateText={updateFlag}
onDelete={removeFlag}
buttonIdCancel="flag-cancel"
buttonIdClear="flag-clear"
buttonIdDelete="flag-remove"
buttonIdSave="flag-save"
buttonTextIdDelete="flags.remove"
Expand Down
5 changes: 4 additions & 1 deletion src/components/Buttons/IconButtonWithTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { MouseEventHandler, ReactElement, ReactNode } from "react";
import { useTranslation } from "react-i18next";

interface IconButtonWithTooltipProps {
buttonId?: string;
buttonLabel?: string;
disabled?: boolean;
icon: ReactElement;
text?: ReactNode;
/** `textId` will only be used if `text` is null or undefined. */
textId?: string;
size?: "large" | "medium" | "small";
onClick?: MouseEventHandler<HTMLButtonElement>;
buttonId?: string;
side?: "bottom" | "left" | "right" | "top";
}

Expand All @@ -26,6 +27,8 @@ export default function IconButtonWithTooltip(
>
<span>
<IconButton
aria-label={props.buttonLabel}
data-testid={props.buttonId}
onClick={props.onClick}
size={props.size || "medium"}
id={props.buttonId}
Expand Down
5 changes: 4 additions & 1 deletion src/components/Buttons/NoteButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { EditTextDialog } from "components/Dialogs";

interface NoteButtonProps {
buttonId?: string;
buttonLabel?: string;
disabled?: boolean;
/** If `noteText` is empty and `updateNote` defined,
* the button will have default add-note hover text. */
Expand All @@ -20,7 +21,8 @@ export default function NoteButton(props: NoteButtonProps): ReactElement {
return (
<>
<IconButtonWithTooltip
buttonId={props.buttonId ?? "entry-note-button"}
buttonId={props.buttonId}
buttonLabel={props.buttonLabel ?? "Note"}
disabled={props.disabled}
icon={
props.noteText ? (
Expand All @@ -46,6 +48,7 @@ export default function NoteButton(props: NoteButtonProps): ReactElement {
close={() => setNoteOpen(false)}
updateText={props.updateNote ?? (() => {})}
buttonIdCancel="note-edit-cancel"
buttonIdClear="note-edit-clear"
buttonIdConfirm="note-edit-confirm"
textFieldId="note-text-field"
/>
Expand Down
2 changes: 2 additions & 0 deletions src/components/Buttons/PartOfSpeechButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getGramCatGroupColor } from "utilities/wordUtilities";

interface PartOfSpeechButtonProps {
buttonId?: string;
buttonLabel?: string;
gramInfo: GrammaticalInfo;
onClick?: () => void;
onlyIcon?: boolean;
Expand Down Expand Up @@ -38,6 +39,7 @@ export default function PartOfSpeechButton(
const CatGroupButton = (): ReactElement => (
<IconButtonWithTooltip
buttonId={props.buttonId}
buttonLabel={props.buttonLabel ?? "Part of speech"}
icon={<Hexagon fontSize="small" sx={{ color }} />}
onClick={props.onClick}
side="top"
Expand Down
5 changes: 4 additions & 1 deletion src/components/Buttons/UndoButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface UndoButtonProps {
buttonIdEnabled?: string;
buttonIdCancel?: string;
buttonIdConfirm?: string;
buttonLabelEnabled?: string;
textIdDialog: string;
textIdDisabled: string;
textIdEnabled: string;
Expand All @@ -34,9 +35,11 @@ export default function UndoButton(props: UndoButtonProps): ReactElement {
{isUndoEnabled ? (
<div>
<Button
variant="outlined"
aria-label={props.buttonLabelEnabled ?? "Undo"}
data-testid={props.buttonIdEnabled}
id={props.buttonIdEnabled}
onClick={() => setUndoDialogOpen(true)}
variant="outlined"
>
{t(props.textIdEnabled)}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CancelConfirmDialog } from "components/Dialogs";
interface DeleteEntryProps {
removeEntry: () => void;
buttonId: string;
buttonLabel?: string;
// confirmId is the translation id for the text of the delete confirmation popup;
// if no confirmId is specified, then there is no popup
// and deletion will happen when the button is pressed
Expand All @@ -34,6 +35,8 @@ export default function DeleteEntry(props: DeleteEntryProps): ReactElement {
<>
<Tooltip title={t("addWords.deleteRow")} placement="top">
<IconButton
aria-label={props.buttonLabel ?? "Delete entry"}
data-testid={props.buttonId}
disabled={props.disabled}
tabIndex={-1}
size="small"
Expand Down
15 changes: 12 additions & 3 deletions src/components/Dialogs/ButtonConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ interface ButtonConfirmationProps {
onConfirm: () => void | Promise<void>;
buttonIdClose?: string;
buttonIdConfirm?: string;
buttonLabelClose?: string;
buttonLabelConfirm?: string;
}

/**
Expand Down Expand Up @@ -52,16 +54,23 @@ export default function ButtonConfirmation(
</DialogContent>
<DialogActions>
<Button
onClick={props.onClose}
variant="outlined"
aria-label={props.buttonLabelClose}
color="primary"
data-testid={props.buttonIdClose}
id={props.buttonIdClose}
onClick={props.onClose}
variant="outlined"
>
{t("buttons.cancel")}
</Button>
<LoadingButton
buttonProps={{
"aria-label": props.buttonLabelConfirm,
"data-testid": props.buttonIdConfirm,
id: props.buttonIdConfirm,
onClick: onConfirm,
}}
loading={loading}
buttonProps={{ id: props.buttonIdConfirm, onClick: onConfirm }}
>
{t("buttons.confirm")}
</LoadingButton>
Expand Down
11 changes: 10 additions & 1 deletion src/components/Dialogs/CancelConfirmDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ interface CancelConfirmDialogProps {
handleConfirm: () => Promise<void> | void;
buttonIdCancel?: string;
buttonIdConfirm?: string;
buttonLabelCancel?: string;
buttonLabelConfirm?: string;
}

/**
Expand Down Expand Up @@ -52,7 +54,9 @@ export default function CancelConfirmDialog(
</DialogContent>
<DialogActions>
<Button
aria-label={props.buttonLabelCancel}
color="primary"
data-testid={props.buttonIdCancel}
disabled={loading}
id={props.buttonIdCancel}
onClick={props.handleCancel}
Expand All @@ -61,7 +65,12 @@ export default function CancelConfirmDialog(
{t("buttons.cancel")}
</Button>
<LoadingButton
buttonProps={{ id: props.buttonIdConfirm, onClick: onConfirm }}
buttonProps={{
"aria-label": props.buttonLabelConfirm,
"data-testid": props.buttonIdConfirm,
id: props.buttonIdConfirm,
onClick: onConfirm,
}}
loading={loading}
>
{t("buttons.confirm")}
Expand Down
19 changes: 17 additions & 2 deletions src/components/Dialogs/DeleteEditTextDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ interface DeleteEditTextDialogProps {
close: () => void;
updateText: (newText: string) => void | Promise<void>;
onDelete?: () => void;
buttonIdCancel?: string;
buttonIdClear?: string;
buttonIdDelete?: string;
buttonIdSave?: string;
buttonTextIdDelete?: string;
Expand Down Expand Up @@ -78,7 +80,12 @@ export default function DeleteEditTextDialog(
const endAdornment = (
<InputAdornment position="end">
<Tooltip title={t("buttons.clearText")} placement={"left"}>
<IconButton size="small" onClick={() => setText("")}>
<IconButton
data-testid={props.buttonIdClear}
id={props.buttonIdClear}
onClick={() => setText("")}
size="small"
>
<Backspace />
</IconButton>
</Tooltip>
Expand All @@ -98,6 +105,8 @@ export default function DeleteEditTextDialog(
<IconButton
size="small"
aria-label="close"
data-testid={props.buttonIdCancel}
id={props.buttonIdCancel}
onClick={onCancel}
style={{ position: "absolute", right: 4, top: 4 }}
>
Expand All @@ -109,6 +118,7 @@ export default function DeleteEditTextDialog(
<TextField
variant="standard"
autoFocus
data-testid={props.textFieldId}
value={text}
onChange={(event) => setText(event.target.value)}
onKeyPress={confirmIfEnter}
Expand All @@ -121,13 +131,18 @@ export default function DeleteEditTextDialog(
onClick={onDelete}
variant="outlined"
color="primary"
data-testid={props.buttonIdDelete}
id={props.buttonIdDelete}
>
{t(props.buttonTextIdDelete ?? "buttons.delete")}
</Button>
<LoadingButton
buttonProps={{
"data-testid": props.buttonIdSave,
id: props.buttonIdSave,
onClick: onSave,
}}
loading={loading}
buttonProps={{ id: props.buttonIdSave, onClick: onSave }}
>
{t(props.buttonTextIdSave ?? "buttons.save")}
</LoadingButton>
Expand Down
11 changes: 10 additions & 1 deletion src/components/Dialogs/EditTextDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ interface EditTextDialogProps {
close: () => void;
updateText: (newText: string) => void | Promise<void>;
buttonIdCancel?: string;
buttonIdClear?: string;
buttonIdConfirm?: string;
buttonTextIdCancel?: string;
buttonTextIdConfirm?: string;
Expand Down Expand Up @@ -73,7 +74,12 @@ export default function EditTextDialog(

const endAdornment = (
<InputAdornment position="end">
<IconButton onClick={() => setText("")} size="large">
<IconButton
data-testid={props.buttonIdClear}
id={props.buttonIdClear}
onClick={() => setText("")}
size="large"
>
<Clear />
</IconButton>
</InputAdornment>
Expand All @@ -91,6 +97,7 @@ export default function EditTextDialog(
<TextField
variant="standard"
autoFocus
data-testid={props.textFieldId}
value={text}
onChange={(event) => setText(event.target.value)}
onKeyPress={confirmIfEnter}
Expand All @@ -103,6 +110,7 @@ export default function EditTextDialog(
onClick={onCancel}
variant="outlined"
color="primary"
data-testid={props.buttonIdCancel}
id={props.buttonIdCancel}
>
{t(props.buttonTextIdCancel ?? "buttons.cancel")}
Expand All @@ -111,6 +119,7 @@ export default function EditTextDialog(
onClick={onConfirm}
variant="outlined"
color="primary"
data-testid={props.buttonIdConfirm}
id={props.buttonIdConfirm}
>
{t(props.buttonTextIdConfirm ?? "buttons.confirm")}
Expand Down
8 changes: 7 additions & 1 deletion src/components/Dialogs/RecordAudioDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import AudioRecorder from "components/Pronunciations/AudioRecorder";

interface RecordAudioDialogProps {
audioId: string;
buttonIdClose?: string;
buttonLabelClose?: string;
close: () => void;
open: boolean;
titleId: string;
Expand All @@ -23,7 +25,11 @@ export default function RecordAudioDialog(
<DialogTitle>
{t(props.titleId)}
<Icon />
<CloseButton close={props.close} />
<CloseButton
buttonId={props.buttonIdClose}
buttonLabel={props.buttonLabelClose}
close={props.close}
/>
</DialogTitle>
<DialogContent>
<AudioRecorder
Expand Down
Loading

0 comments on commit ff4350f

Please sign in to comment.