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

[Backport 2.x] Expanded functionality tests for New Workflow and Workflow List components. #392

Merged
merged 1 commit into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
14 changes: 13 additions & 1 deletion public/pages/workflow_detail/workflow_detail.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ const renderWithRouter = (

return {
...render(
<Provider store={mockStore(workflowId, workflowName, workflowType)}>
<Provider
store={mockStore({
id: workflowId,
name: workflowName,
type: workflowType,
})}
>
<Router history={history}>
<Switch>
<Route
Expand All @@ -59,6 +65,9 @@ const renderWithRouter = (
};

describe('WorkflowDetail Page with create ingestion option', () => {
beforeEach(() => {
jest.clearAllMocks();
});
Object.values(WORKFLOW_TYPE).forEach((type) => {
test(`renders the WorkflowDetail page with ${type} type`, async () => {
const {
Expand Down Expand Up @@ -113,6 +122,9 @@ describe('WorkflowDetail Page with create ingestion option', () => {
});

describe('WorkflowDetail Page Functionality (Custom Workflow)', () => {
beforeEach(() => {
jest.clearAllMocks();
});
test('tests Export button, Tools panel toggling, and Workspace preview', async () => {
const { getByText, container, getByTestId } = renderWithRouter(
workflowId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const renderWithRouter = () =>
);

describe('ImportWorkflowModal', () => {
beforeEach(() => {
jest.clearAllMocks();
});
test('renders the page', () => {
const { getAllByText } = renderWithRouter();
expect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,10 @@ export function ImportWorkflowModal(props: ImportWorkflowModalProps) {
</EuiFlexGroup>
</EuiModalBody>
<EuiModalFooter>
<EuiSmallButtonEmpty onClick={() => onModalClose()}>
<EuiSmallButtonEmpty
onClick={() => onModalClose()}
data-testid="cancelImportButton"
>
Cancel
</EuiSmallButtonEmpty>
<EuiSmallButton
Expand Down
68 changes: 63 additions & 5 deletions public/pages/workflows/new_workflow/new_workflow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@
*/

import React from 'react';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom';
import { Provider } from 'react-redux';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { store } from '../../../store';
import { NewWorkflow } from './new_workflow';
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import configureStore from 'redux-mock-store';
import * as ReactReduxHooks from '../../../store/store';
import '@testing-library/jest-dom';
import { loadPresetWorkflowTemplates } from '../../../../test/utils';
import { INITIAL_ML_STATE } from '../../../../public/store';
import { WORKFLOW_TYPE } from '../../../../common/constants';
import { capitalizeEachWord } from '../../../../test/utils';

jest.mock('../../../services', () => {
const { mockCoreServices } = require('../../../../test');
Expand All @@ -19,6 +25,18 @@ jest.mock('../../../services', () => {
};
});

const mockStore = configureStore([]);
const initialState = {
ml: INITIAL_ML_STATE,
presets: {
loading: false,
presetWorkflows: loadPresetWorkflowTemplates(),
},
};
const store = mockStore(initialState);

const mockDispatch = jest.fn();

const renderWithRouter = () =>
render(
<Provider store={store}>
Expand All @@ -31,8 +49,48 @@ const renderWithRouter = () =>
);

describe('NewWorkflow', () => {
test('renders the search bar', () => {
const { getByPlaceholderText } = renderWithRouter();
beforeEach(() => {
jest.clearAllMocks();
jest.spyOn(ReactReduxHooks, 'useAppDispatch').mockReturnValue(mockDispatch);
});

test('renders the preset workflow templates', () => {
const { getByPlaceholderText, getAllByText } = renderWithRouter();
expect(getByPlaceholderText('Search')).toBeInTheDocument();
Object.values(WORKFLOW_TYPE).forEach((type) => {
if (type !== WORKFLOW_TYPE.UNKNOWN) {
expect(getAllByText(capitalizeEachWord(type))).toHaveLength(1);
}
});
});

test('renders the quick configure for preset workflow templates', async () => {
const {
getAllByTestId,
getAllByText,
getByTestId,
queryByText,
} = renderWithRouter();

// Click the first "Go" button on the templates and test Quick Configure.
const goButtons = getAllByTestId('goButton');
userEvent.click(goButtons[0]);
await waitFor(() =>
expect(getAllByText('Quick configure')).toHaveLength(1)
);

// Verify that the create button is present in the Quick Configure pop-up.
expect(getByTestId('quickConfigureCreateButton')).toBeInTheDocument();

// Click the "Cancel" button in the Quick Configure pop-up.
const quickConfigureCancelButton = getByTestId(
'quickConfigureCancelButton'
);
userEvent.click(quickConfigureCancelButton);

// Ensure the quick configure pop-up is closed after canceling.
await waitFor(() =>
expect(queryByText('quickConfigureCreateButton')).toBeNull()
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ export function QuickConfigureModal(props: QuickConfigureModalProps) {
/>
</EuiModalBody>
<EuiModalFooter>
<EuiSmallButtonEmpty onClick={() => props.onClose()}>
<EuiSmallButtonEmpty
onClick={() => props.onClose()}
data-testid="quickConfigureCancelButton"
>
Cancel
</EuiSmallButtonEmpty>
<EuiSmallButton
Expand Down Expand Up @@ -166,6 +169,7 @@ export function QuickConfigureModal(props: QuickConfigureModalProps) {
console.error(err);
});
}}
data-testid="quickConfigureCreateButton"
fill={true}
color="primary"
>
Expand Down
1 change: 1 addition & 0 deletions public/pages/workflows/new_workflow/use_case.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export function UseCase(props: UseCaseProps) {
onClick={() => {
setIsNameModalOpen(true);
}}
data-testid="goButton"
>
Go
</EuiSmallButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ export function DeleteWorkflowModal(props: DeleteWorkflowModalProps) {
</EuiFlexGroup>
</EuiModalBody>
<EuiModalFooter>
<EuiSmallButtonEmpty onClick={() => props.clearDeleteState()}>
<EuiSmallButtonEmpty
onClick={() => props.clearDeleteState()}
data-testid="cancelDeleteWorkflowButton"
>
{' '}
Cancel
</EuiSmallButtonEmpty>
Expand Down Expand Up @@ -135,6 +138,7 @@ export function DeleteWorkflowModal(props: DeleteWorkflowModalProps) {
setIsDeleting(false);
props.clearDeleteState();
}}
data-testid="deleteWorkflowButton"
fill={true}
color="danger"
>
Expand Down
131 changes: 129 additions & 2 deletions public/pages/workflows/workflow_list/workflow_list.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@
*/

import React from 'react';
import { render } from '@testing-library/react';
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import { Provider } from 'react-redux';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { store } from '../../../store';
import { WorkflowList } from './workflow_list';
import { mockStore } from '../../../../test/utils';
import { WORKFLOW_TYPE } from '../../../../common';
import configureStore from 'redux-mock-store';
import { WorkflowInput } from '../../../../test/interfaces';

jest.mock('../../../services', () => {
const { mockCoreServices } = require('../../../../test');
Expand All @@ -18,6 +23,25 @@ jest.mock('../../../services', () => {
};
});

const workflowSet: WorkflowInput[] = Array.from({ length: 20 }, (_, index) => ({
id: `workflow_id_${index}`,
name: `workflow_name_${index}`,
type: Object.values(WORKFLOW_TYPE)[
Math.floor(Math.random() * Object.values(WORKFLOW_TYPE).length)
],
}));

const mockStore1 = configureStore([]);
const initialState = {
workflows: {
loading: false,
errorMessage: '',
workflows: mockStore(...workflowSet).getState().workflows.workflows, // The `mockStore` used here is from the Test Utils.
},
};

const store = mockStore1(initialState);

const renderWithRouter = () =>
render(
<Provider store={store}>
Expand All @@ -30,8 +54,111 @@ const renderWithRouter = () =>
);

describe('WorkflowList', () => {
beforeEach(() => {
jest.clearAllMocks();
});
test('renders the page', () => {
const { getAllByText } = renderWithRouter();
expect(getAllByText('Manage existing workflows').length).toBeGreaterThan(0);
expect(getAllByText('Name').length).toBeGreaterThan(0);
expect(getAllByText('Type').length).toBeGreaterThan(0);
expect(getAllByText('Last saved').length).toBeGreaterThan(0);
expect(getAllByText('Actions').length).toBeGreaterThan(0);
expect(getAllByText('workflow_name_0').length).toBeGreaterThan(0);
});

test('sorting functionality', async () => {
const { container, getAllByText, queryByText } = renderWithRouter();
expect(getAllByText('workflow_name_0').length).toBeGreaterThan(0);

const sortButtons = container.querySelectorAll(
'[data-test-subj="tableHeaderSortButton"]'
);

// Sort workflows list by Name
expect(sortButtons[0]).toBeInTheDocument();
userEvent.click(sortButtons[0]!);
await waitFor(() => {
expect(queryByText('workflow_name_19')).toBeInTheDocument();
expect(queryByText('workflow_name_0')).toBeNull();
});
userEvent.click(sortButtons[0]!);
await waitFor(() => {
expect(queryByText('workflow_name_0')).toBeInTheDocument();
expect(queryByText('workflow_name_9')).toBeInTheDocument();
expect(queryByText('workflow_name_10')).toBeNull();
expect(queryByText('workflow_name_19')).toBeNull();
});

// Sort workflows list by Type
expect(sortButtons[1]).toBeInTheDocument();
userEvent.click(sortButtons[1]!);
await waitFor(() => {
expect(getAllByText('Custom').length).toBeGreaterThan(0);
expect(queryByText('Unknown')).toBeNull();
});
userEvent.click(sortButtons[1]!);
await waitFor(() => {
expect(queryByText('Unknown')).toBeNull();
expect(getAllByText('Custom').length).toBeGreaterThan(0);
});
});

test('pagination functionality', async () => {
const { container, getByText, queryByText } = renderWithRouter();

// Rows per page 10
const rowsPerPageButton = container.querySelector(
'[data-test-subj="tablePaginationPopoverButton"]'
) as HTMLButtonElement;
expect(rowsPerPageButton).toHaveTextContent('Rows per page: 10');

// Default view 10 items per page
expect(getByText('workflow_name_0')).toBeInTheDocument();
expect(queryByText('workflow_name_19')).toBeNull();

// Navigate to next page
const nextButton = container.querySelector(
'[data-test-subj="pagination-button-next"]'
) as HTMLButtonElement;
userEvent.click(nextButton);
await waitFor(() => {
expect(getByText('workflow_name_19')).toBeInTheDocument();
expect(queryByText('workflow_name_0')).toBeNull();
});

// Navigate to previous page
const previousButton = container.querySelector(
'[data-test-subj="pagination-button-previous"]'
) as HTMLButtonElement;
userEvent.click(previousButton);
await waitFor(() => {
expect(getByText('workflow_name_0')).toBeInTheDocument();
expect(queryByText('workflow_name_19')).toBeNull();
});
});

test('delete action functionality', async () => {
const { getByText, getByTestId, getAllByLabelText } = renderWithRouter();
const deleteButtons = getAllByLabelText('Delete');
userEvent.click(deleteButtons[0]);
await waitFor(() => {
expect(getByText('Delete associated resources')).toBeInTheDocument();
});
expect(getByTestId('deleteWorkflowButton')).toBeInTheDocument();
const cancelDeleteWorkflowButton = getByTestId(
'cancelDeleteWorkflowButton'
);
expect(cancelDeleteWorkflowButton).toBeInTheDocument();
userEvent.click(cancelDeleteWorkflowButton);
});

test('view resources functionality', async () => {
const { getByText, getAllByLabelText } = renderWithRouter();
const viewResourcesButtons = getAllByLabelText('View resources');
userEvent.click(viewResourcesButtons[0]);
await waitFor(() => {
expect(getByText('No existing resources found')).toBeInTheDocument();
});
});
});
Loading
Loading