From d6c5170fde63fca995152d2c234a02919186aa83 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 25 Jan 2021 11:53:01 -0500 Subject: [PATCH 01/15] Add desired hover functionality and a test. --- .../ping_list/columns/ping_timestamp.test.tsx | 23 +++++++ .../ping_list/columns/ping_timestamp.tsx | 60 ++++++++++++++----- 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.test.tsx index 1baeb8a69d34c..b50d8bea1500a 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.test.tsx @@ -5,6 +5,7 @@ */ import React from 'react'; +import { fireEvent, waitFor } from '@testing-library/react'; import { PingTimestamp } from './ping_timestamp'; import { mockReduxHooks } from '../../../../lib/helper/test_helpers'; import { render } from '../../../../lib/helper/rtl_helpers'; @@ -92,4 +93,26 @@ describe('Ping Timestamp component', () => { const { container } = render(); expect(container.querySelector('img')?.src).toBe(src); }); + + it('displays popover image when mouse enters img caption, and hides onLeave', async () => { + const src = 'http://sample.com/sampleImageSrc.png'; + jest.spyOn(observabilityPublic, 'useFetcher').mockReturnValue({ + status: FETCH_STATUS.SUCCESS, + data: { src }, + refetch: () => null, + }); + const { getByAltText, getByText, queryByAltText } = render( + + ); + const caption = getByText('Nov 26, 2020 10:28:56 AM'); + fireEvent.mouseEnter(caption); + + const altText = `A full-size screenshot for this journey step's thumbnail.`; + + await waitFor(() => getByAltText(altText)); + + fireEvent.mouseLeave(caption); + + await waitFor(() => expect(queryByAltText(altText)).toBeNull()); + }); }); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx index 2a35587a1960f..a388872ad249a 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx @@ -9,11 +9,13 @@ import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, + EuiLoadingSpinner, EuiImage, + EuiPopover, EuiSpacer, EuiText, - EuiLoadingSpinner, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import useIntersection from 'react-use/lib/useIntersection'; import moment from 'moment'; import styled from 'styled-components'; @@ -60,13 +62,21 @@ const StepDiv = styled.div` } `; +const POPOVER_IMG_HEIGHT = 360; +const POPOVER_IMG_WIDTH = 640; + interface Props { timestamp: string; ping: Ping; } +const nextAriaLabel = i18n.translate('xpack.uptime.synthetics.nextButton.ariaLabel', { + defaultMessage: 'Next', +}); + export const PingTimestamp = ({ timestamp, ping }: Props) => { const [stepNo, setStepNo] = useState(1); + const [isImagePopoverOpen, setIsImagePopoverOpen] = useState(false); const [stepImages, setStepImages] = useState([]); @@ -113,7 +123,7 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { setStepNo(stepNo - 1); }} iconType="arrowLeft" - aria-label="Next" + aria-label={nextAriaLabel} /> @@ -127,7 +137,7 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { setStepNo(stepNo + 1); }} iconType="arrowRight" - aria-label="Next" + aria-label={nextAriaLabel} /> @@ -140,17 +150,36 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { ); return ( - + setIsImagePopoverOpen(true)} + onMouseLeave={() => setIsImagePopoverOpen(false)} + ref={intersectionRef} + > {imgSrc ? ( - + + } + closePopover={() => setIsImagePopoverOpen(false)} + isOpen={isImagePopoverOpen} + > + + ) : ( @@ -167,6 +196,7 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { className="stepArrows" gutterSize="s" alignItems="center" + onMouseEnter={() => setIsImagePopoverOpen(true)} style={{ position: 'absolute', bottom: 0, left: 30 }} > @@ -178,7 +208,7 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { setStepNo(stepNo - 1); }} iconType="arrowLeft" - aria-label="Next" + aria-label={nextAriaLabel} /> @@ -190,7 +220,7 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { setStepNo(stepNo + 1); }} iconType="arrowRight" - aria-label="Next" + aria-label={nextAriaLabel} /> From 0b2341f8cdee109062e7c4c07ff39473143dab1a Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 25 Jan 2021 11:53:39 -0500 Subject: [PATCH 02/15] Switch render from img to EuiImage for step view. --- .../components/monitor/synthetics/step_screenshot_display.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_screenshot_display.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_screenshot_display.tsx index 3efcff196b55f..716e877c50943 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_screenshot_display.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_screenshot_display.tsx @@ -98,7 +98,7 @@ export const StepScreenshotDisplay: FC = ({ closePopover={() => setIsImagePopoverOpen(false)} isOpen={isImagePopoverOpen} > - { = ({ } ) } - src={imgSrc} + url={imgSrc} style={{ width: POPOVER_IMG_WIDTH, height: POPOVER_IMG_HEIGHT, objectFit: 'contain' }} /> From 0b4f4cdefa8d99970088e1822c8c4e516e19fa04 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 15:12:28 -0500 Subject: [PATCH 03/15] Create new module for ping_timestamp. Extract a function. Add a test. --- .../ping_list/columns/ping_timestamp/index.ts | 7 ++++ .../no_image_available.test.tsx | 17 ++++++++++ .../ping_timestamp/no_image_available.tsx | 29 +++++++++++++++++ .../ping_timestamp.test.tsx | 10 +++--- .../{ => ping_timestamp}/ping_timestamp.tsx | 32 ++++--------------- 5 files changed, 64 insertions(+), 31 deletions(-) create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/index.ts create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_available.test.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_available.tsx rename x-pack/plugins/uptime/public/components/monitor/ping_list/columns/{ => ping_timestamp}/ping_timestamp.test.tsx (92%) rename x-pack/plugins/uptime/public/components/monitor/ping_list/columns/{ => ping_timestamp}/ping_timestamp.tsx (86%) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/index.ts b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/index.ts new file mode 100644 index 0000000000000..db9c18e30cfc1 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { PingTimestamp } from './ping_timestamp'; diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_available.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_available.test.tsx new file mode 100644 index 0000000000000..17e679846a66d --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_available.test.tsx @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render } from '../../../../../lib/helper/rtl_helpers'; +import { NoImageAvailable } from './no_image_available'; + +describe('NoImageAvailable', () => { + it('renders expected text', () => { + const { getByText } = render(); + + expect(getByText('No image available')); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_available.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_available.tsx new file mode 100644 index 0000000000000..2498e07969f11 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_available.tsx @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import React from 'react'; +import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; + +const BorderedText = euiStyled(EuiText)` + width: 120px; + text-align: center; + border: 1px solid ${(props) => props.theme.eui.euiColorLightShade}; +`; + +export const NoImageAvailable = () => { + return ( + + + + + + ); +}; diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx similarity index 92% rename from x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.test.tsx rename to x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx index b50d8bea1500a..66f43a7f4a252 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx @@ -6,11 +6,11 @@ import React from 'react'; import { fireEvent, waitFor } from '@testing-library/react'; -import { PingTimestamp } from './ping_timestamp'; -import { mockReduxHooks } from '../../../../lib/helper/test_helpers'; -import { render } from '../../../../lib/helper/rtl_helpers'; -import { Ping } from '../../../../../common/runtime_types/ping'; -import * as observabilityPublic from '../../../../../../observability/public'; +import { PingTimestamp } from '.'; +import { mockReduxHooks } from '../../../../../lib/helper/test_helpers'; +import { render } from '../../../../../lib/helper/rtl_helpers'; +import { Ping } from '../../../../../../common/runtime_types/ping'; +import * as observabilityPublic from '../../../../../../../observability/public'; mockReduxHooks(); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx similarity index 86% rename from x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx rename to x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx index 5a1f1ea0ca03d..899f55bb4a380 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx @@ -19,13 +19,12 @@ import { i18n } from '@kbn/i18n'; import useIntersection from 'react-use/lib/useIntersection'; import moment from 'moment'; import styled from 'styled-components'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { Ping } from '../../../../../common/runtime_types/ping'; -import { getShortTimeStamp } from '../../../overview/monitor_list/columns/monitor_status_column'; -import { euiStyled } from '../../../../../../../../src/plugins/kibana_react/common'; -import { useFetcher, FETCH_STATUS } from '../../../../../../observability/public'; -import { getJourneyScreenshot } from '../../../../state/api/journey'; -import { UptimeSettingsContext } from '../../../../contexts'; +import { Ping } from '../../../../../../common/runtime_types/ping'; +import { getShortTimeStamp } from '../../../../overview/monitor_list/columns/monitor_status_column'; +import { useFetcher, FETCH_STATUS } from '../../../../../../../observability/public'; +import { getJourneyScreenshot } from '../../../../../state/api/journey'; +import { UptimeSettingsContext } from '../../../../../contexts'; +import { NoImageAvailable } from './no_image_available'; const StepImage = styled(EuiImage)` &&& { @@ -228,22 +227,3 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { ); }; - -const BorderedText = euiStyled(EuiText)` - width: 120px; - text-align: center; - border: 1px solid ${(props) => props.theme.eui.euiColorLightShade}; -`; - -export const NoImageAvailable = () => { - return ( - - - - - - ); -}; From 872c75f9e544e130942799759493369c955f7498 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 16:46:01 -0500 Subject: [PATCH 04/15] Extract nav buttons, translations. Add tests. --- .../ping_timestamp/nav_buttons.test.tsx | 87 +++++++++++++++++++ .../columns/ping_timestamp/nav_buttons.tsx | 58 +++++++++++++ .../columns/ping_timestamp/ping_timestamp.tsx | 44 ++-------- .../columns/ping_timestamp/translations.ts | 15 ++++ 4 files changed, 168 insertions(+), 36 deletions(-) create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/translations.ts diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx new file mode 100644 index 0000000000000..ecedf6daf1b8c --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { fireEvent, waitFor } from '@testing-library/react'; +import React from 'react'; +import { render } from '../../../../../lib/helper/rtl_helpers'; +import { NavButtons, NavButtonsProps } from './nav_buttons'; + +describe('NavButtons', () => { + let defaultProps: NavButtonsProps; + + beforeEach(() => { + defaultProps = { + maxSteps: 3, + stepNo: 2, + setStepNo: jest.fn(), + setIsImagePopoverOpen: jest.fn(), + }; + }); + + it('labels prev and next buttons', () => { + const { getByLabelText } = render(); + + expect(getByLabelText('Previous step')); + expect(getByLabelText('Next step')); + }); + + it('increments step number on next click', async () => { + const { getByLabelText } = render(); + + const nextButton = getByLabelText('Next step'); + + fireEvent.click(nextButton); + + await waitFor(() => { + expect(defaultProps.setStepNo).toHaveBeenCalledTimes(1); + expect(defaultProps.setStepNo).toHaveBeenCalledWith(3); + }); + }); + + it('decrements ste number on prev click', async () => { + const { getByLabelText } = render(); + + const nextButton = getByLabelText('Previous step'); + + fireEvent.click(nextButton); + + await waitFor(() => { + expect(defaultProps.setStepNo).toHaveBeenCalledTimes(1); + expect(defaultProps.setStepNo).toHaveBeenCalledWith(1); + }); + }); + + it('disables `next` button on final step', () => { + defaultProps.stepNo = 3; + + const { getByLabelText } = render(); + + expect(getByLabelText('Next step')).toHaveAttribute('disabled'); + expect(getByLabelText('Previous step')).not.toHaveAttribute('disabled'); + }); + + it('disables `prev` button on final step', () => { + defaultProps.stepNo = 1; + + const { getByLabelText } = render(); + + expect(getByLabelText('Next step')).not.toHaveAttribute('disabled'); + expect(getByLabelText('Previous step')).toHaveAttribute('disabled'); + }); + + it('opens popover when mouse enters', async () => { + const { getByLabelText } = render(); + + const nextButton = getByLabelText('Next step'); + + fireEvent.mouseEnter(nextButton); + + await waitFor(() => { + expect(defaultProps.setIsImagePopoverOpen).toHaveBeenCalledTimes(1); + expect(defaultProps.setIsImagePopoverOpen).toHaveBeenCalledWith(true); + }); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.tsx new file mode 100644 index 0000000000000..d62883a200f60 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiButtonIcon, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; +import React from 'react'; +import { nextAriaLabel, prevAriaLabel } from './translations'; + +export interface NavButtonsProps { + maxSteps?: number; + setIsImagePopoverOpen: React.Dispatch>; + setStepNo: React.Dispatch>; + stepNo: number; +} + +export const NavButtons: React.FC = ({ + maxSteps, + setIsImagePopoverOpen, + setStepNo, + stepNo, +}) => { + return ( + setIsImagePopoverOpen(true)} + style={{ position: 'absolute', bottom: 0, left: 30 }} + > + + { + setStepNo(stepNo - 1); + }} + iconType="arrowLeft" + aria-label={prevAriaLabel} + /> + + + { + setStepNo(stepNo + 1); + }} + iconType="arrowRight" + aria-label={nextAriaLabel} + /> + + + ); +}; diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx index 899f55bb4a380..e9532e949dd78 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx @@ -25,6 +25,8 @@ import { useFetcher, FETCH_STATUS } from '../../../../../../../observability/pub import { getJourneyScreenshot } from '../../../../../state/api/journey'; import { UptimeSettingsContext } from '../../../../../contexts'; import { NoImageAvailable } from './no_image_available'; +import { nextAriaLabel } from './translations'; +import { NavButtons } from './nav_buttons'; const StepImage = styled(EuiImage)` &&& { @@ -70,10 +72,6 @@ interface Props { ping: Ping; } -const nextAriaLabel = i18n.translate('xpack.uptime.synthetics.nextButton.ariaLabel', { - defaultMessage: 'Next', -}); - export const PingTimestamp = ({ timestamp, ping }: Props) => { const [stepNo, setStepNo] = useState(1); const [isImagePopoverOpen, setIsImagePopoverOpen] = useState(false); @@ -192,38 +190,12 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { {ImageCaption} )} - setIsImagePopoverOpen(true)} - style={{ position: 'absolute', bottom: 0, left: 30 }} - > - - { - setStepNo(stepNo - 1); - }} - iconType="arrowLeft" - aria-label={nextAriaLabel} - /> - - - { - setStepNo(stepNo + 1); - }} - iconType="arrowRight" - aria-label={nextAriaLabel} - /> - - + ); }; diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/translations.ts b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/translations.ts new file mode 100644 index 0000000000000..22c16c503028a --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/translations.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +export const prevAriaLabel = i18n.translate('xpack.uptime.synthetics.prevStepButton.airaLabel', { + defaultMessage: 'Previous step', +}); + +export const nextAriaLabel = i18n.translate('xpack.uptime.synthetics.nextStepButton.ariaLabel', { + defaultMessage: 'Next step', +}); From bd595f7b6442a1a88f403ce743fbdb876ef77164 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 17:09:51 -0500 Subject: [PATCH 05/15] Fix a typo. --- .../ping_list/columns/ping_timestamp/nav_buttons.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx index ecedf6daf1b8c..a904f3ac10c01 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx @@ -41,7 +41,7 @@ describe('NavButtons', () => { }); }); - it('decrements ste number on prev click', async () => { + it('decrements step number on prev click', async () => { const { getByLabelText } = render(); const nextButton = getByLabelText('Previous step'); From efbb7757a5d057e58e87c27b79d9707a28896b83 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 17:10:39 -0500 Subject: [PATCH 06/15] Extract caption to own file. Add tests. --- .../columns/ping_timestamp/ping_timestamp.tsx | 59 +++---------- .../step_image_caption.test.tsx | 88 +++++++++++++++++++ .../ping_timestamp/step_image_caption.tsx | 68 ++++++++++++++ 3 files changed, 166 insertions(+), 49 deletions(-) create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.test.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx index e9532e949dd78..70e2a3b90ee93 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx @@ -5,28 +5,17 @@ */ import React, { useContext, useEffect, useState } from 'react'; -import { - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiLoadingSpinner, - EuiImage, - EuiPopover, - EuiSpacer, - EuiText, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiImage, EuiPopover } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import useIntersection from 'react-use/lib/useIntersection'; -import moment from 'moment'; import styled from 'styled-components'; import { Ping } from '../../../../../../common/runtime_types/ping'; -import { getShortTimeStamp } from '../../../../overview/monitor_list/columns/monitor_status_column'; import { useFetcher, FETCH_STATUS } from '../../../../../../../observability/public'; import { getJourneyScreenshot } from '../../../../../state/api/journey'; import { UptimeSettingsContext } from '../../../../../contexts'; import { NoImageAvailable } from './no_image_available'; -import { nextAriaLabel } from './translations'; import { NavButtons } from './nav_buttons'; +import { StepImageCaption } from './step_image_caption'; const StepImage = styled(EuiImage)` &&& { @@ -109,42 +98,14 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { const captionContent = `Step:${stepNo} ${data?.stepName}`; const ImageCaption = ( - <> -
- {imgSrc && ( - - - { - setStepNo(stepNo - 1); - }} - iconType="arrowLeft" - aria-label={nextAriaLabel} - /> - - - {captionContent} - - - { - setStepNo(stepNo + 1); - }} - iconType="arrowRight" - aria-label={nextAriaLabel} - /> - - - )} -
- {/* TODO: Add link to details page once it's available */} - {getShortTimeStamp(moment(timestamp))} - - + ); return ( diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.test.tsx new file mode 100644 index 0000000000000..3ab90ec27bc90 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.test.tsx @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { fireEvent, waitFor } from '@testing-library/react'; +import React from 'react'; +import { render } from '../../../../../lib/helper/rtl_helpers'; +import { StepImageCaption, StepImageCaptionProps } from './step_image_caption'; + +describe('StepImageCaption', () => { + let defaultProps: StepImageCaptionProps; + + beforeEach(() => { + defaultProps = { + captionContent: 'test caption content', + imgSrc: 'http://sample.com/sampleImageSrc.png', + maxSteps: 3, + setStepNo: jest.fn(), + stepNo: 2, + timestamp: '2020-11-26T15:28:56.896Z', + }; + }); + + it('labels prev and next buttons', () => { + const { getByLabelText } = render(); + + expect(getByLabelText('Previous step')); + expect(getByLabelText('Next step')); + }); + + it('increments step number on next click', async () => { + const { getByLabelText } = render(); + + const nextButton = getByLabelText('Next step'); + + fireEvent.click(nextButton); + + await waitFor(() => { + expect(defaultProps.setStepNo).toHaveBeenCalledTimes(1); + expect(defaultProps.setStepNo).toHaveBeenCalledWith(3); + }); + }); + + it('decrements step number on prev click', async () => { + const { getByLabelText } = render(); + + const nextButton = getByLabelText('Previous step'); + + fireEvent.click(nextButton); + + await waitFor(() => { + expect(defaultProps.setStepNo).toHaveBeenCalledTimes(1); + expect(defaultProps.setStepNo).toHaveBeenCalledWith(1); + }); + }); + + it('disables `next` button on final step', () => { + defaultProps.stepNo = 3; + + const { getByLabelText } = render(); + + expect(getByLabelText('Next step')).toHaveAttribute('disabled'); + expect(getByLabelText('Previous step')).not.toHaveAttribute('disabled'); + }); + + it('disables `prev` button on final step', () => { + defaultProps.stepNo = 1; + + const { getByLabelText } = render(); + + expect(getByLabelText('Next step')).not.toHaveAttribute('disabled'); + expect(getByLabelText('Previous step')).toHaveAttribute('disabled'); + }); + + it('renders a timestamp', () => { + const { getByText } = render(); + + getByText('Nov 26, 2020 10:28:56 AM'); + }); + + it('renders caption content', () => { + const { getByText } = render(); + + getByText('test caption content'); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx new file mode 100644 index 0000000000000..281e41874dd8d --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; +import React from 'react'; +import moment from 'moment'; +import { nextAriaLabel, prevAriaLabel } from './translations'; +import { getShortTimeStamp } from '../../../../overview/monitor_list/columns/monitor_status_column'; + +export interface StepImageCaptionProps { + captionContent: string; + imgSrc?: string; + maxSteps?: number; + setStepNo: React.Dispatch>; + stepNo: number; + timestamp: string; +} + +export const StepImageCaption: React.FC = ({ + captionContent, + imgSrc, + maxSteps, + setStepNo, + stepNo, + timestamp, +}) => { + return ( + <> +
+ {imgSrc && ( + + + { + setStepNo(stepNo - 1); + }} + iconType="arrowLeft" + aria-label={prevAriaLabel} + /> + + + {captionContent} + + + { + setStepNo(stepNo + 1); + }} + iconType="arrowRight" + aria-label={nextAriaLabel} + /> + + + )} +
+ {/* TODO: Add link to details page once it's available */} + {getShortTimeStamp(moment(timestamp))} + + + ); +}; From 519565eae3f889c34af94d3f3d6f4de76450179a Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 17:29:59 -0500 Subject: [PATCH 07/15] Extract no image display to dedicated file. Add aria label. Add tests. --- .../ping_timestamp/no_image_display.test.tsx | 44 +++++++++++++++++++ .../ping_timestamp/no_image_display.tsx | 39 ++++++++++++++++ .../columns/ping_timestamp/ping_timestamp.tsx | 22 +++------- .../columns/ping_timestamp/translations.ts | 7 +++ 4 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_display.test.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_display.tsx diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_display.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_display.test.tsx new file mode 100644 index 0000000000000..24080e2f4061d --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_display.test.tsx @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render } from '../../../../../lib/helper/rtl_helpers'; +import { NoImageDisplay, NoImageDisplayProps } from './no_image_display'; +import { imageLoadingSpinnerAriaLabel } from './translations'; + +describe('NoImageDisplay', () => { + let defaultProps: NoImageDisplayProps; + beforeEach(() => { + defaultProps = { + imageCaption:
test caption
, + isLoading: false, + isPending: false, + }; + }); + + it('renders a loading spinner for loading state', () => { + defaultProps.isLoading = true; + const { getByText, getByLabelText } = render(); + + expect(getByLabelText(imageLoadingSpinnerAriaLabel)); + expect(getByText('test caption')); + }); + + it('renders a loading spinner for pending state', () => { + defaultProps.isPending = true; + const { getByText, getByLabelText } = render(); + + expect(getByLabelText(imageLoadingSpinnerAriaLabel)); + expect(getByText('test caption')); + }); + + it('renders no image available when not loading or pending', () => { + const { getByText } = render(); + + expect(getByText('No image available')); + expect(getByText('test caption')); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_display.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_display.tsx new file mode 100644 index 0000000000000..185f488d5acd2 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/no_image_display.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiFlexItem, EuiFlexGroup, EuiLoadingSpinner } from '@elastic/eui'; +import React from 'react'; +import { NoImageAvailable } from './no_image_available'; +import { imageLoadingSpinnerAriaLabel } from './translations'; + +export interface NoImageDisplayProps { + imageCaption: JSX.Element; + isLoading: boolean; + isPending: boolean; +} + +export const NoImageDisplay: React.FC = ({ + imageCaption, + isLoading, + isPending, +}) => { + return ( + + + {isLoading || isPending ? ( + + ) : ( + + )} + + {imageCaption} + + ); +}; diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx index 70e2a3b90ee93..fc1114223838e 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx @@ -5,7 +5,7 @@ */ import React, { useContext, useEffect, useState } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiImage, EuiPopover } from '@elastic/eui'; +import { EuiImage, EuiPopover } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import useIntersection from 'react-use/lib/useIntersection'; import styled from 'styled-components'; @@ -13,8 +13,8 @@ import { Ping } from '../../../../../../common/runtime_types/ping'; import { useFetcher, FETCH_STATUS } from '../../../../../../../observability/public'; import { getJourneyScreenshot } from '../../../../../state/api/journey'; import { UptimeSettingsContext } from '../../../../../contexts'; -import { NoImageAvailable } from './no_image_available'; import { NavButtons } from './nav_buttons'; +import { NoImageDisplay } from './no_image_display'; import { StepImageCaption } from './step_image_caption'; const StepImage = styled(EuiImage)` @@ -92,9 +92,6 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { const imgSrc = stepImages[stepNo] || data?.src; - const isLoading = status === FETCH_STATUS.LOADING; - const isPending = status === FETCH_STATUS.PENDING; - const captionContent = `Step:${stepNo} ${data?.stepName}`; const ImageCaption = ( @@ -140,16 +137,11 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { /> ) : ( - - - {isLoading || isPending ? ( - - ) : ( - - )} - - {ImageCaption} - + )} Date: Tue, 26 Jan 2021 23:25:51 -0500 Subject: [PATCH 08/15] Make import path more explicit. --- .../ping_list/columns/ping_timestamp/ping_timestamp.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx index 66f43a7f4a252..4d1cf7ffbd7c9 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { fireEvent, waitFor } from '@testing-library/react'; -import { PingTimestamp } from '.'; +import { PingTimestamp } from './ping_timestamp'; import { mockReduxHooks } from '../../../../../lib/helper/test_helpers'; import { render } from '../../../../../lib/helper/rtl_helpers'; import { Ping } from '../../../../../../common/runtime_types/ping'; From b518415c9159594c2d814fdf79fee9e3a97e8638 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 23:26:26 -0500 Subject: [PATCH 09/15] Move step image popover to dedicated file. Add tests. --- .../columns/ping_timestamp/ping_timestamp.tsx | 49 ++------------ .../step_image_popover.test.tsx | 60 +++++++++++++++++ .../ping_timestamp/step_image_popover.tsx | 65 +++++++++++++++++++ 3 files changed, 132 insertions(+), 42 deletions(-) create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.test.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.tsx diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx index fc1114223838e..ee3006b5a3607 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx @@ -5,8 +5,6 @@ */ import React, { useContext, useEffect, useState } from 'react'; -import { EuiImage, EuiPopover } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import useIntersection from 'react-use/lib/useIntersection'; import styled from 'styled-components'; import { Ping } from '../../../../../../common/runtime_types/ping'; @@ -16,19 +14,7 @@ import { UptimeSettingsContext } from '../../../../../contexts'; import { NavButtons } from './nav_buttons'; import { NoImageDisplay } from './no_image_display'; import { StepImageCaption } from './step_image_caption'; - -const StepImage = styled(EuiImage)` - &&& { - display: flex; - figcaption { - white-space: nowrap; - align-self: center; - margin-left: 8px; - margin-top: 8px; - text-decoration: none !important; - } - } -`; +import { StepImagePopover } from './step_image_popover'; const StepDiv = styled.div` figure.euiImage { @@ -53,9 +39,6 @@ const StepDiv = styled.div` } `; -const POPOVER_IMG_HEIGHT = 360; -const POPOVER_IMG_WIDTH = 640; - interface Props { timestamp: string; ping: Ping; @@ -112,30 +95,12 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { ref={intersectionRef} > {imgSrc ? ( - - } - closePopover={() => setIsImagePopoverOpen(false)} - isOpen={isImagePopoverOpen} - > - - + ) : ( { + let defaultProps: StepImagePopoverProps; + + beforeEach(() => { + defaultProps = { + captionContent: 'test caption', + imageCaption:
test caption element
, + imgSrc: 'http://sample.com/sampleImageSrc.png', + isImagePopoverOpen: false, + }; + }); + + it('opens popover when click on img caption, and hides when popover is closed', async () => { + const { getByAltText, getByLabelText, queryByLabelText } = render( + + ); + + const closeFullScreenButton = 'Close full screen test caption image'; + + expect(queryByLabelText(closeFullScreenButton)).toBeNull(); + + const caption = getByAltText('test caption'); + fireEvent.click(caption); + + await waitFor(() => { + const closeButton = getByLabelText(closeFullScreenButton); + fireEvent.click(closeButton); + }); + + await waitFor(() => { + expect(queryByLabelText(closeFullScreenButton)).toBeNull(); + }); + }); + + it('shows the popover when `isOpen` is true', () => { + defaultProps.isImagePopoverOpen = true; + + const { getByAltText } = render(); + + expect(getByAltText(`A larger version of the screenshot for this journey step's thumbnail.`)); + }); + + it('renders caption content', () => { + const { getByRole } = render(); + const image = getByRole('img'); + expect(image).toHaveAttribute('alt', 'test caption'); + expect(image).toHaveAttribute('src', 'http://sample.com/sampleImageSrc.png'); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.tsx new file mode 100644 index 0000000000000..d49256388831f --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.tsx @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiImage, EuiPopover } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import styled from 'styled-components'; + +const POPOVER_IMG_HEIGHT = 360; +const POPOVER_IMG_WIDTH = 640; + +const StepImage = styled(EuiImage)` + &&& { + display: flex; + figcaption { + white-space: nowrap; + align-self: center; + margin-left: 8px; + margin-top: 8px; + text-decoration: none !important; + } + } +`; +export interface StepImagePopoverProps { + captionContent: string; + imageCaption: JSX.Element; + imgSrc: string; + isImagePopoverOpen: boolean; +} + +export const StepImagePopover: React.FC = ({ + captionContent, + imageCaption, + imgSrc, + isImagePopoverOpen, +}) => { + return ( + + } + isOpen={isImagePopoverOpen} + > + + + ); +}; From 1a14d65457447cab4419cdf9ad1070fb39ab219a Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 23:34:17 -0500 Subject: [PATCH 10/15] Clean up inline code in timestamp component. --- .../columns/ping_timestamp/ping_timestamp.tsx | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx index ee3006b5a3607..858187bd9aca7 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import React, { useContext, useEffect, useState } from 'react'; import useIntersection from 'react-use/lib/useIntersection'; import styled from 'styled-components'; @@ -45,7 +46,7 @@ interface Props { } export const PingTimestamp = ({ timestamp, ping }: Props) => { - const [stepNo, setStepNo] = useState(1); + const [stepNumber, setStepNumber] = useState(1); const [isImagePopoverOpen, setIsImagePopoverOpen] = useState(false); const [stepImages, setStepImages] = useState([]); @@ -54,7 +55,7 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { const { basePath } = useContext(UptimeSettingsContext); - const imgPath = basePath + `/api/uptime/journey/screenshot/${ping.monitor.check_group}/${stepNo}`; + const imgPath = `${basePath}/api/uptime/journey/screenshot/${ping.monitor.check_group}/${stepNumber}`; const intersection = useIntersection(intersectionRef, { root: null, @@ -63,9 +64,9 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { }); const { data, status } = useFetcher(() => { - if (intersection && intersection.intersectionRatio === 1 && !stepImages[stepNo - 1]) + if (intersection && intersection.intersectionRatio === 1 && !stepImages[stepNumber - 1]) return getJourneyScreenshot(imgPath); - }, [intersection?.intersectionRatio, stepNo]); + }, [intersection?.intersectionRatio, stepNumber]); useEffect(() => { if (data) { @@ -73,17 +74,23 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { } }, [data]); - const imgSrc = stepImages[stepNo] || data?.src; + const imgSrc = stepImages[stepNumber] || data?.src; - const captionContent = `Step:${stepNo} ${data?.stepName}`; + const captionContent = i18n.translate('xpack.uptime.synthetics.pingTimestamp.captionContent', { + defaultMessage: 'Step: {stepNumber} {stepName}', + values: { + stepNumber, + stepName: data?.stepName, + }, + }); const ImageCaption = ( ); @@ -111,8 +118,8 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { ); From d519c2601597723ee26d727e1e8a59fc1740844e Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 23:38:25 -0500 Subject: [PATCH 11/15] Explicit var names. --- .../columns/ping_timestamp/nav_buttons.tsx | 78 +++++++++---------- .../columns/ping_timestamp/ping_timestamp.tsx | 8 +- .../ping_timestamp/step_image_caption.tsx | 16 ++-- 3 files changed, 50 insertions(+), 52 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.tsx index d62883a200f60..1c24caba6a917 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.tsx @@ -11,48 +11,46 @@ import { nextAriaLabel, prevAriaLabel } from './translations'; export interface NavButtonsProps { maxSteps?: number; setIsImagePopoverOpen: React.Dispatch>; - setStepNo: React.Dispatch>; - stepNo: number; + setStepNumber: React.Dispatch>; + stepNumber: number; } export const NavButtons: React.FC = ({ maxSteps, setIsImagePopoverOpen, - setStepNo, - stepNo, -}) => { - return ( - setIsImagePopoverOpen(true)} - style={{ position: 'absolute', bottom: 0, left: 30 }} - > - - { - setStepNo(stepNo - 1); - }} - iconType="arrowLeft" - aria-label={prevAriaLabel} - /> - - - { - setStepNo(stepNo + 1); - }} - iconType="arrowRight" - aria-label={nextAriaLabel} - /> - - - ); -}; + setStepNumber, + stepNumber, +}) => ( + setIsImagePopoverOpen(true)} + style={{ position: 'absolute', bottom: 0, left: 30 }} + > + + { + setStepNumber(stepNumber - 1); + }} + iconType="arrowLeft" + aria-label={prevAriaLabel} + /> + + + { + setStepNumber(stepNumber + 1); + }} + iconType="arrowRight" + aria-label={nextAriaLabel} + /> + + +); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx index 858187bd9aca7..86ccd91331098 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx @@ -89,8 +89,8 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { captionContent={captionContent} imgSrc={imgSrc} maxSteps={data?.maxSteps} - setStepNo={setStepNumber} - stepNo={stepNumber} + setStepNumber={setStepNumber} + stepNumber={stepNumber} timestamp={timestamp} /> ); @@ -118,8 +118,8 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { ); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx index 281e41874dd8d..c5da98bacc431 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx @@ -14,8 +14,8 @@ export interface StepImageCaptionProps { captionContent: string; imgSrc?: string; maxSteps?: number; - setStepNo: React.Dispatch>; - stepNo: number; + setStepNumber: React.Dispatch>; + stepNumber: number; timestamp: string; } @@ -23,8 +23,8 @@ export const StepImageCaption: React.FC = ({ captionContent, imgSrc, maxSteps, - setStepNo, - stepNo, + setStepNumber, + stepNumber, timestamp, }) => { return ( @@ -34,10 +34,10 @@ export const StepImageCaption: React.FC = ({ { - setStepNo(stepNo - 1); + setStepNumber(stepNumber - 1); }} iconType="arrowLeft" aria-label={prevAriaLabel} @@ -48,10 +48,10 @@ export const StepImageCaption: React.FC = ({ { - setStepNo(stepNo + 1); + setStepNumber(stepNumber + 1); }} iconType="arrowRight" aria-label={nextAriaLabel} From 73cf9adb81d0eca895ec2c3cffcf3c0b928e777c Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 23:41:15 -0500 Subject: [PATCH 12/15] Simplicity. --- .../ping_timestamp/step_image_popover.tsx | 48 +++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.tsx index d49256388831f..b44b2786b7788 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.tsx @@ -36,30 +36,28 @@ export const StepImagePopover: React.FC = ({ imageCaption, imgSrc, isImagePopoverOpen, -}) => { - return ( - - } - isOpen={isImagePopoverOpen} - > - ( + - - ); -}; + } + isOpen={isImagePopoverOpen} + > + + +); From 349db316987a175e2c3f7303e627b565864630c7 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Jan 2021 23:56:58 -0500 Subject: [PATCH 13/15] Fix refactoring issues in test files. --- .../columns/ping_timestamp/nav_buttons.test.tsx | 17 +++++++++-------- .../ping_timestamp/ping_timestamp.test.tsx | 6 +++--- .../ping_timestamp/step_image_caption.test.tsx | 17 +++++++++-------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx index a904f3ac10c01..c8acfd48a9913 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/nav_buttons.test.tsx @@ -15,8 +15,8 @@ describe('NavButtons', () => { beforeEach(() => { defaultProps = { maxSteps: 3, - stepNo: 2, - setStepNo: jest.fn(), + stepNumber: 2, + setStepNumber: jest.fn(), setIsImagePopoverOpen: jest.fn(), }; }); @@ -36,8 +36,8 @@ describe('NavButtons', () => { fireEvent.click(nextButton); await waitFor(() => { - expect(defaultProps.setStepNo).toHaveBeenCalledTimes(1); - expect(defaultProps.setStepNo).toHaveBeenCalledWith(3); + expect(defaultProps.setStepNumber).toHaveBeenCalledTimes(1); + expect(defaultProps.setStepNumber).toHaveBeenCalledWith(3); }); }); @@ -49,22 +49,23 @@ describe('NavButtons', () => { fireEvent.click(nextButton); await waitFor(() => { - expect(defaultProps.setStepNo).toHaveBeenCalledTimes(1); - expect(defaultProps.setStepNo).toHaveBeenCalledWith(1); + expect(defaultProps.setStepNumber).toHaveBeenCalledTimes(1); + expect(defaultProps.setStepNumber).toHaveBeenCalledWith(1); }); }); it('disables `next` button on final step', () => { - defaultProps.stepNo = 3; + defaultProps.stepNumber = 3; const { getByLabelText } = render(); + // getByLabelText('Next step'); expect(getByLabelText('Next step')).toHaveAttribute('disabled'); expect(getByLabelText('Previous step')).not.toHaveAttribute('disabled'); }); it('disables `prev` button on final step', () => { - defaultProps.stepNo = 1; + defaultProps.stepNumber = 1; const { getByLabelText } = render(); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx index 4d1cf7ffbd7c9..a934f6fa39b22 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.test.tsx @@ -14,8 +14,8 @@ import * as observabilityPublic from '../../../../../../../observability/public' mockReduxHooks(); -jest.mock('../../../../../../observability/public', () => { - const originalModule = jest.requireActual('../../../../../../observability/public'); +jest.mock('../../../../../../../observability/public', () => { + const originalModule = jest.requireActual('../../../../../../../observability/public'); return { ...originalModule, @@ -107,7 +107,7 @@ describe('Ping Timestamp component', () => { const caption = getByText('Nov 26, 2020 10:28:56 AM'); fireEvent.mouseEnter(caption); - const altText = `A full-size screenshot for this journey step's thumbnail.`; + const altText = `A larger version of the screenshot for this journey step's thumbnail.`; await waitFor(() => getByAltText(altText)); diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.test.tsx index 3ab90ec27bc90..ef1d0cb388a18 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.test.tsx @@ -17,8 +17,8 @@ describe('StepImageCaption', () => { captionContent: 'test caption content', imgSrc: 'http://sample.com/sampleImageSrc.png', maxSteps: 3, - setStepNo: jest.fn(), - stepNo: 2, + setStepNumber: jest.fn(), + stepNumber: 2, timestamp: '2020-11-26T15:28:56.896Z', }; }); @@ -38,8 +38,8 @@ describe('StepImageCaption', () => { fireEvent.click(nextButton); await waitFor(() => { - expect(defaultProps.setStepNo).toHaveBeenCalledTimes(1); - expect(defaultProps.setStepNo).toHaveBeenCalledWith(3); + expect(defaultProps.setStepNumber).toHaveBeenCalledTimes(1); + expect(defaultProps.setStepNumber).toHaveBeenCalledWith(3); }); }); @@ -51,22 +51,23 @@ describe('StepImageCaption', () => { fireEvent.click(nextButton); await waitFor(() => { - expect(defaultProps.setStepNo).toHaveBeenCalledTimes(1); - expect(defaultProps.setStepNo).toHaveBeenCalledWith(1); + expect(defaultProps.setStepNumber).toHaveBeenCalledTimes(1); + expect(defaultProps.setStepNumber).toHaveBeenCalledWith(1); }); }); it('disables `next` button on final step', () => { - defaultProps.stepNo = 3; + defaultProps.stepNumber = 3; const { getByLabelText } = render(); + // getByLabelText('Next step'); expect(getByLabelText('Next step')).toHaveAttribute('disabled'); expect(getByLabelText('Previous step')).not.toHaveAttribute('disabled'); }); it('disables `prev` button on final step', () => { - defaultProps.stepNo = 1; + defaultProps.stepNumber = 1; const { getByLabelText } = render(); From ad1ebbd073d78b0ad3c27f47c165c06bdfca3aa8 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 1 Feb 2021 11:50:22 -0500 Subject: [PATCH 14/15] Move translations to central file. --- .../columns/ping_timestamp/ping_timestamp.tsx | 10 ++-------- .../columns/ping_timestamp/step_image_popover.tsx | 6 ++---- .../columns/ping_timestamp/translations.ts | 13 +++++++++++++ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx index 86ccd91331098..6d605f25f6f68 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/ping_timestamp.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { i18n } from '@kbn/i18n'; import React, { useContext, useEffect, useState } from 'react'; import useIntersection from 'react-use/lib/useIntersection'; import styled from 'styled-components'; @@ -16,6 +15,7 @@ import { NavButtons } from './nav_buttons'; import { NoImageDisplay } from './no_image_display'; import { StepImageCaption } from './step_image_caption'; import { StepImagePopover } from './step_image_popover'; +import { formatCaptionContent } from './translations'; const StepDiv = styled.div` figure.euiImage { @@ -76,13 +76,7 @@ export const PingTimestamp = ({ timestamp, ping }: Props) => { const imgSrc = stepImages[stepNumber] || data?.src; - const captionContent = i18n.translate('xpack.uptime.synthetics.pingTimestamp.captionContent', { - defaultMessage: 'Step: {stepNumber} {stepName}', - values: { - stepNumber, - stepName: data?.stepName, - }, - }); + const captionContent = formatCaptionContent(stepNumber, data?.maxSteps); const ImageCaption = ( = ({ isOpen={isImagePopoverOpen} > diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/translations.ts b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/translations.ts index 6e526f42071ec..ad49143a68057 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/translations.ts +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/translations.ts @@ -20,3 +20,16 @@ export const imageLoadingSpinnerAriaLabel = i18n.translate( defaultMessage: 'An animated spinner indicating the image is loading', } ); + +export const fullSizeImageAlt = i18n.translate('xpack.uptime.synthetics.thumbnail.fullSize.alt', { + defaultMessage: `A larger version of the screenshot for this journey step's thumbnail.`, +}); + +export const formatCaptionContent = (stepNumber: number, stepName?: number) => + i18n.translate('xpack.uptime.synthetics.pingTimestamp.captionContent', { + defaultMessage: 'Step: {stepNumber} {stepName}', + values: { + stepNumber, + stepName, + }, + }); From 0dfd62df257a0eecb5bab8c786c27a8b81153761 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 1 Feb 2021 11:55:46 -0500 Subject: [PATCH 15/15] Rename test for better accuracy. --- .../columns/ping_timestamp/step_image_popover.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.test.tsx index baa5dfb9bd11f..184794c1465aa 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_timestamp/step_image_popover.test.tsx @@ -21,7 +21,7 @@ describe('StepImagePopover', () => { }; }); - it('opens popover when click on img caption, and hides when popover is closed', async () => { + it('opens displays full-size image on click, hides after close is closed', async () => { const { getByAltText, getByLabelText, queryByLabelText } = render( );