From 15e4cdfd7c6ac4ec4acfc7617c5ebdd857ad790a Mon Sep 17 00:00:00 2001 From: yujin-emma Date: Tue, 7 May 2024 22:09:04 +0000 Subject: [PATCH 1/2] add test for edit data source form Signed-off-by: yujin-emma --- .../edit_form/edit_data_source_form.test.tsx | 194 ++++++++++++++++++ .../edit_form/edit_data_source_form.tsx | 3 + .../update_aws_credential_modal.test.tsx | 67 ++++++ .../data_source_management/public/mocks.ts | 15 ++ 4 files changed, 279 insertions(+) create mode 100644 src/plugins/data_source_management/public/components/edit_data_source/components/update_aws_credential_modal/update_aws_credential_modal.test.tsx 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 index be5a3a31be73..876e36bf56ff 100644 --- 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 @@ -12,6 +12,7 @@ import { existingDatasourceNamesList, mockDataSourceAttributesWithNoAuth, mockDataSourceAttributesWithRegisteredAuth, + mockDataSourceAttributesWithSigV4Auth, } from '../../../../mocks'; import { OpenSearchDashboardsContextProvider } from '../../../../../../opensearch_dashboards_react/public'; import { EditDataSourceForm } from './edit_data_source_form'; @@ -34,6 +35,13 @@ const usernameFieldIdentifier = 'datasourceUsername'; const usernameFormRowIdentifier = '[data-test-subj="editDatasourceUsernameFormRow"]'; const passwordFieldIdentifier = '[data-test-subj="updateDataSourceFormPasswordField"]'; const updatePasswordBtnIdentifier = '[data-test-subj="editDatasourceUpdatePasswordBtn"]'; +const updateAwsCredsBtnIdentifier = '[data-test-subj="editDatasourceUpdateAwsCredentialBtn"]'; +const regionFieldIdentifier = 'dataSourceRegion'; +const accessKeyFieldIdentifier = 'dataSourceAccessKey'; +const accessKeyFormRowIdentifier = '[data-test-subj="editDataSourceFormAccessKeyField"]'; +const secretKeyFieldIdentifier = 'dataSourceSecretKey'; +const secretKeyFormRowIdentifier = '[data-test-subj="editDataSourceFormSecretKeyField"]'; + describe('Datasource Management: Edit Datasource Form', () => { const mockedContext = mockManagementPlugin.createDataSourceManagementContext(); mockedContext.authenticationMethodRegistry.registerAuthenticationMethod( @@ -351,6 +359,192 @@ describe('Datasource Management: Edit Datasource Form', () => { expect(mockFn).toHaveBeenCalled(); }); }); + + describe('Case 3: With AWSsigv4', () => { + beforeEach(() => { + component = mount( + wrapWithIntl( + + ), + { + wrappingComponent: OpenSearchDashboardsContextProvider, + wrappingComponentProps: { + services: mockedContext, + }, + } + ); + component.update(); + }); + + test('should render normally', () => { + // @ts-ignore + expect(component.find({ name: titleFieldIdentifier }).first().props().value).toBe( + mockDataSourceAttributesWithSigV4Auth.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, + mockDataSourceAttributesWithSigV4Auth.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 access key as required field', () => { + /* Validate empty accessKey - required */ + updateInputFieldAndBlur(component, accessKeyFieldIdentifier, ''); + // @ts-ignore + expect(component.find(accessKeyFormRowIdentifier).first().props().isInvalid).toBe(true); + + /* change to original accessKey */ + updateInputFieldAndBlur( + component, + accessKeyFieldIdentifier, + mockDataSourceAttributesWithSigV4Auth.auth.credentials.accessKey + ); + // @ts-ignore + expect(component.find(accessKeyFormRowIdentifier).first().props().isInvalid).toBe(false); + /* change to valid updated accessKey */ + updateInputFieldAndBlur(component, accessKeyFieldIdentifier, 'test123'); + // @ts-ignore + expect(component.find(accessKeyFormRowIdentifier).first().props().isInvalid).toBe(false); + }); + test('should validate secret key as required field', () => { + /* Validate empty secretKey - required */ + updateInputFieldAndBlur(component, secretKeyFieldIdentifier, ''); + // @ts-ignore + expect(component.find(secretKeyFormRowIdentifier).first().props().isInvalid).toBe(true); + + /* change to original secretKey */ + updateInputFieldAndBlur( + component, + secretKeyFieldIdentifier, + mockDataSourceAttributesWithSigV4Auth.auth.credentials.secretKey + ); + // @ts-ignore + expect(component.find(secretKeyFormRowIdentifier).first().props().isInvalid).toBe(false); + /* change to valid updated secretKey */ + updateInputFieldAndBlur(component, secretKeyFieldIdentifier, 'test123'); + // @ts-ignore + expect(component.find(secretKeyFormRowIdentifier).first().props().isInvalid).toBe(false); + }); + /* Functionality */ + test('should display update aws credential modal on update button click and should update the credentials', () => { + act(() => { + component.find(updateAwsCredsBtnIdentifier).first().simulate('click'); + }); + component.update(); + expect(component.find('UpdateAwsCredentialModal').exists()).toBe(true); + + /* Update password */ + act(() => { + // @ts-ignore + component.find('UpdateAwsCredentialModal').prop('handleUpdateAwsCredential')('test123'); + }); + component.update(); + expect(mockFn).toHaveBeenCalled(); + expect(component.find('UpdateAwsCredentialModal').exists()).toBe(false); + }); + test("should hide username & password fields when 'AWS Sigv4' is selected as the credential type", () => { + setAuthTypeValue(authTypeSelectIdentifier, AuthType.SigV4); + 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('With Registered Authentication', () => { 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 63336cca5d32..e227e5e2087c 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 @@ -882,6 +882,7 @@ export class EditDataSourceForm extends React.Component diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/update_aws_credential_modal/update_aws_credential_modal.test.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/update_aws_credential_modal/update_aws_credential_modal.test.tsx new file mode 100644 index 000000000000..e7c7f0209438 --- /dev/null +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/update_aws_credential_modal/update_aws_credential_modal.test.tsx @@ -0,0 +1,67 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { mount, shallow } from 'enzyme'; +import { render } from '@testing-library/react'; +import { UpdateAwsCredentialModal } from './update_aws_credential_modal'; +import { SigV4ServiceName } from '../../../../../../data_source/common/data_sources'; +import { EuiFormRow, EuiModalHeaderTitle } from '@elastic/eui'; +import { FormattedMessage } from 'react-intl'; + +describe('UpdateAwsCredentialModal', () => { + const mockHandleUpdateAwsCredential = jest.fn(); + const mockCloseUpdateAwsCredentialModal = jest.fn(); + + const props = { + region: 'us-east-1', + service: SigV4ServiceName.OpenSearch, + handleUpdateAwsCredential: mockHandleUpdateAwsCredential, + closeUpdateAwsCredentialModal: mockCloseUpdateAwsCredentialModal, + }; + + it('updates new access key state on input change', () => { + const wrapper = shallow(); + const newAccessKeyInput = wrapper.find('[name="updatedAccessKey"]'); + newAccessKeyInput.simulate('change', { target: { value: 'new_access_key' } }); + expect(wrapper.find('[name="updatedAccessKey"]').prop('value')).toEqual('new_access_key'); + }); + + it('renders modal with correct header title', () => { + const wrapper = shallow(); + const headerTitle = wrapper.find(EuiModalHeaderTitle).props().children; + expect(headerTitle).toEqual( +

+ +

+ ); + }); + + it('renders modal with correct label for updated secret key', () => { + const wrapper = shallow(); + expect(wrapper.find(EuiFormRow).at(4).props().label).toEqual('Updated secret key'); + }); + + it('renders modal with correct label for updated access key', () => { + const wrapper = shallow(); + expect(wrapper.find(EuiFormRow).at(3).props().label).toEqual('Updated access key'); + }); + + it('renders modal with correct region', () => { + const container = render(); + expect(container.getByTestId('data-source-update-credential-region')).toBeVisible(); + const text = container.getByTestId('data-source-update-credential-region'); + expect(text.textContent).toBe(props.region); + }); + + it('renders modal with service name select', () => { + const container = render(); + expect(container.getByTestId('data-source-update-credential-service-name')).toBeVisible(); + }); +}); diff --git a/src/plugins/data_source_management/public/mocks.ts b/src/plugins/data_source_management/public/mocks.ts index 3d991bd3e10a..0e5ec60bc307 100644 --- a/src/plugins/data_source_management/public/mocks.ts +++ b/src/plugins/data_source_management/public/mocks.ts @@ -267,6 +267,21 @@ export const mockDataSourceAttributesWithAuth = { }, }; +export const mockDataSourceAttributesWithSigV4Auth = { + id: 'test', + title: 'create-test-ds', + description: 'jest testing', + endpoint: 'https://test.com', + auth: { + type: AuthType.SigV4, + credentials: { + accessKey: 'test123', + secretKey: 'test123', + region: 'us-east-1', + }, + }, +}; + export const mockDataSourceAttributesWithNoAuth = { id: 'test123', title: 'create-test-ds123', From 9246ebc8d00e48838d54cb8cdf9286f1fdea82b5 Mon Sep 17 00:00:00 2001 From: "opensearch-changeset-bot[bot]" <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 01:09:57 +0000 Subject: [PATCH 2/2] Changeset file for PR #6742 created/updated --- changelogs/fragments/6742.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/6742.yml diff --git a/changelogs/fragments/6742.yml b/changelogs/fragments/6742.yml new file mode 100644 index 000000000000..390210dff311 --- /dev/null +++ b/changelogs/fragments/6742.yml @@ -0,0 +1,2 @@ +fix: +- Add test for edit data source form ([#6742](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6742)) \ No newline at end of file