From 41fb296e27734468aa0af39e8451f66f907d905e Mon Sep 17 00:00:00 2001 From: mpabba3003 Date: Thu, 13 Oct 2022 08:58:31 -0700 Subject: [PATCH 1/6] adding unit test cases for edit data source page Signed-off-by: mpabba3003 --- .../edit_data_source.test.tsx.snap | 1193 ++++++++++ .../edit_data_source_form.test.tsx.snap | 2072 +++++++++++++++++ .../edit_form/edit_data_source_form.test.tsx | 328 +++ .../edit_form/edit_data_source_form.tsx | 105 +- .../header/__snapshots__/header.test.tsx.snap | 175 ++ .../components/header/header.test.tsx | 98 + .../components/header/header.tsx | 4 +- .../update_password_modal.test.tsx.snap | 886 +++++++ .../update_password_modal.test.tsx | 118 + .../update_password_modal.tsx | 15 +- .../edit_data_source.test.tsx | 140 ++ .../edit_data_source/edit_data_source.tsx | 5 +- .../data_source_management/public/mocks.ts | 13 + 13 files changed, 5097 insertions(+), 55 deletions(-) create mode 100644 src/plugins/data_source_management/public/components/edit_data_source/__snapshots__/edit_data_source.test.tsx.snap create mode 100644 src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/__snapshots__/edit_data_source_form.test.tsx.snap create mode 100644 src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.test.tsx create mode 100644 src/plugins/data_source_management/public/components/edit_data_source/components/header/__snapshots__/header.test.tsx.snap create mode 100644 src/plugins/data_source_management/public/components/edit_data_source/components/header/header.test.tsx create mode 100644 src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/__snapshots__/update_password_modal.test.tsx.snap create mode 100644 src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.test.tsx create mode 100644 src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.test.tsx diff --git a/src/plugins/data_source_management/public/components/edit_data_source/__snapshots__/edit_data_source.test.tsx.snap b/src/plugins/data_source_management/public/components/edit_data_source/__snapshots__/edit_data_source.test.tsx.snap new file mode 100644 index 000000000000..905c58fcf117 --- /dev/null +++ b/src/plugins/data_source_management/public/components/edit_data_source/__snapshots__/edit_data_source.test.tsx.snap @@ -0,0 +1,1193 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Datasource Management: Edit Datasource Wizard should load resources successfully should render normally 1`] = ` + + + +
+ + +
+ +
+ +
+
+ +

+ create-test-ds +

+
+ +
+ +
+
+ + +
+ + + + + + + +
+
+
+ +
+ +
+ +
+ +
+

+ + Connection Details + +

+
+
+ +
+
+ + This connection information is used for reference in tables and when adding to a data source connection +

+ } + title={ +

+ Object Details +

+ } + > +
+ +
+ +
+ +

+ Object Details +

+
+ +
+ +
+

+ This connection information is used for reference in tables and when adding to a data source connection +

+
+
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+ + Description + + + - + optional + + + } + labelType="label" + > +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+ +
+

+ + Endpoint + +

+
+
+ +
+
+ + This connection information is used for reference in tables and when adding to a data source connection +

+ } + title={ +

+ Endpoint URL +

+ } + > +
+ +
+ +
+ +

+ Endpoint URL +

+
+ +
+ +
+

+ This connection information is used for reference in tables and when adding to a data source connection +

+
+
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+ +
+

+ + Authentication + +

+
+
+ +
+
+ + Authentication Method + + } + > +
+ +
+ +
+ +

+ Authentication Method +

+
+
+
+ +
+ +
+
+ + + +
+
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ +
+
+ + +
+ + +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+ +
+
+ + + +
+
+ +
+ +
+ + , + ] + } + compressed={false} + fullWidth={false} + icon="lock" + isLoading={false} + > +
+
+ + + + +
+ + + + + +
+
+
+ + + +
+
+
+
+
+ +
+ + + + + +
+
+
+
+
+
+
+
+ +
+ +
+ +
+ +
+ + +
+ + +
+ + + + +`; diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/__snapshots__/edit_data_source_form.test.tsx.snap b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/__snapshots__/edit_data_source_form.test.tsx.snap new file mode 100644 index 000000000000..f4c42d4b41fc --- /dev/null +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/__snapshots__/edit_data_source_form.test.tsx.snap @@ -0,0 +1,2072 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Datasource Management: Edit Datasource Form Case 1: With Username & Password should render normally 1`] = ` + + +
+ +
+ +
+
+ +

+ create-test-ds +

+
+ +
+ +
+
+ + +
+ + + + + + + +
+
+
+ +
+ +
+ +
+ +
+

+ + Connection Details + +

+
+
+ +
+
+ + This connection information is used for reference in tables and when adding to a data source connection +

+ } + title={ +

+ Object Details +

+ } + > +
+ +
+ +
+ +

+ Object Details +

+
+ +
+ +
+

+ This connection information is used for reference in tables and when adding to a data source connection +

+
+
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+ + Description + + + - + optional + + + } + labelType="label" + > +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+ +
+

+ + Endpoint + +

+
+
+ +
+
+ + This connection information is used for reference in tables and when adding to a data source connection +

+ } + title={ +

+ Endpoint URL +

+ } + > +
+ +
+ +
+ +

+ Endpoint URL +

+
+ +
+ +
+

+ This connection information is used for reference in tables and when adding to a data source connection +

+
+
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+ +
+

+ + Authentication + +

+
+
+ +
+
+ + Authentication Method + + } + > +
+ +
+ +
+ +

+ Authentication Method +

+
+
+
+ +
+ +
+
+ + + +
+
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ +
+
+ + +
+ + +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+ +
+
+ + + +
+
+ +
+ +
+ + , + ] + } + compressed={false} + fullWidth={false} + icon="lock" + isLoading={false} + > +
+
+ + + + +
+ + + + + +
+
+
+ + + +
+
+
+
+
+ +
+ + + + + +
+
+
+
+
+
+
+
+ +
+ +
+ +
+ +
+ + +
+ + +
+ + + +`; + +exports[`Datasource Management: Edit Datasource Form Case 2: With No Authentication should render normally 1`] = ` + + +
+ +
+ +
+
+ +

+ create-test-ds123 +

+
+ +
+ +
+
+ + +
+ + + + + + + +
+
+
+ +
+ +
+ +
+ +
+

+ + Connection Details + +

+
+
+ +
+
+ + This connection information is used for reference in tables and when adding to a data source connection +

+ } + title={ +

+ Object Details +

+ } + > +
+ +
+ +
+ +

+ Object Details +

+
+ +
+ +
+

+ This connection information is used for reference in tables and when adding to a data source connection +

+
+
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+ + Description + + + - + optional + + + } + labelType="label" + > +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+ +
+

+ + Endpoint + +

+
+
+ +
+
+ + This connection information is used for reference in tables and when adding to a data source connection +

+ } + title={ +

+ Endpoint URL +

+ } + > +
+ +
+ +
+ +

+ Endpoint URL +

+
+ +
+ +
+

+ This connection information is used for reference in tables and when adding to a data source connection +

+
+
+
+
+
+
+ +
+ +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+ +
+

+ + Authentication + +

+
+
+ +
+
+ + Authentication Method + + } + > +
+ +
+ +
+ +

+ Authentication Method +

+
+
+
+ +
+ +
+
+ + + +
+
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ +
+
+ + +
+ +
+ +
+ +
+ +
+ +
+ + +
+ + +
+ + + +`; diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.test.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.test.tsx new file mode 100644 index 000000000000..000b019b3ee3 --- /dev/null +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.test.tsx @@ -0,0 +1,328 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { mount, ReactWrapper } from 'enzyme'; +import React from 'react'; +import { wrapWithIntl } from 'test_utils/enzyme_helpers'; +import { + mockDataSourceAttributesWithAuth, + mockManagementPlugin, + existingDatasourceNamesList, + mockDataSourceAttributesWithNoAuth, +} from '../../../../mocks'; +import { OpenSearchDashboardsContextProvider } from '../../../../../../opensearch_dashboards_react/public'; +import { EditDataSourceForm } from './edit_data_source_form'; +import { act } from 'react-dom/test-utils'; +import { AuthType } from '../../../../types'; + +const titleFieldIdentifier = 'dataSourceTitle'; +const titleFormRowIdentifier = '[data-test-subj="editDataSourceTitleFormRow"]'; +const endpointFieldIdentifier = '[data-test-subj="editDatasourceEndpointField"]'; +const descriptionFieldIdentifier = 'dataSourceDescription'; +const descriptionFormRowIdentifier = '[data-test-subj="editDataSourceDescriptionFormRow"]'; +const authTypeRadioIdentifier = '[data-test-subj="editDataSourceSelectAuthType"]'; +const usernameFieldIdentifier = 'datasourceUsername'; +const usernameFormRowIdentifier = '[data-test-subj="editDatasourceUsernameFormRow"]'; +const passwordFieldIdentifier = '[data-test-subj="updateDataSourceFormPasswordField"]'; +const updatePasswordBtnIdentifier = '[data-test-subj="editDatasourceUpdatePasswordBtn"]'; +describe('Datasource Management: Edit Datasource Form', () => { + const mockedContext = mockManagementPlugin.createDataSourceManagementContext(); + let component: ReactWrapper, React.Component<{}, {}, any>>; + const mockFn = jest.fn(); + + const updateInputFieldAndBlur = ( + comp: ReactWrapper, React.Component<{}, {}, any>>, + fieldName: string, + updatedValue: string, + isTestSubj?: boolean + ) => { + const field = isTestSubj ? comp.find(fieldName) : comp.find({ name: fieldName }); + act(() => { + field.last().simulate('change', { target: { value: updatedValue } }); + }); + comp.update(); + act(() => { + field.last().simulate('focus').simulate('blur'); + }); + comp.update(); + }; + + describe('Case 1: With Username & Password', () => { + beforeEach(() => { + component = mount( + wrapWithIntl( + + ), + { + wrappingComponent: OpenSearchDashboardsContextProvider, + wrappingComponentProps: { + services: mockedContext, + }, + } + ); + component.update(); + }); + + test('should render normally', () => { + expect(component).toMatchSnapshot(); + // @ts-ignore + expect(component.find({ name: titleFieldIdentifier }).first().props().value).toBe( + mockDataSourceAttributesWithAuth.title + ); + expect(component.find(endpointFieldIdentifier).first().props().disabled).toBe(true); + }); + + /* Validation */ + test('should validate title as required field & no duplicates allowed', () => { + /* Validate empty title - required */ + updateInputFieldAndBlur(component, titleFieldIdentifier, ''); + // @ts-ignore + expect(component.find(titleFormRowIdentifier).first().props().isInvalid).toBe(true); + + /* Validate duplicate title */ + updateInputFieldAndBlur(component, titleFieldIdentifier, 'DuP20'); + // @ts-ignore + expect(component.find(titleFormRowIdentifier).first().props().isInvalid).toBe(true); + + /* change to original title */ + updateInputFieldAndBlur( + component, + titleFieldIdentifier, + mockDataSourceAttributesWithAuth.title + ); + // @ts-ignore + expect(component.find(titleFormRowIdentifier).first().props().isInvalid).toBe(false); + + /* change to valid updated title */ + updateInputFieldAndBlur(component, titleFieldIdentifier, 'test007'); + // @ts-ignore + expect(component.find(titleFormRowIdentifier).first().props().isInvalid).toBe(false); + }); + test('should validate username as required field', () => { + /* Validate empty username - required */ + updateInputFieldAndBlur(component, usernameFieldIdentifier, ''); + // @ts-ignore + expect(component.find(usernameFormRowIdentifier).first().props().isInvalid).toBe(true); + + /* change to original username */ + updateInputFieldAndBlur( + component, + usernameFieldIdentifier, + mockDataSourceAttributesWithAuth.auth.credentials.username + ); + // @ts-ignore + expect(component.find(usernameFormRowIdentifier).first().props().isInvalid).toBe(false); + /* change to valid updated username */ + updateInputFieldAndBlur(component, usernameFieldIdentifier, 'test'); + // @ts-ignore + expect(component.find(usernameFormRowIdentifier).first().props().isInvalid).toBe(false); + }); + test('should validate that password field is disabled & update stored password button is shown', () => { + expect(component.find(passwordFieldIdentifier).first().props().disabled).toBe(true); + expect(component.find(updatePasswordBtnIdentifier).exists()).toBe(true); + }); + /* Functionality */ + test('should display update password modal on update stored password button click & on update confirmation should update the password', () => { + act(() => { + component.find(updatePasswordBtnIdentifier).first().simulate('click'); + }); + component.update(); + expect(component.find('UpdatePasswordModal').exists()).toBe(true); + + /* Update password */ + act(() => { + // @ts-ignore + component.find('UpdatePasswordModal').prop('handleUpdatePassword')('testPassword'); + }); + component.update(); + expect(mockFn).toHaveBeenCalled(); + expect(component.find('UpdatePasswordModal').exists()).toBe(false); + }); + test("should hide username & password fields when 'No Authentication' is selected as the credential type", () => { + act(() => { + // @ts-ignore + component.find(authTypeRadioIdentifier).first().prop('onChange')(AuthType.NoAuth); + }); + component.update(); + expect(component.find(usernameFormRowIdentifier).exists()).toBe(false); + expect(component.find(passwordFieldIdentifier).exists()).toBe(false); + }); + + /* Cancel Changes */ + test('should reset form on click cancel changes', async () => { + await new Promise((resolve) => + setTimeout(() => { + updateInputFieldAndBlur(component, descriptionFieldIdentifier, ''); + expect( + // @ts-ignore + component.find(descriptionFormRowIdentifier).first().props().isInvalid + ).toBeUndefined(); + resolve(); + }, 100) + ); + await new Promise((resolve) => + setTimeout(() => { + /* Updated description*/ + updateInputFieldAndBlur(component, descriptionFieldIdentifier, 'testDescription'); + expect( + // @ts-ignore + component.find(descriptionFormRowIdentifier).first().props().isInvalid + ).toBeUndefined(); + + expect(component.find('[data-test-subj="datasource-edit-cancelButton"]').exists()).toBe( + true + ); + component + .find('[data-test-subj="datasource-edit-cancelButton"]') + .first() + .simulate('click'); + resolve(); + }, 100) + ); + }); + + /* Save Changes */ + test('should update the form with Username&Password on click save changes', async () => { + await new Promise((resolve) => + setTimeout(() => { + updateInputFieldAndBlur(component, descriptionFieldIdentifier, ''); + expect( + // @ts-ignore + component.find(descriptionFormRowIdentifier).first().props().isInvalid + ).toBeUndefined(); + resolve(); + }, 100) + ); + await new Promise((resolve) => + setTimeout(() => { + /* Updated description*/ + updateInputFieldAndBlur(component, descriptionFieldIdentifier, 'testDescription'); + expect( + // @ts-ignore + component.find(descriptionFormRowIdentifier).first().props().isInvalid + ).toBeUndefined(); + + expect(component.find('[data-test-subj="datasource-edit-saveButton"]').exists()).toBe( + true + ); + component.find('[data-test-subj="datasource-edit-saveButton"]').first().simulate('click'); + expect(mockFn).toHaveBeenCalled(); + resolve(); + }, 100) + ); + }); + }); + + describe('Case 2: With No Authentication', () => { + beforeEach(() => { + component = mount( + wrapWithIntl( + + ), + { + wrappingComponent: OpenSearchDashboardsContextProvider, + wrappingComponentProps: { + services: mockedContext, + }, + } + ); + component.update(); + }); + + test('should render normally', () => { + expect(component).toMatchSnapshot(); + // @ts-ignore + expect(component.find({ name: titleFieldIdentifier }).first().props().value).toBe( + mockDataSourceAttributesWithNoAuth.title + ); + expect(component.find(endpointFieldIdentifier).first().props().disabled).toBe(true); + }); + + /* functionality */ + + test("should show username & password fields when 'Username & Password' is selected as the credential type", () => { + act(() => { + // @ts-ignore + component.find(authTypeRadioIdentifier).first().prop('onChange')( + // @ts-ignore + AuthType.UsernamePasswordType + ); + }); + component.update(); + expect(component.find(usernameFormRowIdentifier).exists()).toBe(true); + expect(component.find(passwordFieldIdentifier).exists()).toBe(true); + }); + + /* validation - Password */ + + test('should validate password as required field', () => { + act(() => { + // @ts-ignore + component.find(authTypeRadioIdentifier).first().prop('onChange')( + // @ts-ignore + AuthType.UsernamePasswordType + ); + }); + component.update(); + + /* Validate empty username - required */ + updateInputFieldAndBlur(component, passwordFieldIdentifier, '', true); + // @ts-ignore + expect(component.find(passwordFieldIdentifier).first().props().isInvalid).toBe(true); + + /* change to original username */ + updateInputFieldAndBlur(component, passwordFieldIdentifier, 'test123', true); + // @ts-ignore + expect(component.find(passwordFieldIdentifier).first().props().isInvalid).toBe(false); + }); + + test('should delete datasource on confirmation from header', () => { + // @ts-ignore + component.find('Header').prop('onClickDeleteIcon')(); + expect(mockFn).toHaveBeenCalled(); + }); + + /* Save Changes */ + test('should update the form with NoAUth on click save changes', async () => { + await new Promise((resolve) => + setTimeout(() => { + updateInputFieldAndBlur(component, descriptionFieldIdentifier, ''); + expect( + // @ts-ignore + component.find(descriptionFormRowIdentifier).first().props().isInvalid + ).toBeUndefined(); + resolve(); + }, 100) + ); + await new Promise((resolve) => + setTimeout(() => { + /* Updated description*/ + updateInputFieldAndBlur(component, descriptionFieldIdentifier, 'testDescription'); + expect( + // @ts-ignore + component.find(descriptionFormRowIdentifier).first().props().isInvalid + ).toBeUndefined(); + + expect(component.find('[data-test-subj="datasource-edit-saveButton"]').exists()).toBe( + true + ); + component.find('[data-test-subj="datasource-edit-saveButton"]').first().simulate('click'); + expect(mockFn).toHaveBeenCalled(); + resolve(); + }, 100) + ); + }); + }); +}); diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx index 424d4cb9f5a8..d0530896c976 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx @@ -295,7 +295,12 @@ export class EditDataSourceForm extends React.Component { return ( <> - {UPDATE_STORED_PASSWORD} + + {UPDATE_STORED_PASSWORD} + {this.state.showUpdatePasswordModal ? ( {/* Description */} - + @@ -426,6 +436,7 @@ export class EditDataSourceForm extends React.Component this.onChangeAuthType(id)} name="Credential" + data-test-subj="editDataSourceSelectAuthType" /> @@ -443,8 +454,10 @@ export class EditDataSourceForm extends React.Component { - let bottomBar = null; - - if (this.state.showUpdateOptions) { - bottomBar = ( - - - - - - this.resetFormValues()} - aria-describedby="aria-describedby.countOfUnsavedSettings" - data-test-subj="datasource-edit-cancelButton" - > - {CANCEL_CHANGES} - - - - - {SAVE_CHANGES} - - - - - ); - } - return bottomBar; + return ( + + + + + + this.resetFormValues()} + aria-describedby="aria-describedby.countOfUnsavedSettings" + data-test-subj="datasource-edit-cancelButton" + > + {CANCEL_CHANGES} + + + + + {SAVE_CHANGES} + + + + + ); }; renderContent = () => { @@ -574,7 +581,7 @@ export class EditDataSourceForm extends React.Component - {this.renderBottomBar()} + {this.state.showUpdateOptions ? this.renderBottomBar() : null} diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/header/__snapshots__/header.test.tsx.snap b/src/plugins/data_source_management/public/components/edit_data_source/components/header/__snapshots__/header.test.tsx.snap new file mode 100644 index 000000000000..d9877a2cdc1d --- /dev/null +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/header/__snapshots__/header.test.tsx.snap @@ -0,0 +1,175 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Datasource Management: Edit Datasource Header do not show delete icon should render normally 1`] = ` + +
+ +
+ +
+
+ +

+ testTest20 +

+
+ +
+ +
+
+ + +
+ +
+ +
+
+`; + +exports[`Datasource Management: Edit Datasource Header show delete icon should render normally 1`] = ` + +
+ +
+ +
+
+ +

+ testTest20 +

+
+ +
+ +
+
+ + +
+ + + + + + + +
+
+
+ +
+
+`; diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.test.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.test.tsx new file mode 100644 index 000000000000..36a3551d9ada --- /dev/null +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.test.tsx @@ -0,0 +1,98 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { mount, ReactWrapper } from 'enzyme'; +import React from 'react'; +import { Header } from './header'; +import { wrapWithIntl } from 'test_utils/enzyme_helpers'; +import { mockManagementPlugin } from '../../../../mocks'; +import { OpenSearchDashboardsContextProvider } from '../../../../../../opensearch_dashboards_react/public'; +import { act } from 'react-dom/test-utils'; + +const headerTitleIdentifier = '[data-test-subj="editDataSourceTitle"]'; +const deleteIconIdentifier = '[data-test-subj="editDatasourceDeleteIcon"]'; +const confirmModalIdentifier = '[data-test-subj="editDatasourceDeleteConfirmModal"]'; + +describe('Datasource Management: Edit Datasource Header', () => { + const mockedContext = mockManagementPlugin.createDataSourceManagementContext(); + let component: ReactWrapper, React.Component<{}, {}, any>>; + const mockFn = jest.fn(); + const dataSourceName = 'testTest20'; + + describe('show delete icon', () => { + beforeEach(() => { + component = mount( + wrapWithIntl( +
+ ), + { + wrappingComponent: OpenSearchDashboardsContextProvider, + wrappingComponentProps: { + services: mockedContext, + }, + } + ); + }); + + test('should render normally', () => { + expect(component).toMatchSnapshot(); + expect(component.find(headerTitleIdentifier).last().text()).toBe(dataSourceName); + }); + test('should show confirm delete modal pop up on trash icon click and cancel button work normally', () => { + component.find(deleteIconIdentifier).first().simulate('click'); + // test if modal pop up when click the delete button + expect(component.find(confirmModalIdentifier).exists()).toBe(true); + + act(() => { + // @ts-ignore + component.find(confirmModalIdentifier).first().props().onCancel(); + }); + + component.update(); + expect(component.find(confirmModalIdentifier).exists()).toBe(false); + }); + test('should show confirm delete modal pop up on trash icon click and confirm button should delete datasource', () => { + component.find(deleteIconIdentifier).first().simulate('click'); + // test if modal pop up when click the delete button + expect(component.find(confirmModalIdentifier).exists()).toBe(true); + + act(() => { + // @ts-ignore + component.find(confirmModalIdentifier).first().props().onConfirm(); + }); + + component.update(); + expect(component.find(confirmModalIdentifier).exists()).toBe(false); + }); + }); + describe('do not show delete icon', () => { + beforeEach(() => { + component = mount( + wrapWithIntl( +
+ ), + { + wrappingComponent: OpenSearchDashboardsContextProvider, + wrappingComponentProps: { + services: mockedContext, + }, + } + ); + }); + test('should render normally', () => { + expect(component).toMatchSnapshot(); + expect(component.find(headerTitleIdentifier).last().text()).toBe(dataSourceName); + expect(component.find(deleteIconIdentifier).exists()).toBe(false); + }); + }); +}); diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.tsx index 974e29ff0635..358a419394eb 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.tsx +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.tsx @@ -49,6 +49,7 @@ export const Header = ({ { setIsDeleteModalVisible(true); }} @@ -72,6 +73,7 @@ export const Header = ({ cancelButtonText={CANCEL_TEXT} confirmButtonText={DELETE_TEXT} defaultFocusedButton="confirm" + data-test-subj="editDatasourceDeleteConfirmModal" >

{DS_LISTING_DATA_SOURCE_DELETE_IMPACT}

{DS_LISTING_DATA_SOURCE_DELETE_WARNING}

@@ -85,7 +87,7 @@ export const Header = ({
- +

{dataSourceName}

diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/__snapshots__/update_password_modal.test.tsx.snap b/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/__snapshots__/update_password_modal.test.tsx.snap new file mode 100644 index 000000000000..d10048a4d128 --- /dev/null +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/__snapshots__/update_password_modal.test.tsx.snap @@ -0,0 +1,886 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Datasource Management: Update Stored Password Modal should render normally 1`] = ` + +
+ + + + +
+
+ +
+
+
+

+ Update stored password +

+
+
+
+
+
+
+
+ Update credential password to reflect accurate password to gain access to the endpoint. +
+
+
+
+
+
+
+ +
+
+
+ test_user +
+
+
+
+
+ +
+
+
+
+ +
+ + +
+
+ +
+
+
+
+
+ +
+
+
+
+ +
+ + +
+
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+ } + > + +
+
+ + + + + +
+ +
+ +
+

+ Update stored password +

+
+
+
+
+ +
+
+ +
+
+ +
+ Update credential password to reflect accurate password to gain access to the endpoint. +
+
+
+
+
+ +
+ + +
+ +
+
+ + + +
+
+ +
+ test_user +
+
+
+
+
+ +
+
+ + + +
+
+ + , + ] + } + compressed={false} + fullWidth={false} + icon="lock" + isLoading={false} + > +
+
+ + + + +
+ + + + + +
+
+
+ + + +
+
+
+
+
+
+ +
+
+ + + +
+
+ + , + ] + } + compressed={false} + fullWidth={false} + icon="lock" + isLoading={false} + > +
+
+ + + + +
+ + + + + +
+
+
+ + + +
+
+
+
+
+
+
+
+
+
+ + +
+ + + + + + + + +
+
+
+
+
+ + + + + +
+ +`; diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.test.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.test.tsx new file mode 100644 index 000000000000..764570c7160d --- /dev/null +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.test.tsx @@ -0,0 +1,118 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { mount, ReactWrapper } from 'enzyme'; +import React from 'react'; +import { UpdatePasswordModal } from './update_password_modal'; + +const usernameIdentifier = '[data-test-subj="data-source-update-password-username"]'; +const confirmBtnIdentifier = '[data-test-subj="updateStoredPasswordConfirmBtn"]'; +const cancelBtnIdentifier = '[data-test-subj="updateStoredPasswordCancelBtn"]'; +const updatedPasswordFieldIdentifier = + '[data-test-subj="updateStoredPasswordUpdatedPasswordField"]'; +const confirmUpdatedPasswordFieldIdentifier = + '[data-test-subj="updateStoredPasswordConfirmUpdatedPasswordField"]'; +describe('Datasource Management: Update Stored Password Modal', () => { + let component: ReactWrapper, React.Component<{}, {}, any>>; + const mockUserName = 'test_user'; + const mockFn = jest.fn(); + + beforeEach(async () => { + component = mount( + + ); + }); + + test('should render normally', () => { + expect(component).toMatchSnapshot(); + expect(component.find(usernameIdentifier).last().text()).toBe(mockUserName); + expect(component.find(confirmBtnIdentifier).last().props().disabled).toBe(true); + }); + + test('should close modal when cancel button is clicked', () => { + spyOn(component.props(), 'closeUpdatePasswordModal').and.callThrough(); + component.find(cancelBtnIdentifier).last().simulate('click'); + expect(component.props().closeUpdatePasswordModal).toHaveBeenCalled(); + }); + + /* Validations */ + test('should show validation error on blur on Confirm Password field & remove existing error when input is provided and onblur is called', () => { + // @ts-ignore + component.find(updatedPasswordFieldIdentifier).last().simulate('blur'); + + expect(component.find(updatedPasswordFieldIdentifier).first().prop('isInvalid')).toBe(true); + expect(component.find(confirmBtnIdentifier).last().props().disabled).toBe(true); + + // @ts-ignore + component + .find(updatedPasswordFieldIdentifier) + .last() + .simulate('change', { target: { value: 'abc' } }) + .simulate('blur'); + expect(component.find(updatedPasswordFieldIdentifier).first().prop('isInvalid')).toBe(false); + }); + test('should show validation error on blur on Confirm Password fields & remove existing error when input is provided and onblur is called', () => { + /* Set updated Password field*/ + + // @ts-ignore + component + .find(updatedPasswordFieldIdentifier) + .last() + .simulate('change', { target: { value: 'abc' } }) + .simulate('blur'); + + // @ts-ignore + component.find(confirmUpdatedPasswordFieldIdentifier).last().simulate('blur'); + + expect(component.find(confirmUpdatedPasswordFieldIdentifier).first().prop('isInvalid')).toBe( + true + ); + + /* Password not match */ + // @ts-ignore + component + .find(confirmUpdatedPasswordFieldIdentifier) + .last() + .simulate('change', { target: { value: 'ab' } }) + .simulate('blur'); + expect(component.find(confirmUpdatedPasswordFieldIdentifier).first().prop('isInvalid')).toBe( + true + ); + + /* Valid passwords */ + // @ts-ignore + component + .find(confirmUpdatedPasswordFieldIdentifier) + .last() + .simulate('change', { target: { value: 'abc' } }) + .simulate('blur'); + expect(component.find(confirmUpdatedPasswordFieldIdentifier).first().prop('isInvalid')).toBe( + false + ); + }); + test('should update password when form is valid', () => { + spyOn(component.props(), 'handleUpdatePassword').and.callThrough(); + // @ts-ignore + component + .find(updatedPasswordFieldIdentifier) + .last() + .simulate('change', { target: { value: 'abc' } }) + .simulate('blur'); + + component + .find(confirmUpdatedPasswordFieldIdentifier) + .last() + .simulate('change', { target: { value: 'abc' } }) + .simulate('blur'); + + expect(component.find(updatedPasswordFieldIdentifier).first().prop('isInvalid')).toBe(false); + component.find(confirmBtnIdentifier).last().simulate('click'); + expect(component.props().handleUpdatePassword).toHaveBeenCalled(); + }); +}); diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.tsx index 5e7307abc7db..be4e4a88785c 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.tsx +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.tsx @@ -89,12 +89,15 @@ export const UpdatePasswordModal = ({ {/* Username */} - {username} + + {username} + {/* updated Password */} - {CANCEL_TEXT} + + {CANCEL_TEXT} + { + const mockedContext = mockManagementPlugin.createDataSourceManagementContext(); + let component: ReactWrapper, React.Component<{}, {}, any>>; + const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; + + describe('should fail to load resources', () => { + beforeEach(async () => { + spyOn(utils, 'getDataSources').and.throwError(''); + spyOn(utils, 'getDataSourceById').and.throwError(''); + await act(async () => { + component = mount( + wrapWithIntl( + + ), + { + wrappingComponent: OpenSearchDashboardsContextProvider, + wrappingComponentProps: { + services: mockedContext, + }, + } + ); + }); + component.update(); + }); + + test('should NOT render normally', () => { + expect(utils.getDataSources).not.toHaveBeenCalled(); + expect(utils.getDataSourceById).toHaveBeenCalled(); + expect(history.push).toBeCalledWith(''); + }); + }); + + describe('should load resources successfully', () => { + beforeEach(async () => { + spyOn(utils, 'getDataSources').and.returnValue(Promise.resolve(getMappedDataSources)); + spyOn(utils, 'getDataSourceById').and.returnValue( + Promise.resolve(mockDataSourceAttributesWithAuth) + ); + await act(async () => { + component = mount( + wrapWithIntl( + + ), + { + wrappingComponent: OpenSearchDashboardsContextProvider, + wrappingComponentProps: { + services: mockedContext, + }, + } + ); + }); + component.update(); + }); + + test('should render normally', () => { + expect(component).toMatchSnapshot(); + expect(component.find(notFoundIdentifier).exists()).toBe(false); + expect(utils.getDataSources).toHaveBeenCalled(); + expect(utils.getDataSourceById).toHaveBeenCalled(); + }); + test('should update datasource successfully', async () => { + spyOn(utils, 'updateDataSourceById').and.returnValue({}); + + await act(async () => { + // @ts-ignore + await component.find(formIdentifier).first().prop('handleSubmit')( + mockDataSourceAttributesWithAuth + ); + }); + expect(utils.updateDataSourceById).toHaveBeenCalled(); + expect(history.push).toBeCalledWith(''); + }); + test('should fail to update datasource', async () => { + spyOn(utils, 'updateDataSourceById').and.throwError('error'); + await act(async () => { + // @ts-ignore + await component.find(formIdentifier).first().prop('handleSubmit')( + mockDataSourceAttributesWithAuth + ); + }); + component.update(); + expect(utils.updateDataSourceById).toHaveBeenCalled(); + }); + test('should delete datasource successfully', async () => { + spyOn(utils, 'deleteDataSourceById').and.returnValue({}); + + await act(async () => { + // @ts-ignore + await component.find(formIdentifier).first().prop('onDeleteDataSource')( + mockDataSourceAttributesWithAuth + ); + }); + expect(utils.deleteDataSourceById).toHaveBeenCalled(); + expect(history.push).toBeCalledWith(''); + }); + test('should fail to delete datasource', async () => { + spyOn(utils, 'deleteDataSourceById').and.throwError('error'); + await act(async () => { + // @ts-ignore + await component.find(formIdentifier).first().prop('onDeleteDataSource')( + mockDataSourceAttributesWithAuth + ); + }); + component.update(); + expect(utils.deleteDataSourceById).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.tsx b/src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.tsx index e502adc5d5ca..8c6bd902f288 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.tsx +++ b/src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.tsx @@ -32,7 +32,7 @@ const defaultDataSource: DataSourceAttributes = { }, }; -const EditDataSource: React.FunctionComponent> = ( +export const EditDataSource: React.FunctionComponent> = ( props: RouteComponentProps<{ id: string }> ) => { /* Initialization */ @@ -65,6 +65,7 @@ const EditDataSource: React.FunctionComponent { if (!isLoading && (!dataSource || !dataSource.id)) { - return

Data Source not found!

; + return

Data Source not found!

; } return ( <> diff --git a/src/plugins/data_source_management/public/mocks.ts b/src/plugins/data_source_management/public/mocks.ts index 2e0333121e28..9abf28a1b96f 100644 --- a/src/plugins/data_source_management/public/mocks.ts +++ b/src/plugins/data_source_management/public/mocks.ts @@ -96,6 +96,8 @@ export const getDataSourcesResponse = { ], }; +export const existingDatasourceNamesList = ['test123', 'testTest20', 'TeSt', 'duplicateTest', 'dup20']; + export const getMappedDataSources = [ { id: 'test', @@ -136,6 +138,17 @@ export const mockDataSourceAttributesWithAuth = { }, }, }; + +export const mockDataSourceAttributesWithNoAuth = { + id: 'test123', + title: 'create-test-ds123', + description: 'jest testing', + endpoint: 'https://test.com', + auth: { + type: AuthType.NoAuth, + credentials: undefined, + }, +}; export const getDataSourceByIdWithCredential = { attributes: { id: 'alpha-test', From 9b8dfc506df89984d30a7204ac0b47d7154eb026 Mon Sep 17 00:00:00 2001 From: mpabba3003 Date: Thu, 13 Oct 2022 09:00:25 -0700 Subject: [PATCH 2/6] lint mock file Signed-off-by: mpabba3003 --- src/plugins/data_source_management/public/mocks.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/data_source_management/public/mocks.ts b/src/plugins/data_source_management/public/mocks.ts index 9abf28a1b96f..c078247956e0 100644 --- a/src/plugins/data_source_management/public/mocks.ts +++ b/src/plugins/data_source_management/public/mocks.ts @@ -96,7 +96,13 @@ export const getDataSourcesResponse = { ], }; -export const existingDatasourceNamesList = ['test123', 'testTest20', 'TeSt', 'duplicateTest', 'dup20']; +export const existingDatasourceNamesList = [ + 'test123', + 'testTest20', + 'TeSt', + 'duplicateTest', + 'dup20', +]; export const getMappedDataSources = [ { From 6d0598393420fe304c25cdc1e9ffd582e9e94135 Mon Sep 17 00:00:00 2001 From: mpabba3003 Date: Thu, 13 Oct 2022 09:04:52 -0700 Subject: [PATCH 3/6] updating snapshot Signed-off-by: mpabba3003 --- .../__snapshots__/edit_data_source.test.tsx.snap | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/plugins/data_source_management/public/components/edit_data_source/__snapshots__/edit_data_source.test.tsx.snap b/src/plugins/data_source_management/public/components/edit_data_source/__snapshots__/edit_data_source.test.tsx.snap index 905c58fcf117..161eb5bc0aae 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/__snapshots__/edit_data_source.test.tsx.snap +++ b/src/plugins/data_source_management/public/components/edit_data_source/__snapshots__/edit_data_source.test.tsx.snap @@ -287,6 +287,7 @@ exports[`Datasource Management: Edit Datasource Wizard should load resources suc className="euiFlexItem euiDescribedFormGroup__fields euiDescribedFormGroup__fieldPadding--xsmall" >