From b5179a3ab845ec3b643f415c8d4a44c5496c3015 Mon Sep 17 00:00:00 2001 From: Laura Benz <48948963+L-M-K-B@users.noreply.github.com> Date: Fri, 23 Jun 2023 17:10:37 +0200 Subject: [PATCH] GrafanaUI: Define tooltip or aria-label as required for IconButton (#69699) * refactor: modify interfaces to make tooltip or aria-label required * refactor: change functionality around aria-label and tooltip * refactor: change and add information in storybook documentation * refactor: remove default from tooltip * refactor: IconButton to make tooltip or aria-label required * refactor: Fix tests * refactor: Fix tests * refactor: Fix tests * refactor: Fix tests * feat: add migration guide for breaking change * feat: add latest requirements to storybook docs * refactor: separate iconbutton story with and without tooltip * refactor: remove exported baseArgs * refactor: clean up and restructure original story * refactor: adjust styling * refactor: enable control for tooltip * refactor: clean up * refactor: enable control for aria-label * refactor: fix theme getting the wrong theme * refactor: fix tests * refactor: adjust story * refactor: remove confusing story * refactor: adjust controls for stories --- .../migration-guide/v10.0.x-v10.1.x/_index.md | 29 +++++ .../src/components/IconButton/IconButton.mdx | 10 +- .../IconButton/IconButton.story.tsx | 92 ++++++++------ .../src/components/IconButton/IconButton.tsx | 116 ++++++++++-------- .../grafana-ui/src/components/Modal/Modal.tsx | 2 +- .../src/components/Select/SelectBase.test.tsx | 2 +- .../src/components/TagsInput/TagItem.tsx | 3 +- .../Layers/LayerDragDropList.test.tsx | 8 +- .../components/Layers/LayerDragDropList.tsx | 2 - .../QueryOperationRowHeader.test.tsx | 4 +- .../QueryOperationRowHeader.tsx | 1 - .../BrowseActions/DeleteModal.test.tsx | 2 +- .../BrowseActions/MoveModal.test.tsx | 2 +- .../browse-dashboards/components/NameCell.tsx | 2 +- .../LibraryPanelsSearch.test.tsx | 6 +- .../query/components/QueryEditorRows.test.tsx | 2 +- .../query/components/QueryGroup.test.tsx | 4 +- .../components/ServiceAccountsListItem.tsx | 3 +- .../DimensionFields.test.tsx | 4 +- .../components/TracesQueryEditor/Filter.tsx | 2 +- .../TracesQueryEditor/Filters.test.tsx | 6 +- .../SearchTraceQLEditor/SearchField.test.tsx | 4 +- 22 files changed, 187 insertions(+), 119 deletions(-) create mode 100644 docs/sources/developers/plugins/migration-guide/v10.0.x-v10.1.x/_index.md diff --git a/docs/sources/developers/plugins/migration-guide/v10.0.x-v10.1.x/_index.md b/docs/sources/developers/plugins/migration-guide/v10.0.x-v10.1.x/_index.md new file mode 100644 index 000000000000..01818e3e5f25 --- /dev/null +++ b/docs/sources/developers/plugins/migration-guide/v10.0.x-v10.1.x/_index.md @@ -0,0 +1,29 @@ +--- +description: Guide for migrating plugins from Grafana v10.0.x to v10.1.x +keywords: + - grafana + - plugins + - migration + - plugin + - documentation +title: Migrate plugins from Grafana 10.0.x to 10.1.x +menutitle: v10.0.x to v10.1.x +weight: 1900 +--- + +# Migrate plugins from Grafana version 10.0.x to 10.1.x + +## Accessibility update for IconButton component in grafana-ui + +We updated the component's TypeScript interface due to an accessibility issue. This change was delivered to the core `grafana` repo with [PR 69699](https://github.com/grafana/grafana/pull/69699). + +In case you are using the IconButton component in your plugin you will get TypeScript errors related to the change. + +**Recommended actions:** + +- Review use cases of IconButton in your plugin. +- Add a meaningful tooltip which the component will also use as an aria-label. +- Another option is to set an aria-label. In this case a tooltip will not be shown. + +**Please note:** +The IconButton used to have a property called `ariaLabel` which got deprecated with this change. You can now use the regular property `aria-label` instead. diff --git a/packages/grafana-ui/src/components/IconButton/IconButton.mdx b/packages/grafana-ui/src/components/IconButton/IconButton.mdx index c8190bca17cf..8d64adf442b5 100644 --- a/packages/grafana-ui/src/components/IconButton/IconButton.mdx +++ b/packages/grafana-ui/src/components/IconButton/IconButton.mdx @@ -1,17 +1,23 @@ import { Meta, ArgTypes } from '@storybook/blocks'; import { IconButton } from './IconButton'; +import { Icon } from '../Icon/Icon'; import { Alert } from '../Alert/Alert'; # IconButton -This component looks just like an icon but behaves like a button. It fulfils an action when you click it and has hover and focus states. You can choose which icon size you would like to use. +This component looks just like an icon but behaves like a button. It fulfils an action when you click it and has a hover as well a focus states. You can choose which icon size you would like to use. `IconButton` is best used when you only want an icon instead of a button with text, for example when you want to place a solitary clickable icon next to text. An example where an `IconButton` is used in Grafana is the hamburger icon at the top left which opens the new navigation. When using `IconButton` right next to a text element consider wrapping both in a flex container and use `align-items: center;` to make them align properly. -Always keep in mind to add text for a tooltip and an aria label. +There are two options to use the IconButton: + +- with `Tooltip`: This is the preferred option since we don't want to rely on assumptions when it comes to the meaning an `Icon` has. Add a text for the `Tooltip`. It will be used for the `aria-label` as well. +- without `Tooltip`: This is an option for use cases where the `Icon` is unambiguous e.g for expanding a folder. Add a text for the `aria-label` and there will **not** be a `Tooltip`. + +The IconButton used to have a property called `ariaLabel` which got deprecated. You can now use the regular property `aria-label` instead. After reviewing this component we would like you to know that there are only 5 sizes available (sizes xs to xl). Sizes diff --git a/packages/grafana-ui/src/components/IconButton/IconButton.story.tsx b/packages/grafana-ui/src/components/IconButton/IconButton.story.tsx index 011f3bdafc75..304e7ae96562 100644 --- a/packages/grafana-ui/src/components/IconButton/IconButton.story.tsx +++ b/packages/grafana-ui/src/components/IconButton/IconButton.story.tsx @@ -7,13 +7,16 @@ import { IconSize, IconName } from '../../types'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { HorizontalGroup, VerticalGroup } from '../Layout/Layout'; -import { IconButton, IconButtonVariant, Props as IconButtonProps } from './IconButton'; +import { BasePropsWithTooltip, IconButton, IconButtonVariant, Props as IconButtonProps } from './IconButton'; import mdx from './IconButton.mdx'; interface ScenarioProps { background: 'canvas' | 'primary' | 'secondary'; } +const defaultExcludes = ['ariaLabel', 'aria-label']; +const additionalExcludes = ['size', 'name', 'variant', 'iconType']; + const meta: Meta = { title: 'Buttons/IconButton', component: IconButton, @@ -22,6 +25,7 @@ const meta: Meta = { docs: { page: mdx, }, + controls: { exclude: defaultExcludes }, }, args: { name: 'apps', @@ -30,7 +34,8 @@ const meta: Meta = { tooltip: 'sample tooltip message', tooltipPlacement: 'top', variant: 'secondary', - ariaLabel: 'sample aria-label content', + ariaLabel: 'this property is deprecated', + ['aria-label']: 'sample aria-label content', }, argTypes: { tooltip: { @@ -43,7 +48,7 @@ export const Basic: StoryFn = (args: IconButtonProps) => { return ; }; -export const ExamplesSizes = () => { +export const ExamplesSizes = (args: BasePropsWithTooltip) => { const theme = useTheme2(); const sizes: IconSize[] = ['xs', 'sm', 'md', 'lg', 'xl']; const icons: IconName[] = ['search', 'trash-alt', 'arrow-left', 'times']; @@ -56,17 +61,22 @@ export const ExamplesSizes = () => { `; return ( - + {variants.map((variant) => { return ( -
+

{variant}

{icons.map((icon) => { return (
{sizes.map((size) => ( - + ))}
@@ -81,7 +91,7 @@ export const ExamplesSizes = () => {
{sizes.map((size) => ( - + ))}
@@ -91,7 +101,42 @@ export const ExamplesSizes = () => { ); }; -export const ExamplesBackground = () => { +ExamplesSizes.parameters = { + controls: { + exclude: [...defaultExcludes, ...additionalExcludes], + }, +}; + +export const ExamplesBackground = (args: BasePropsWithTooltip) => { + const RenderBackgroundScenario = ({ background }: ScenarioProps) => { + const theme = useTheme2(); + const variants: IconButtonVariant[] = ['primary', 'secondary', 'destructive']; + + return ( +
+ +
{background}
+
+ {variants.map((variant) => { + return ; + })} + +
+
+
+ ); + }; + return (
@@ -101,33 +146,10 @@ export const ExamplesBackground = () => { ); }; -const RenderBackgroundScenario = ({ background }: ScenarioProps) => { - const theme = useTheme2(); - const variants: IconButtonVariant[] = ['primary', 'secondary', 'destructive']; - - return ( -
- -
{background}
-
- {variants.map((variant) => { - return ; - })} - -
-
-
- ); +ExamplesBackground.parameters = { + controls: { + exclude: [...defaultExcludes, ...additionalExcludes], + }, }; export default meta; diff --git a/packages/grafana-ui/src/components/IconButton/IconButton.tsx b/packages/grafana-ui/src/components/IconButton/IconButton.tsx index 5951bf3892b7..da29b23a4134 100644 --- a/packages/grafana-ui/src/components/IconButton/IconButton.tsx +++ b/packages/grafana-ui/src/components/IconButton/IconButton.tsx @@ -15,76 +15,92 @@ export type IconButtonVariant = 'primary' | 'secondary' | 'destructive'; type LimitedIconSize = ComponentSize | 'xl'; -export interface Props extends React.ButtonHTMLAttributes { +interface BaseProps extends Omit, 'aria-label'> { /** Name of the icon **/ name: IconName; /** Icon size - sizes xxl and xxxl are deprecated and when used being decreased to xl*/ size?: IconSize; /** Type of the icon - mono or default */ iconType?: IconType; - /** Tooltip content to display on hover */ - tooltip?: PopoverContent; - /** Position of the tooltip */ - tooltipPlacement?: TooltipPlacement; /** Variant to change the color of the Icon */ variant?: IconButtonVariant; - /** Text available only for screen readers. Will use tooltip text as fallback. */ +} + +export interface BasePropsWithTooltip extends BaseProps { + /** Tooltip content to display on hover and as the aria-label */ + tooltip: PopoverContent; + /** Position of the tooltip */ + tooltipPlacement?: TooltipPlacement; +} + +interface BasePropsWithAriaLabel extends BaseProps { + /** @deprecated use aria-label instead*/ ariaLabel?: string; + /** Text available only for screen readers. No tooltip will be set in this case. */ + ['aria-label']: string; } -export const IconButton = React.forwardRef( - ( - { - name, - size = 'md', - iconType, - tooltip, - tooltipPlacement, - ariaLabel, - className, - variant = 'secondary', - ...restProps - }, - ref - ) => { - const theme = useTheme2(); - let limitedIconSize: LimitedIconSize; - - // very large icons (xl to xxxl) are unified to size xl - if (size === 'xxl' || size === 'xxxl') { - deprecationWarning('IconButton', 'size="xxl" and size="xxxl"', 'size="xl"'); - limitedIconSize = 'xl'; - } else { - limitedIconSize = size; - } - - const styles = getStyles(theme, limitedIconSize, variant); - const tooltipString = typeof tooltip === 'string' ? tooltip : ''; - - // When using tooltip, ref is forwarded to Tooltip component instead for https://github.com/grafana/grafana/issues/65632 - const button = ( +export type Props = BasePropsWithTooltip | BasePropsWithAriaLabel; + +export const IconButton = React.forwardRef((props, ref) => { + const { size = 'md', variant = 'secondary' } = props; + + const theme = useTheme2(); + let limitedIconSize: LimitedIconSize; + + // very large icons (xl to xxxl) are unified to size xl + if (size === 'xxl' || size === 'xxxl') { + deprecationWarning('IconButton', 'size="xxl" and size="xxxl"', 'size="xl"'); + limitedIconSize = 'xl'; + } else { + limitedIconSize = size; + } + + const styles = getStyles(theme, limitedIconSize, variant); + + let ariaLabel: string | undefined; + let buttonRef: typeof ref | undefined; + + if ('tooltip' in props) { + const { tooltip } = props; + ariaLabel = typeof tooltip === 'string' ? tooltip : undefined; + } else if ('ariaLabel' in props || 'aria-label' in props) { + const { ariaLabel: deprecatedAriaLabel, ['aria-label']: ariaLabelProp } = props; + ariaLabel = ariaLabelProp || deprecatedAriaLabel; + buttonRef = ref; + } + + // When using tooltip, ref is forwarded to Tooltip component instead for https://github.com/grafana/grafana/issues/65632 + if ('tooltip' in props) { + const { name, iconType, className, tooltip, tooltipPlacement, ...restProps } = props; + return ( + + + + ); + } else { + const { name, iconType, className, ...restProps } = props; + return ( ); - - if (tooltip) { - return ( - - {button} - - ); - } - - return button; } -); +}); IconButton.displayName = 'IconButton'; diff --git a/packages/grafana-ui/src/components/Modal/Modal.tsx b/packages/grafana-ui/src/components/Modal/Modal.tsx index f67256316532..696458402a02 100644 --- a/packages/grafana-ui/src/components/Modal/Modal.tsx +++ b/packages/grafana-ui/src/components/Modal/Modal.tsx @@ -84,7 +84,7 @@ export function Modal(props: PropsWithChildren) { typeof title !== 'string' && title }
- +
{children}
diff --git a/packages/grafana-ui/src/components/Select/SelectBase.test.tsx b/packages/grafana-ui/src/components/Select/SelectBase.test.tsx index f2b04373235b..4b4eb14b8bb5 100644 --- a/packages/grafana-ui/src/components/Select/SelectBase.test.tsx +++ b/packages/grafana-ui/src/components/Select/SelectBase.test.tsx @@ -233,7 +233,7 @@ describe('SelectBase', () => { expect(screen.getByLabelText('My select')).toBeInTheDocument(); - await userEvent.click(screen.getByLabelText('Remove Option 1')); + await userEvent.click(screen.getAllByLabelText('Remove')[0]); expect(onChangeHandler).toHaveBeenCalledWith([], { action: 'remove-value', name: undefined, diff --git a/packages/grafana-ui/src/components/TagsInput/TagItem.tsx b/packages/grafana-ui/src/components/TagsInput/TagItem.tsx index 97e0eba129cc..c74f573ded17 100644 --- a/packages/grafana-ui/src/components/TagsInput/TagItem.tsx +++ b/packages/grafana-ui/src/components/TagsInput/TagItem.tsx @@ -28,8 +28,7 @@ export const TagItem = ({ name, disabled, onRemove }: Props) => { name="times" size="lg" disabled={disabled} - ariaLabel={`Remove "${name}" tag`} - tooltip="Remove tag" + tooltip={`Remove "${name}" tag`} onClick={() => onRemove(name)} className={styles.buttonStyles} /> diff --git a/public/app/core/components/Layers/LayerDragDropList.test.tsx b/public/app/core/components/Layers/LayerDragDropList.test.tsx index 710c7a0ff90d..4d7ec105927c 100644 --- a/public/app/core/components/Layers/LayerDragDropList.test.tsx +++ b/public/app/core/components/Layers/LayerDragDropList.test.tsx @@ -25,15 +25,15 @@ describe('LayerDragDropList', () => { it('showActions', () => { renderScenario({ showActions: () => true }); - expect(screen.getAllByLabelText('Duplicate button').length).toEqual(2); - expect(screen.getAllByLabelText('Remove button').length).toEqual(2); + expect(screen.getAllByLabelText('Duplicate').length).toEqual(2); + expect(screen.getAllByLabelText('Remove').length).toEqual(2); }); it('showActions - no duplicate', () => { renderScenario({ showActions: () => true, onDuplicate: undefined }); - expect(screen.getAllByLabelText('Remove button').length).toEqual(2); - expect(screen.queryAllByLabelText('Duplicate button').length).toEqual(0); + expect(screen.getAllByLabelText('Remove').length).toEqual(2); + expect(screen.queryAllByLabelText('Duplicate').length).toEqual(0); }); it('renders draggable icon', () => { diff --git a/public/app/core/components/Layers/LayerDragDropList.tsx b/public/app/core/components/Layers/LayerDragDropList.tsx index 232eafd040d7..7c07662bdb6c 100644 --- a/public/app/core/components/Layers/LayerDragDropList.tsx +++ b/public/app/core/components/Layers/LayerDragDropList.tsx @@ -81,7 +81,6 @@ export const LayerDragDropList = ({ onDuplicate(element)} /> @@ -90,7 +89,6 @@ export const LayerDragDropList = ({ onDelete(element)} /> diff --git a/public/app/core/components/QueryOperationRow/QueryOperationRowHeader.test.tsx b/public/app/core/components/QueryOperationRow/QueryOperationRowHeader.test.tsx index f03ec2525fd1..7043bae11a00 100644 --- a/public/app/core/components/QueryOperationRow/QueryOperationRowHeader.test.tsx +++ b/public/app/core/components/QueryOperationRow/QueryOperationRowHeader.test.tsx @@ -24,11 +24,11 @@ describe('QueryOperationRowHeader', () => { describe('collapsable property', () => { test('should show the button to collapse the query row by default', () => { setup(); - expect(screen.getByLabelText('toggle collapse and expand query row')).toBeInTheDocument(); + expect(screen.getByLabelText('Collapse query row')).toBeInTheDocument(); }); test('should hide the button to collapse the query row when collapsable is set as false', () => { setup({ collapsable: false }); - expect(screen.queryByLabelText('toggle collapse and expand query row')).not.toBeInTheDocument(); + expect(screen.queryByLabelText('Collapse query row')).not.toBeInTheDocument(); }); }); }); diff --git a/public/app/core/components/QueryOperationRow/QueryOperationRowHeader.tsx b/public/app/core/components/QueryOperationRow/QueryOperationRowHeader.tsx index fc40ebda1864..c47df9f117d8 100644 --- a/public/app/core/components/QueryOperationRow/QueryOperationRowHeader.tsx +++ b/public/app/core/components/QueryOperationRow/QueryOperationRowHeader.tsx @@ -40,7 +40,6 @@ export const QueryOperationRowHeader = ({ {collapsable && ( { it('calls onDismiss when clicking the X', async () => { render(); - await userEvent.click(await screen.findByRole('button', { name: 'Close dialog' })); + await userEvent.click(await screen.findByRole('button', { name: 'Close' })); expect(mockOnDismiss).toHaveBeenCalled(); }); }); diff --git a/public/app/features/browse-dashboards/components/BrowseActions/MoveModal.test.tsx b/public/app/features/browse-dashboards/components/BrowseActions/MoveModal.test.tsx index c860dd6d2fd6..182e712f1fea 100644 --- a/public/app/features/browse-dashboards/components/BrowseActions/MoveModal.test.tsx +++ b/public/app/features/browse-dashboards/components/BrowseActions/MoveModal.test.tsx @@ -113,7 +113,7 @@ describe('browse-dashboards MoveModal', () => { it('calls onDismiss when clicking the X', async () => { render(); - await userEvent.click(await screen.findByRole('button', { name: 'Close dialog' })); + await userEvent.click(await screen.findByRole('button', { name: 'Close' })); expect(mockOnDismiss).toHaveBeenCalled(); }); }); diff --git a/public/app/features/browse-dashboards/components/NameCell.tsx b/public/app/features/browse-dashboards/components/NameCell.tsx index 0d40a7ff574f..f4f01fd6c8ea 100644 --- a/public/app/features/browse-dashboards/components/NameCell.tsx +++ b/public/app/features/browse-dashboards/components/NameCell.tsx @@ -74,7 +74,7 @@ export function NameCell({ row: { original: data }, onFolderClick }: NameCellPro onFolderClick(item.uid, !isOpen); }} name={isOpen ? 'angle-down' : 'angle-right'} - ariaLabel={isOpen ? 'Collapse folder' : 'Expand folder'} + tooltip={isOpen ? 'Collapse folder' : 'Expand folder'} /> )} diff --git a/public/app/features/library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch.test.tsx b/public/app/features/library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch.test.tsx index a2cf52e73a51..b35ea5810b3e 100644 --- a/public/app/features/library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch.test.tsx +++ b/public/app/features/library-panels/components/LibraryPanelsSearch/LibraryPanelsSearch.test.tsx @@ -318,7 +318,7 @@ describe('LibraryPanelsSearch', () => { expect(card()).toBeInTheDocument(); expect(within(card()).getByText(/library panel name/i)).toBeInTheDocument(); expect(within(card()).getByText(/library panel description/i)).toBeInTheDocument(); - expect(within(card()).getByLabelText(/delete button on panel type card/i)).toBeInTheDocument(); + expect(within(card()).getByLabelText(/Delete/i)).toBeInTheDocument(); }); }); @@ -354,9 +354,9 @@ describe('LibraryPanelsSearch', () => { } ); - await userEvent.click(screen.getByLabelText(/delete button on panel type card/i)); + await userEvent.click(screen.getByLabelText('Delete')); await waitFor(() => expect(screen.getByText('Do you want to delete this panel?')).toBeInTheDocument()); - await userEvent.click(screen.getByRole('button', { name: 'Delete' })); + await userEvent.click(screen.getAllByRole('button', { name: 'Delete' })[1]); await waitFor(() => { expect(getLibraryPanelsSpy).toHaveBeenCalledWith({ diff --git a/public/app/features/query/components/QueryEditorRows.test.tsx b/public/app/features/query/components/QueryEditorRows.test.tsx index 61581fcfee01..706e24236308 100644 --- a/public/app/features/query/components/QueryEditorRows.test.tsx +++ b/public/app/features/query/components/QueryEditorRows.test.tsx @@ -96,7 +96,7 @@ describe('QueryEditorRows', () => { const queryEditorRows = await screen.findAllByTestId('query-editor-row'); for (const childQuery of queryEditorRows) { - const toggleExpandButton = queryByLabelText(childQuery, 'toggle collapse and expand query row') as HTMLElement; + const toggleExpandButton = queryByLabelText(childQuery, 'Collapse query row') as HTMLElement; expect(toggleExpandButton).toBeInTheDocument(); expect(toggleExpandButton.getAttribute('aria-expanded')).toBe('true'); diff --git a/public/app/features/query/components/QueryGroup.test.tsx b/public/app/features/query/components/QueryGroup.test.tsx index 0622a48c872a..da30cb5a836a 100644 --- a/public/app/features/query/components/QueryGroup.test.tsx +++ b/public/app/features/query/components/QueryGroup.test.tsx @@ -80,7 +80,7 @@ describe('QueryGroup', () => { await userEvent.click(addExpressionButton); const lastQueryEditorRow = (await screen.findAllByTestId('query-editor-row')).at(-1); - const lastEditorToggleRow = (await screen.findAllByLabelText('toggle collapse and expand query row')).at(-1); + const lastEditorToggleRow = (await screen.findAllByLabelText('Collapse query row')).at(-1); expect(lastEditorToggleRow?.getAttribute('aria-expanded')).toBe('true'); expect(lastQueryEditorRow?.firstElementChild?.children.length).toBe(2); @@ -97,7 +97,7 @@ describe('QueryGroup', () => { await userEvent.click(addQueryButton); const lastQueryEditorRow = (await screen.findAllByTestId('query-editor-row')).at(-1); - const lastEditorToggleRow = (await screen.findAllByLabelText('toggle collapse and expand query row')).at(-1); + const lastEditorToggleRow = (await screen.findAllByLabelText('Collapse query row')).at(-1); expect(lastEditorToggleRow?.getAttribute('aria-expanded')).toBe('true'); expect(lastQueryEditorRow?.firstElementChild?.children.length).toBe(2); diff --git a/public/app/features/serviceaccounts/components/ServiceAccountsListItem.tsx b/public/app/features/serviceaccounts/components/ServiceAccountsListItem.tsx index be2be78b47b6..d0c21a74e602 100644 --- a/public/app/features/serviceaccounts/components/ServiceAccountsListItem.tsx +++ b/public/app/features/serviceaccounts/components/ServiceAccountsListItem.tsx @@ -132,8 +132,7 @@ const ServiceAccountListItem = memo( name="trash-alt" size="md" onClick={() => onRemoveButtonClick(serviceAccount)} - aria-label={`Delete service account ${serviceAccount.name}`} - tooltip="Delete account" + tooltip={`Delete service account ${serviceAccount.name}`} /> )} diff --git a/public/app/plugins/datasource/azuremonitor/components/MetricsQueryEditor/DimensionFields.test.tsx b/public/app/plugins/datasource/azuremonitor/components/MetricsQueryEditor/DimensionFields.test.tsx index 8c367e8c6b61..913a37be6f68 100644 --- a/public/app/plugins/datasource/azuremonitor/components/MetricsQueryEditor/DimensionFields.test.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/MetricsQueryEditor/DimensionFields.test.tsx @@ -201,8 +201,8 @@ describe(`Azure Monitor QueryEditor`, () => { /> ); await screen.findByText('testlabel'); - const labelClear = await screen.findByLabelText('Remove testlabel'); - await user.click(labelClear); + const labelClear = await screen.findAllByLabelText('Remove'); + await user.click(labelClear[0]); mockQuery = setDimensionFilterValue(mockQuery, 0, 'filters', []); expect(onQueryChange).toHaveBeenCalledWith({ ...mockQuery, diff --git a/public/app/plugins/datasource/azuremonitor/components/TracesQueryEditor/Filter.tsx b/public/app/plugins/datasource/azuremonitor/components/TracesQueryEditor/Filter.tsx index daca2da11256..7ec0f9f428b4 100644 --- a/public/app/plugins/datasource/azuremonitor/components/TracesQueryEditor/Filter.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/TracesQueryEditor/Filter.tsx @@ -270,7 +270,7 @@ const Filter = ( onCloseMenu={() => onFieldChange('filters', item, selected, onChange)} hideSelectedOptions={false} /> - + ); }; diff --git a/public/app/plugins/datasource/azuremonitor/components/TracesQueryEditor/Filters.test.tsx b/public/app/plugins/datasource/azuremonitor/components/TracesQueryEditor/Filters.test.tsx index 26306b1aaf9b..8a2bb4f14641 100644 --- a/public/app/plugins/datasource/azuremonitor/components/TracesQueryEditor/Filters.test.tsx +++ b/public/app/plugins/datasource/azuremonitor/components/TracesQueryEditor/Filters.test.tsx @@ -281,7 +281,7 @@ describe(`Traces Filters`, () => { rerender ); - const removeButtons = screen.getAllByLabelText('Remove'); + const removeButtons = screen.getAllByLabelText('Remove filter'); mockQuery = { ...mockQuery, @@ -388,9 +388,9 @@ describe(`Traces Filters`, () => { ], }, }; - const removeLabel = screen.getByLabelText(`Remove test-app-id-2`); + const removeLabel = screen.getAllByLabelText(`Remove`); await act(async () => { - await userEvent.click(removeLabel); + await userEvent.click(removeLabel[1]); }); rerender( diff --git a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.test.tsx b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.test.tsx index 9af673c1ad97..924414b81458 100644 --- a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.test.tsx +++ b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/SearchField.test.tsx @@ -112,8 +112,8 @@ describe('SearchField', () => { expect(updateFilter).toHaveBeenCalledWith({ ...filter, value: ['driver', 'customer'] }); // Remove the first value - const firstValRemove = await screen.findByLabelText('Remove driver'); - await user.click(firstValRemove); + const firstValRemove = await screen.findAllByLabelText('Remove'); + await user.click(firstValRemove[0]); expect(updateFilter).toHaveBeenCalledWith({ ...filter, value: ['customer'] }); } });