From 5f5c48ac5f98d622aeb974ee15faedfde7193a6c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 9 Jan 2025 08:14:56 +0000 Subject: [PATCH] [Enhancement] Use HTTP service instead of fetch for plugin check (#9052) * Use HTTP service instead of fetch Signed-off-by: Jialiang Liang * resolve comments Signed-off-by: Jialiang Liang * Add mock for addDanger() Signed-off-by: Jialiang Liang * Add unit test for sql definition preview Signed-off-by: Jialiang Liang * Fix the typo of class title O_o Signed-off-by: Jialiang Liang * Fix the snapshot issue Signed-off-by: Jialiang Liang --------- Signed-off-by: Jialiang Liang (cherry picked from commit f7ecf99a0b1d86adeeb34345422809b12dce6152) Signed-off-by: github-actions[bot] --- .../create/create_acceleration.test.tsx | 1 + .../create/create_acceleration.tsx | 3 +- .../preview_sql_definition.test.tsx.snap | 339 ++++++++++++++++++ .../selectors/preview_sql_definition.test.tsx | 167 +++++++++ ...fintion.tsx => preview_sql_definition.tsx} | 26 +- 5 files changed, 515 insertions(+), 21 deletions(-) create mode 100644 src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/__snapshots__/preview_sql_definition.test.tsx.snap create mode 100644 src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/preview_sql_definition.test.tsx rename src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/{preview_sql_defintion.tsx => preview_sql_definition.tsx} (85%) diff --git a/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/create/create_acceleration.test.tsx b/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/create/create_acceleration.test.tsx index f2acd4afa9e3..c444ea4089e5 100644 --- a/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/create/create_acceleration.test.tsx +++ b/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/create/create_acceleration.test.tsx @@ -26,6 +26,7 @@ const mockNotifications = { toasts: { addWarning: jest.fn(), addSuccess: jest.fn(), + addDanger: jest.fn(), }, }; diff --git a/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/create/create_acceleration.tsx b/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/create/create_acceleration.tsx index 556e6a1a690c..bb30898b6668 100644 --- a/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/create/create_acceleration.tsx +++ b/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/create/create_acceleration.tsx @@ -36,7 +36,7 @@ import { CatalogCacheManager } from '../../../../../framework/catalog_cache/cach import { IndexAdvancedSettings } from '../selectors/index_advanced_settings'; import { IndexSettingOptions } from '../selectors/index_setting_options'; import { IndexTypeSelector } from '../selectors/index_type_selector'; -import { PreviewSQLDefinition } from '../selectors/preview_sql_defintion'; +import { PreviewSQLDefinition } from '../selectors/preview_sql_definition'; import { AccelerationDataSourceSelector } from '../selectors/source_selector'; import { QueryVisualEditor } from '../visual_editors/query_visual_editor'; import { CreateAccelerationButton } from './create_acceleration_button'; @@ -277,6 +277,7 @@ export const CreateAcceleration = ({ resetFlyout={resetFlyout} notifications={notifications} application={application} + http={http} /> diff --git a/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/__snapshots__/preview_sql_definition.test.tsx.snap b/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/__snapshots__/preview_sql_definition.test.tsx.snap new file mode 100644 index 000000000000..2e81bf73d5bd --- /dev/null +++ b/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/__snapshots__/preview_sql_definition.test.tsx.snap @@ -0,0 +1,339 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PreviewSQLDefinition renders component correctly 1`] = ` + + +

+ Preview SQL definition +

+ + } + id="accordion1" + initialIsOpen={false} + isLoading={false} + isLoadingMessage={false} + paddingSize="l" + > +
+
+ +
+
+ +
+
+ +
+ +
+ + + + + +
+
+ +
+ + + + + +
+
+
+
+ +
+ + + +
+
+                      
+                    
+
+
+
+
+
+ +
+
+ + +`; diff --git a/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/preview_sql_definition.test.tsx b/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/preview_sql_definition.test.tsx new file mode 100644 index 000000000000..c7d626cde10f --- /dev/null +++ b/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/preview_sql_definition.test.tsx @@ -0,0 +1,167 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { mount } from 'enzyme'; +import { act } from 'react-dom/test-utils'; +import { PreviewSQLDefinition } from './preview_sql_definition'; +import { EuiButton } from '@elastic/eui'; +import { coreMock } from '../../../../../../../core/public/mocks'; +import { formValidator, hasError } from '../create/utils'; + +jest.mock('../visual_editors/query_builder', () => ({ + accelerationQueryBuilder: jest.fn(() => 'mocked SQL query'), +})); + +jest.mock('../create/utils', () => ({ + formValidator: jest.fn(() => ({})), + hasError: jest.fn(() => false), +})); + +describe('PreviewSQLDefinition', () => { + const mockCoreStart = coreMock.createStart(); + const mockAccelerationFormData = { + dataSource: 'test_source', + formErrors: {}, + }; + + const mockSetAccelerationFormData = jest.fn(); + const mockResetFlyout = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + mockCoreStart.http.get.mockResolvedValue({ + status: { + statuses: [{ id: 'plugin:queryWorkbenchDashboards' }], + }, + }); + }); + + const mountComponent = async () => { + const wrapper = mount( + + ); + + await act(async () => { + await Promise.resolve(); + }); + wrapper.update(); + + return wrapper; + }; + + test('renders component correctly', async () => { + const wrapper = await mountComponent(); + expect(wrapper).toMatchSnapshot(); + }); + + test('opens SQL Workbench when button is clicked', async () => { + const wrapper = await mountComponent(); + + const button = wrapper.findWhere( + (node) => node.type() === EuiButton && node.prop('data-test-subj') === 'workbenchButton' + ); + + expect(button.exists()).toBe(true); + expect(button.length).toBe(1); + + await act(async () => { + button.prop('onClick')(); + await Promise.resolve(); + }); + + expect(mockCoreStart.application.navigateToApp).toHaveBeenCalledWith(expect.any(String), { + path: '#/test_source', + state: { + language: 'sql', + queryToRun: 'mocked SQL query', + }, + }); + expect(mockResetFlyout).toHaveBeenCalled(); + }); + + test('displays error toast if SQL Workbench plugin check fails', async () => { + mockCoreStart.http.get.mockRejectedValueOnce(new Error('Error checking plugin')); + + await mountComponent(); + + expect(mockCoreStart.notifications.toasts.addDanger).toHaveBeenCalledWith( + 'Error checking Query Workbench Plugin Installation status.' + ); + }); + + test('shows update preview button when form data changes', async () => { + const wrapper = await mountComponent(); + + const previewButton = wrapper.findWhere( + (node) => node.type() === EuiButton && node.text().includes('Generate preview') + ); + + await act(async () => { + previewButton.prop('onClick')(); + await Promise.resolve(); + }); + + await act(async () => { + wrapper.setProps({ + accelerationFormData: { ...mockAccelerationFormData, dataSource: 'new_source' }, + }); + await Promise.resolve(); + }); + wrapper.update(); + + const updateButton = wrapper.findWhere( + (node) => node.type() === EuiButton && node.text().includes('Update preview') + ); + + expect(updateButton.exists()).toBe(true); + }); + + test('validates form before opening SQL Workbench', async () => { + // Mock form validation to return errors + (formValidator as jest.Mock).mockReturnValueOnce({ someField: 'error' }); + (hasError as jest.Mock).mockReturnValueOnce(true); + + const wrapper = await mountComponent(); + + const button = wrapper.findWhere( + (node) => node.type() === EuiButton && node.prop('data-test-subj') === 'workbenchButton' + ); + + await act(async () => { + button.prop('onClick')(); + await Promise.resolve(); + }); + + expect(mockCoreStart.application.navigateToApp).not.toHaveBeenCalled(); + expect(mockSetAccelerationFormData).toHaveBeenCalledWith({ + ...mockAccelerationFormData, + formErrors: { someField: 'error' }, + }); + }); + + test('hides SQL Workbench button when plugin is not installed', async () => { + mockCoreStart.http.get.mockResolvedValueOnce({ + status: { + statuses: [{ id: 'some-other-plugin' }], + }, + }); + + const wrapper = await mountComponent(); + + const button = wrapper.findWhere( + (node) => node.type() === EuiButton && node.prop('data-test-subj') === 'workbenchButton' + ); + + expect(button.exists()).toBe(false); + }); +}); diff --git a/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/preview_sql_defintion.tsx b/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/preview_sql_definition.tsx similarity index 85% rename from src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/preview_sql_defintion.tsx rename to src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/preview_sql_definition.tsx index 382d47a61a96..20e9af8e8412 100644 --- a/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/preview_sql_defintion.tsx +++ b/src/plugins/data_source_management/public/components/direct_query_data_sources_components/acceleration_creation/selectors/preview_sql_definition.tsx @@ -13,7 +13,7 @@ import { EuiText, } from '@elastic/eui'; import React, { useEffect, useState } from 'react'; -import { ApplicationStart, NotificationsStart } from 'opensearch-dashboards/public'; +import { ApplicationStart, NotificationsStart, HttpStart } from 'opensearch-dashboards/public'; import { queryWorkbenchPluginCheck, queryWorkbenchPluginID, @@ -28,6 +28,7 @@ interface PreviewSQLDefinitionProps { resetFlyout: () => void; notifications: NotificationsStart; application: ApplicationStart; + http: HttpStart; } export const PreviewSQLDefinition = ({ @@ -36,6 +37,7 @@ export const PreviewSQLDefinition = ({ resetFlyout, notifications, application, + http, }: PreviewSQLDefinitionProps) => { const [isPreviewStale, setIsPreviewStale] = useState(false); const [isPreviewTriggered, setIsPreviewTriggered] = useState(false); @@ -60,24 +62,8 @@ export const PreviewSQLDefinition = ({ }; const checkIfSQLWorkbenchPluginIsInstalled = () => { - fetch('/api/status', { - headers: { - 'Content-Type': 'application/json', - 'osd-xsrf': 'true', - 'accept-language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6', - pragma: 'no-cache', - 'sec-fetch-dest': 'empty', - 'sec-fetch-mode': 'cors', - 'sec-fetch-site': 'same-origin', - }, - method: 'GET', - referrerPolicy: 'strict-origin-when-cross-origin', - mode: 'cors', - credentials: 'include', - }) - .then(function (response) { - return response.json(); - }) + http + .get('/api/status') .then((data) => { for (let i = 0; i < data.status.statuses.length; ++i) { if (data.status.statuses[i].id.includes(queryWorkbenchPluginCheck)) { @@ -108,7 +94,7 @@ export const PreviewSQLDefinition = ({ }; const queryWorkbenchButton = sqlWorkbenchPLuginExists ? ( - + Edit in Query Workbench ) : (