fix: label related accessibility issues with FavoriteEntity
Signed-off-by: Mikko Korhonen <mikko.korhonen@op.fi>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
Fix label related accessibility issues with `FavorityEntity`
|
||||
@@ -686,6 +686,7 @@ export function MockEntityListContextProvider<
|
||||
|
||||
// @public
|
||||
export class MockStarredEntitiesApi implements StarredEntitiesApi {
|
||||
constructor(opts?: { starredEntities?: string[] });
|
||||
// (undocumented)
|
||||
starredEntitie$(): Observable<Set<string>>;
|
||||
// (undocumented)
|
||||
|
||||
@@ -29,6 +29,10 @@ export class MockStarredEntitiesApi implements StarredEntitiesApi {
|
||||
ZenObservable.SubscriptionObserver<Set<string>>
|
||||
>();
|
||||
|
||||
constructor(opts: { starredEntities?: string[] } = {}) {
|
||||
this.starredEntities = new Set(opts.starredEntities);
|
||||
}
|
||||
|
||||
private readonly observable = new ObservableImpl<Set<string>>(subscriber => {
|
||||
subscriber.next(new Set(this.starredEntities));
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { storageApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
import { MockStarredEntitiesApi, starredEntitiesApiRef } from '../../apis';
|
||||
import { FavoriteEntity } from './FavoriteEntity';
|
||||
import { ComponentEntity } from '@backstage/catalog-model';
|
||||
import {
|
||||
MockStorageApi,
|
||||
renderInTestApp,
|
||||
TestApiProvider,
|
||||
} from '@backstage/test-utils';
|
||||
import { screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
const entity: ComponentEntity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'example',
|
||||
},
|
||||
spec: {
|
||||
type: 'service',
|
||||
lifecycle: 'experimental',
|
||||
owner: 'user:default/john.doe_example.com',
|
||||
},
|
||||
};
|
||||
|
||||
const mockStorage = MockStorageApi.create();
|
||||
|
||||
describe('<FavoriteEntity/>', () => {
|
||||
it('should add to favorites', async () => {
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[storageApiRef, mockStorage],
|
||||
[starredEntitiesApiRef, new MockStarredEntitiesApi()],
|
||||
]}
|
||||
>
|
||||
<FavoriteEntity entity={entity} />
|
||||
</TestApiProvider>,
|
||||
);
|
||||
|
||||
const addToFavorite = screen.getByRole('button', {
|
||||
name: 'Add to favorites',
|
||||
});
|
||||
|
||||
// Should keep the label when hovering
|
||||
await userEvent.hover(addToFavorite);
|
||||
expect(addToFavorite).toBeInTheDocument();
|
||||
|
||||
await userEvent.click(addToFavorite);
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: 'Remove from favorites',
|
||||
}),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should remove from favorites', async () => {
|
||||
await renderInTestApp(
|
||||
<TestApiProvider
|
||||
apis={[
|
||||
[storageApiRef, mockStorage],
|
||||
[
|
||||
starredEntitiesApiRef,
|
||||
new MockStarredEntitiesApi({
|
||||
starredEntities: ['component:default/example'],
|
||||
}),
|
||||
],
|
||||
]}
|
||||
>
|
||||
<FavoriteEntity entity={entity} />
|
||||
</TestApiProvider>,
|
||||
);
|
||||
|
||||
const removeFromFavorites = screen.getByRole('button', {
|
||||
name: 'Remove from favorites',
|
||||
});
|
||||
|
||||
// Should keep the label when hovering
|
||||
await userEvent.hover(removeFromFavorites);
|
||||
expect(removeFromFavorites).toBeInTheDocument();
|
||||
|
||||
await userEvent.click(removeFromFavorites);
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: 'Add to favorites',
|
||||
}),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { Entity, stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
@@ -46,20 +46,24 @@ export const FavoriteEntity = (props: FavoriteEntityProps) => {
|
||||
props.entity,
|
||||
);
|
||||
const { t } = useTranslationRef(catalogReactTranslationRef);
|
||||
const title = isStarredEntity
|
||||
? t('favoriteEntity.removeFromFavorites')
|
||||
: t('favoriteEntity.addToFavorites');
|
||||
|
||||
const id = `favorite-${stringifyEntityRef(props.entity).replace(
|
||||
/[^a-zA-Z0-9-_]/g,
|
||||
'-',
|
||||
)}`;
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
aria-label="favorite"
|
||||
aria-label={title}
|
||||
id={id}
|
||||
color="inherit"
|
||||
{...props}
|
||||
onClick={() => toggleStarredEntity()}
|
||||
>
|
||||
<Tooltip
|
||||
title={
|
||||
isStarredEntity
|
||||
? t('favoriteEntity.removeFromFavorites')
|
||||
: t('favoriteEntity.addToFavorites')
|
||||
}
|
||||
>
|
||||
<Tooltip id={id} title={title}>
|
||||
{isStarredEntity ? <YellowStar /> : <StarBorder />}
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
|
||||
@@ -119,7 +119,7 @@ describe('CardHeader', () => {
|
||||
</TestApiProvider>,
|
||||
);
|
||||
|
||||
const favorite = getByRole('button', { name: 'favorite' });
|
||||
const favorite = getByRole('button', { name: 'Add to favorites' });
|
||||
|
||||
await fireEvent.click(favorite);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user