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

voidmatcha pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/master by this push:
     new adea3b9551 [ZEPPELIN-6545] Move the classic-suite gating to a 
dedicated Playwright config
adea3b9551 is described below

commit adea3b955148eb9c7f990e682309261fec660099
Author: Minho Jang <[email protected]>
AuthorDate: Sat Jul 18 11:03:34 2026 +0900

    [ZEPPELIN-6545] Move the classic-suite gating to a dedicated Playwright 
config
    
    ### What is this PR for?
    
    This PR separates the classic UI Playwright e2e suite from the main 
Playwright config.
    
    After ZEPPELIN-6527, classic specs under `e2e/tests/classic/` were wired 
into the shared config and gated with `E2E_CLASSIC` plus argv sniffing. That 
made plain `npm run e2e` depend on a `-Pweb-classic` server, allowed false 
positives from arguments like `--grep tests/classic`, and caused the coverage 
reporter to run for classic pages that are outside the coverage denominator.
    
    This change moves classic execution to a dedicated 
`playwright.classic.config.js`, updates `e2e:classic` and CI wiring to use it, 
removes the env/argv detection from the main config, and keeps the coverage 
reporter on the main suite only.
    
    
    ### What type of PR is it?
    Improvement
    
    ### What is the Jira issue?
    * https://issues.apache.org/jira/browse/ZEPPELIN-6545
    
    ### How should this be tested?
    - `cd zeppelin-web-angular && npm run e2e -- tests/classic --list 
--reporter=list`
      - Verifies the main Playwright config no longer selects classic specs.
    - `cd zeppelin-web-angular && npm run e2e:classic -- --list --reporter=list`
      - Verifies classic specs are selected only through the dedicated classic 
config.
    - `rg "E2E_CLASSIC|process\\.argv|isClassicOnlyRun|E2E_MODE" 
zeppelin-web-angular .github/workflows/frontend.yml`
      - Verifies the old env/argv gating was removed.
    - `rg "reporter\\.coverage" zeppelin-web-angular/playwright.config.js 
zeppelin-web-angular/playwright.classic.config.js`
      - Verifies the coverage reporter is only configured for the main suite.
    
    
    ### Questions:
    * Does the license files need to update? No
    * Is there breaking changes for older versions? No
    * Does this needs documentation? Edit AGENTS.md about modified classic 
suite config
    
    
    Closes #5317 from miinhho/test/move-classic-suite-gate.
    
    Signed-off-by: YONGJAE LEE <[email protected]>
---
 .github/workflows/frontend.yml                    |  9 +--
 zeppelin-web-angular/.gitignore                   |  2 +
 zeppelin-web-angular/e2e/AGENTS.md                | 23 +++++---
 zeppelin-web-angular/package.json                 |  5 +-
 zeppelin-web-angular/playwright.classic.config.js | 47 ++++++++++++++++
 zeppelin-web-angular/playwright.config.js         | 68 +++++------------------
 zeppelin-web-angular/playwright.shared.js         | 39 +++++++++++++
 zeppelin-web-angular/pom.xml                      | 14 +++++
 8 files changed, 139 insertions(+), 68 deletions(-)

diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml
index 872bfe6133..1998142a41 100644
--- a/.github/workflows/frontend.yml
+++ b/.github/workflows/frontend.yml
@@ -109,15 +109,16 @@ jobs:
           mkdir -p $ZEPPELIN_E2E_TEST_NOTEBOOK_DIR
           echo "Created test notebook directory: 
$ZEPPELIN_E2E_TEST_NOTEBOOK_DIR"
       - name: Run headless E2E test with Maven
-        env:
-          E2E_MODE: ${{ matrix.mode }}
-        run: xvfb-run --auto-servernum --server-args="-screen 0 1024x768x24" 
./mvnw verify -pl zeppelin-web-angular -Pweb-e2e ${MAVEN_ARGS}
+        # Classic UI e2e runs only on the anonymous leg, like the legacy 
Protractor suite
+        run: xvfb-run --auto-servernum --server-args="-screen 0 1024x768x24" 
./mvnw verify -pl zeppelin-web-angular -Pweb-e2e -Dweb.e2e.classic.disabled=${{ 
matrix.mode != 'anonymous' }} ${MAVEN_ARGS}
       - name: Upload Playwright Report
         uses: actions/upload-artifact@v6
         if: always()
         with:
           name: playwright-report-${{ matrix.mode }}
-          path: zeppelin-web-angular/playwright-report/
+          path: |
+            zeppelin-web-angular/playwright-report/
+            zeppelin-web-angular/playwright-report-classic/
           retention-days: 3
       - name: Print Zeppelin logs
         if: always()
diff --git a/zeppelin-web-angular/.gitignore b/zeppelin-web-angular/.gitignore
index 42b640c2fd..d0a457873a 100644
--- a/zeppelin-web-angular/.gitignore
+++ b/zeppelin-web-angular/.gitignore
@@ -45,8 +45,10 @@ Thumbs.db
 
 # Playwright
 /playwright-report/
+/playwright-report-classic/
 /playwright-coverage/
 /test-results/
+/test-results-classic/
 /playwright/.cache/
 /playwright/.auth/
 
diff --git a/zeppelin-web-angular/e2e/AGENTS.md 
b/zeppelin-web-angular/e2e/AGENTS.md
index 1fe1c62acf..900756358a 100644
--- a/zeppelin-web-angular/e2e/AGENTS.md
+++ b/zeppelin-web-angular/e2e/AGENTS.md
@@ -21,8 +21,10 @@ limitations under the License.
 > to the repository-root AGENTS.md, loaded only when working under `e2e/`.
 > See [AGENTS.md specification](https://github.com/agentsmd/agents.md).
 
-Config: `zeppelin-web-angular/playwright.config.js`. This file is the shared 
source
-of truth for E2E conventions; Codex and agents.md-native tools read it 
directly.
+Config: `zeppelin-web-angular/playwright.config.js` (Angular UI) and
+`playwright.classic.config.js` (legacy classic UI), sharing 
`playwright.shared.js`.
+This document is the shared source of truth for E2E conventions; Codex and
+agents.md-native tools read it directly.
 Claude Code / Gemini users can symlink `CLAUDE.md` / `GEMINI.md` to it locally
 (both gitignored, personal, not committed).
 
@@ -122,7 +124,8 @@ exercised transitively and are not counted.
 | `npm run e2e:headed` | Headed run |
 | `npm run e2e:debug` | Step-by-step debugger |
 | `npm run e2e:report` | Open last HTML report |
-| `npm run e2e:ci` | CI mode (`CI=true`, baseURL `:8080`) |
+| `npm run e2e:report:classic` | Open last classic HTML report |
+| `npm run e2e:ci` | CI mode (`CI=true`, baseURL `:8080`), main then classic 
suite |
 | `npm run e2e:codegen` | Record against `:4200` |
 | `npm run e2e:cleanup` | Delete leftover test notebooks 
(`e2e/cleanup-util.ts`) |
 
@@ -204,12 +207,14 @@ the Angular/React suites.
   the first `ParagraphCtrl` paragraph, or `.ace_text-input` attached).
 - **Coverage:** `PAGES` is the Angular coverage denominator; classic pages are
   intentionally outside it, so `addPageAnnotationBeforeEach` is not used here.
-- **Running:** the `classic` project targets `http://localhost:8080` (Desktop
-  Chrome only) and needs a Zeppelin server built with `-Pweb-classic` — the
-  `:4200` dev server does not serve `/classic`. Run it with `npm run 
e2e:classic`
-  (sets `E2E_CLASSIC=1`); running a `tests/classic/*` file path directly is 
also
-  detected. In CI the classic project runs only in the anonymous matrix leg
-  (`E2E_MODE`), matching the anonymous-only legacy Protractor suite.
+- **Running:** the classic suite has its own config, 
`playwright.classic.config.js`
+  (Desktop Chrome only, targets `http://localhost:8080`), and needs a Zeppelin
+  server built with `-Pweb-classic` — the `:4200` dev server does not serve
+  `/classic`, so a plain `npm run e2e` never includes it. Run it with
+  `npm run e2e:classic` (single spec: `npm run e2e:classic -- 
tests/classic/<spec>`).
+  In CI the workflow enables it on the anonymous matrix leg only
+  (`-Dweb.e2e.classic.disabled=false`), matching the anonymous-only legacy
+  Protractor suite.
 - **POM:** inlining locators/helpers is acceptable while the suite is this 
small;
   if it grows, move them behind `models/classic-*.ts` / `*.util.ts`.
 - The React-migration / framework-neutral-spec guidance does not apply to
diff --git a/zeppelin-web-angular/package.json 
b/zeppelin-web-angular/package.json
index 441c4cb5ea..55ae7ab835 100644
--- a/zeppelin-web-angular/package.json
+++ b/zeppelin-web-angular/package.json
@@ -21,12 +21,13 @@
     "test:eslint-rules": "node --test eslint-rules/",
     "e2e": "playwright test",
     "e2e:fast": "playwright test --project=chromium",
-    "e2e:classic": "cross-env E2E_CLASSIC=1 playwright test --project=classic",
+    "e2e:classic": "playwright test --config playwright.classic.config.js",
     "e2e:ui": "playwright test --ui",
     "e2e:headed": "playwright test --headed",
     "e2e:debug": "playwright test --debug",
     "e2e:report": "playwright show-report",
-    "e2e:ci": "export CI=true && playwright test",
+    "e2e:report:classic": "playwright show-report playwright-report-classic",
+    "e2e:ci": "export CI=true && playwright test && playwright test --config 
playwright.classic.config.js",
     "e2e:codegen": "playwright codegen http://localhost:4200";,
     "e2e:cleanup": "npx tsx e2e/cleanup-util.ts"
   },
diff --git a/zeppelin-web-angular/playwright.classic.config.js 
b/zeppelin-web-angular/playwright.classic.config.js
new file mode 100644
index 0000000000..e7a3fc6364
--- /dev/null
+++ b/zeppelin-web-angular/playwright.classic.config.js
@@ -0,0 +1,47 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const { defineConfig, devices } = require('@playwright/test');
+const { baseConfig } = require('./playwright.shared');
+
+// Classic UI suite (e2e/tests/classic/): needs a Zeppelin server built with 
-Pweb-classic
+// (:4200 does not serve /classic, hence no webServer). Run with: npm run 
e2e:classic
+process.env.PLAYWRIGHT_BASE_URL = process.env.PLAYWRIGHT_BASE_URL || 
'http://localhost:8080';
+
+module.exports = defineConfig({
+  ...baseConfig,
+  testMatch: /tests\/classic\/.*\.spec\.ts/,
+  outputDir: 'test-results-classic',
+  // Classic pages are outside the PAGES coverage denominator, so no coverage 
reporter.
+  reporter: [
+    [!!process.env.CI ? 'github' : 'list'],
+    ['html', { outputFolder: 'playwright-report-classic', open: 
!!process.env.CI ? 'never' : 'always' }]
+  ],
+  use: {
+    ...baseConfig.use,
+    baseURL: process.env.PLAYWRIGHT_BASE_URL
+  },
+  projects: [
+    {
+      name: 'setup',
+      testMatch: /global\.setup\.ts/
+    },
+    {
+      name: 'classic',
+      use: {
+        ...devices['Desktop Chrome'],
+        storageState: 'playwright/.auth/user.json'
+      },
+      dependencies: ['setup']
+    }
+  ]
+});
diff --git a/zeppelin-web-angular/playwright.config.js 
b/zeppelin-web-angular/playwright.config.js
index 4e019e8fd5..617d5776ed 100644
--- a/zeppelin-web-angular/playwright.config.js
+++ b/zeppelin-web-angular/playwright.config.js
@@ -11,41 +11,24 @@
  */
 
 const { defineConfig, devices } = require('@playwright/test');
+const { baseConfig } = require('./playwright.shared');
 
-const classicTests = /tests\/classic\/.*\.spec\.ts/;
-const isClassicOnlyRun = process.env.E2E_CLASSIC === '1' || 
process.argv.some(arg => arg.includes('tests/classic'));
-const defaultBaseURL = process.env.CI || isClassicOnlyRun ? 
'http://localhost:8080' : 'http://localhost:4200';
+const defaultBaseURL = process.env.CI ? 'http://localhost:8080' : 
'http://localhost:4200';
 process.env.PLAYWRIGHT_BASE_URL = process.env.PLAYWRIGHT_BASE_URL || 
defaultBaseURL;
 
 // https://playwright.dev/docs/test-configuration
 module.exports = defineConfig({
-  testDir: './e2e',
-  globalSetup: require.resolve('./e2e/global-setup'),
-  globalTeardown: require.resolve('./e2e/global-teardown'),
-  fullyParallel: true,
-  forbidOnly: !!process.env.CI,
-  retries: process.env.CI ? 2 : 1,
-  workers: 5,
-  timeout: 300000,
-  expect: {
-    timeout: 60000
-  },
+  ...baseConfig,
+  // The legacy classic UI suite runs separately via 
playwright.classic.config.js.
+  testIgnore: /tests\/classic\/.*\.spec\.ts/,
   reporter: [
     [!!process.env.CI ? 'github' : 'list'],
     ['html', { open: !!process.env.CI ? 'never' : 'always' }],
     ['./e2e/reporter.coverage.ts']
   ],
   use: {
-    baseURL: process.env.PLAYWRIGHT_BASE_URL,
-    trace: 'on-first-retry', // https://playwright.dev/docs/trace-viewer
-    screenshot: process.env.CI ? 'off' : 'only-on-failure',
-    video: process.env.CI ? 'off' : 'retain-on-failure',
-    launchOptions: {
-      args: ['--disable-dev-shm-usage']
-    },
-    headless: true,
-    actionTimeout: 60000,
-    navigationTimeout: 180000
+    ...baseConfig.use,
+    baseURL: process.env.PLAYWRIGHT_BASE_URL
   },
   projects: [
     // Auth setup runs once and writes playwright/.auth/user.json, which the 
browser
@@ -55,24 +38,8 @@ module.exports = defineConfig({
       name: 'setup',
       testMatch: /global\.setup\.ts/
     },
-    // skip classic in the auth CI leg (its Protractor predecessor was 
anonymous-only)
-    ...(process.env.E2E_MODE === 'auth'
-      ? []
-      : [
-          {
-            name: 'classic',
-            testMatch: classicTests,
-            use: {
-              ...devices['Desktop Chrome'],
-              baseURL: 'http://localhost:8080',
-              storageState: 'playwright/.auth/user.json'
-            },
-            dependencies: ['setup']
-          }
-        ]),
     {
       name: 'chromium',
-      testIgnore: classicTests,
       use: {
         ...devices['Desktop Chrome'],
         permissions: ['clipboard-read', 'clipboard-write'],
@@ -82,7 +49,6 @@ module.exports = defineConfig({
     },
     {
       name: 'Google Chrome',
-      testIgnore: classicTests,
       use: {
         ...devices['Desktop Chrome'],
         channel: 'chrome',
@@ -93,7 +59,6 @@ module.exports = defineConfig({
     },
     {
       name: 'firefox',
-      testIgnore: classicTests,
       use: {
         ...devices['Desktop Firefox'],
         storageState: 'playwright/.auth/user.json'
@@ -102,7 +67,6 @@ module.exports = defineConfig({
     },
     {
       name: 'webkit',
-      testIgnore: classicTests,
       use: {
         ...devices['Desktop Safari'],
         launchOptions: {
@@ -114,7 +78,6 @@ module.exports = defineConfig({
     },
     {
       name: 'Microsoft Edge',
-      testIgnore: classicTests,
       use: {
         ...devices['Desktop Edge'],
         channel: 'msedge',
@@ -124,13 +87,12 @@ module.exports = defineConfig({
       dependencies: ['setup']
     }
   ],
-  webServer:
-    process.env.CI || isClassicOnlyRun
-      ? undefined
-      : {
-          command: 'npm run start',
-          url: 'http://localhost:4200',
-          reuseExistingServer: true,
-          timeout: 2 * 60 * 1000
-        }
+  webServer: process.env.CI
+    ? undefined
+    : {
+        command: 'npm run start',
+        url: 'http://localhost:4200',
+        reuseExistingServer: true,
+        timeout: 2 * 60 * 1000
+      }
 });
diff --git a/zeppelin-web-angular/playwright.shared.js 
b/zeppelin-web-angular/playwright.shared.js
new file mode 100644
index 0000000000..cb3c254f46
--- /dev/null
+++ b/zeppelin-web-angular/playwright.shared.js
@@ -0,0 +1,39 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Settings shared by playwright.config.js and playwright.classic.config.js.
+const baseConfig = {
+  testDir: './e2e',
+  globalSetup: require.resolve('./e2e/global-setup'),
+  globalTeardown: require.resolve('./e2e/global-teardown'),
+  fullyParallel: true,
+  forbidOnly: !!process.env.CI,
+  retries: process.env.CI ? 2 : 1,
+  workers: 5,
+  timeout: 300000,
+  expect: {
+    timeout: 60000
+  },
+  use: {
+    trace: 'on-first-retry', // https://playwright.dev/docs/trace-viewer
+    screenshot: process.env.CI ? 'off' : 'only-on-failure',
+    video: process.env.CI ? 'off' : 'retain-on-failure',
+    launchOptions: {
+      args: ['--disable-dev-shm-usage']
+    },
+    headless: true,
+    actionTimeout: 60000,
+    navigationTimeout: 180000
+  }
+};
+
+module.exports = { baseConfig };
diff --git a/zeppelin-web-angular/pom.xml b/zeppelin-web-angular/pom.xml
index 113bb69e79..6c9a164688 100644
--- a/zeppelin-web-angular/pom.xml
+++ b/zeppelin-web-angular/pom.xml
@@ -33,6 +33,8 @@
   <properties>
     <web.e2e.disabled>true</web.e2e.disabled>
     <web.e2e.enabled>false</web.e2e.enabled>
+    <!-- Classic UI e2e runs opt-in: CI enables it on the anonymous leg only. 
-->
+    <web.e2e.classic.disabled>true</web.e2e.classic.disabled>
     <zeppelin.daemon.package.base>../bin</zeppelin.daemon.package.base>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 
@@ -128,6 +130,18 @@
             </configuration>
           </execution>
 
+          <execution>
+            <id>npm e2e classic</id>
+            <goals>
+              <goal>npm</goal>
+            </goals>
+            <phase>integration-test</phase>
+            <configuration>
+              <skip>${web.e2e.classic.disabled}</skip>
+              <arguments>run e2e:classic</arguments>
+            </configuration>
+          </execution>
+
         </executions>
       </plugin>
 

Reply via email to