/* * SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. * * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ import React from 'react'; import { Provider } from 'react-redux'; import userEvent from '@testing-library/user-event'; import { HashRouter as Router, RouteComponentProps, Route, Switch, } from 'react-router-dom'; import { render, waitFor } from '@testing-library/react'; import { ReviewAndCreate } from '../ReviewAndCreate'; import configureStore from '../../../../redux/configureStore'; import { httpClientMock, coreServicesMock } from '../../../../../test/mocks'; import { CoreServicesContext } from '../../../../components/CoreServices/CoreServices'; import { INITIAL_DETECTOR_JOB_VALUES } from '../../../DetectorJobs/utils/constants'; import { INITIAL_MODEL_CONFIGURATION_VALUES } from '../../../ConfigureModel/utils/constants'; import { INITIAL_DETECTOR_DEFINITION_VALUES } from '../../../DefineDetector/utils/constants'; const renderWithRouter = (isEdit: boolean = false) => ({ ...render( ( )} /> ), }); describe(' spec', () => { test('renders the component, validation loading', () => { const { container, getByText } = renderWithRouter(false); expect(container.firstChild).toMatchSnapshot(); getByText('Review and create'); getByText('Detector settings'); getByText('Model configuration'); getByText('Detector schedule'); getByText('Create detector'); getByText('Validating detector configurations'); getByText('Validating model configurations'); }); }); describe('Validation no issue', () => { test('renders succesful validation callout', async () => { httpClientMock.post = jest.fn().mockResolvedValue({ ok: true, response: {}, }); const { getByText } = renderWithRouter(false); await waitFor(() => {}); getByText('Detector settings are validated'); getByText('Model configurations are validated'); }); }); describe('validation model issue found', () => { test('renders filter query validation issue', async () => { httpClientMock.post = jest.fn().mockResolvedValue({ ok: true, response: { model: { filter_query: { message: 'Data is too sparse after data filter is applied. Consider changing the data filter', }, }, }, }); const { getByText } = renderWithRouter(false); await waitFor(() => {}); getByText('We identified some areas that might improve your model'); getByText( 'Data is too sparse after data filter is applied. Consider changing the data filter' ); getByText('Model configurations are validated'); }); test('renders dectector interval validation issue', async () => { httpClientMock.post = jest.fn().mockResolvedValue({ ok: true, response: { model: { detector_interval: { message: 'The selected detector interval might collect sparse data. Consider changing interval length to: 4', }, }, }, }); const { getByText } = renderWithRouter(false); await waitFor(() => {}); getByText('We identified some areas that might improve your model'); getByText( 'The selected detector interval might collect sparse data. Consider changing interval length to: 4' ); getByText('Model configurations are validated'); }); test('renders category field validation issue', async () => { httpClientMock.post = jest.fn().mockResolvedValue({ ok: true, response: { model: { category_field: { message: 'Data is most likely too sparse with the given category fields. Consider revising category field/s or ingesting more data', }, }, }, }); const { getByText } = renderWithRouter(false); await waitFor(() => {}); getByText('We identified some areas that might improve your model'); getByText( 'Data is most likely too sparse with the given category fields. Consider revising category field/s or ingesting more data' ); getByText('Detector settings are validated'); }); test('renders success callout on internal aggregation validation issue (aggregation)', async () => { httpClientMock.post = jest.fn().mockResolvedValue({ ok: true, response: { model: { timeout: { message: 'Model validation experienced issues completing', }, }, }, }); const { getByText } = renderWithRouter(false); await waitFor(() => {}); // Currently in case of internal aggregation failure we don't block users and let them continue with creating a detector // this failure is caused by an issue with Opensearch core and not necessarily user input getByText('Detector settings are validated'); getByText('Model configurations are validated'); }); }); describe('issue in detector validation', () => { test('issues in detector timestamp', async () => { httpClientMock.post = jest.fn().mockResolvedValue({ ok: true, response: { detector: { time_field: { message: 'Timestamp field: timestamp must be of type date', }, }, }, }); const { getByText } = renderWithRouter(false); await waitFor(() => {}); // Currently in case of internal aggregation failure we don't block users and let them continue with creating a detector // this failure is caused by an issue with Opensearch core and not necessarily user input getByText('Timestamp field: timestamp must be of type date'); getByText('Issues found in the detector settings'); getByText('Model configurations are validated'); }); test('issues in feature query', async () => { httpClientMock.post = jest.fn().mockResolvedValue({ ok: true, response: { detector: { feature_attributes: { message: 'Feature has an invalid query returning empty aggregated data: f_1, Feature has an invalid query causing a runtime exception: f_2', sub_issues: { f_1: 'Feature has an invalid query returning empty aggregated data: f_1', f_2: 'Feature has an invalid query causing a runtime exception: f_2', }, }, }, }, }); const { getByText } = renderWithRouter(false); await waitFor(() => {}); getByText( 'The "f_1" Feature has an invalid query returning empty aggregated data: f_1' ); getByText( 'The "f_2" Feature has an invalid query causing a runtime exception: f_2' ); getByText('Issues found in the model configuration'); getByText('Detector settings are validated'); }); test('issues in feature query', async () => { httpClientMock.post = jest.fn().mockResolvedValue({ ok: true, response: { detector: { feature_attributes: { message: 'Detector has duplicate feature names: f_1, f_2', }, }, }, }); const { container, getByText } = renderWithRouter(false); await waitFor(() => {}); expect(container).toMatchSnapshot(); getByText('Issues found in the model configuration'); getByText('Detector settings are validated'); }); }); describe('create Detector', () => { test('renders succesful validation callout', async () => { httpClientMock.post = jest.fn().mockResolvedValue({ ok: true, response: {}, }); const { getByText, getByTestId } = renderWithRouter(false); await waitFor(() => {}); getByText('Detector settings are validated'); getByText('Model configurations are validated'); userEvent.click(getByTestId('createDetectorButton')); }); });