Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit tests for expression function and bug fixes #503

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const ConfirmUnlinkDetectorModal = (
return (
<EuiOverlayMask>
<EuiModal
data-test-subj="startDetectorsModal"
data-test-subj="unlinkDetectorsModal"
onClose={props.onHide}
maxWidth={450}
>
Expand All @@ -52,14 +52,14 @@ export const ConfirmUnlinkDetectorModal = (
<EuiModalFooter>
{isLoading ? null : (
<EuiButtonEmpty
data-test-subj="cancelButton"
data-test-subj="cancelUnlinkButton"
onClick={props.onHide}
>
Cancel
</EuiButtonEmpty>
)}
<EuiButton
data-test-subj="confirmButton"
data-test-subj="confirmUnlinkButton"
color="primary"
fill
isLoading={isLoading}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { findAllByTestId, render, waitFor } from '@testing-library/react';
import { ConfirmUnlinkDetectorModal } from '../index';
import { getRandomDetector } from '../../../../../../public/redux/reducers/__tests__/utils';
import { DetectorListItem } from '../../../../../../public/models/interfaces';
import userEvent from '@testing-library/user-event';

describe('ConfirmUnlinkDetectorModal spec', () => {
beforeEach(() => {
jest.clearAllMocks();
});

const testDetectors = [
{
id: 'detectorId1',
name: 'test-detector-1',
},
{
id: 'detectorId2',
name: 'test-detector-2',
},
] as DetectorListItem[];

const ConfirmUnlinkDetectorModalProps = {
detector: testDetectors[0],
onHide: jest.fn(),
onConfirm: jest.fn(),
onUnlinkDetector: jest.fn(),
isListLoading: false,
};

test('renders the component correctly', () => {
const { container, getByText } = render(
<ConfirmUnlinkDetectorModal {...ConfirmUnlinkDetectorModalProps} />
);
getByText('Remove association?');
getByText(
'Removing association unlinks test-detector-1 detector from the visualization but does not delete it. The detector association can be restored.'
);
expect(container).toMatchSnapshot();
});
test('should call onConfirm() when closing', async () => {
const { container, getByText, getByTestId } = render(
<ConfirmUnlinkDetectorModal {...ConfirmUnlinkDetectorModalProps} />
);
getByText('Remove association?');
await waitFor(() => {});
ohltyler marked this conversation as resolved.
Show resolved Hide resolved
userEvent.click(getByTestId('confirmUnlinkButton'));
await waitFor(() => {});
expect(ConfirmUnlinkDetectorModalProps.onConfirm).toHaveBeenCalled();
});
test('should call onConfirm() when closing', async () => {
const { container, getByText, getByTestId } = render(
<ConfirmUnlinkDetectorModal {...ConfirmUnlinkDetectorModalProps} />
);
getByText('Remove association?');
await waitFor(() => {});
userEvent.click(getByTestId('confirmUnlinkButton'));
await waitFor(() => {});
expect(ConfirmUnlinkDetectorModalProps.onConfirm).toHaveBeenCalled();
});
test('should call onHide() when closing', async () => {
const { getByTestId } = render(
<ConfirmUnlinkDetectorModal {...ConfirmUnlinkDetectorModalProps} />
);
await waitFor(() => {});
userEvent.click(getByTestId('cancelUnlinkButton'));
await waitFor(() => {});
expect(ConfirmUnlinkDetectorModalProps.onHide).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { findAllByTestId, render, waitFor } from '@testing-library/react';
import { EmptyAssociatedDetectorMessage } from '../index';
import { getRandomDetector } from '../../../../../../public/redux/reducers/__tests__/utils';
import { DetectorListItem } from '../../../../../../public/models/interfaces';
import userEvent from '@testing-library/user-event';

describe('ConfirmUnlinkDetectorModal spec', () => {
beforeEach(() => {
jest.clearAllMocks();
});

test('renders the component with filter applied', () => {
const { container, getByText } = render(
<EmptyAssociatedDetectorMessage
isFilterApplied={true}
embeddableTitle="test-title"
/>
);
getByText('There are no detectors matching your search');
expect(container).toMatchSnapshot();
});
test('renders the component with filter applied', () => {
const { container, getByText } = render(
<EmptyAssociatedDetectorMessage
isFilterApplied={false}
embeddableTitle="test-title"
/>
);
getByText(
'There are no anomaly detectors associated with test-title visualization.'
);
expect(container).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`CodeModal spec renders the component 1`] = `
<div
aria-hidden="true"
data-aria-hidden="true"
/>
`;

exports[`ConfirmUnlinkDetectorModal spec renders the component 1`] = `
<div
aria-hidden="true"
data-aria-hidden="true"
/>
`;

exports[`ConfirmUnlinkDetectorModal spec renders the component correctly 1`] = `
<div
aria-hidden="true"
data-aria-hidden="true"
/>
`;
ohltyler marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ConfirmUnlinkDetectorModal spec renders the component with filter applied 1`] = `
<div>
<div
class="euiEmptyPrompt"
data-test-subj="emptyAssociatedDetectorFlyoutMessage"
style="max-width: 45em;"
>
<h3
class="euiTitle euiTitle--small"
>
No anomaly detectors to display
</h3>
<span
class="euiTextColor euiTextColor--subdued"
>
<div
class="euiSpacer euiSpacer--m"
/>
<div
class="euiText euiText--medium"
>
<div
class="euiText euiText--medium"
>
<p>
There are no detectors matching your search
</p>
</div>
</div>
</span>
</div>
</div>
`;

exports[`ConfirmUnlinkDetectorModal spec renders the component with filter applied 2`] = `
<div>
<div
class="euiEmptyPrompt"
data-test-subj="emptyAssociatedDetectorFlyoutMessage"
style="max-width: 45em;"
>
<h3
class="euiTitle euiTitle--small"
>
No anomaly detectors to display
</h3>
<span
class="euiTextColor euiTextColor--subdued"
>
<div
class="euiSpacer euiSpacer--m"
/>
<div
class="euiText euiText--medium"
>
<div
class="euiText euiText--medium"
>
<p>
There are no anomaly detectors associated with test-title visualization.
</p>
</div>
</div>
</span>
</div>
</div>
`;
152 changes: 152 additions & 0 deletions public/expressions/__tests__/overlay_anomalies.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { setClient } from '../../services';
import { httpClientMock, coreServicesMock } from '../../../test/mocks';
import {
convertAnomaliesToPointInTimeEventsVisLayer,
getAnomalies,
getVisLayerError,
getDetectorResponse,
} from '../overlay_anomalies';
import {
anomalyResultSummary,
noAnomaliesResultResponse,
parsedAnomalies,
selectedDetectors,
} from '../../pages/utils/__tests__/constants';
import {
DETECTOR_HAS_BEEN_DELETED,
START_OR_END_TIME_INVALID_ERROR,
VIS_LAYER_PLUGIN_TYPE,
} from '../constants';
import { PLUGIN_NAME } from '../../utils/constants';
import { VisLayerErrorTypes } from '../../../../../src/plugins/vis_augmenter/public';
import { DOES_NOT_HAVE_PERMISSIONS_KEY_WORD } from '../../../server/utils/helpers';

describe('overlay_anomalies spec', () => {
setClient(httpClientMock);

const ADPluginResource = {
type: VIS_LAYER_PLUGIN_TYPE,
id: 'hNX8l4ABuV34PY9I1EAZ',
name: 'test-1',
urlPath: `${PLUGIN_NAME}#/detectors/hNX8l4ABuV34PY9I1EAZ/results`, //details page for detector in AD plugin
};

describe('getAnomalies()', () => {
test('One anomaly', async () => {
httpClientMock.post = jest.fn().mockResolvedValue(anomalyResultSummary);
const receivedAnomalies = await getAnomalies(
'hNX8l4ABuV34PY9I1EAZ',
1589258564789,
1589258684789
);
expect(receivedAnomalies).toStrictEqual(parsedAnomalies);
});
test('No Anomalies', async () => {
httpClientMock.post = jest
.fn()
.mockResolvedValue(noAnomaliesResultResponse);
const receivedAnomalies = await getAnomalies(
'hNX8l4ABuV34PY9I1EAZ',
1589258564789,
1589258684789
);
expect(receivedAnomalies).toStrictEqual([]);
});
test('Failed response', async () => {
httpClientMock.post = jest.fn().mockResolvedValue({ ok: false });
const receivedAnomalies = await getAnomalies(
'hNX8l4ABuV34PY9I1EAZ',
1589258564789,
1589258684789
);
expect(receivedAnomalies).toStrictEqual([]);
});
});
describe('getDetectorResponse()', () => {
test('get detector', async () => {
httpClientMock.get = jest
.fn()
.mockResolvedValue({ ok: true, response: selectedDetectors[0] });
const receivedAnomalies = await getDetectorResponse(
'gtU2l4ABuV34PY9ITTdm'
);
expect(receivedAnomalies).toStrictEqual({
ok: true,
response: selectedDetectors[0],
});
});
});
describe('convertAnomaliesToPointInTimeEventsVisLayer()', () => {
test('convert anomalies to PointInTimeEventsVisLayer', async () => {
const expectedTimeStamp =
parsedAnomalies[0].startTime +
(parsedAnomalies[0].endTime - parsedAnomalies[0].startTime) / 2;
const expectedPointInTimeEventsVisLayer = {
events: [
{
metadata: {},
timestamp: expectedTimeStamp,
},
],
originPlugin: 'anomalyDetectionDashboards',
pluginResource: {
id: 'hNX8l4ABuV34PY9I1EAZ',
name: 'test-1',
type: 'Anomaly Detectors',
urlPath:
'anomaly-detection-dashboards#/detectors/hNX8l4ABuV34PY9I1EAZ/results',
},
type: 'PointInTimeEvents',
};
const pointInTimeEventsVisLayer =
await convertAnomaliesToPointInTimeEventsVisLayer(
parsedAnomalies,
ADPluginResource
);
expect(pointInTimeEventsVisLayer).toStrictEqual(
expectedPointInTimeEventsVisLayer
);
});
});
describe('getErrorLayerVisLayer()', () => {
test('get resource deleted ErrorVisLayer', async () => {
ohltyler marked this conversation as resolved.
Show resolved Hide resolved
const error = new Error(
'Anomaly Detector - ' + DETECTOR_HAS_BEEN_DELETED
);
const expectedVisLayerError = {
type: VisLayerErrorTypes.RESOURCE_DELETED,
message: error.message,
};
const visLayerError = await getVisLayerError(error);
console.log('receivedError: ' + JSON.stringify(visLayerError));
expect(visLayerError).toStrictEqual(expectedVisLayerError);
});
test('get no permission ErrorVisLayer', async () => {
const error = new Error(
'Anomaly Detector - ' + DOES_NOT_HAVE_PERMISSIONS_KEY_WORD
);
const expectedVisLayerError = {
type: VisLayerErrorTypes.PERMISSIONS_FAILURE,
message: error.message,
};
const visLayerError = await getVisLayerError(error);
console.log('recievedError: ' + JSON.stringify(visLayerError));
expect(visLayerError).toStrictEqual(expectedVisLayerError);
});
test('get fetch issue ErrorVisLayer', async () => {
const error = new Error(START_OR_END_TIME_INVALID_ERROR);
const expectedVisLayerError = {
type: VisLayerErrorTypes.FETCH_FAILURE,
message: error.message,
};
const visLayerError = await getVisLayerError(error);
console.log('recievedError: ' + JSON.stringify(visLayerError));
expect(visLayerError).toStrictEqual(expectedVisLayerError);
});
});
});
4 changes: 4 additions & 0 deletions public/expressions/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ export const TYPE_OF_EXPR_VIS_LAYERS = 'vis_layers';
export const OVERLAY_ANOMALIES = 'overlay_anomalies';

export const PLUGIN_EVENT_TYPE = 'Anomalies';

export const DETECTOR_HAS_BEEN_DELETED = 'detector has been deleted';

export const START_OR_END_TIME_INVALID_ERROR = 'start or end time invalid';
Loading