diff --git a/public/pages/workflow_detail/workflow_detail.test.tsx b/public/pages/workflow_detail/workflow_detail.test.tsx new file mode 100644 index 00000000..070bbba0 --- /dev/null +++ b/public/pages/workflow_detail/workflow_detail.test.tsx @@ -0,0 +1,93 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { + RouteComponentProps, + Route, + Switch, + Router, + Redirect, +} from 'react-router-dom'; +import { WorkflowDetail } from './workflow_detail'; +import { WorkflowDetailRouterProps } from '../../pages'; +import '@testing-library/jest-dom'; +import { mockStore, resizeObserverMock } from '../../../test/utils'; +import { createMemoryHistory } from 'history'; +import { WORKFLOW_TYPE } from '../../../common'; + +jest.mock('../../services', () => { + const { mockCoreServices } = require('../../../test'); + return { + ...jest.requireActual('../../services'), + ...mockCoreServices, + }; +}); + +const workflowId = '12345'; +const workflowName = 'test_workflow'; + +const history = createMemoryHistory({ + initialEntries: [`/workflow/${workflowId}`], +}); + +window.ResizeObserver = resizeObserverMock; + +const renderWithRouter = ( + workflowId: string, + workflowName: string, + workflowType: WORKFLOW_TYPE +) => ({ + ...render( + + + + ) => { + return ; + }} + /> + + + + ), +}); + +describe('WorkflowDetail', () => { + Object.values(WORKFLOW_TYPE).forEach((type) => { + test(`renders the page with ${type} type`, () => { + const { getAllByText, getByText, getByRole } = renderWithRouter( + workflowId, + workflowName, + type + ); + + expect(getAllByText(workflowName).length).toBeGreaterThan(0); + expect(getAllByText('Create an ingest pipeline').length).toBeGreaterThan( + 0 + ); + expect(getAllByText('Skip ingestion pipeline').length).toBeGreaterThan(0); + expect(getAllByText('Define ingest pipeline').length).toBeGreaterThan(0); + expect(getAllByText('Tools').length).toBeGreaterThan(0); + expect(getAllByText('Preview').length).toBeGreaterThan(0); + expect(getAllByText('Not started').length).toBeGreaterThan(0); + expect( + getAllByText((content) => content.startsWith('Last updated:')).length + ).toBeGreaterThan(0); + expect(getAllByText('Search pipeline').length).toBeGreaterThan(0); + expect(getByText('Close')).toBeInTheDocument(); + expect(getByText('Export')).toBeInTheDocument(); + expect(getByText('Visual')).toBeInTheDocument(); + expect(getByText('JSON')).toBeInTheDocument(); + expect(getByRole('tab', { name: 'Run ingestion' })).toBeInTheDocument(); + expect(getByRole('tab', { name: 'Run queries' })).toBeInTheDocument(); + expect(getByRole('tab', { name: 'Errors' })).toBeInTheDocument(); + expect(getByRole('tab', { name: 'Resources' })).toBeInTheDocument(); + }); + }); +}); diff --git a/public/pages/workflows/new_workflow/utils.ts b/public/pages/workflows/new_workflow/utils.ts index 8988c739..f6dbb4e6 100644 --- a/public/pages/workflows/new_workflow/utils.ts +++ b/public/pages/workflows/new_workflow/utils.ts @@ -60,7 +60,7 @@ export function enrichPresetWorkflowWithUiMetadata( } as WorkflowTemplate; } -function fetchEmptyMetadata(): UIState { +export function fetchEmptyMetadata(): UIState { return { type: WORKFLOW_TYPE.CUSTOM, config: { @@ -125,7 +125,7 @@ function fetchEmptyMetadata(): UIState { }; } -function fetchSemanticSearchMetadata(): UIState { +export function fetchSemanticSearchMetadata(): UIState { let baseState = fetchEmptyMetadata(); baseState.type = WORKFLOW_TYPE.SEMANTIC_SEARCH; baseState.config.ingest.enrich.processors = [new MLIngestProcessor().toObj()]; @@ -143,7 +143,7 @@ function fetchSemanticSearchMetadata(): UIState { return baseState; } -function fetchMultimodalSearchMetadata(): UIState { +export function fetchMultimodalSearchMetadata(): UIState { let baseState = fetchEmptyMetadata(); baseState.type = WORKFLOW_TYPE.MULTIMODAL_SEARCH; baseState.config.ingest.enrich.processors = [new MLIngestProcessor().toObj()]; @@ -163,7 +163,7 @@ function fetchMultimodalSearchMetadata(): UIState { return baseState; } -function fetchHybridSearchMetadata(): UIState { +export function fetchHybridSearchMetadata(): UIState { let baseState = fetchEmptyMetadata(); baseState.type = WORKFLOW_TYPE.HYBRID_SEARCH; baseState.config.ingest.enrich.processors = [new MLIngestProcessor().toObj()]; diff --git a/test/utils.ts b/test/utils.ts new file mode 100644 index 00000000..c0d053c4 --- /dev/null +++ b/test/utils.ts @@ -0,0 +1,84 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { WORKFLOW_TYPE } from '../common/constants'; +import { UIState, Workflow } from '../common/interfaces'; +import { + fetchEmptyMetadata, + fetchHybridSearchMetadata, + fetchMultimodalSearchMetadata, + fetchSemanticSearchMetadata, +} from '../public/pages/workflows/new_workflow/utils'; + +export function mockStore( + workflowId: string, + workflowName: string, + workflowType: WORKFLOW_TYPE +) { + return { + getState: () => ({ + opensearch: { + errorMessage: '', + }, + ml: {}, + workflows: { + loading: false, + errorMessage: '', + workflows: { + [workflowId]: generateWorkflow( + workflowId, + workflowName, + workflowType + ), + }, + }, + }), + dispatch: jest.fn(), + subscribe: jest.fn(), + replaceReducer: jest.fn(), + [Symbol.observable]: jest.fn(), + }; +} + +function generateWorkflow( + workflowId: string, + workflowName: string, + workflowType: WORKFLOW_TYPE +): Workflow { + return { + id: workflowId, + name: workflowName, + version: { template: '1.0.0', compatibility: ['2.17.0', '3.0.0'] }, + ui_metadata: getConfig(workflowType), + }; +} +function getConfig(workflowType: WORKFLOW_TYPE) { + let uiMetadata = {} as UIState; + switch (workflowType) { + case WORKFLOW_TYPE.SEMANTIC_SEARCH: { + uiMetadata = fetchSemanticSearchMetadata(); + break; + } + case WORKFLOW_TYPE.MULTIMODAL_SEARCH: { + uiMetadata = fetchMultimodalSearchMetadata(); + break; + } + case WORKFLOW_TYPE.HYBRID_SEARCH: { + uiMetadata = fetchHybridSearchMetadata(); + break; + } + default: { + uiMetadata = fetchEmptyMetadata(); + break; + } + } + return uiMetadata; +} + +export const resizeObserverMock = jest.fn().mockImplementation(() => ({ + observe: jest.fn(), + unobserve: jest.fn(), + disconnect: jest.fn(), +}));