mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Uptime] Add tests for new waterfall components (#115856)
* Add `aria-label`s for icon and icon buttons. * Fix typo. * Create test wrapper to help with testing context-reliant components. * Create tests for `WaterfallMarkerIcon` component. * Create tests for `WaterfallMarkerTrend` component. * Simplify test wrapper. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
9c92ac881a
commit
063e30b6a8
5 changed files with 266 additions and 5 deletions
|
@ -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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { fireEvent, waitFor } from '@testing-library/dom';
|
||||
import { render } from '../../../../../lib/helper/rtl_helpers';
|
||||
import { WaterfallMarkerIcon } from './waterfall_marker_icon';
|
||||
import { TestWrapper } from './waterfall_marker_test_helper';
|
||||
|
||||
describe('<WaterfallMarkerIcon />', () => {
|
||||
it('renders a dot icon when `field` is an empty string', () => {
|
||||
const { getByLabelText } = render(<WaterfallMarkerIcon field="" label="" />);
|
||||
expect(getByLabelText('An icon indicating that this marker has no field associated with it'));
|
||||
});
|
||||
|
||||
it('renders an embeddable when opened', async () => {
|
||||
const { getByLabelText, getByText } = render(
|
||||
<TestWrapper
|
||||
activeStep={{
|
||||
'@timestamp': '123',
|
||||
_id: 'id',
|
||||
synthetics: {
|
||||
type: 'step/end',
|
||||
step: {
|
||||
index: 0,
|
||||
name: 'test-name',
|
||||
},
|
||||
},
|
||||
monitor: {
|
||||
id: 'mon-id',
|
||||
check_group: 'group',
|
||||
timespan: {
|
||||
gte: '1988-10-09T12:00:00.000Z',
|
||||
lt: '1988-10-10T12:00:00.000Z',
|
||||
},
|
||||
},
|
||||
}}
|
||||
basePath="xyz"
|
||||
>
|
||||
<WaterfallMarkerIcon field="testField" label="Test Field" />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const expandButton = getByLabelText(
|
||||
'Use this icon button to show metrics for this annotation marker.'
|
||||
);
|
||||
|
||||
fireEvent.click(expandButton);
|
||||
|
||||
await waitFor(() => {
|
||||
getByText('Test Field');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiButtonIcon, EuiIcon, EuiPopover } from '@elastic/eui';
|
||||
import { WaterfallMarkerTrend } from './waterfall_marker_trend';
|
||||
|
||||
|
@ -13,7 +14,15 @@ export function WaterfallMarkerIcon({ field, label }: { field: string; label: st
|
|||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
if (!field) {
|
||||
return <EuiIcon type="dot" size="l" />;
|
||||
return (
|
||||
<EuiIcon
|
||||
aria-label={i18n.translate('xpack.uptime.synthetics.markers.noFieldIcon.label', {
|
||||
defaultMessage: 'An icon indicating that this marker has no field associated with it',
|
||||
})}
|
||||
type="dot"
|
||||
size="l"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -25,6 +34,9 @@ export function WaterfallMarkerIcon({ field, label }: { field: string; label: st
|
|||
zIndex={100}
|
||||
button={
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate('xpack.uptime.synthetics.markers.openEmbeddableButton.label', {
|
||||
defaultMessage: 'Use this icon button to show metrics for this annotation marker.',
|
||||
})}
|
||||
iconType="dot"
|
||||
iconSize="l"
|
||||
color="text"
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { UptimeStartupPluginsContext } from '../../../../../contexts';
|
||||
import { WaterfallContext } from '../context/waterfall_chart';
|
||||
import { JourneyStep } from '../../../../../../common/runtime_types';
|
||||
|
||||
const EmbeddableMock = ({
|
||||
title,
|
||||
appendTitle,
|
||||
reportType,
|
||||
attributes,
|
||||
}: {
|
||||
title: string;
|
||||
appendTitle: JSX.Element | undefined;
|
||||
reportType: string;
|
||||
attributes: unknown;
|
||||
axisTitlesVisibility: { x: boolean; yLeft: boolean; yRight: boolean };
|
||||
legendIsVisible: boolean;
|
||||
}) => (
|
||||
<div>
|
||||
<h1>{title}</h1>
|
||||
<div aria-label="append title">{appendTitle}</div>
|
||||
<div>{reportType}</div>
|
||||
<div aria-label="attributes">{JSON.stringify(attributes)}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const TestWrapper = ({
|
||||
basePath,
|
||||
activeStep,
|
||||
children,
|
||||
}: {
|
||||
basePath: string;
|
||||
activeStep?: JourneyStep;
|
||||
children: JSX.Element;
|
||||
}) => (
|
||||
<UptimeStartupPluginsContext.Provider
|
||||
value={{
|
||||
// @ts-expect-error incomplete implementation for test purposes
|
||||
observability: {
|
||||
ExploratoryViewEmbeddable: jest.fn((props: any) => <EmbeddableMock {...props} />),
|
||||
},
|
||||
}}
|
||||
>
|
||||
<WaterfallContext.Provider
|
||||
value={{
|
||||
activeStep,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WaterfallContext.Provider>
|
||||
</UptimeStartupPluginsContext.Provider>
|
||||
);
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { render } from '../../../../../lib/helper/rtl_helpers';
|
||||
import { WaterfallMarkerTrend } from './waterfall_marker_trend';
|
||||
import moment from 'moment';
|
||||
import { JourneyStep } from '../../../../../../common/runtime_types';
|
||||
import { TestWrapper } from './waterfall_marker_test_helper';
|
||||
|
||||
describe('<WaterfallMarkerTrend />', () => {
|
||||
const mockDiff = jest.fn();
|
||||
|
||||
jest.spyOn(moment.prototype, 'diff').mockImplementation(mockDiff);
|
||||
|
||||
let activeStep: JourneyStep | undefined;
|
||||
beforeEach(() => {
|
||||
activeStep = {
|
||||
'@timestamp': '123',
|
||||
_id: 'id',
|
||||
synthetics: {
|
||||
type: 'step/end',
|
||||
step: {
|
||||
index: 0,
|
||||
name: 'test-name',
|
||||
},
|
||||
},
|
||||
monitor: {
|
||||
id: 'mon-id',
|
||||
check_group: 'group',
|
||||
timespan: {
|
||||
gte: '1988-10-09T12:00:00.000Z',
|
||||
lt: '1988-10-10T12:00:00.000Z',
|
||||
},
|
||||
},
|
||||
};
|
||||
mockDiff.mockReturnValue(0);
|
||||
});
|
||||
|
||||
const BASE_PATH = 'xyz';
|
||||
|
||||
it('supplies props', () => {
|
||||
const { getByLabelText, getByText, getByRole } = render(
|
||||
<TestWrapper activeStep={activeStep} basePath={BASE_PATH}>
|
||||
<WaterfallMarkerTrend title="test title" field="field" />
|
||||
</TestWrapper>,
|
||||
{
|
||||
core: {
|
||||
http: {
|
||||
// @ts-expect-error incomplete implementation for testing purposes
|
||||
basePath: {
|
||||
get: () => BASE_PATH,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
const heading = getByRole('heading');
|
||||
expect(heading.innerHTML).toEqual('test title');
|
||||
expect(getByLabelText('append title').innerHTML.indexOf(BASE_PATH)).not.toBe(-1);
|
||||
expect(getByText('kpi-over-time'));
|
||||
expect(getByLabelText('attributes').innerHTML.indexOf('0s')).not.toBe(-1);
|
||||
expect(getByLabelText('attributes').innerHTML.indexOf('0h')).toBe(-1);
|
||||
expect(getByLabelText('attributes').innerHTML.indexOf('0m')).toBe(-1);
|
||||
expect(getByLabelText('attributes').innerHTML.indexOf('0d')).toBe(-1);
|
||||
});
|
||||
|
||||
it('handles days', () => {
|
||||
mockDiff.mockReturnValue(10);
|
||||
const { getByLabelText } = render(
|
||||
<TestWrapper activeStep={activeStep} basePath={BASE_PATH}>
|
||||
<WaterfallMarkerTrend title="test title" field="field" />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const attributesText = getByLabelText('attributes').innerHTML;
|
||||
|
||||
expect(attributesText.indexOf('480s')).toBe(-1);
|
||||
expect(attributesText.indexOf('480h')).toBe(-1);
|
||||
expect(attributesText.indexOf('480m')).toBe(-1);
|
||||
expect(attributesText.indexOf('480d')).not.toBe(-1);
|
||||
});
|
||||
|
||||
it('handles hours', () => {
|
||||
mockDiff.mockReturnValueOnce(0);
|
||||
mockDiff.mockReturnValue(10);
|
||||
const { getByLabelText } = render(
|
||||
<TestWrapper activeStep={activeStep} basePath={BASE_PATH}>
|
||||
<WaterfallMarkerTrend title="test title" field="field" />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const attributesText = getByLabelText('attributes').innerHTML;
|
||||
|
||||
expect(attributesText.indexOf('480s')).toBe(-1);
|
||||
expect(attributesText.indexOf('480h')).not.toBe(-1);
|
||||
expect(attributesText.indexOf('480m')).toBe(-1);
|
||||
expect(attributesText.indexOf('480d')).toBe(-1);
|
||||
});
|
||||
|
||||
it('handles minutes', () => {
|
||||
mockDiff.mockReturnValueOnce(0);
|
||||
mockDiff.mockReturnValueOnce(0);
|
||||
mockDiff.mockReturnValue(10);
|
||||
const { getByLabelText } = render(
|
||||
<TestWrapper activeStep={activeStep} basePath={BASE_PATH}>
|
||||
<WaterfallMarkerTrend title="test title" field="field" />
|
||||
</TestWrapper>
|
||||
);
|
||||
|
||||
const attributesText = getByLabelText('attributes').innerHTML;
|
||||
|
||||
expect(attributesText.indexOf('480s')).toBe(-1);
|
||||
expect(attributesText.indexOf('480h')).toBe(-1);
|
||||
expect(attributesText.indexOf('480m')).not.toBe(-1);
|
||||
expect(attributesText.indexOf('480d')).toBe(-1);
|
||||
});
|
||||
|
||||
it('returns null for missing active step', () => {
|
||||
activeStep = undefined;
|
||||
const { container } = render(
|
||||
<TestWrapper activeStep={activeStep} basePath={BASE_PATH}>
|
||||
<WaterfallMarkerTrend title="test title" field="field" />
|
||||
</TestWrapper>
|
||||
);
|
||||
expect(container.innerHTML).toBe('');
|
||||
});
|
||||
});
|
|
@ -9,8 +9,8 @@ import React from 'react';
|
|||
import { EuiButton } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import moment from 'moment';
|
||||
import { useKibana } from '../../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { useUptimeStartPlugins } from '../../../../../contexts/uptime_startup_plugins_context';
|
||||
import { useUptimeSettingsContext } from '../../../../../contexts/uptime_settings_context';
|
||||
import { AllSeries, createExploratoryViewUrl } from '../../../../../../../observability/public';
|
||||
import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common';
|
||||
import { useWaterfallContext } from '../context/waterfall_chart';
|
||||
|
@ -40,9 +40,9 @@ const getLast48Intervals = (activeStep: JourneyStep) => {
|
|||
export function WaterfallMarkerTrend({ title, field }: { title: string; field: string }) {
|
||||
const { observability } = useUptimeStartPlugins();
|
||||
|
||||
const EmbeddableExpVIew = observability!.ExploratoryViewEmbeddable;
|
||||
const EmbeddableExpView = observability!.ExploratoryViewEmbeddable;
|
||||
|
||||
const { basePath } = useUptimeSettingsContext();
|
||||
const basePath = useKibana().services.http?.basePath?.get();
|
||||
|
||||
const { activeStep } = useWaterfallContext();
|
||||
|
||||
|
@ -75,7 +75,7 @@ export function WaterfallMarkerTrend({ title, field }: { title: string; field: s
|
|||
|
||||
return (
|
||||
<Wrapper>
|
||||
<EmbeddableExpVIew
|
||||
<EmbeddableExpView
|
||||
title={title}
|
||||
appendTitle={
|
||||
<EuiButton iconType={'visArea'} href={href} target="_blank" size="s">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue