From fa38d901ff4fd90fb28a665a937ebf7da4e9e71c Mon Sep 17 00:00:00 2001 From: lizhensheng Date: Wed, 31 Jan 2024 16:51:41 +0800 Subject: [PATCH 1/3] [test]:(Data Export) complete Create component unit tests --- jest.config.js | 1 + .../__snapshots__/index.test.tsx.snap | 1301 +++++++++++++ .../Create/__tests__/index.test.tsx | 57 + .../__tests__/BaseInfoFormItem.test.tsx | 17 + .../BaseInfoFormItem.test.tsx.snap | 101 ++ .../__tests__/ExportMethodItems.test.tsx | 18 + .../ExportMethodItems.test.tsx.snap | 62 + .../ExportSourceForm/ExportSourceFormItem.tsx | 13 +- .../__tests__/ExportSourceFormItem.test.tsx | 100 + .../__snapshots__/index.test.tsx.snap | 1378 ++++++++++++++ .../CreateTask/__tests__/index.test.tsx | 103 ++ .../Create/components/CreateTask/index.tsx | 15 +- .../components/CreateTask/index.type.ts | 6 +- .../__snapshots__/index.test.tsx.snap | 435 +++++ .../components/SubmitResult/index.test.tsx | 23 + .../__snapshots__/index.test.tsx.snap | 1605 +++++++++++++++++ .../UpdateInfoDrawer/index.test.tsx | 108 ++ .../SubmitWorkflow/UpdateInfoDrawer/index.tsx | 4 +- .../__snapshots__/index.test.tsx.snap | 212 +++ .../SubmitWorkflow/__tests__/index.test.tsx | 100 + .../components/SubmitWorkflow/index.tsx | 6 +- .../__snapshots__/index.redux.test.ts.snap | 36 + .../hooks/__tests__/index.redux.test.ts | 133 ++ .../useCreateExportTaskForm.test.tsx | 231 +++ .../Create/hooks/index.redux.ts | 21 +- .../Create/hooks/useCreateExportTaskForm.ts | 19 +- .../mockUseCreateDataExportReduxManage.ts | 34 + .../testUtils/mockUseCreateExportTaskForm.ts | 22 + packages/base/src/store/dataExport/index.ts | 4 +- .../src/testUtils/mockApi/dataExport/data.ts | 15 +- .../src/testUtils/mockApi/dataExport/index.ts | 29 +- packages/shared/lib/testUtil/common.tsx | 20 + 32 files changed, 6184 insertions(+), 45 deletions(-) create mode 100644 packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap create mode 100644 packages/base/src/page/DataExportManagement/Create/__tests__/index.test.tsx create mode 100644 packages/base/src/page/DataExportManagement/Create/components/CreateTask/BaseInfoForm/__tests__/BaseInfoFormItem.test.tsx create mode 100644 packages/base/src/page/DataExportManagement/Create/components/CreateTask/BaseInfoForm/__tests__/__snapshots__/BaseInfoFormItem.test.tsx.snap create mode 100644 packages/base/src/page/DataExportManagement/Create/components/CreateTask/ExportMethodForm/__tests__/ExportMethodItems.test.tsx create mode 100644 packages/base/src/page/DataExportManagement/Create/components/CreateTask/ExportMethodForm/__tests__/__snapshots__/ExportMethodItems.test.tsx.snap create mode 100644 packages/base/src/page/DataExportManagement/Create/components/CreateTask/ExportSourceForm/__tests__/ExportSourceFormItem.test.tsx create mode 100644 packages/base/src/page/DataExportManagement/Create/components/CreateTask/__tests__/__snapshots__/index.test.tsx.snap create mode 100644 packages/base/src/page/DataExportManagement/Create/components/CreateTask/__tests__/index.test.tsx create mode 100644 packages/base/src/page/DataExportManagement/Create/components/SubmitResult/__snapshots__/index.test.tsx.snap create mode 100644 packages/base/src/page/DataExportManagement/Create/components/SubmitResult/index.test.tsx create mode 100644 packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/UpdateInfoDrawer/__snapshots__/index.test.tsx.snap create mode 100644 packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/UpdateInfoDrawer/index.test.tsx create mode 100644 packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/__snapshots__/index.test.tsx.snap create mode 100644 packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/index.test.tsx create mode 100644 packages/base/src/page/DataExportManagement/Create/hooks/__tests__/__snapshots__/index.redux.test.ts.snap create mode 100644 packages/base/src/page/DataExportManagement/Create/hooks/__tests__/index.redux.test.ts create mode 100644 packages/base/src/page/DataExportManagement/Create/hooks/__tests__/useCreateExportTaskForm.test.tsx create mode 100644 packages/base/src/page/DataExportManagement/Create/testUtils/mockUseCreateDataExportReduxManage.ts create mode 100644 packages/base/src/page/DataExportManagement/Create/testUtils/mockUseCreateExportTaskForm.ts diff --git a/jest.config.js b/jest.config.js index b1366fe15..d432f1676 100644 --- a/jest.config.js +++ b/jest.config.js @@ -38,6 +38,7 @@ module.exports = { 'packages/**/src/App.tsx', 'packages/shared/api/common/**', '!packages/**/index.type.ts', + '!packages/**/index.enum.ts', '!packages/sqle/src/page/AuditPlan/**' ], setupFilesAfterEnv: ['/jest-setup.ts'], diff --git a/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap new file mode 100644 index 000000000..fdb1adbee --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap @@ -0,0 +1,1301 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`first should match snapshot when pageState is equal CREATE_TASK 1`] = ` +
+
+
+
+
+ +
+ +
+
+
+
+
+

+ + + + + + + 创建导出工单 + +

+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + + 4 / 3000 + + + +
+
+
+
+
+ + +
+
+
+ + + + + + + 4 / 3000 + + + + + + + + + + + + + + + + + +`; diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/UpdateInfoDrawer/index.test.tsx b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/UpdateInfoDrawer/index.test.tsx new file mode 100644 index 000000000..ce744240d --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/UpdateInfoDrawer/index.test.tsx @@ -0,0 +1,108 @@ +import { mockUseCurrentProject } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentProject'; +import { mockUseCurrentUser } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentUser'; +import { + mockCreateDataExportRedux, + mockUseCreateDataExportReduxManage +} from '../../../testUtils/mockUseCreateDataExportReduxManage'; +import { + mockUseCreateExportTaskForm, + mockUseCreateExportTaskFormReturn +} from '../../../testUtils/mockUseCreateExportTaskForm'; +import { superRender } from '../../../../../../testUtils/customRender'; +import UpdateInfoDrawer from '.'; +import { act, fireEvent, renderHook, screen } from '@testing-library/react'; +import { useForm } from 'antd/es/form/Form'; +import { ignoreInvalidValueForCSSStyleProperty } from '@actiontech/shared/lib/testUtil/common'; +import { getBySelector } from '@actiontech/shared/lib/testUtil/customQuery'; +import { ModalName } from '../../../../../../data/ModalName'; + +describe('test base/DataExport/Create/UpdateInfoDrawer', () => { + ignoreInvalidValueForCSSStyleProperty(); + + const customRender = ( + mockCreateExportTaskForm?: Parameters< + typeof mockUseCreateExportTaskForm + >[0], + mockRedux?: Parameters[0] + ) => { + mockUseCreateDataExportReduxManage({ + ...mockRedux, + updateDataExportInfoOpen: true + }); + mockUseCreateExportTaskForm(); + const { result: baseForm } = renderHook(() => useForm()); + const { result: sourceForm } = renderHook(() => useForm()); + const { result: methodForm } = renderHook(() => useForm()); + + mockUseCreateExportTaskForm({ + baseForm: baseForm.current[0], + sourceForm: sourceForm.current[0], + methodForm: methodForm.current[0], + ...mockCreateExportTaskForm + }); + + return superRender(); + }; + + beforeEach(() => { + jest.useFakeTimers(); + mockUseCurrentUser(); + mockUseCurrentProject(); + }); + afterEach(() => { + jest.useRealTimers(); + jest.clearAllMocks(); + jest.clearAllTimers(); + }); + + it('should match snapshot', () => { + const { baseElement } = customRender(); + expect(baseElement).toMatchSnapshot(); + }); + + it('should match snapshot when auditLoading is equal true', () => { + const { baseElement } = customRender({ auditLoading: true }); + expect(baseElement).toMatchSnapshot(); + fireEvent.click(getBySelector('.closed-icon-custom')); + expect(mockCreateDataExportRedux.updateModalStatus).not.toBeCalled(); + }); + + it('should execute updateModalStatus when closed drawer', () => { + customRender(); + + fireEvent.click(getBySelector('.closed-icon-custom')); + expect(mockCreateDataExportRedux.updateModalStatus).toBeCalledTimes(1); + expect(mockCreateDataExportRedux.updateModalStatus).toBeCalledWith({ + modalName: ModalName.DMS_UPDATE_EXPORT_TASK_INFO, + status: false + }); + }); + + it('should close drawer when after audited success', async () => { + mockUseCreateExportTaskFormReturn.auditAction.mockImplementation(() => + Promise.resolve(true) + ); + customRender(); + + fireEvent.click(screen.getByText('审 核')); + + expect(mockUseCreateExportTaskFormReturn.auditAction).toBeCalledTimes(1); + + await act(async () => jest.advanceTimersByTime(0)); + + expect(mockCreateDataExportRedux.updateModalStatus).toBeCalledTimes(1); + expect(mockCreateDataExportRedux.updateModalStatus).toBeCalledWith({ + modalName: ModalName.DMS_UPDATE_EXPORT_TASK_INFO, + status: false + }); + + jest.clearAllMocks(); + mockUseCreateExportTaskFormReturn.auditAction.mockImplementation(() => + Promise.resolve(false) + ); + + fireEvent.click(screen.getByText('审 核')); + await act(async () => jest.advanceTimersByTime(0)); + expect(mockCreateDataExportRedux.updateModalStatus).toBeCalledTimes(0); + }); +}); diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/UpdateInfoDrawer/index.tsx b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/UpdateInfoDrawer/index.tsx index 026a08601..9cfadd137 100644 --- a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/UpdateInfoDrawer/index.tsx +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/UpdateInfoDrawer/index.tsx @@ -1,6 +1,6 @@ import { BasicDrawer } from '@actiontech/shared'; import useCreateDataExportReduxManage from '../../../hooks/index.redux'; -import useCreateExportTaskFrom from '../../../hooks/useCreateExportTaskForm'; +import useCreateExportTaskForm from '../../../hooks/useCreateExportTaskForm'; import { useRef } from 'react'; import { ModalName } from '../../../../../../data/ModalName'; import { Divider, Spin } from 'antd'; @@ -39,7 +39,7 @@ const UpdateInfoDrawer: React.FC = () => { auditAction, formatSQLAction, auditLoading - } = useCreateExportTaskFrom(); + } = useCreateExportTaskForm(); const closeHandle = () => { if (auditLoading) { diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/__snapshots__/index.test.tsx.snap new file mode 100644 index 000000000..fcf740544 --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/__snapshots__/index.test.tsx.snap @@ -0,0 +1,212 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test base/DataExport/Create/SubmitWorkflow should match snapshot 1`] = ` +
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+ test +
+
+ desc +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+ 序号 + + 执行语句 + + 审核结果 +
+
+
+
+
+
+
+
+
+
+
+`; diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/index.test.tsx b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/index.test.tsx new file mode 100644 index 000000000..79878e46a --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/index.test.tsx @@ -0,0 +1,100 @@ +import { mockUseCurrentProject } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentProject'; +import SubmitExportWorkflow from '..'; +import { superRender } from '../../../../../../testUtils/customRender'; +import { + mockCreateDataExportRedux, + mockUseCreateDataExportReduxManage +} from '../../../testUtils/mockUseCreateDataExportReduxManage'; +import { act, fireEvent, screen } from '@testing-library/react'; +import { ModalName } from '../../../../../../data/ModalName'; +import dataExport from '../../../../../../testUtils/mockApi/dataExport'; +import { mockProjectInfo } from '@actiontech/shared/lib/testUtil/mockHook/data'; +import { AddDataExportWorkflowResponseData } from '../../../../../../testUtils/mockApi/dataExport/data'; +import { CreateDataExportPageEnum } from '../../../../../../store/dataExport'; +import { createSpyFailResponse } from '@actiontech/shared/lib/testUtil/mockApi'; + +describe('test base/DataExport/Create/SubmitWorkflow', () => { + beforeEach(() => { + jest.useFakeTimers(); + mockUseCurrentProject(); + mockUseCreateDataExportReduxManage(); + }); + afterEach(() => { + jest.clearAllMocks(); + jest.clearAllTimers(); + jest.useRealTimers(); + }); + + it('should match snapshot', () => { + const { container } = superRender(); + + expect(container).toMatchSnapshot(); + expect(mockCreateDataExportRedux.initModalStatus).toBeCalledTimes(1); + }); + + it('should execute updateModalStatus when clicked edit button', () => { + superRender(); + fireEvent.click(screen.getByText('编辑工单信息')); + expect(mockCreateDataExportRedux.updateModalStatus).toBeCalledTimes(1); + expect(mockCreateDataExportRedux.updateModalStatus).toBeCalledWith({ + modalName: ModalName.DMS_UPDATE_EXPORT_TASK_INFO, + status: true + }); + }); + + it('should disabled edit button and submit button when submitLoading is equal true', () => { + mockUseCreateDataExportReduxManage({ submitLoading: true }); + superRender(); + + expect(screen.getByText('编辑工单信息').closest('button')).toBeDisabled(); + expect(screen.getByText('提交工单').closest('button')).toBeDisabled(); + }); + + it('should send submit request when clicked submit button', async () => { + const addDataExportWorkflowSpy = dataExport.AddDataExportWorkflow(); + superRender(); + + fireEvent.click(screen.getByText('提交工单')); + expect(mockCreateDataExportRedux.updateSubmitLoading).toBeCalledTimes(1); + expect(mockCreateDataExportRedux.updateSubmitLoading).nthCalledWith( + 1, + true + ); + + expect(addDataExportWorkflowSpy).toBeCalledTimes(1); + expect(addDataExportWorkflowSpy).toBeCalledWith({ + project_uid: mockProjectInfo.projectID, + data_export_workflow: { + name: mockCreateDataExportRedux.formValues.baseValues.workflow_subject, + desc: mockCreateDataExportRedux.formValues.baseValues.desc, + tasks: mockCreateDataExportRedux.taskIDs.map((v) => ({ task_uid: v })) + } + }); + + await act(async () => jest.advanceTimersByTime(3000)); + expect(mockCreateDataExportRedux.updateWorkflowID).toBeCalledTimes(1); + expect(mockCreateDataExportRedux.updateWorkflowID).toBeCalledWith( + AddDataExportWorkflowResponseData?.export_data_workflow_uid + ); + expect(mockCreateDataExportRedux.updatePageState).toBeCalledTimes(1); + expect(mockCreateDataExportRedux.updatePageState).toBeCalledWith( + CreateDataExportPageEnum.SUBMIT_RESULT + ); + + expect(mockCreateDataExportRedux.updateSubmitLoading).toBeCalledTimes(2); + expect(mockCreateDataExportRedux.updateSubmitLoading).nthCalledWith( + 2, + false + ); + + jest.clearAllMocks(); + + addDataExportWorkflowSpy.mockImplementation(() => + createSpyFailResponse({}) + ); + fireEvent.click(screen.getByText('提交工单')); + await act(async () => jest.advanceTimersByTime(3000)); + expect(mockCreateDataExportRedux.updateWorkflowID).toBeCalledTimes(0); + expect(mockCreateDataExportRedux.updatePageState).toBeCalledTimes(0); + }); +}); diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/index.tsx b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/index.tsx index 93a34f55c..579a9e483 100644 --- a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/index.tsx +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/index.tsx @@ -20,7 +20,7 @@ const SubmitExportWorkflow: React.FC = () => { initModalStatus, submitLoading, updateModalStatus, - updateSubmitState, + updateSubmitLoading, taskIDs, updatePageState, updateWorkflowID @@ -28,7 +28,7 @@ const SubmitExportWorkflow: React.FC = () => { const { projectID } = useCurrentProject(); const submit = () => { - updateSubmitState(true); + updateSubmitLoading(true); dms .AddDataExportWorkflow({ project_uid: projectID, @@ -45,7 +45,7 @@ const SubmitExportWorkflow: React.FC = () => { } }) .finally(() => { - updateSubmitState(false); + updateSubmitLoading(false); }); }; diff --git a/packages/base/src/page/DataExportManagement/Create/hooks/__tests__/__snapshots__/index.redux.test.ts.snap b/packages/base/src/page/DataExportManagement/Create/hooks/__tests__/__snapshots__/index.redux.test.ts.snap new file mode 100644 index 000000000..27d385d89 --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/hooks/__tests__/__snapshots__/index.redux.test.ts.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test useCreateDataExportReduxManage should match snapshot 1`] = ` +Object { + "auditLoading": false, + "clearAllState": [Function], + "formValues": Object { + "baseValues": Object { + "desc": "desc", + "workflow_subject": "test", + }, + "methodValues": Object { + "exportMethod": "sql", + "sql": "select 1;", + }, + "sourceValues": Object { + "dbService": "121", + }, + }, + "initModalStatus": [Function], + "pageState": "CREATE_TASK", + "submitLoading": false, + "taskIDs": Array [ + "11111", + ], + "updateAuditLoading": [Function], + "updateDataExportInfoOpen": false, + "updateFormValues": [Function], + "updateModalStatus": [Function], + "updatePageState": [Function], + "updateSubmitLoading": [Function], + "updateTaskIDs": [Function], + "updateWorkflowID": [Function], + "workflowID": "123", +} +`; diff --git a/packages/base/src/page/DataExportManagement/Create/hooks/__tests__/index.redux.test.ts b/packages/base/src/page/DataExportManagement/Create/hooks/__tests__/index.redux.test.ts new file mode 100644 index 000000000..0c5257566 --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/hooks/__tests__/index.redux.test.ts @@ -0,0 +1,133 @@ +import { useDispatch, useSelector } from 'react-redux'; +import { ModalName } from '../../../../../data/ModalName'; +import { mockCreateDataExportRedux } from '../../testUtils/mockUseCreateDataExportReduxManage'; +import { renderHook } from '@testing-library/react-hooks'; +import useCreateDataExportReduxManage from '../index.redux'; + +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useDispatch: jest.fn(), + useSelector: jest.fn() +})); + +describe('test useCreateDataExportReduxManage', () => { + const useSelectorMock = useSelector as jest.Mock; + const dispatchSpy = jest.fn(); + + beforeEach(() => { + (useDispatch as jest.Mock).mockImplementation(() => dispatchSpy); + useSelectorMock.mockImplementation((e) => + e({ + dataExport: { + modalStatus: { [ModalName.DMS_UPDATE_EXPORT_TASK_INFO]: false }, + create: { + formValues: mockCreateDataExportRedux.formValues, + pageState: mockCreateDataExportRedux.pageState, + auditLoading: mockCreateDataExportRedux.auditLoading, + submitLoading: mockCreateDataExportRedux.submitLoading, + taskIDs: mockCreateDataExportRedux.taskIDs, + workflowID: mockCreateDataExportRedux.workflowID + } + } + }) + ); + }); + + afterEach(() => { + jest.clearAllMocks(); + jest.clearAllTimers(); + }); + + it('should match snapshot', () => { + const { result } = renderHook(() => useCreateDataExportReduxManage()); + expect(result.current).toMatchSnapshot(); + }); + + it('should execute dispatch', () => { + const { result } = renderHook(() => useCreateDataExportReduxManage()); + + result.current.updateFormValues(mockCreateDataExportRedux.formValues); + expect(dispatchSpy).toBeCalledTimes(1); + expect(dispatchSpy).toBeCalledWith({ + payload: { + formValues: mockCreateDataExportRedux.formValues + }, + type: 'dataExportManagement/updateFormValues' + }); + + result.current.updatePageState(mockCreateDataExportRedux.pageState); + expect(dispatchSpy).toBeCalledTimes(2); + expect(dispatchSpy).nthCalledWith(2, { + payload: { + pageState: mockCreateDataExportRedux.pageState + }, + type: 'dataExportManagement/updatePageState' + }); + + result.current.updateAuditLoading(mockCreateDataExportRedux.auditLoading); + expect(dispatchSpy).toBeCalledTimes(3); + expect(dispatchSpy).nthCalledWith(3, { + payload: { + auditLoading: mockCreateDataExportRedux.auditLoading + }, + type: 'dataExportManagement/updateAuditLoading' + }); + + result.current.updateSubmitLoading(mockCreateDataExportRedux.submitLoading); + expect(dispatchSpy).toBeCalledTimes(4); + expect(dispatchSpy).nthCalledWith(4, { + payload: { + submitLoading: mockCreateDataExportRedux.submitLoading + }, + type: 'dataExportManagement/updateSubmitLoading' + }); + + result.current.initModalStatus(); + expect(dispatchSpy).toBeCalledTimes(5); + expect(dispatchSpy).nthCalledWith(5, { + payload: { + modalStatus: { + [ModalName.DMS_UPDATE_EXPORT_TASK_INFO]: false + } + }, + type: 'dataExportManagement/initModalStatus' + }); + + result.current.updateModalStatus({ + modalName: ModalName.DMS_UPDATE_EXPORT_TASK_INFO, + status: true + }); + expect(dispatchSpy).toBeCalledTimes(6); + expect(dispatchSpy).nthCalledWith(6, { + payload: { + modalName: ModalName.DMS_UPDATE_EXPORT_TASK_INFO, + status: true + }, + type: 'dataExportManagement/updateModalStatus' + }); + + result.current.updateTaskIDs(mockCreateDataExportRedux.taskIDs); + expect(dispatchSpy).toBeCalledTimes(7); + expect(dispatchSpy).nthCalledWith(7, { + payload: { + taskIDs: mockCreateDataExportRedux.taskIDs + }, + type: 'dataExportManagement/updateAuditedTaskID' + }); + + result.current.updateWorkflowID(mockCreateDataExportRedux.workflowID); + expect(dispatchSpy).toBeCalledTimes(8); + expect(dispatchSpy).nthCalledWith(8, { + payload: { + workflowID: mockCreateDataExportRedux.workflowID + }, + type: 'dataExportManagement/updateCreatedWorkflowID' + }); + + result.current.clearAllState(); + expect(dispatchSpy).toBeCalledTimes(9); + expect(dispatchSpy).nthCalledWith(9, { + type: 'dataExportManagement/clearAllCreateState' + }); + }); +}); diff --git a/packages/base/src/page/DataExportManagement/Create/hooks/__tests__/useCreateExportTaskForm.test.tsx b/packages/base/src/page/DataExportManagement/Create/hooks/__tests__/useCreateExportTaskForm.test.tsx new file mode 100644 index 000000000..c2fc8383e --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/hooks/__tests__/useCreateExportTaskForm.test.tsx @@ -0,0 +1,231 @@ +import { + act, + cleanup, + fireEvent, + render, + renderHook, + screen +} from '@testing-library/react'; +import useCreateExportTaskForm from '../useCreateExportTaskForm'; +import { Button, Form, Input } from 'antd'; +import { mockUseCurrentProject } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentProject'; +import { mockUseCreateDataExportReduxManage } from '../../testUtils/mockUseCreateDataExportReduxManage'; +import dbServices from '../../../../../testUtils/mockApi/dbServices'; +import { DBServicesList } from '../../../../../testUtils/mockApi/global/data'; +import { formatterSQL } from 'sqle/src/utils/FormatterSQL'; +import { mockProjectInfo } from '@actiontech/shared/lib/testUtil/mockHook/data'; +import dataExport from '../../../../../testUtils/mockApi/dataExport'; +import { AddDataExportTaskResponseData } from '../../../../../testUtils/mockApi/dataExport/data'; +import { useState } from 'react'; +import { createSpyFailResponse } from '@actiontech/shared/lib/testUtil/mockApi'; + +describe('test base/DataExport/Create/hooks/useCreateExportTaskForm', () => { + const CustomCom = ({ + baseForm, + sourceForm, + methodForm, + auditAction, + auditLoading, + formatSQLAction, + resetAllForms + }: ReturnType) => { + const [auditResultValue, setAuditResultValue] = useState(''); + return ( + <> +
+ + + +
+
+ + + + + + +
+
+ + + +
+ +
+ audit action return value: {auditResultValue ?? ''} +
+ + + + + + ); + }; + + beforeEach(() => { + mockUseCurrentProject(); + mockUseCreateDataExportReduxManage(); + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.clearAllMocks(); + jest.clearAllTimers(); + jest.useRealTimers(); + }); + + it('should format sql when executed "formatSQLAction"', async () => { + const listDbServiceSpy = dbServices.ListDBServices(); + + const { result } = renderHook(() => useCreateExportTaskForm()); + + render(); + + fireEvent.change(screen.getByLabelText('sql'), { + target: { value: 'select 1;' } + }); + + fireEvent.click(screen.getByText('formatSQLAction')); + expect(listDbServiceSpy).toBeCalledTimes(0); + expect(screen.getByLabelText('sql')).toHaveValue(formatterSQL('select 1;')); + + fireEvent.change(screen.getByLabelText('dbService'), { + target: { value: '100' } + }); + fireEvent.change(screen.getByLabelText('sql'), { + target: { value: 'select 2;' } + }); + + fireEvent.click(screen.getByText('formatSQLAction')); + expect(listDbServiceSpy).toBeCalledTimes(1); + + await act(async () => jest.advanceTimersByTime(3000)); + + expect(screen.getByLabelText('sql')).toHaveValue( + formatterSQL('select 2;', DBServicesList[0].db_type) + ); + }); + + it('should execute "auditAction" when clicked audit button', async () => { + const addDataExportTaskSpy = dataExport.AddDataExportTask(); + const updateAuditLoadingSpy = jest.fn(); + const updateFormValuesSpy = jest.fn(); + const updateTaskIDsSpy = jest.fn(); + const auditLoading = false; + + mockUseCreateDataExportReduxManage({ + auditLoading, + updateAuditLoading: updateAuditLoadingSpy, + updateFormValues: updateFormValuesSpy, + updateTaskIDs: updateTaskIDsSpy + }); + + const { result } = renderHook(() => useCreateExportTaskForm()); + + render(); + fireEvent.change(screen.getByLabelText('name'), { + target: { value: 'name' } + }); + fireEvent.change(screen.getByLabelText('dbService'), { + target: { value: '100' } + }); + fireEvent.change(screen.getByLabelText('schema'), { + target: { value: 'schema' } + }); + fireEvent.change(screen.getByLabelText('sql'), { + target: { value: 'select 1;' } + }); + + fireEvent.click(screen.getByText('auditAction')); + await act(async () => jest.advanceTimersByTime(0)); + + expect(updateAuditLoadingSpy).toBeCalledTimes(1); + expect(updateAuditLoadingSpy).toBeCalledWith(true); + + expect(addDataExportTaskSpy).toBeCalledTimes(1); + expect(addDataExportTaskSpy).toBeCalledWith({ + project_uid: mockProjectInfo.projectID, + data_export_tasks: [ + { + database_name: 'schema', + db_service_uid: '100', + export_sql: 'select 1;' + } + ] + }); + await act(async () => jest.advanceTimersByTime(3000)); + expect(updateFormValuesSpy).toBeCalledTimes(1); + expect(updateFormValuesSpy).toBeCalledWith({ + baseValues: { + name: 'name' + }, + methodValues: { + sql: 'select 1;' + }, + sourceValues: { + dbService: '100', + schema: 'schema' + } + }); + expect(updateTaskIDsSpy).toBeCalledTimes(1); + expect(updateTaskIDsSpy).toBeCalledWith( + AddDataExportTaskResponseData?.data_export_task_uids + ); + + expect(updateAuditLoadingSpy).toBeCalledTimes(2); + expect(updateAuditLoadingSpy).toBeCalledWith(false); + expect(screen.getByTestId('audit-result-content')).toHaveTextContent( + 'audit action return value: true' + ); + + cleanup(); + addDataExportTaskSpy.mockImplementation(() => createSpyFailResponse({})); + render(); + fireEvent.click(screen.getByText('auditAction')); + await act(async () => jest.advanceTimersByTime(0)); + await act(async () => jest.advanceTimersByTime(3000)); + expect(screen.getByTestId('audit-result-content')).toHaveTextContent( + 'audit action return value: false' + ); + }); + + it('should rest all forms when executed "resetAllForm"', async () => { + const { result } = renderHook(() => useCreateExportTaskForm()); + + render(); + + fireEvent.change(screen.getByLabelText('name'), { + target: { value: 'name' } + }); + fireEvent.change(screen.getByLabelText('dbService'), { + target: { value: '100' } + }); + fireEvent.change(screen.getByLabelText('schema'), { + target: { value: 'schema' } + }); + fireEvent.change(screen.getByLabelText('sql'), { + target: { value: 'select 1;' } + }); + + fireEvent.click(screen.getByText('resetAllForms')); + expect(screen.getByLabelText('name')).toHaveValue(''); + expect(screen.getByLabelText('dbService')).toHaveValue(''); + expect(screen.getByLabelText('schema')).toHaveValue(''); + expect(screen.getByLabelText('sql')).toHaveValue(''); + }); +}); diff --git a/packages/base/src/page/DataExportManagement/Create/hooks/index.redux.ts b/packages/base/src/page/DataExportManagement/Create/hooks/index.redux.ts index 84eb1dabb..84d6616c4 100644 --- a/packages/base/src/page/DataExportManagement/Create/hooks/index.redux.ts +++ b/packages/base/src/page/DataExportManagement/Create/hooks/index.redux.ts @@ -7,12 +7,13 @@ import { initDataExportModalStatus, updateCreateDataExportFormValues, updateCreateDataExportPageState, - updateCreateDataExportAuditState, - updateCreateDataExportSubmitState, + updateCreateDataExportAuditLoading, + updateCreateDataExportSubmitLoading, updateDataExportModalStatus, updateDataExportAuditedTaskID, updateDataExportCreatedWorkflowID, - clearDataExportAllCreateState + clearDataExportAllCreateState, + CreateFormValuesType } from '../../../../store/dataExport'; import { ModalName } from '../../../../data/ModalName'; @@ -28,7 +29,7 @@ const useCreateDataExportReduxManage = () => { const dispatch = useDispatch(); const updateFormValues = useCallback( - (formValues: any) => { + (formValues: CreateFormValuesType) => { dispatch(updateCreateDataExportFormValues({ formValues })); }, [dispatch] @@ -41,16 +42,16 @@ const useCreateDataExportReduxManage = () => { [dispatch] ); - const updateAuditState = useCallback( + const updateAuditLoading = useCallback( (auditLoading: boolean) => { - dispatch(updateCreateDataExportAuditState({ auditLoading })); + dispatch(updateCreateDataExportAuditLoading({ auditLoading })); }, [dispatch] ); - const updateSubmitState = useCallback( + const updateSubmitLoading = useCallback( (submitLoading: boolean) => { - dispatch(updateCreateDataExportSubmitState({ submitLoading })); + dispatch(updateCreateDataExportSubmitLoading({ submitLoading })); }, [dispatch] ); @@ -94,8 +95,8 @@ const useCreateDataExportReduxManage = () => { ...state, updateFormValues, updatePageState, - updateAuditState, - updateSubmitState, + updateAuditLoading, + updateSubmitLoading, initModalStatus, updateModalStatus, updateTaskIDs, diff --git a/packages/base/src/page/DataExportManagement/Create/hooks/useCreateExportTaskForm.ts b/packages/base/src/page/DataExportManagement/Create/hooks/useCreateExportTaskForm.ts index 9fadbbd2b..9952a094e 100644 --- a/packages/base/src/page/DataExportManagement/Create/hooks/useCreateExportTaskForm.ts +++ b/packages/base/src/page/DataExportManagement/Create/hooks/useCreateExportTaskForm.ts @@ -10,12 +10,12 @@ import { } from '../components/CreateTask/index.type'; import { ResponseCode } from '@actiontech/shared/lib/enum'; -const useCreateExportTaskFrom = () => { +const useCreateExportTaskForm = () => { const [baseForm] = useForm(); const [sourceForm] = useForm(); const [methodForm] = useForm(); const { projectID } = useCurrentProject(); - const { auditLoading, updateAuditState, updateFormValues, updateTaskIDs } = + const { auditLoading, updateAuditLoading, updateFormValues, updateTaskIDs } = useCreateDataExportReduxManage(); const formatSQLAction = () => { @@ -50,12 +50,18 @@ const useCreateExportTaskFrom = () => { } }; + const resetAllForms = () => { + baseForm.resetFields(); + sourceForm.resetFields(); + methodForm.resetFields(); + }; + const auditAction = async () => { const baseValues = await baseForm.validateFields(); const sourceValues = await sourceForm.validateFields(); const methodValues = await methodForm.validateFields(); - updateAuditState(true); + updateAuditLoading(true); return dms .AddDataExportTask({ @@ -77,7 +83,7 @@ const useCreateExportTaskFrom = () => { return false; }) .finally(() => { - updateAuditState(false); + updateAuditLoading(false); }); }; @@ -87,8 +93,9 @@ const useCreateExportTaskFrom = () => { methodForm, auditLoading, formatSQLAction, - auditAction + auditAction, + resetAllForms }; }; -export default useCreateExportTaskFrom; +export default useCreateExportTaskForm; diff --git a/packages/base/src/page/DataExportManagement/Create/testUtils/mockUseCreateDataExportReduxManage.ts b/packages/base/src/page/DataExportManagement/Create/testUtils/mockUseCreateDataExportReduxManage.ts new file mode 100644 index 000000000..2fda7fc7c --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/testUtils/mockUseCreateDataExportReduxManage.ts @@ -0,0 +1,34 @@ +import { CreateDataExportPageEnum } from '../../../../store/dataExport'; +import { ExportMethodEnum } from '../components/CreateTask/ExportMethodForm/index.enum'; +import * as useCreateDataExportReduxManage from '../hooks/index.redux'; + +export const mockCreateDataExportRedux = { + updateDataExportInfoOpen: false, + formValues: { + baseValues: { workflow_subject: 'test', desc: 'desc' }, + sourceValues: { dbService: '121' }, + methodValues: { sql: 'select 1;', exportMethod: ExportMethodEnum.sql } + }, + pageState: CreateDataExportPageEnum.CREATE_TASK, + auditLoading: false, + submitLoading: false, + taskIDs: ['11111'], + workflowID: '123', + updateFormValues: jest.fn(), + updatePageState: jest.fn(), + updateAuditLoading: jest.fn(), + updateSubmitLoading: jest.fn(), + initModalStatus: jest.fn(), + updateModalStatus: jest.fn(), + updateTaskIDs: jest.fn(), + updateWorkflowID: jest.fn(), + clearAllState: jest.fn() +}; + +export const mockUseCreateDataExportReduxManage = ( + data?: Partial +) => { + const spy = jest.spyOn(useCreateDataExportReduxManage, 'default'); + spy.mockImplementation(() => ({ ...mockCreateDataExportRedux, ...data })); + return spy; +}; diff --git a/packages/base/src/page/DataExportManagement/Create/testUtils/mockUseCreateExportTaskForm.ts b/packages/base/src/page/DataExportManagement/Create/testUtils/mockUseCreateExportTaskForm.ts new file mode 100644 index 000000000..4e1dab427 --- /dev/null +++ b/packages/base/src/page/DataExportManagement/Create/testUtils/mockUseCreateExportTaskForm.ts @@ -0,0 +1,22 @@ +import * as useCreateExportTaskForm from '../hooks/useCreateExportTaskForm'; + +export const mockUseCreateExportTaskFormReturn = { + baseForm: null as any, + sourceForm: null as any, + methodForm: null as any, + auditLoading: false, + formatSQLAction: jest.fn(), + auditAction: jest.fn(), + resetAllForms: jest.fn() +}; + +export const mockUseCreateExportTaskForm = ( + data?: Partial +) => { + const spy = jest.spyOn(useCreateExportTaskForm, 'default'); + spy.mockImplementation(() => ({ + ...mockUseCreateExportTaskFormReturn, + ...data + })); + return spy; +}; diff --git a/packages/base/src/store/dataExport/index.ts b/packages/base/src/store/dataExport/index.ts index 58507d037..ed96575bd 100644 --- a/packages/base/src/store/dataExport/index.ts +++ b/packages/base/src/store/dataExport/index.ts @@ -182,8 +182,8 @@ const dataExportManagement = createSlice({ export const { updateFormValues: updateCreateDataExportFormValues, updatePageState: updateCreateDataExportPageState, - updateAuditLoading: updateCreateDataExportAuditState, - updateSubmitLoading: updateCreateDataExportSubmitState, + updateAuditLoading: updateCreateDataExportAuditLoading, + updateSubmitLoading: updateCreateDataExportSubmitLoading, initModalStatus: initDataExportModalStatus, updateModalStatus: updateDataExportModalStatus, updateAuditedTaskID: updateDataExportAuditedTaskID, diff --git a/packages/base/src/testUtils/mockApi/dataExport/data.ts b/packages/base/src/testUtils/mockApi/dataExport/data.ts index 4137a6b1b..315653380 100644 --- a/packages/base/src/testUtils/mockApi/dataExport/data.ts +++ b/packages/base/src/testUtils/mockApi/dataExport/data.ts @@ -1,4 +1,8 @@ -import { IListDataExportWorkflow } from '@actiontech/shared/lib/api/base/service/common'; +import { + IAddDataExportTaskReply, + IAddDataExportWorkflowReply, + IListDataExportWorkflow +} from '@actiontech/shared/lib/api/base/service/common'; import { ListDataExportWorkflowStatusEnum } from '@actiontech/shared/lib/api/base/service/common.enum'; export const DataExportWorkflowList: IListDataExportWorkflow[] = [ @@ -38,3 +42,12 @@ export const DataExportWorkflowList: IListDataExportWorkflow[] = [ current_step_type: '' } ]; + +export const AddDataExportTaskResponseData: IAddDataExportTaskReply['data'] = { + data_export_task_uids: ['1752522203951271936'] +}; + +export const AddDataExportWorkflowResponseData: IAddDataExportWorkflowReply['data'] = + { + export_data_workflow_uid: '1483489234842342' + }; diff --git a/packages/base/src/testUtils/mockApi/dataExport/index.ts b/packages/base/src/testUtils/mockApi/dataExport/index.ts index ac8738c0f..db1b2fb8b 100644 --- a/packages/base/src/testUtils/mockApi/dataExport/index.ts +++ b/packages/base/src/testUtils/mockApi/dataExport/index.ts @@ -3,11 +3,18 @@ import { MockSpyApy, createSpySuccessResponse } from '@actiontech/shared/lib/testUtil/mockApi'; -import { DataExportWorkflowList } from './data'; +import { + AddDataExportTaskResponseData, + AddDataExportWorkflowResponseData, + DataExportWorkflowList +} from './data'; class MockDataExportApi implements MockSpyApy { public mockAllApi() { this.ListDataExportWorkflows(); + this.batchCloseWorkflowAction(); + this.AddDataExportTask(); + this.AddDataExportWorkflow(); } public ListDataExportWorkflows() { @@ -25,6 +32,26 @@ class MockDataExportApi implements MockSpyApy { spy.mockImplementation(() => createSpySuccessResponse({})); return spy; } + + public AddDataExportTask() { + const spy = jest.spyOn(dms, 'AddDataExportTask'); + spy.mockImplementation(() => + createSpySuccessResponse({ + data: AddDataExportTaskResponseData + }) + ); + return spy; + } + + public AddDataExportWorkflow() { + const spy = jest.spyOn(dms, 'AddDataExportWorkflow'); + spy.mockImplementation(() => + createSpySuccessResponse({ + data: AddDataExportWorkflowResponseData + }) + ); + return spy; + } } export default new MockDataExportApi(); diff --git a/packages/shared/lib/testUtil/common.tsx b/packages/shared/lib/testUtil/common.tsx index a5409f9fb..d890d1b4a 100644 --- a/packages/shared/lib/testUtil/common.tsx +++ b/packages/shared/lib/testUtil/common.tsx @@ -146,3 +146,23 @@ export const ignoreComponentAutoCreatedListNoKey = () => { console.error = error; }); }; + +export const ignoreInvalidValueForCSSStyleProperty = () => { + const error = console.error; + + beforeAll(() => { + console.error = (...arg) => { + if ( + typeof arg[0] === 'string' && + arg[0].includes('`NaN` is an invalid value for the') + ) { + return; + } + error(...arg); + }; + }); + + afterAll(() => { + console.error = error; + }); +}; From c8119e53b93eaf568052943a34923e2e23462831 Mon Sep 17 00:00:00 2001 From: lizhensheng Date: Wed, 31 Jan 2024 17:54:34 +0800 Subject: [PATCH 2/3] [feature]: Add SQL type pre-check when submitting workflow --- .../src/hooks/useDbService/index.test.tsx | 4 +- .../base/src/locale/zh-CN/dmsDataExport.ts | 7 +- .../Common/AuditResultList/Table/column.tsx | 5 + .../Common/AuditResultList/Table/index.tsx | 11 +- .../AuditResultList/Table/index.type.ts | 1 + .../Common/AuditResultList/index.tsx | 9 +- .../Common/AuditResultList/index.type.ts | 1 + .../Common/TaskStatus/index.tsx | 8 + .../__snapshots__/index.test.tsx.snap | 17 +- .../__snapshots__/index.test.tsx.snap | 966 +++++++++++++++++- .../SubmitWorkflow/__tests__/index.test.tsx | 48 +- .../components/SubmitWorkflow/index.tsx | 43 +- .../TaskDetail/ResultCard/AuditResultTag.tsx | 5 +- .../TaskDetail/ResultCard/index.tsx | 18 +- .../Detail/components/ExportDetail/style.ts | 93 ++ .../__snapshots__/index.ce.test.tsx.snap | 2 +- .../src/testUtils/mockApi/dataExport/data.ts | 73 +- .../src/testUtils/mockApi/dataExport/index.ts | 24 +- .../shared/lib/api/base/service/common.d.ts | 2 + .../lib/api/base/service/common.enum.ts | 10 +- .../lib/api/base/service/dms/index.enum.ts | 4 +- 21 files changed, 1306 insertions(+), 45 deletions(-) diff --git a/packages/base/src/hooks/useDbService/index.test.tsx b/packages/base/src/hooks/useDbService/index.test.tsx index 99b8f4690..741463272 100644 --- a/packages/base/src/hooks/useDbService/index.test.tsx +++ b/packages/base/src/hooks/useDbService/index.test.tsx @@ -38,13 +38,13 @@ describe('useDbService', () => { result.current.updateDbServiceList({ project_uid: projectID, functional_module: - ListDBServiceTipsFunctionalModuleEnum.create_audit_plan + ListDBServiceTipsFunctionalModuleEnum.create_export_task }) ); expect(listDbServicesSpy).toBeCalled(); expect(listDbServicesSpy).toBeCalledWith({ functional_module: - ListDBServiceTipsFunctionalModuleEnum.create_audit_plan, + ListDBServiceTipsFunctionalModuleEnum.create_export_task, project_uid: projectID }); expect(result.current.loading).toBeTruthy(); diff --git a/packages/base/src/locale/zh-CN/dmsDataExport.ts b/packages/base/src/locale/zh-CN/dmsDataExport.ts index 19cf05fdd..2c19396a0 100644 --- a/packages/base/src/locale/zh-CN/dmsDataExport.ts +++ b/packages/base/src/locale/zh-CN/dmsDataExport.ts @@ -11,7 +11,8 @@ export default { export_failed: '导出失败', expired: '已过期', rejected: '已驳回', - canceled: '已关闭' + canceled: '已关闭', + file_deleted: '已移除' }, batchCancel: { messageWarn: @@ -49,7 +50,8 @@ export default { sourceTitle: '工单导出对象', methodTitle: '导出方式', updateInfoAction: '编辑工单信息', - submitAction: '提交工单' + submitAction: '提交工单', + submitTips: '仅支持对DQL语句创建导出工单' }, result: { success: '工单创建成功', @@ -162,6 +164,7 @@ export default { column: { number: '序号', execSql: '执行语句', + sqlType: '语句类型', auditResult: '审核结果' } } diff --git a/packages/base/src/page/DataExportManagement/Common/AuditResultList/Table/column.tsx b/packages/base/src/page/DataExportManagement/Common/AuditResultList/Table/column.tsx index 4aacb7440..20e144909 100644 --- a/packages/base/src/page/DataExportManagement/Common/AuditResultList/Table/column.tsx +++ b/packages/base/src/page/DataExportManagement/Common/AuditResultList/Table/column.tsx @@ -32,6 +32,11 @@ export const AuditResultForCreateOrderColumn = ( ); } }, + { + dataIndex: 'export_sql_type', + title: () => t('dmsDataExport.common.auditResult.column.sqlType'), + render: (type: string) => type || '-' + }, { dataIndex: 'audit_sql_result', title: () => t('dmsDataExport.common.auditResult.column.auditResult'), diff --git a/packages/base/src/page/DataExportManagement/Common/AuditResultList/Table/index.tsx b/packages/base/src/page/DataExportManagement/Common/AuditResultList/Table/index.tsx index e12202d34..fb9a0d6f2 100644 --- a/packages/base/src/page/DataExportManagement/Common/AuditResultList/Table/index.tsx +++ b/packages/base/src/page/DataExportManagement/Common/AuditResultList/Table/index.tsx @@ -13,7 +13,8 @@ import { IListDataExportTaskSQL } from '@actiontech/shared/lib/api/base/service/ const AuditResultTable: React.FC = ({ taskID, - projectID + projectID, + updateExecuteSQLsTypeIsDQL }) => { const [currentAuditResultRecord, setCurrentAuditResultRecord] = useState(); @@ -44,10 +45,12 @@ const AuditResultTable: React.FC = ({ ready: typeof taskID === 'string', refreshDeps: [pagination, taskID], onSuccess(res) { - // updateTaskRecordTotalNum?.(taskID ?? '', res.total ?? 0); + updateExecuteSQLsTypeIsDQL?.( + !!res.list?.every((item) => item.export_sql_type === 'dql') + ); }, onError() { - // updateTaskRecordTotalNum?.(taskID ?? '', 0); + updateExecuteSQLsTypeIsDQL?.(true); } } ); @@ -56,7 +59,7 @@ const AuditResultTable: React.FC = ({ <> void; }; export type AuditResultDrawerProps = { diff --git a/packages/base/src/page/DataExportManagement/Common/AuditResultList/index.tsx b/packages/base/src/page/DataExportManagement/Common/AuditResultList/index.tsx index 4f05b3336..7f8ff4ab1 100644 --- a/packages/base/src/page/DataExportManagement/Common/AuditResultList/index.tsx +++ b/packages/base/src/page/DataExportManagement/Common/AuditResultList/index.tsx @@ -11,7 +11,8 @@ import { ResponseCode } from '@actiontech/shared/lib/enum'; const AuditResultList: React.FC = ({ taskIDs, - projectID + projectID, + updateExecuteSQLsTypeIsDQL }) => { const [tasks, setTasks] = useState([]); @@ -56,7 +57,11 @@ const AuditResultList: React.FC = ({ /> - + ); }; diff --git a/packages/base/src/page/DataExportManagement/Common/AuditResultList/index.type.ts b/packages/base/src/page/DataExportManagement/Common/AuditResultList/index.type.ts index 6fef9e46c..ba40897f9 100644 --- a/packages/base/src/page/DataExportManagement/Common/AuditResultList/index.type.ts +++ b/packages/base/src/page/DataExportManagement/Common/AuditResultList/index.type.ts @@ -1,4 +1,5 @@ export type AuditResultListProps = { taskIDs: string[]; projectID: string; + updateExecuteSQLsTypeIsDQL?: (val: boolean) => void; }; diff --git a/packages/base/src/page/DataExportManagement/Common/TaskStatus/index.tsx b/packages/base/src/page/DataExportManagement/Common/TaskStatus/index.tsx index bce0fd002..91933d0c8 100644 --- a/packages/base/src/page/DataExportManagement/Common/TaskStatus/index.tsx +++ b/packages/base/src/page/DataExportManagement/Common/TaskStatus/index.tsx @@ -6,6 +6,7 @@ import { } from 'sqle/src/icon/Order'; import { t } from '../../../../locale'; import { StatusStyleWrapper } from '../style'; +import { IconDelete } from '@actiontech/shared/lib/Icon/common'; const taskStatusMap = () => { return new Map([ @@ -36,6 +37,13 @@ const taskStatusMap = () => { {t('dmsDataExport.status.wait_for_export')} + ], + [ + GetDataExportTaskStatusEnum.file_deleted, + <> + + {t('dmsDataExport.status.file_deleted')} + ] ]); }; diff --git a/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap index fdb1adbee..8bf949da5 100644 --- a/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/base/src/page/DataExportManagement/Create/__tests__/__snapshots__/index.test.tsx.snap @@ -1231,6 +1231,12 @@ exports[`first should match snapshot when pageState is equal SUBMIT_WORKFLOW 1`] > 执行语句 + + 语句类型 + + +
+   +
+
执行语句 + + 语句类型 + + +
+   +
+
`; + +exports[`test base/DataExport/Create/SubmitWorkflow should match snapshot 2`] = ` +
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+ test +
+
+ desc +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 序号 + + 执行语句 + + 语句类型 + + 审核结果 +
+ 1 + +
+
+ + + SELECT + + + + 1 + + ; + +
+
+ + + +
+
+
+ dql + +
+
+ + + + + + + 审核通过 + +
+
+
+ 2 + +
+
+ + + SELECT + + + + 1 + + ; + +
+
+ + + +
+
+
+ dql + +
+
+ + + + + + + 审核通过 + +
+
+
+ 3 + +
+
+ + + SELECT + + + + 1 + + ; + +
+
+ + + +
+
+
+ dql + +
+
+ + + + + + + 审核通过 + +
+
+
+ 4 + +
+
+ + + SELECT + + + + 1 + + ; + +
+
+ + + +
+
+
+ dql + +
+
+ + + + + + + 审核通过 + +
+
+
+ 5 + +
+
+ + + SELECT + + + + 1 + + ; + +
+
+ + + +
+
+
+ dql + +
+
+ + + + + + + 审核通过 + +
+
+
+ 6 + +
+
+ + + SELECT + + + + 1 + + ; + +
+
+ + + +
+
+
+ dql + +
+
+ + + + + + + 审核通过 + +
+
+
+
+
+
+
    +
  • + + 共 6 条数据 + +
  • +
  • + +
  • +
  • + + 1 + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+
+
+
+`; diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/index.test.tsx b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/index.test.tsx index 79878e46a..45a9e49f6 100644 --- a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/index.test.tsx +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/__tests__/index.test.tsx @@ -5,16 +5,24 @@ import { mockCreateDataExportRedux, mockUseCreateDataExportReduxManage } from '../../../testUtils/mockUseCreateDataExportReduxManage'; -import { act, fireEvent, screen } from '@testing-library/react'; +import { act, cleanup, fireEvent, screen } from '@testing-library/react'; import { ModalName } from '../../../../../../data/ModalName'; import dataExport from '../../../../../../testUtils/mockApi/dataExport'; import { mockProjectInfo } from '@actiontech/shared/lib/testUtil/mockHook/data'; -import { AddDataExportWorkflowResponseData } from '../../../../../../testUtils/mockApi/dataExport/data'; +import { + AddDataExportWorkflowResponseData, + ListDataExportTaskSQLsResponseData +} from '../../../../../../testUtils/mockApi/dataExport/data'; import { CreateDataExportPageEnum } from '../../../../../../store/dataExport'; -import { createSpyFailResponse } from '@actiontech/shared/lib/testUtil/mockApi'; +import { + createSpyFailResponse, + createSpySuccessResponse +} from '@actiontech/shared/lib/testUtil/mockApi'; describe('test base/DataExport/Create/SubmitWorkflow', () => { beforeEach(() => { + dataExport.BatchGetDataExportTask(); + dataExport.ListDataExportTaskSQLs(); jest.useFakeTimers(); mockUseCurrentProject(); mockUseCreateDataExportReduxManage(); @@ -23,13 +31,19 @@ describe('test base/DataExport/Create/SubmitWorkflow', () => { jest.clearAllMocks(); jest.clearAllTimers(); jest.useRealTimers(); + cleanup(); }); - it('should match snapshot', () => { + it('should match snapshot', async () => { const { container } = superRender(); expect(container).toMatchSnapshot(); expect(mockCreateDataExportRedux.initModalStatus).toBeCalledTimes(1); + + await act(async () => jest.advanceTimersByTime(3000)); + await act(async () => jest.advanceTimersByTime(3000)); + + expect(container).toMatchSnapshot(); }); it('should execute updateModalStatus when clicked edit button', () => { @@ -97,4 +111,30 @@ describe('test base/DataExport/Create/SubmitWorkflow', () => { expect(mockCreateDataExportRedux.updateWorkflowID).toBeCalledTimes(0); expect(mockCreateDataExportRedux.updatePageState).toBeCalledTimes(0); }); + + it('should disabled submit button when sqls is exits dml type', async () => { + dataExport.ListDataExportTaskSQLs().mockImplementation(() => + createSpySuccessResponse({ + data: [ + ...ListDataExportTaskSQLsResponseData, + { + uid: 10, + sql: 'SELECT 1;', + export_status: '', + export_sql_type: 'dml', + audit_level: '' + } + ] + }) + ); + + superRender(); + await act(async () => jest.advanceTimersByTime(3000)); + await act(async () => jest.advanceTimersByTime(3000)); + expect(screen.getByText('提交工单').closest('button')).toBeDisabled(); + fireEvent.mouseOver(screen.getByText('提交工单')); + await act(async () => jest.advanceTimersByTime(300)); + + expect(screen.getByText('仅支持对DQL语句创建导出工单')).toBeInTheDocument(); + }); }); diff --git a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/index.tsx b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/index.tsx index 579a9e483..5744088cf 100644 --- a/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/index.tsx +++ b/packages/base/src/page/DataExportManagement/Create/components/SubmitWorkflow/index.tsx @@ -1,8 +1,13 @@ import { useCurrentProject } from '@actiontech/shared/lib/global'; import useCreateDataExportReduxManage from '../../hooks/index.redux'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import UpdateInfoDrawer from './UpdateInfoDrawer'; -import { BasicButton, PageHeader } from '@actiontech/shared'; +import { + BasicButton, + BasicToolTips, + EmptyBox, + PageHeader +} from '@actiontech/shared'; import { useTranslation } from 'react-i18next'; import BackToWorkflowList from '../../../Common/BackToWorkflowList'; import { Space } from 'antd'; @@ -27,6 +32,8 @@ const SubmitExportWorkflow: React.FC = () => { } = useCreateDataExportReduxManage(); const { projectID } = useCurrentProject(); + const [executeSQLsIsDQL, updateExecuteSQLsTypeIsDQL] = useState(true); + const submit = () => { updateSubmitLoading(true); dms @@ -70,13 +77,27 @@ const SubmitExportWorkflow: React.FC = () => { > {t('dmsDataExport.create.update.updateInfoAction')} - + + {t('dmsDataExport.create.update.submitAction')} + + + } > - {t('dmsDataExport.create.update.submitAction')} - + + {t('dmsDataExport.create.update.submitAction')} + + } /> @@ -85,7 +106,11 @@ const SubmitExportWorkflow: React.FC = () => { desc={formValues?.baseValues?.desc} /> - + diff --git a/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/TaskDetail/ResultCard/AuditResultTag.tsx b/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/TaskDetail/ResultCard/AuditResultTag.tsx index 1ff95d221..bf68383a6 100644 --- a/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/TaskDetail/ResultCard/AuditResultTag.tsx +++ b/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/TaskDetail/ResultCard/AuditResultTag.tsx @@ -1,6 +1,4 @@ import { BasicTag } from '@actiontech/shared'; -import { IAuditResult } from '@actiontech/shared/lib/api/sqle/service/common'; - import { useTranslation } from 'react-i18next'; import { RuleResV1LevelEnum } from '@actiontech/shared/lib/api/sqle/service/common.enum'; import { useMemo } from 'react'; @@ -11,8 +9,9 @@ import { IconOrderAuditResultWarning, IconOrderAuditResultError } from 'sqle/src/icon/Order'; +import { IAuditSQLResult } from '@actiontech/shared/lib/api/base/service/common'; -const AuditResultTag: React.FC<{ auditResult?: IAuditResult[] }> = ({ +const AuditResultTag: React.FC<{ auditResult?: IAuditSQLResult[] }> = ({ auditResult }) => { const { t } = useTranslation(); diff --git a/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/TaskDetail/ResultCard/index.tsx b/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/TaskDetail/ResultCard/index.tsx index ad0688f80..8c052cb0c 100644 --- a/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/TaskDetail/ResultCard/index.tsx +++ b/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/TaskDetail/ResultCard/index.tsx @@ -1,14 +1,14 @@ import { BasicButton, Copy } from '@actiontech/shared'; import { Divider, Space, message } from 'antd'; import { useTranslation } from 'react-i18next'; -import { - DataSourceResultCardStyleWrapper, - DataSourceResultSqlOptionsStyleWrapper -} from 'sqle/src/page/Order/AuditDetail/style'; import { ExportResultCardProp } from './index.type'; import HighlightCode from 'sqle/src/utils/HighlightCode'; -import AuditResultTag from 'sqle/src/page/Order/AuditDetail/DataSourceResultList/components/AuditResultTag'; import AuditResultTree from './AuditResultTree'; +import { + ExportContentStyleWrapper, + ExportResultCardStyleWrapper +} from '../../style'; +import AuditResultTag from './AuditResultTag'; const ExportResultCard: React.FC = (props) => { const { t } = useTranslation(); @@ -21,7 +21,7 @@ const ExportResultCard: React.FC = (props) => { }; return ( - + {contextHolder}
@@ -39,9 +39,9 @@ const ExportResultCard: React.FC = (props) => {
- + {t('dmsDataExport.detail.exportResult.taskDetail.exportContent')} - +
@@ -82,7 +82,7 @@ const ExportResultCard: React.FC = (props) => {
           }
         /> */}
       
- + ); }; diff --git a/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/style.ts b/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/style.ts index be76ba251..886431c69 100644 --- a/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/style.ts +++ b/packages/base/src/page/DataExportManagement/Detail/components/ExportDetail/style.ts @@ -18,3 +18,96 @@ export const WorkflowDetailExportResultStyleWrapper = styled('section')` } } `; + +export const ExportResultCardStyleWrapper = styled('div')` + width: 100%; + border-radius: 8px; + border: 1px solid + ${({ theme }) => theme.sharedTheme.uiToken.colorBorderSecondary}; + background: ${({ theme }) => theme.sharedTheme.uiToken.colorBgBase}; + margin-bottom: 20px; + + & .result-card-header { + height: 60px; + padding: 16px 20px; + display: flex; + justify-content: space-between; + + .number { + color: ${({ theme }) => theme.sharedTheme.uiToken.colorTextBase}; + font-size: 14px; + font-style: normal; + font-weight: 700; + margin-right: 0 12px 0 4px; + } + + .result-card-status-wrap { + display: flex; + margin-left: 4px; + + .result-card-status-divider { + height: 28px; + margin: 0 12px 0 4px; + } + } + } + + & .result-card-content { + padding: 16px 20px; + + .result-card-content-options { + display: flex; + } + + .result-card-sql-wrap { + margin-top: 8px; + padding-bottom: 2px; + } + + .code-line { + height: 26px; + line-height: 26px; + + .code-line-number { + display: inline-block; + width: 24px; + text-align: center; + color: ${({ theme }) => theme.sharedTheme.uiToken.colorTextQuaternary}; + user-select: none; + } + } + + & .ant-collapse.result-record-collapse .ant-collapse-header { + padding: 8px 0; + + .ant-collapse-header-text { + color: ${({ theme }) => theme.sharedTheme.uiToken.colorTextBase}; + font-weight: 500; + } + } + } + + .result-card-footer { + padding: 16px 20px; + border-top: 1px solid + ${({ theme }) => theme.sharedTheme.basic.colorGrayLine}; + } +`; + +export const ExportContentStyleWrapper = styled('div')<{ + active: boolean; +}>` + padding: 0 12px; + border-radius: 4px; + background: ${({ active, theme }) => + active + ? theme.sharedTheme.basic.colorPrimaryBgActive + : theme.sharedTheme.basic.colorBgLayoutGray}; + height: 28px; + line-height: 28px; + color: ${({ active, theme }) => + active + ? theme.sharedTheme.uiToken.colorPrimary + : theme.sharedTheme.uiToken.colorTextTertiary}; + margin-right: 4px; +`; diff --git a/packages/base/src/page/DataExportManagement/__tests__/__snapshots__/index.ce.test.tsx.snap b/packages/base/src/page/DataExportManagement/__tests__/__snapshots__/index.ce.test.tsx.snap index 530901242..5c96ef7f5 100644 --- a/packages/base/src/page/DataExportManagement/__tests__/__snapshots__/index.ce.test.tsx.snap +++ b/packages/base/src/page/DataExportManagement/__tests__/__snapshots__/index.ce.test.tsx.snap @@ -758,7 +758,7 @@ exports[`test base/DataExport ce should match snapshot 1`] = ` > diff --git a/packages/base/src/testUtils/mockApi/dataExport/data.ts b/packages/base/src/testUtils/mockApi/dataExport/data.ts index 315653380..cc08f1bb8 100644 --- a/packages/base/src/testUtils/mockApi/dataExport/data.ts +++ b/packages/base/src/testUtils/mockApi/dataExport/data.ts @@ -1,9 +1,14 @@ import { IAddDataExportTaskReply, IAddDataExportWorkflowReply, + IGetDataExportTask, + IListDataExportTaskSQL, IListDataExportWorkflow } from '@actiontech/shared/lib/api/base/service/common'; -import { ListDataExportWorkflowStatusEnum } from '@actiontech/shared/lib/api/base/service/common.enum'; +import { + GetDataExportTaskStatusEnum, + ListDataExportWorkflowStatusEnum +} from '@actiontech/shared/lib/api/base/service/common.enum'; export const DataExportWorkflowList: IListDataExportWorkflow[] = [ { @@ -51,3 +56,69 @@ export const AddDataExportWorkflowResponseData: IAddDataExportWorkflowReply['dat { export_data_workflow_uid: '1483489234842342' }; + +export const BatchGetDataExportTaskResponseData: IGetDataExportTask[] = [ + { + task_uid: '1752623436938612736', + db_info: { + uid: '1752583372904861696', + name: 'bl1', + db_type: '', + database_name: '' + }, + status: GetDataExportTaskStatusEnum.init, + file_name: '', + audit_result: { + audit_level: '', + score: 100, + pass_rate: 1 + }, + export_type: 'SQL', + export_file_type: 'CSV' + } +]; + +export const ListDataExportTaskSQLsResponseData: IListDataExportTaskSQL[] = [ + { + uid: 1, + sql: 'SELECT 1;', + export_status: '', + export_sql_type: 'dql', + audit_level: '' + }, + { + uid: 2, + sql: 'SELECT 1;', + export_status: '', + export_sql_type: 'dql', + audit_level: '' + }, + { + uid: 3, + sql: 'SELECT 1;', + export_status: '', + export_sql_type: 'dql', + audit_level: '' + }, + { + uid: 4, + sql: 'SELECT 1;', + export_status: '', + export_sql_type: 'dql', + audit_level: '' + }, + { + uid: 5, + sql: 'SELECT 1;', + export_status: '', + export_sql_type: 'dql', + audit_level: '' + }, + { + uid: 6, + sql: 'SELECT 1;', + export_status: '', + export_sql_type: 'dql', + audit_level: '' + } +]; diff --git a/packages/base/src/testUtils/mockApi/dataExport/index.ts b/packages/base/src/testUtils/mockApi/dataExport/index.ts index db1b2fb8b..ec4ab0d44 100644 --- a/packages/base/src/testUtils/mockApi/dataExport/index.ts +++ b/packages/base/src/testUtils/mockApi/dataExport/index.ts @@ -6,7 +6,9 @@ import { import { AddDataExportTaskResponseData, AddDataExportWorkflowResponseData, - DataExportWorkflowList + BatchGetDataExportTaskResponseData, + DataExportWorkflowList, + ListDataExportTaskSQLsResponseData } from './data'; class MockDataExportApi implements MockSpyApy { @@ -52,6 +54,26 @@ class MockDataExportApi implements MockSpyApy { ); return spy; } + + public BatchGetDataExportTask() { + const spy = jest.spyOn(dms, 'BatchGetDataExportTask'); + spy.mockImplementation(() => + createSpySuccessResponse({ + data: BatchGetDataExportTaskResponseData + }) + ); + return spy; + } + + public ListDataExportTaskSQLs() { + const spy = jest.spyOn(dms, 'ListDataExportTaskSQLs'); + spy.mockImplementation(() => + createSpySuccessResponse({ + data: ListDataExportTaskSQLsResponseData + }) + ); + return spy; + } } export default new MockDataExportApi(); diff --git a/packages/shared/lib/api/base/service/common.d.ts b/packages/shared/lib/api/base/service/common.d.ts index 5fb9e6f02..f2fd12a11 100644 --- a/packages/shared/lib/api/base/service/common.d.ts +++ b/packages/shared/lib/api/base/service/common.d.ts @@ -795,6 +795,8 @@ export interface IListDataExportTaskSQL { audit_sql_result?: IAuditSQLResult[]; + export_sql_type?: string; + export_status?: string; sql?: string; diff --git a/packages/shared/lib/api/base/service/common.enum.ts b/packages/shared/lib/api/base/service/common.enum.ts index 0fc1c13f6..46aebbabf 100644 --- a/packages/shared/lib/api/base/service/common.enum.ts +++ b/packages/shared/lib/api/base/service/common.enum.ts @@ -5,7 +5,9 @@ export enum GetDataExportTaskStatusEnum { 'finish' = 'finish', - 'failed' = 'failed' + 'failed' = 'failed', + + 'file_deleted' = 'file_deleted' } export enum GetUserAuthenticationTypeEnum { @@ -127,7 +129,11 @@ export enum OpPermissionItemOpPermissionTypeEnum { 'save_audit_plan' = 'save_audit_plan', - 'sql_query' = 'sql_query' + 'sql_query' = 'sql_query', + + 'create_export_task' = 'create_export_task', + + 'audit_export_workflow' = 'audit_export_workflow' } export enum OpPermissionItemRangeTypeEnum { diff --git a/packages/shared/lib/api/base/service/dms/index.enum.ts b/packages/shared/lib/api/base/service/dms/index.enum.ts index a16d9fd5d..22b1e24be 100644 --- a/packages/shared/lib/api/base/service/dms/index.enum.ts +++ b/packages/shared/lib/api/base/service/dms/index.enum.ts @@ -37,12 +37,10 @@ export enum ListDBServicesOrderByEnum { } export enum ListDBServiceTipsFunctionalModuleEnum { - 'create_audit_plan' = 'create_audit_plan', + 'save_audit_plan' = 'save_audit_plan', 'create_workflow' = 'create_workflow', - 'sql_manage' = 'sql_manage', - 'create_export_task' = 'create_export_task' } From a06af024cb78a6ad0b6bb27d6606a972874ff483 Mon Sep 17 00:00:00 2001 From: lizhensheng Date: Thu, 1 Feb 2024 11:31:43 +0800 Subject: [PATCH 3/3] [chore]: Add comment for ignoreInvalidValueForCSSStyleProperty [skip ci] --- packages/shared/lib/testUtil/common.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/shared/lib/testUtil/common.tsx b/packages/shared/lib/testUtil/common.tsx index d890d1b4a..b4b7db1c9 100644 --- a/packages/shared/lib/testUtil/common.tsx +++ b/packages/shared/lib/testUtil/common.tsx @@ -147,6 +147,10 @@ export const ignoreComponentAutoCreatedListNoKey = () => { }); }; +/** + * 过滤 NaN is an invalid value for the height css style property. 问题 + * 看起来应该是测试环境中某个原因导致 TextArea 组件高度设置错误了。 需要后面细究下啥原因。 + */ export const ignoreInvalidValueForCSSStyleProperty = () => { const error = console.error;