Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions workspaces/extensions/e2e-tests/utils/accessibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export async function runAccessibilityTests(
page: Page,
testInfo: TestInfo,
attachName = 'accessibility-scan-results.json',
options: { skipFailures?: boolean } = { skipFailures: true },
) {
const accessibilityScanResults = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
Expand All @@ -32,10 +31,8 @@ export async function runAccessibilityTests(
contentType: 'application/json',
});

if (!options?.skipFailures) {
expect(
accessibilityScanResults.violations,
'Accessibility violations found',
).toEqual([]);
}
expect(
accessibilityScanResults.violations,
'Accessibility violations found',
).toEqual([]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export const BadgeChip = ({ plugin }: { plugin: ExtensionsPlugin }) => {
label={options.label}
variant="outlined"
size="small"
title={options.tooltip}
aria-label={options.tooltip ?? options.label}
sx={{
cursor: 'pointer',
}}
Expand All @@ -142,7 +142,11 @@ export const BadgeTriange = ({ plugin }: { plugin: ExtensionsPlugin }) => {
<div style={{ position: 'relative' }}>
<div style={{ position: 'absolute' }}>
<Tooltip title={options.tooltip} placement="top" arrow>
<div style={{ width: size, height: size }}>
<div
style={{ width: size, height: size }}
role="img"
aria-label={options.tooltip}
>
<div
style={{
position: 'absolute',
Expand All @@ -153,6 +157,7 @@ export const BadgeTriange = ({ plugin }: { plugin: ExtensionsPlugin }) => {
}}
/>
<TaskAltIcon
aria-hidden="true"
style={{
position: 'absolute',
top: 4,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export const DownloadPackageYaml = ({
<IconButton
size="small"
disabled
aria-label={t('installedPackages.table.tooltips.downloadPackage')}
sx={{ color: theme => theme.palette.action.disabled }}
>
<FileDownloadOutlinedIcon />
Expand Down Expand Up @@ -111,6 +112,7 @@ export const DownloadPackageYaml = ({
<Tooltip title={t('installedPackages.table.tooltips.downloadPackage')}>
<IconButton
size="small"
aria-label={t('installedPackages.table.tooltips.downloadPackage')}
sx={{ color: theme => theme.palette.text.primary }}
onClick={async () => {
try {
Expand Down Expand Up @@ -175,6 +177,7 @@ export const EditPackage = ({
<IconButton
size="small"
disabled
aria-label={t('installedPackages.table.tooltips.editPackage')}
sx={{ color: theme => theme.palette.action.disabled }}
>
<EditIcon />
Expand All @@ -199,6 +202,7 @@ export const EditPackage = ({
const viewIcon = (
<IconButton
size="small"
aria-label={t('actions.view')}
sx={{ color: theme => theme.palette.text.primary }}
onClick={() =>
navigate(packagePathWithSearchParams, {
Expand Down Expand Up @@ -252,6 +256,7 @@ export const EditPackage = ({
<Tooltip title={t('installedPackages.table.tooltips.editPackage')}>
<IconButton
size="small"
aria-label={t('installedPackages.table.tooltips.editPackage')}
sx={{ color: theme => theme.palette.text.primary }}
onClick={() =>
navigate(packagePathWithSearchParams, { state: { editAction: true } })
Expand Down Expand Up @@ -287,9 +292,16 @@ export const TogglePackage = ({
);
const disabledIcon = (
<Box component="span" display="inline-flex">
<IconButton size="small" disabled>
{isPackageEnabled ? <Switch checked disabled /> : <Switch disabled />}
</IconButton>
<Switch
size="small"
checked={isPackageEnabled}
disabled
inputProps={{
'aria-label': isPackageEnabled
? t('installedPackages.table.tooltips.disablePackage')
: t('installedPackages.table.tooltips.enablePackage'),
}}
/>
</Box>
);

Expand Down Expand Up @@ -388,13 +400,16 @@ export const TogglePackage = ({
: t('installedPackages.table.tooltips.enablePackage')
}
>
<IconButton
<Switch
size="small"
sx={{ color: theme => theme.palette.text.primary }}
onClick={handleToggle}
>
{isPackageEnabled ? <Switch checked /> : <Switch />}
</IconButton>
checked={isPackageEnabled}
onChange={handleToggle}
inputProps={{
'aria-label': isPackageEnabled
? t('installedPackages.table.tooltips.disablePackage')
: t('installedPackages.table.tooltips.enablePackage'),
}}
/>
</Tooltip>
);
};
Expand All @@ -410,20 +425,24 @@ export const UninstallPackage = ({ pkg }: { pkg: InstalledPackageRow }) => {
: t('tooltips.missingDynamicArtifact' as any, { type: 'package' })
}
>
<IconButton
size="small"
disabled
sx={{ color: theme => theme.palette.action.disabled }}
>
<DeleteIcon />
</IconButton>
<Box component="span" display="inline-flex">
<IconButton
size="small"
disabled
aria-label={t('button.uninstall')}
sx={{ color: theme => theme.palette.action.disabled }}
>
<DeleteIcon />
</IconButton>
</Box>
</Tooltip>
);
}

return (
<IconButton
size="small"
aria-label={t('button.uninstall')}
sx={{ color: theme => theme.palette.text.primary }}
onClick={() => {}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,26 @@ export const PluginCard = ({ plugin }: { plugin: ExtensionsPlugin }) => {

return (
<Card
component="article"
variant="outlined"
role="link"
tabIndex={0}
aria-label={plugin.metadata.title ?? plugin.metadata.name}
sx={{
position: 'relative',
'&:hover': { backgroundColor: 'background.default', cursor: 'pointer' },
'&:hover, &:focus-visible': {
backgroundColor: 'background.default',
cursor: 'pointer',
outline: theme => `2px solid ${theme.palette.primary.main}`,
},
}}
onClick={() => navigate(pluginPath)}
onKeyDown={e => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
navigate(pluginPath);
}
}}
>
<BadgeTriange plugin={plugin} />
<CardContent sx={{ backgroundColor: 'transparent' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,24 @@ const testPlugin: ExtensionsPlugin = {
describe('PluginIcon', () => {
it('should render without error', () => {
const { getByRole } = render(<PluginIcon plugin={testPlugin} size={40} />);
expect(getByRole('img')).toBeInTheDocument();
expect(getByRole('img').style.backgroundImage).toEqual(
const img = getByRole('img');
expect(img).toBeInTheDocument();
expect(img).toHaveAttribute('aria-label', 'APIs with Test plugin');
expect(img.style.backgroundImage).toEqual(
'url("https://backstage.io/icons/test-plugin.png")',
);
});

it('should render no image when icon is missing', () => {
it('should render fallback icon when icon is missing', () => {
const testPluginWithoutIcon = {
...testPlugin,
spec: { ...testPlugin.spec, icon: undefined },
};
const { queryAllByRole } = render(
const { getByRole } = render(
<PluginIcon plugin={testPluginWithoutIcon} size={40} />,
);
expect(queryAllByRole('img')).toHaveLength(0);
const img = getByRole('img');
expect(img).toBeInTheDocument();
expect(img).toHaveAttribute('aria-label', 'APIs with Test plugin');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@ export const PluginIcon = ({
}) => {
const icon = plugin?.spec?.icon;

const title = plugin?.metadata?.title ?? plugin?.metadata?.name ?? '';

if (!icon) {
return (
<CardMedia
role="img"
aria-label={title}
sx={{
width: size,
height: size,
Expand All @@ -39,6 +43,7 @@ export const PluginIcon = ({
}}
>
<NoIconIcon
aria-hidden="true"
sx={{
width: size,
height: size,
Expand All @@ -52,6 +57,8 @@ export const PluginIcon = ({

return (
<CardMedia
role="img"
aria-label={title}
image={icon}
sx={{
width: size,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
return (
<Box
role="tabpanel"
id={`tabpanel-${index}`}
aria-labelledby={`tab-${index}`}
sx={{ flex: 1, overflow: 'auto', p: 2, scrollbarWidth: 'thin' }}
>
<Typography component="div">
Expand All @@ -88,24 +90,26 @@
<Typography variant="h5" sx={{ fontWeight: 'bold', mb: 1 }}>
{Object.keys(item)[0]}
</Typography>
{item?.[Object.keys(item)[0]]?.map?.(ex => (
<>
<Typography variant="h6" sx={{ fontWeight: 'bold', mb: 1 }}>
{ex.title}
{ex.content !== 'string' && (
<Button
sx={{ float: 'right' }}
onClick={() =>
handleApplyContent(ex.content, Object.keys(item)[0])
}
>
{t('common.apply')}
</Button>
)}
</Typography>
<Markdown content={getExampleAsMarkdown(ex.content)} />
</>
))}
{item?.[Object.keys(item)[0]]?.map?.(
(ex: { title: string; content: string }, exIdx: number) => (
<Box key={exIdx}>

Check warning on line 95 in workspaces/extensions/plugins/extensions/src/components/TabPanel.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not use Array index in keys

See more on https://sonarcloud.io/project/issues?id=redhat-developer_rhdh-plugins&issues=AZ7_s-I00gw_RpEzM1NL&open=AZ7_s-I00gw_RpEzM1NL&pullRequest=3583
<Typography variant="h6" sx={{ fontWeight: 'bold', mb: 1 }}>
{ex.title}
{ex.content !== 'string' && (
<Button
sx={{ float: 'right' }}
onClick={() =>
handleApplyContent(ex.content, Object.keys(item)[0])
}
>
{t('common.apply')}
</Button>
)}
</Typography>
<Markdown content={getExampleAsMarkdown(ex.content)} />
</Box>
),
)}
</Box>
))
) : (
Expand Down
Loading