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>