This is an automated email from the ASF dual-hosted git repository.

jli pushed a commit to branch fix-master-ci
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 289aa1ebcf3c2265b46f9ec7451bc8658dbd6e08
Author: Joe Li <[email protected]>
AuthorDate: Wed Mar 4 22:17:11 2026 -0800

    test(DatasourceControl): add regression guards for OOM fix
    
    Prevent re-introducing the OOM crash fixed in fe5f0b0 by adding:
    - fetchMock unmatched call assertion in afterEach (catches leaked routes)
    - pre-commit hook banning mockImplementationOnce in DatasourceControl tests
    - scoped ESLint await-async-events rule for this test file
    - CI heap-check job with 520MB threshold, mockImpl guard, and await guard
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 .github/workflows/superset-frontend.yml            | 63 ++++++++++++++++++++++
 .pre-commit-config.yaml                            |  6 +++
 superset-frontend/.eslintrc.js                     | 11 ++++
 .../DatasourceControl/DatasourceControl.test.tsx   | 13 ++++-
 4 files changed, 92 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/superset-frontend.yml 
b/.github/workflows/superset-frontend.yml
index db22843e30..59d9d51650 100644
--- a/.github/workflows/superset-frontend.yml
+++ b/.github/workflows/superset-frontend.yml
@@ -95,6 +95,69 @@ jobs:
           name: coverage-artifacts-${{ matrix.shard }}
           path: superset-frontend/coverage
 
+  heap-check-datasource-control:
+    needs: frontend-build
+    if: needs.frontend-build.outputs.should-run == 'true'
+    runs-on: ubuntu-24.04
+    steps:
+      - name: Download Docker Image Artifact
+        uses: actions/download-artifact@v8
+        with:
+          name: docker-image
+
+      - name: Load Docker Image
+        run: docker load < docker-image.tar.gz
+
+      - name: Heap check DatasourceControl test (must stay under 520 MB)
+        run: |
+          docker run --rm $TAG bash -c '
+            node --max-old-space-size=8192 \
+              node_modules/.bin/jest \
+              --logHeapUsage \
+              --maxWorkers=1 \
+              --testPathPatterns="DatasourceControl\.test" \
+              2>&1 | tee /tmp/heap-output.txt
+
+            max_heap=$(grep -oP "\d+ MB heap size" /tmp/heap-output.txt \
+              | grep -oP "\d+" | sort -n | tail -1)
+
+            echo "Peak heap usage: ${max_heap:-unknown} MB"
+
+            if [ -z "$max_heap" ]; then
+              echo "WARNING: Could not parse heap usage"
+              exit 0
+            fi
+
+            if [ "$max_heap" -gt 520 ]; then
+              echo "FAIL: Heap usage (${max_heap} MB) exceeds 520 MB 
threshold."
+              echo "The DatasourceEditor mock may have been removed."
+              exit 1
+            fi
+
+            echo "PASS: Heap usage within threshold"
+          '
+
+      - name: Guard against mockImplementationOnce
+        run: |
+          docker run --rm $TAG bash -c '
+            if grep -rn "mockImplementationOnce" 
src/explore/components/controls/DatasourceControl/DatasourceControl.test.tsx; 
then
+              echo "FAIL: mockImplementationOnce is banned in this file"
+              exit 1
+            fi
+            echo "PASS: No mockImplementationOnce found"
+          '
+
+      - name: Guard against un-awaited userEvent
+        run: |
+          docker run --rm $TAG bash -c '
+            
FILE=src/explore/components/controls/DatasourceControl/DatasourceControl.test.tsx
+            if grep -Pn "(?<!await\s)userEvent\.\w+\(" "$FILE" | grep -v 
"import\|//"; then
+              echo "FAIL: All userEvent calls must be awaited"
+              exit 1
+            fi
+            echo "PASS: All userEvent calls are awaited"
+          '
+
   report-coverage:
     needs: [sharded-jest-tests]
     if: needs.frontend-build.outputs.should-run == 'true'
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index a15303b2a3..30768f570d 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -67,6 +67,12 @@ repos:
         language: system
         pass_filenames: true
         files: ^superset-frontend/.*\.(js|jsx|ts|tsx|css|scss|sass|json)$
+      - id: no-mock-implementation-once-datasource
+        name: ban mockImplementationOnce in DatasourceControl tests
+        entry: bash -c 'for f in "$@"; do if echo "$f" | grep -q 
"DatasourceControl.test"; then if grep -n "mockImplementationOnce" "$f"; then 
echo "[ERROR] mockImplementationOnce is banned in DatasourceControl.test.tsx"; 
echo "Use scoped jest.spyOn(...).mockImplementation(...) instead."; exit 1; fi; 
fi; done'
+        language: system
+        pass_filenames: true
+        files: DatasourceControl\.test\.(ts|tsx)$
   - repo: local
     hooks:
       - id: oxlint-frontend
diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js
index db01c79e74..c56b598e01 100644
--- a/superset-frontend/.eslintrc.js
+++ b/superset-frontend/.eslintrc.js
@@ -515,6 +515,17 @@ module.exports = {
         ],
       },
     },
+    {
+      files: [
+        
'src/explore/components/controls/DatasourceControl/DatasourceControl.test.tsx',
+      ],
+      rules: {
+        'testing-library/await-async-events': [
+          'error',
+          { eventModule: 'userEvent' },
+        ],
+      },
+    },
   ],
   ignorePatterns,
 };
diff --git 
a/superset-frontend/src/explore/components/controls/DatasourceControl/DatasourceControl.test.tsx
 
b/superset-frontend/src/explore/components/controls/DatasourceControl/DatasourceControl.test.tsx
index f5dfca9739..5b319e3d08 100644
--- 
a/superset-frontend/src/explore/components/controls/DatasourceControl/DatasourceControl.test.tsx
+++ 
b/superset-frontend/src/explore/components/controls/DatasourceControl/DatasourceControl.test.tsx
@@ -54,6 +54,15 @@ beforeEach(() => {
 
 afterEach(() => {
   window.location = originalLocation;
+
+  const unmatched = fetchMock.callHistory.calls('unmatched');
+  if (unmatched.length > 0) {
+    const urls = unmatched.map(call => call.url).join(', ');
+    throw new Error(
+      `fetchMock: ${unmatched.length} unmatched call(s): ${urls}`,
+    );
+  }
+
   fetchMock.clearHistory().removeRoutes();
   jest.restoreAllMocks();
 });
@@ -284,7 +293,9 @@ test('Click on Edit dataset', async () => {
 
   await userEvent.click(screen.getByText('Edit dataset'));
 
-  expect(await 
screen.findByTestId('mock-datasource-editor')).toBeInTheDocument();
+  expect(
+    await screen.findByTestId('mock-datasource-editor'),
+  ).toBeInTheDocument();
 });
 
 test('Edit dataset should be disabled when user is not admin', async () => {

Reply via email to