From f48e3d2a0d31fad4f2b7b5d64e521379a4636410 Mon Sep 17 00:00:00 2001 From: sunjinkang Date: Mon, 16 Mar 2026 17:26:00 +0800 Subject: [PATCH 1/2] [test]: add test for ai banner and governance --- .../__snapshots__/index.test.tsx.snap | 274 +++ .../Home/AIBanner/__test__/index.test.tsx | 217 +++ .../__snapshots__/index.test.tsx.snap | 593 +++++++ .../SqlRewrittenExampleDrawer/index.test.tsx | 30 + .../base/src/page/Home/AIBanner/index.tsx | 4 +- .../QuickActions/__tests__/index.test.tsx | 2 +- .../page/Nav/SideMenu/QuickActions/index.tsx | 2 +- .../router.ce.base.test.tsx.snap | 1030 +++++++----- .../router.ce.sqle.test.tsx.snap | 406 +++-- packages/dms-kit/docs/CHANGELOG.md | 6 +- packages/dms-kit/package.json | 2 +- packages/dms-kit/src/data/routePaths.ts | 7 +- .../testUtil/mockApi/sqle/statistic/data.ts | 157 ++ .../testUtil/mockApi/sqle/statistic/index.ts | 50 + .../__snapshots__/index.test.tsx.snap | 1493 +++++++++++++++++ .../__snapshots__/index.test.tsx.snap | 1068 ++++++++++++ .../components/ExecutionData/index.test.tsx | 73 + .../__snapshots__/index.test.tsx.snap | 476 ++++++ .../__snapshots__/index.test.tsx.snap | 24 + .../CardSectionTitle/index.test.tsx | 36 + .../__snapshots__/index.test.tsx.snap | 301 ++++ .../ProjectIOAnalysis/index.test.tsx | 147 ++ .../__snapshots__/index.test.tsx.snap | 29 + .../TopProblemDistribution/index.test.tsx | 117 ++ .../components/ManagementView/index.test.tsx | 123 ++ .../__snapshots__/index.test.tsx.snap | 20 + .../components/ModuleTitle/index.test.tsx | 33 + .../__snapshots__/index.test.tsx.snap | 219 +++ .../__snapshots__/index.test.tsx.snap | 120 ++ .../components/EfficiencyCards/index.test.tsx | 60 + .../StrategicInsight/index.test.tsx | 74 + .../AIGovernanceTab/index.test.tsx | 56 + .../sqle/src/page/ReportStatistics/index.tsx | 15 +- packages/sqle/src/router/config.tsx | 2 +- 34 files changed, 6718 insertions(+), 548 deletions(-) create mode 100644 packages/base/src/page/Home/AIBanner/__test__/__snapshots__/index.test.tsx.snap create mode 100644 packages/base/src/page/Home/AIBanner/__test__/index.test.tsx create mode 100644 packages/base/src/page/Home/AIBanner/components/SqlRewrittenExampleDrawer/__snapshots__/index.test.tsx.snap create mode 100644 packages/base/src/page/Home/AIBanner/components/SqlRewrittenExampleDrawer/index.test.tsx create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/__snapshots__/index.test.tsx.snap create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ExecutionData/__snapshots__/index.test.tsx.snap create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ExecutionData/index.test.tsx create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ManagementView/__snapshots__/index.test.tsx.snap create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ManagementView/components/CardSectionTitle/__snapshots__/index.test.tsx.snap create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ManagementView/components/CardSectionTitle/index.test.tsx create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ManagementView/components/ProjectIOAnalysis/__snapshots__/index.test.tsx.snap create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ManagementView/components/ProjectIOAnalysis/index.test.tsx create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ManagementView/components/TopProblemDistribution/__snapshots__/index.test.tsx.snap create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ManagementView/components/TopProblemDistribution/index.test.tsx create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ManagementView/index.test.tsx create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ModuleTitle/__snapshots__/index.test.tsx.snap create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/ModuleTitle/index.test.tsx create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/StrategicInsight/__snapshots__/index.test.tsx.snap create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/StrategicInsight/components/EfficiencyCards/__snapshots__/index.test.tsx.snap create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/StrategicInsight/components/EfficiencyCards/index.test.tsx create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/components/StrategicInsight/index.test.tsx create mode 100644 packages/sqle/src/page/ReportStatistics/AIGovernanceTab/index.test.tsx diff --git a/packages/base/src/page/Home/AIBanner/__test__/__snapshots__/index.test.tsx.snap b/packages/base/src/page/Home/AIBanner/__test__/__snapshots__/index.test.tsx.snap new file mode 100644 index 0000000000..4a868e11e4 --- /dev/null +++ b/packages/base/src/page/Home/AIBanner/__test__/__snapshots__/index.test.tsx.snap @@ -0,0 +1,274 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test base/home/AIBanner should match snapshot and render metrics and actions by modules 1`] = ` + +
+
+
+
+ +
+
+
+
+ +`; diff --git a/packages/base/src/page/Home/AIBanner/__test__/index.test.tsx b/packages/base/src/page/Home/AIBanner/__test__/index.test.tsx new file mode 100644 index 0000000000..f2211ea497 --- /dev/null +++ b/packages/base/src/page/Home/AIBanner/__test__/index.test.tsx @@ -0,0 +1,217 @@ +import { act, fireEvent, screen } from '@testing-library/react'; +import { useNavigate } from 'react-router-dom'; +import statistic from '@actiontech/shared/lib/testUtil/mockApi/sqle/statistic'; +import { createSpySuccessResponse } from '@actiontech/shared/lib/testUtil/mockApi'; +import { mockUseCurrentUser } from '@actiontech/shared/lib/testUtil/mockHook/mockUseCurrentUser'; +import { + ignoreConsoleErrors, + UtilsConsoleErrorStringsEnum +} from '@actiontech/shared/lib/testUtil/common'; +import { ROUTE_PATHS } from '@actiontech/dms-kit'; +import { mockUseRecentlyOpenedProjects } from '../../../Nav/SideMenu/testUtils/mockUseRecentlyOpenedProjects'; +import { baseSuperRender } from '../../../../testUtils/superRender'; +import AIBanner from '..'; + +jest.mock('react-router-dom', () => { + return { + ...jest.requireActual('react-router-dom'), + useNavigate: jest.fn() + }; +}); + +const mockMessageInfo = jest.fn(); +jest.mock('antd', () => ({ + ...jest.requireActual('antd'), + message: { + ...jest.requireActual('antd').message, + info: (...args: unknown[]) => mockMessageInfo(...args) + } +})); + +describe('test base/home/AIBanner', () => { + const navigateSpy = jest.fn(); + const mockedUseNavigate = useNavigate as jest.Mock; + let requestBannerSpy: jest.SpyInstance; + ignoreConsoleErrors([UtilsConsoleErrorStringsEnum.INVALID_CUSTOM_ATTRIBUTE]); + + beforeEach(() => { + jest.useFakeTimers(); + mockMessageInfo.mockClear(); + requestBannerSpy = statistic.getAIHubBanner(); + mockedUseNavigate.mockImplementation(() => navigateSpy); + mockUseCurrentUser(); + mockUseRecentlyOpenedProjects({ currentProjectID: '1' }); + }); + + afterEach(() => { + jest.clearAllMocks(); + jest.clearAllTimers(); + }); + + it('should match snapshot and render metrics and actions by modules', async () => { + const { baseElement } = baseSuperRender(); + await act(async () => jest.advanceTimersByTime(3300)); + + expect(screen.getByText('AI治理效能洞察')).toBeInTheDocument(); + expect(screen.getByText('风险拦截')).toBeInTheDocument(); + expect(screen.getByText('性能优化')).toBeInTheDocument(); + expect(screen.getByText('AI 性能引擎')).toBeInTheDocument(); + expect(screen.getByText('AI 智能修正')).toBeInTheDocument(); + expect(screen.getByText('18')).toBeInTheDocument(); + expect(screen.getByText('12')).toBeInTheDocument(); + expect(screen.getByText('高')).toBeInTheDocument(); + expect(screen.getByText('中')).toBeInTheDocument(); + expect(baseElement).toMatchSnapshot(); + }); + + it('should navigate to report statistics when clicked "view full report"', async () => { + baseSuperRender(); + await act(async () => jest.advanceTimersByTime(3300)); + + expect(screen.getByText('查看完整报告')).toBeInTheDocument(); + fireEvent.click(screen.getByText('查看完整报告')); + + expect(navigateSpy).toHaveBeenCalledTimes(1); + expect(navigateSpy).toHaveBeenCalledWith( + `${ROUTE_PATHS.SQLE.REPORT_STATISTICS.index.path}?tab=ai-governance` + ); + }); + + it('should navigate to related page when current project id exists', async () => { + mockUseRecentlyOpenedProjects({ currentProjectID: '1' }); + + baseSuperRender(); + await act(async () => jest.advanceTimersByTime(3300)); + + expect(screen.getByText('AI 性能引擎')).toBeInTheDocument(); + fireEvent.click(screen.getByText('AI 性能引擎')); + + expect(navigateSpy).toHaveBeenCalledWith( + '/sqle/project/1/sql-audit/create-optimization' + ); + }); + + it('should open project selector modal when current project id is undefined', async () => { + mockUseRecentlyOpenedProjects({ currentProjectID: '' }); + + baseSuperRender(); + await act(async () => jest.advanceTimersByTime(3300)); + + expect(screen.getByText('AI 性能引擎')).toBeInTheDocument(); + expect(screen.queryByText('选择项目')).not.toBeInTheDocument(); + + fireEvent.click(screen.getByText('AI 性能引擎')); + + expect(navigateSpy).not.toHaveBeenCalled(); + expect(screen.getByText('选择项目')).toBeInTheDocument(); + }); + + it('should render no metric and action buttons when api returns empty modules', async () => { + requestBannerSpy.mockImplementation(() => + createSpySuccessResponse({ + data: { + modules: [] + } + }) + ); + + baseSuperRender(); + await act(async () => jest.advanceTimersByTime(3300)); + + expect(screen.getByText('查看完整报告')).toBeInTheDocument(); + expect(screen.queryByText('风险拦截')).not.toBeInTheDocument(); + expect(screen.queryByText('性能优化')).not.toBeInTheDocument(); + expect(screen.queryByText('AI 性能引擎')).not.toBeInTheDocument(); + expect(screen.queryByText('AI 智能修正')).not.toBeInTheDocument(); + }); + + it('should show paid feature prompt and not navigate when view full report clicked with all modules disabled', async () => { + requestBannerSpy.mockImplementation(() => + createSpySuccessResponse({ + data: { + modules: [ + { ai_module_type: 'performance_engine', is_enabled: false }, + { ai_module_type: 'smart_correction', is_enabled: false } + ] + } + }) + ); + + baseSuperRender(); + await act(async () => jest.advanceTimersByTime(3300)); + + fireEvent.click(screen.getByText('查看完整报告')); + + expect(mockMessageInfo).toHaveBeenCalled(); + expect(navigateSpy).not.toHaveBeenCalled(); + }); + + it('should show paid feature prompt when AI performance engine clicked with module disabled', async () => { + requestBannerSpy.mockImplementation(() => + createSpySuccessResponse({ + data: { + modules: [ + { + ai_module_type: 'performance_engine', + is_enabled: false, + banner_cards: [{ need_display: true }] + }, + { + ai_module_type: 'smart_correction', + is_enabled: true, + banner_cards: [{ need_display: true }] + } + ] + } + }) + ); + + baseSuperRender(); + await act(async () => jest.advanceTimersByTime(3300)); + + fireEvent.click(screen.getByText('AI 性能引擎')); + + expect(mockMessageInfo).toHaveBeenCalled(); + expect(navigateSpy).not.toHaveBeenCalled(); + }); + + it('should show paid feature prompt when AI smart correction clicked with module disabled', async () => { + requestBannerSpy.mockImplementation(() => + createSpySuccessResponse({ + data: { + modules: [ + { + ai_module_type: 'performance_engine', + is_enabled: true, + banner_cards: [{ need_display: true }] + }, + { + ai_module_type: 'smart_correction', + is_enabled: false, + banner_cards: [{ need_display: true }] + } + ] + } + }) + ); + + baseSuperRender(); + await act(async () => jest.advanceTimersByTime(3300)); + + fireEvent.click(screen.getByText('AI 智能修正')); + + expect(mockMessageInfo).toHaveBeenCalled(); + expect(screen.queryByText('重写详情')).not.toBeInTheDocument(); + }); + + it('should open SqlRewrittenExampleDrawer when AI smart correction clicked', async () => { + baseSuperRender(); + await act(async () => jest.advanceTimersByTime(3300)); + + expect(screen.queryByText('重写详情')).not.toBeInTheDocument(); + + fireEvent.click(screen.getByText('AI 智能修正')); + + expect(screen.getByText('重写详情')).toBeInTheDocument(); + }); +}); diff --git a/packages/base/src/page/Home/AIBanner/components/SqlRewrittenExampleDrawer/__snapshots__/index.test.tsx.snap b/packages/base/src/page/Home/AIBanner/components/SqlRewrittenExampleDrawer/__snapshots__/index.test.tsx.snap new file mode 100644 index 0000000000..b13f3cbcf8 --- /dev/null +++ b/packages/base/src/page/Home/AIBanner/components/SqlRewrittenExampleDrawer/__snapshots__/index.test.tsx.snap @@ -0,0 +1,593 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SqlRewrittenExampleDrawer should match snapshot 1`] = ` + +
+
+
+
+