From ce4f91e3c91e9f86394e9da1485d281add194a5d Mon Sep 17 00:00:00 2001 From: lizhensheng Date: Wed, 18 Mar 2026 16:08:11 +0800 Subject: [PATCH 1/2] [chore](jest): Introduce Jest Projects for conditional compilation, MenuList tests and execution docs --- .github/workflows/main.yml | 41 +- jest.config.js | 126 +- package.json | 4 +- .../hooks/useOpPermission/index.sqle.test.tsx | 55 + .../__snapshots__/index.sqle.test.tsx.snap | 5469 +++++++++++++++++ .../__snapshots__/index.test.tsx.snap | 35 + .../Nav/SideMenu/MenuList/index.sqle.test.tsx | 253 + .../page/Nav/SideMenu/MenuList/index.test.tsx | 41 +- .../__tests__/PermissionList.sqle.test.tsx | 52 + .../PermissionList.sqle.test.tsx.snap | 309 + scripts/jest/README.md | 315 + scripts/jest/custom-filter.js | 43 - scripts/jest/custom-transform.js | 59 +- scripts/jest/merge-report-json.js | 120 +- scripts/jest/run-ci-ce.sh | 13 - scripts/jest/run-ci-ee.sh | 31 - scripts/jest/run-ci.sh | 29 + scripts/jest/run-coverage.sh | 25 +- scripts/jest/run.sh | 29 +- 19 files changed, 6764 insertions(+), 285 deletions(-) create mode 100644 packages/base/src/hooks/useOpPermission/index.sqle.test.tsx create mode 100644 packages/base/src/page/Nav/SideMenu/MenuList/__snapshots__/index.sqle.test.tsx.snap create mode 100644 packages/base/src/page/Nav/SideMenu/MenuList/__snapshots__/index.test.tsx.snap create mode 100644 packages/base/src/page/Nav/SideMenu/MenuList/index.sqle.test.tsx create mode 100644 packages/base/src/page/UserCenter/components/PermissionList/__tests__/PermissionList.sqle.test.tsx create mode 100644 packages/base/src/page/UserCenter/components/PermissionList/__tests__/__snapshots__/PermissionList.sqle.test.tsx.snap create mode 100644 scripts/jest/README.md delete mode 100644 scripts/jest/custom-filter.js delete mode 100644 scripts/jest/run-ci-ce.sh delete mode 100644 scripts/jest/run-ci-ee.sh create mode 100644 scripts/jest/run-ci.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b1559d986b..397ad2eb92 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: - name: Code lint checker run: pnpm checker - test-ee: + test: runs-on: ubuntu-latest if: ${{ !contains(github.event.pull_request.title, '[skip checker]') }} strategy: @@ -34,65 +34,41 @@ jobs: - name: Install dependencies uses: ./.github/actions/catch-install-pnpm - - name: Coverage test report ee - run: sh ./scripts/jest/run-ci-ee.sh ${{ matrix.shard }} ${{ strategy.job-total }} + - name: Coverage test report + run: sh ./scripts/jest/run-ci.sh ${{ matrix.shard }} ${{ strategy.job-total }} - uses: actions/upload-artifact@v4 with: name: coverage-artifacts-${{ matrix.shard }} path: coverage/ - test-ce: - runs-on: ubuntu-latest - if: ${{ !contains(github.event.pull_request.title, '[skip checker]') }} - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install dependencies - uses: ./.github/actions/catch-install-pnpm - - - name: Coverage test report ce - run: sh ./scripts/jest/run-ci-ce.sh - - - uses: actions/upload-artifact@v4 - with: - name: ce-coverage-artifacts - path: ce_coverage/ - report: runs-on: ubuntu-latest if: ${{ !contains(github.event.pull_request.title, '[skip checker]') }} - needs: [test-ee, test-ce] + needs: [test] steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Get CE Coverage - uses: actions/download-artifact@v4 - with: - name: ce-coverage-artifacts - path: ce_coverage - - - name: Get EE Coverage 1 + - name: Get Coverage 1 uses: actions/download-artifact@v4 with: name: coverage-artifacts-1 path: coverage - - name: Get EE Coverage 2 + - name: Get Coverage 2 uses: actions/download-artifact@v4 with: name: coverage-artifacts-2 path: coverage - - name: Get EE Coverage 3 + - name: Get Coverage 3 uses: actions/download-artifact@v4 with: name: coverage-artifacts-3 path: coverage - - name: Get EE Coverage 4 + - name: Get Coverage 4 uses: actions/download-artifact@v4 with: name: coverage-artifacts-4 @@ -115,7 +91,6 @@ jobs: uses: geekyeggo/delete-artifact@v5 with: name: | - ce-coverage-artifacts coverage-artifacts-1 coverage-artifacts-2 coverage-artifacts-3 diff --git a/jest.config.js b/jest.config.js index 631a7d8b79..ccffa34416 100644 --- a/jest.config.js +++ b/jest.config.js @@ -7,7 +7,39 @@ const { pathsToModuleNameMapper } = require('ts-jest'); compilerOptions.paths['~/*'][0] = path.resolve(compilerOptions.paths['~/*'][0]); -module.exports = { +const sharedModuleNameMapper = { + '.+\\.(css|style|less|sass|scss|ttf|woff|woff2)$': 'identity-obj-proxy', + '@ant-design/plots': + '/packages/shared/lib/testUtil/mockModule/mockAntDesignPlots.jsx', + 'monaco-editor': + '/packages/shared/lib/testUtil/mockModule/mockEditor.jsx', + '@monaco-editor/react': + '/packages/shared/lib/testUtil/mockModule/mockEditor.jsx', + '@uiw/react-md-editor': + '/packages/shared/lib/testUtil/mockModule/mockEditor.jsx', + '@actiontech/(.*)': '/packages/$1', + '@react-sigma/core(.*)$': + '/packages/shared/lib/testUtil/mockModule/mockSigmaCore.tsx', + '@react-sigma/graph-search$': + '/packages/shared/lib/testUtil/mockModule/mockSigmaGraphSearch.tsx', + ...pathsToModuleNameMapper(compilerOptions.paths) +}; + +const sharedIgnorePatterns = ['/node_modules/', '/demo/', '/demos/']; + +// Naming conventions for condition-specific test files: +// *.ce.test.{ts,tsx} → CE project (ee=false, ce=true, sqle=true) +// *.ce.sqle.test.{ts,tsx} → CE project (ee=false, ce=true, sqle=true) +// *.sqle.test.{ts,tsx} → sqle project (ee=true, ce=false, sqle=true, dms=false) +// *.ee.test.{ts,tsx} → ee project (ee=true, dms=true) [default] +// *.test.{ts,tsx} → ee project (default) +const CE_TEST_PATTERN = '\\.ce\\.test\\.[jt]sx?$'; +const CE_TEST_PATH_PATTERN = '/ce\\.test\\.[jt]sx?$'; +const SQLE_TEST_PATTERN = '\\.sqle\\.test\\.[jt]sx?$'; +const SQLE_TEST_PATH_PATTERN = '/sqle\\.test\\.[jt]sx?$'; +const CE_SQLE_TEST_PATTERN = '\\.ce\\.sqle\\.test\\.[jt]sx?$'; + +const sharedProjectConfig = { transform: { '^.+\\.(ts|tsx|js|jsx)$': '/scripts/jest/custom-transform.js', '^.+\\.(png|jpg|jpeg|css|json)$': '/scripts/jest/file-transform.js' @@ -19,24 +51,7 @@ module.exports = { moduleFileExtensions: ['ts', 'tsx', 'js', 'json', 'jsx', 'node'], testEnvironment: 'jest-environment-jsdom', resetMocks: true, - moduleNameMapper: { - '.+\\.(css|style|less|sass|scss|ttf|woff|woff2)$': 'identity-obj-proxy', - '@ant-design/plots': - '/packages/shared/lib/testUtil/mockModule/mockAntDesignPlots.jsx', - 'monaco-editor': - '/packages/shared/lib/testUtil/mockModule/mockEditor.jsx', - '@monaco-editor/react': - '/packages/shared/lib/testUtil/mockModule/mockEditor.jsx', - '@uiw/react-md-editor': - '/packages/shared/lib/testUtil/mockModule/mockEditor.jsx', - '@actiontech/(.*)': '/packages/$1', - '@react-sigma/core(.*)$': - '/packages/shared/lib/testUtil/mockModule/mockSigmaCore.tsx', - '@react-sigma/graph-search$': - '/packages/shared/lib/testUtil/mockModule/mockSigmaGraphSearch.tsx', - ...pathsToModuleNameMapper(compilerOptions.paths) - }, - + moduleNameMapper: sharedModuleNameMapper, collectCoverageFrom: [ 'packages/**/{src,lib}/{page,components,hooks,global,store,utils}/**/*.{ts,tsx}', 'packages/**/src/App.tsx', @@ -49,8 +64,77 @@ module.exports = { '!packages/**/demo/**', '!packages/**/demos/**' ], - setupFilesAfterEnv: ['/jest-setup.ts'], - testPathIgnorePatterns: ['/node_modules/', '/demo/', '/demos/'], + setupFilesAfterEnv: ['/jest-setup.ts'] +}; + +module.exports = { + projects: [ + { + ...sharedProjectConfig, + displayName: 'ee', + globals: { + TEST_CONDITIONS: { + ee: true, + ce: false, + sqle: true, + provision: true, + dms: true, + demo: false + } + }, + // Exclude CE-named and sqle-named test files; they have dedicated projects + testPathIgnorePatterns: [ + ...sharedIgnorePatterns, + CE_TEST_PATTERN, + CE_TEST_PATH_PATTERN, + SQLE_TEST_PATTERN, + SQLE_TEST_PATH_PATTERN + ] + }, + { + ...sharedProjectConfig, + displayName: 'ce', + globals: { + TEST_CONDITIONS: { + ee: false, + ce: true, + sqle: true, + provision: false, + dms: false, + demo: false + } + }, + // CE project: run ce-named and ce.sqle-named test files + testMatch: [ + '**/*.ce.test.{ts,tsx}', + '**/ce.test.{ts,tsx}', + '**/*.ce.sqle.test.{ts,tsx}', + '**/ce.sqle.test.{ts,tsx}' + ], + testPathIgnorePatterns: sharedIgnorePatterns + }, + { + ...sharedProjectConfig, + displayName: 'sqle', + globals: { + TEST_CONDITIONS: { + // EE + SQLE without DMS/PROVISION — covers [sqle && !dms] conditions + ee: true, + ce: false, + sqle: true, + provision: false, + dms: false, + demo: false + } + }, + // sqle project: run sqle-named files, but NOT ce.sqle files (those belong to CE project) + testMatch: ['**/*.sqle.test.{ts,tsx}', '**/sqle.test.{ts,tsx}'], + testPathIgnorePatterns: [ + ...sharedIgnorePatterns, + CE_SQLE_TEST_PATTERN + ] + } + ], reporters: [ 'default', [ diff --git a/package.json b/package.json index 793e9cf061..567c18aebd 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "checker": "concurrently \"pnpm ts-check\" \"pnpm eslint\" \"pnpm stylelint\" \"pnpm prettier:c\"", "test": "sh ./scripts/jest/run.sh", "test:c": "sh ./scripts/jest/run-coverage.sh", - "test:ci": "sh ./scripts/jest/run-ci-ee.sh && sh ./scripts/jest/run-ci-ce.sh && node ./scripts/jest/merge-report-json.js", + "test:ci": "sh ./scripts/jest/run-ci.sh 1 1 && node ./scripts/jest/merge-report-json.js", "test:clean": "jest --clearCache", "icon:g": "pnpm --filter @actiontech/icons icon:g", "icon:docs:g": "pnpm --filter @actiontech/icons docs:g", @@ -149,4 +149,4 @@ "@babel/core": "^7.22.0", "@ant-design/cssinjs": "1.17.0" } -} +} \ No newline at end of file diff --git a/packages/base/src/hooks/useOpPermission/index.sqle.test.tsx b/packages/base/src/hooks/useOpPermission/index.sqle.test.tsx new file mode 100644 index 0000000000..89ea116535 --- /dev/null +++ b/packages/base/src/hooks/useOpPermission/index.sqle.test.tsx @@ -0,0 +1,55 @@ +import { cleanup, act, renderHook } from '@testing-library/react'; +import useOpPermission from '.'; +import userCenter from '@actiontech/shared/lib/testUtil/mockApi/base/userCenter'; +import { ListOpPermissionsServiceEnum } from '@actiontech/shared/lib/api/base/service/OpPermission/index.enum'; + +// Verifies the [sqle && !dms] branch: service is set to sqle when calling ListOpPermissions + +describe('test useOpPermission - sqle mode', () => { + let listOpPermissionSpy: jest.SpyInstance; + + beforeEach(() => { + listOpPermissionSpy = userCenter.getOpPermissionsList(); + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + cleanup(); + }); + + it('should call ListOpPermissions with service=sqle', async () => { + const { result } = renderHook(() => useOpPermission()); + + act(() => { + result.current.updateOpPermissionList(); + }); + + await act(async () => jest.advanceTimersByTime(3000)); + + expect(listOpPermissionSpy).toHaveBeenCalledTimes(1); + expect(listOpPermissionSpy).toHaveBeenCalledWith( + expect.objectContaining({ + service: ListOpPermissionsServiceEnum.sqle + }) + ); + }); + + it('should call ListOpPermissions with service=sqle when filterBy is provided', async () => { + const { result } = renderHook(() => useOpPermission()); + + act(() => { + result.current.updateOpPermissionList(); + }); + + await act(async () => jest.advanceTimersByTime(3000)); + + expect(listOpPermissionSpy).toHaveBeenCalledWith( + expect.objectContaining({ + service: ListOpPermissionsServiceEnum.sqle + }) + ); + expect(result.current.loading).toBeFalsy(); + expect(result.current.opPermissionList.length).toBeGreaterThan(0); + }); +}); diff --git a/packages/base/src/page/Nav/SideMenu/MenuList/__snapshots__/index.sqle.test.tsx.snap b/packages/base/src/page/Nav/SideMenu/MenuList/__snapshots__/index.sqle.test.tsx.snap new file mode 100644 index 0000000000..4b7da020fe --- /dev/null +++ b/packages/base/src/page/Nav/SideMenu/MenuList/__snapshots__/index.sqle.test.tsx.snap @@ -0,0 +1,5469 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`base/Nav/SideMenu/MenuList - sqle mode 基础渲染 renders SQLE menu structure - snapshot 1`] = ` + +
+ + + +`; + +exports[`base/Nav/SideMenu/MenuList - sqle mode 权限过滤 hides permission-gated items when checkPagePermission returns false 1`] = ` + +
+ + + +`; + +exports[`base/Nav/SideMenu/MenuList - sqle mode 权限过滤 shows all items when checkPagePermission returns true 1`] = ` + +
+ + + +`; + +exports[`base/Nav/SideMenu/MenuList - sqle mode 权限过滤 shows all items when userOperationPermissions is null (default) - snapshot 1`] = ` + +
+ + + +`; + +exports[`base/Nav/SideMenu/MenuList - sqle mode 路由激活菜单 selects member when at member route 1`] = ` + +
+ + + +`; + +exports[`base/Nav/SideMenu/MenuList - sqle mode 路由激活菜单 selects project-overview when at sqle overview route 1`] = ` + +
+ + + +`; + +exports[`base/Nav/SideMenu/MenuList - sqle mode 路由激活菜单 selects rule-template by walking up nested sub-path 1`] = ` + +
+ + + +`; diff --git a/packages/base/src/page/Nav/SideMenu/MenuList/__snapshots__/index.test.tsx.snap b/packages/base/src/page/Nav/SideMenu/MenuList/__snapshots__/index.test.tsx.snap new file mode 100644 index 0000000000..140f0e1a79 --- /dev/null +++ b/packages/base/src/page/Nav/SideMenu/MenuList/__snapshots__/index.test.tsx.snap @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`base/page/Nav/SideMenu/MenuList - dms mode renders empty menu in dms mode - snapshot 1`] = ` + +
+
@@ -2318,6 +2332,20 @@ exports[`base/System-ee render snap 2`] = ` Git SSH配置
+
@@ -4582,6 +4610,20 @@ exports[`base/System-ee render snap 3`] = ` Git SSH配置
+
@@ -6277,6 +6319,20 @@ exports[`base/System-ee should changed current active tab when url params is exi Git SSH配置 + diff --git a/packages/base/src/page/System/index.test.tsx b/packages/base/src/page/System/index.test.tsx index c4cf691dfb..48a40e845f 100644 --- a/packages/base/src/page/System/index.test.tsx +++ b/packages/base/src/page/System/index.test.tsx @@ -63,7 +63,7 @@ describe('base/System-ee', () => { '.ant-segmented-item-label', baseElement ); - expect(segmentedEle.length).toBe(7); + expect(segmentedEle.length).toBe(8); fireEvent.click(segmentedEle[1]); await act(async () => jest.advanceTimersByTime(500)); expect(baseElement).toMatchSnapshot(); diff --git a/packages/sqle/src/page/ReportStatistics/__snapshots__/ce.test.tsx.snap b/packages/sqle/src/page/ReportStatistics/__snapshots__/index.ce.test.tsx.snap similarity index 100% rename from packages/sqle/src/page/ReportStatistics/__snapshots__/ce.test.tsx.snap rename to packages/sqle/src/page/ReportStatistics/__snapshots__/index.ce.test.tsx.snap diff --git a/packages/sqle/src/page/ReportStatistics/ce.test.tsx b/packages/sqle/src/page/ReportStatistics/index.ce.test.tsx similarity index 100% rename from packages/sqle/src/page/ReportStatistics/ce.test.tsx rename to packages/sqle/src/page/ReportStatistics/index.ce.test.tsx diff --git a/packages/sqle/src/page/Whitelist/__snapshots__/ce.test.tsx.snap b/packages/sqle/src/page/Whitelist/__snapshots__/index.ce.test.tsx.snap similarity index 100% rename from packages/sqle/src/page/Whitelist/__snapshots__/ce.test.tsx.snap rename to packages/sqle/src/page/Whitelist/__snapshots__/index.ce.test.tsx.snap diff --git a/packages/sqle/src/page/Whitelist/ce.test.tsx b/packages/sqle/src/page/Whitelist/index.ce.test.tsx similarity index 100% rename from packages/sqle/src/page/Whitelist/ce.test.tsx rename to packages/sqle/src/page/Whitelist/index.ce.test.tsx