diff --git a/packages/sqle/src/components/ReportDrawer/__snapshots__/index.test.tsx.snap b/packages/sqle/src/components/ReportDrawer/__snapshots__/index.test.tsx.snap index 0edfa5954..d8652261a 100644 --- a/packages/sqle/src/components/ReportDrawer/__snapshots__/index.test.tsx.snap +++ b/packages/sqle/src/components/ReportDrawer/__snapshots__/index.test.tsx.snap @@ -309,3 +309,229 @@ exports[`sqle/components/ReportDrawer render snap when has data 1`] = ` `; + +exports[`sqle/components/ReportDrawer render snap when showSourceFile is true 1`] = ` + +
+
+
+
+ + +`; diff --git a/packages/sqle/src/components/ReportDrawer/index.test.tsx b/packages/sqle/src/components/ReportDrawer/index.test.tsx index 57e4d4ade..8429390b9 100644 --- a/packages/sqle/src/components/ReportDrawer/index.test.tsx +++ b/packages/sqle/src/components/ReportDrawer/index.test.tsx @@ -46,6 +46,32 @@ describe('sqle/components/ReportDrawer', () => { data: { sql: 'select 1', sqlSourceFile: 'file_source', + sqlStartLine: 3, + auditResult: [ + { + rule_name: 'rule a', + message: 'message', + level: 'level', + annotation: 'annotation', + db_type: 'mysql' + } + ] + }, + onClose: jest.fn() + }); + expect(baseElement).toMatchSnapshot(); + }); + + it('render snap when showSourceFile is true', () => { + const { baseElement } = customRender({ + open: true, + title: 'this is a title', + showAnnotation: true, + showSourceFile: true, + data: { + sql: 'select 1', + sqlSourceFile: 'file_source', + sqlStartLine: 3, auditResult: [ { rule_name: 'rule a', diff --git a/packages/sqle/src/components/RuleList/RuleList.tsx b/packages/sqle/src/components/RuleList/RuleList.tsx index 0ae9c7cbe..ae9186ced 100644 --- a/packages/sqle/src/components/RuleList/RuleList.tsx +++ b/packages/sqle/src/components/RuleList/RuleList.tsx @@ -29,6 +29,7 @@ import { IconDisabledRule, IconEnabledRule } from '../../icon/Rule'; import BasicEmpty from '@actiontech/shared/lib/components/BasicEmpty'; import RuleDetailModal from './RuleDetailModal'; import { useBoolean } from 'ahooks'; +import { isEqual } from 'lodash'; const scrollStepRange = 30; @@ -203,10 +204,16 @@ const RuleList: React.FC = ({ } }; + const rulesRef = useRef(); + useEffect(() => { - stepRef.current = 0; - setScrollData([]); - onScroll(); + // fix Warning: Maximum update depth exceeded + if (!isEqual(rulesRef.current, rules)) { + rulesRef.current = rules; + stepRef.current = 0; + setScrollData([]); + onScroll(); + } // eslint-disable-next-line react-hooks/exhaustive-deps }, [rules]); @@ -237,10 +244,10 @@ const RuleList: React.FC = ({ } scrollableTarget="rule-list-wrapper-id" > - {scrollData?.map((v) => { + {scrollData?.map((v, index) => { return ( { (res) => res.data.data?.map((v) => ({ ...v, + rule_name: v.rule_id, level: v.level as RuleResV1LevelEnum | undefined })) ?? [] ) diff --git a/packages/sqle/src/page/CustomRule/CustomRuleList/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/CustomRule/CustomRuleList/__snapshots__/index.test.tsx.snap new file mode 100644 index 000000000..b3b86617a --- /dev/null +++ b/packages/sqle/src/page/CustomRule/CustomRuleList/__snapshots__/index.test.tsx.snap @@ -0,0 +1,1291 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`sqle/CustomRuleList click rule item 1`] = ` + +
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + 数据源类型 + + + 请选择{{name}} + + + +
+ +
+
+
+ + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + notice + +
+
+ + test-custom-rule1 + +
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ 暂无更多规则 +
+
+
+
+
+
+
+
+
+
+
+
+
+ + +`; + +exports[`sqle/CustomRuleList should match snap shot 1`] = ` + +
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + 数据源类型 + + + 请选择{{name}} + + + +
+ +
+
+
+ + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + notice + +
+
+ + test-custom-rule1 + +
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+ + + + + + + notice + +
+
+ + test-custom-rule2 + +
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ 暂无更多规则 +
+
+
+
+
+
+
+
+
+
+ +`; + +exports[`sqle/CustomRuleList should render empty tips when request return null 1`] = ` + +
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + 数据源类型 + + + 请选择{{name}} + + + +
+ +
+
+
+ + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + +
+
+ + 暂无更多规则 + +
+ +
+
+
+
+
+
+
+ +`; diff --git a/packages/sqle/src/page/CustomRule/CustomRuleList/index.test.tsx b/packages/sqle/src/page/CustomRule/CustomRuleList/index.test.tsx new file mode 100644 index 000000000..7a5073050 --- /dev/null +++ b/packages/sqle/src/page/CustomRule/CustomRuleList/index.test.tsx @@ -0,0 +1,178 @@ +import { cleanup, screen, act, fireEvent } from '@testing-library/react'; +import { renderWithReduxAndTheme } from '@actiontech/shared/lib/testUtil/customRender'; +import CustomRuleList from '.'; +import { getBySelector } from '@actiontech/shared/lib/testUtil/customQuery'; +import EventEmitter from '../../../utils/EventEmitter'; +import EmitterKey from '../../../data/EmitterKey'; +import { mockUseDbServiceDriver } from '@actiontech/shared/lib/testUtil/mockHook/mockUseDbServiceDriver'; +import rule_template from '../../../testUtils/mockApi/rule_template'; +import { customRuleMockData } from '../../../testUtils/mockApi/rule_template/data'; +import configuration from '../../../testUtils/mockApi/configuration'; +import { createSpySuccessResponse } from '@actiontech/shared/lib/testUtil/mockApi'; +import { useNavigate } from 'react-router-dom'; + +jest.mock('react-router-dom', () => { + return { + ...jest.requireActual('react-router-dom'), + useNavigate: jest.fn() + }; +}); + +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useDispatch: jest.fn(), + useSelector: jest.fn() +})); + +describe('sqle/CustomRuleList', () => { + let getCustomRulesSpy: jest.SpyInstance; + let getDrivers: jest.SpyInstance; + const navigateSpy = jest.fn(); + beforeEach(() => { + (useNavigate as jest.Mock).mockImplementation(() => navigateSpy); + jest.useFakeTimers(); + mockUseDbServiceDriver(); + getCustomRulesSpy = rule_template.getCustomRules(); + getDrivers = configuration.getDrivers(); + }); + + afterEach(() => { + jest.useRealTimers(); + jest.clearAllTimers(); + jest.clearAllMocks(); + cleanup(); + }); + + const customRender = () => renderWithReduxAndTheme(); + + it('should match snap shot', async () => { + const { baseElement } = customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + expect(getCustomRulesSpy).toBeCalledTimes(1); + expect(getDrivers).toBeCalledTimes(1); + expect(baseElement).toMatchSnapshot(); + }); + + it('should render empty tips when request return null', async () => { + getCustomRulesSpy.mockClear(); + getCustomRulesSpy.mockImplementation(() => createSpySuccessResponse({})); + const { baseElement } = customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + expect(getCustomRulesSpy).toBeCalledTimes(1); + expect(getDrivers).toBeCalledTimes(1); + expect(baseElement).toMatchSnapshot(); + }); + + it('filter custom rule list', async () => { + const { baseElement } = customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + expect(getCustomRulesSpy).toBeCalledTimes(1); + fireEvent.mouseDown(getBySelector('.ant-select-selection-search-input')); + await act(async () => jest.advanceTimersByTime(300)); + fireEvent.click( + getBySelector('.ant-select-item-option-content', baseElement) + ); + await act(async () => jest.advanceTimersByTime(3000)); + expect(getCustomRulesSpy).toBeCalledWith({ + filter_db_type: 'mysql', + filter_desc: '' + }); + const searchInputEle = getBySelector( + '.basic-input-wrapper #actiontech-table-search-input', + baseElement + ); + await act(async () => { + fireEvent.input(searchInputEle, { + target: { value: 'test' } + }); + await jest.advanceTimersByTime(300); + }); + await act(async () => { + fireEvent.keyDown(searchInputEle, { + key: 'Enter', + code: 'Enter', + keyCode: 13 + }); + await act(() => jest.advanceTimersByTime(300)); + }); + expect(getCustomRulesSpy).toBeCalledWith({ + filter_db_type: 'mysql', + filter_desc: 'test' + }); + }); + + it('should refresh table when emit "Refresh_Custom_Rule_Template_List" event', async () => { + customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + expect(getCustomRulesSpy).toBeCalledTimes(1); + await act(async () => + EventEmitter.emit(EmitterKey.Refresh_Custom_Rule_Template_List) + ); + await act(async () => jest.advanceTimersByTime(3000)); + expect(getCustomRulesSpy).toBeCalledTimes(2); + }); + + it('click rule item', async () => { + getCustomRulesSpy.mockClear(); + getCustomRulesSpy.mockImplementation(() => + createSpySuccessResponse({ data: [customRuleMockData[0]] }) + ); + const { baseElement } = customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + const ruleItem = getBySelector('.infinite-scroll-component', baseElement) + .children[0]; + fireEvent.click(ruleItem); + await act(async () => jest.advanceTimersByTime(300)); + expect(screen.getByText('查看规则')).toBeInTheDocument(); + expect(screen.getByText('规则知识库')).toBeInTheDocument(); + expect(baseElement).toMatchSnapshot(); + }); + + it('edit rule item', async () => { + getCustomRulesSpy.mockClear(); + getCustomRulesSpy.mockImplementation(() => + createSpySuccessResponse({ data: [customRuleMockData[0]] }) + ); + const { baseElement } = customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + const ruleItem = getBySelector('.infinite-scroll-component', baseElement) + .children[0]; + fireEvent.mouseEnter(ruleItem); + await act(async () => jest.advanceTimersByTime(300)); + const editButton = getBySelector( + '.action-wrapper .custom-icon-edit', + ruleItem + ); + fireEvent.click(editButton); + await act(async () => jest.advanceTimersByTime(300)); + expect(navigateSpy).toBeCalledTimes(1); + }); + + it('delete rule item', async () => { + getCustomRulesSpy.mockClear(); + getCustomRulesSpy.mockImplementation(() => + createSpySuccessResponse({ data: [customRuleMockData[0]] }) + ); + const deleteCustomRuleSpy = rule_template.deleteCustomRule(); + const { baseElement } = customRender(); + await act(async () => jest.advanceTimersByTime(3000)); + const ruleItem = getBySelector('.infinite-scroll-component', baseElement) + .children[0]; + const editButton = getBySelector( + '.action-wrapper .disabled-rule-item', + ruleItem + ); + fireEvent.click(editButton); + await act(async () => jest.advanceTimersByTime(300)); + expect(screen.getByText('是否确认删除该规则?')).toBeInTheDocument(); + fireEvent.click(screen.getByText('确 认')); + await act(async () => jest.advanceTimersByTime(3000)); + expect(deleteCustomRuleSpy).toBeCalledTimes(1); + expect(deleteCustomRuleSpy).toBeCalledWith({ + rule_id: customRuleMockData[0].rule_id + }); + expect( + screen.getByText(`规则 ${customRuleMockData[0].desc} 删除成功`) + ).toBeInTheDocument(); + }); +}); diff --git a/packages/sqle/src/page/GlobalRuleTemplate/CloneRuleTemplateModal/__snapshots__/index.test.tsx.snap b/packages/sqle/src/page/GlobalRuleTemplate/CloneRuleTemplateModal/__snapshots__/index.test.tsx.snap new file mode 100644 index 000000000..df53821ad --- /dev/null +++ b/packages/sqle/src/page/GlobalRuleTemplate/CloneRuleTemplateModal/__snapshots__/index.test.tsx.snap @@ -0,0 +1,234 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`sqle/GlobalRuleTemplate/CloneRuleTemplateModal should match snapshot 1`] = ` + +
+
+
+
+
+