fix: [Obs Synthetics > Monitor detail][KEYBOARD]: Test run screenshots (in modal) need more comprehensive alt text (#187363)

Closes: https://github.com/elastic/observability-dev/issues/3688

## Description

The synthetics monitors include thumbnail screenshots that open a larger
preview window. The alt text on these larger screenshots is very generic
and could be improved by concatenating more information. Screenshot and
suggested copy attached below.

### Steps to recreate

1. Open the
[Synthetics](https://keep-serverless-fyzdg-f07c50.kb.eu-west-1.aws.qa.elastic.cloud/app/synthetics)
view
2. Create a monitor if none exist
3. Click on that monitor and navigate to the [full monitor
detail](8b88e937-f917-4f12-9325-8ab005cffea5?locationId=us_central_qa)
view
4. Click on a thumbnail and verify the modal opens
5. Turn on the screen reader of your choosing
6. Navigate to the image and verify the generic alt text

### What was changed?: 

1. The `label` attribute for `ScreenshotImage` calling was changed to a
unified version in all places. Now it's always follow next rule:
`"{stepName}", {stepNumber} of {totalSteps}`

### Screen: 

<img width="1256" alt="image"
src="dad6d098-8c29-4310-9988-784d227e30e1">
This commit is contained in:
Alexey Antonov 2024-07-03 20:22:49 +03:00 committed by GitHub
parent 78fa3c36c3
commit 0ead26a742
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 31 additions and 19 deletions

View file

@ -62,7 +62,7 @@ describe('JourneyScreenshotPreview', () => {
const { getByAltText, getByText, queryByAltText } = render(
<JourneyScreenshotPreview {...defaultProps} />
);
const img = getByAltText('First step');
const img = getByAltText('"First step", 1 of 2');
fireEvent.click(img);
expect(dialogProps.checkGroup).toEqual(defaultProps.checkGroup);
expect(getByAltText('img-in-dialog')).not.toBeNull();
@ -75,7 +75,7 @@ describe('JourneyScreenshotPreview', () => {
<JourneyScreenshotPreview {...defaultProps} />
);
const img = getByAltText('First step');
const img = getByAltText('"First step", 1 of 2');
const euiPopoverMessage =
'You are in a dialog. Press Escape, or tap/click outside the dialog to close.'; // Helps to detect if popover is open
expect(queryByText(euiPopoverMessage)).toBeNull();
@ -88,7 +88,7 @@ describe('JourneyScreenshotPreview', () => {
it('renders the correct image', () => {
const { getByAltText } = render(<JourneyScreenshotPreview {...defaultProps} />);
const img = getByAltText('First step');
const img = getByAltText('"First step", 1 of 2');
expect(img).toHaveAttribute('src', testImgUrl1);
});
});

View file

@ -8,6 +8,7 @@
import React, { useCallback, useState, MouseEvent } from 'react';
import { EuiPopover, useEuiTheme } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { POPOVER_SCREENSHOT_SIZE, ScreenshotImageSize } from '../screenshot/screenshot_size';
import { JourneyScreenshotDialog } from '../screenshot/journey_screenshot_dialog';
import { ScreenshotImage } from '../screenshot/screenshot_image';
@ -77,7 +78,14 @@ export const JourneyScreenshotPreview: React.FC<StepImagePopoverProps> = ({
const renderScreenshotImage = (screenshotSize: ScreenshotImageSize) => (
<ScreenshotImage
label={stepName}
label={i18n.translate('xpack.synthetics.monitorTestResult.screenshotImageLabel', {
defaultMessage: '"{stepName}", {stepNumber} of {totalSteps}',
values: {
stepName,
stepNumber,
totalSteps: maxSteps ?? stepNumber,
},
})}
imgSrc={imgSrc}
isLoading={isLoading}
size={screenshotSize}

View file

@ -69,8 +69,6 @@ export const JourneyScreenshotDialog = ({
const { url, loading, stepName, maxSteps } = imageResult?.[imgPath] ?? {};
const imgSrc = stepNumber === initialStepNumber ? initialImgSrc ?? url : url;
const stepCountLabel = formatScreenshotStepsCount(stepNumber, maxSteps ?? stepNumber);
useEffect(() => {
if (isOpen) {
setStepNumber(initialStepNumber);
@ -122,7 +120,14 @@ export const JourneyScreenshotDialog = ({
>
<ModalBodyStyled css={{ display: 'flex' }}>
<ScreenshotImage
label={stepCountLabel}
label={i18n.translate('xpack.synthetics.monitor.screenshotImageLabel', {
defaultMessage: '"{stepName}", {stepNumber} of {totalSteps}',
values: {
stepName,
stepNumber,
totalSteps: maxSteps ?? stepNumber,
},
})}
imgSrc={imgSrc}
isLoading={!!loading}
animateLoading={false}
@ -172,7 +177,15 @@ export const JourneyScreenshotDialog = ({
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false} css={{ flexBasis: 'fit-content' }}>
<EuiText color={euiTheme.colors.text}>{stepCountLabel}</EuiText>
<EuiText color={euiTheme.colors.text}>
{i18n.translate('xpack.synthetics.monitor.stepOfSteps', {
defaultMessage: 'Step: {stepNumber} of {totalSteps}',
values: {
stepNumber,
totalSteps: maxSteps ?? stepNumber,
},
})}
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<EuiButtonEmpty
@ -241,15 +254,6 @@ export const getScreenshotUrl = ({
).replace('{stepIndex}', stepNumber.toString())}`;
};
export const formatScreenshotStepsCount = (stepNumber: number, totalSteps: number) =>
i18n.translate('xpack.synthetics.monitor.stepOfSteps', {
defaultMessage: 'Step: {stepNumber} of {totalSteps}',
values: {
stepNumber,
totalSteps,
},
});
const prevAriaLabel = i18n.translate('xpack.synthetics.monitor.step.previousStep', {
defaultMessage: 'Previous step',
});

View file

@ -69,7 +69,7 @@ describe('JourneyStepScreenshotContainer', () => {
<JourneyStepScreenshotContainer checkGroup={checkGroup} />
);
const img = getByAltText('First step');
const img = getByAltText('"First step", 1 of 2');
const euiPopoverMessage =
'You are in a dialog. Press Escape, or tap/click outside the dialog to close.';
expect(queryByText(euiPopoverMessage)).toBeNull();
@ -88,7 +88,7 @@ describe('JourneyStepScreenshotContainer', () => {
<JourneyStepScreenshotContainer checkGroup={checkGroup} />
);
const img = getByAltText('First step');
const img = getByAltText('"First step", 1 of 2');
await waitFor(() => img);
fireEvent.click(img);