This is an automated email from the ASF dual-hosted git repository.
tbonelee 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 7f7b995c35 [ZEPPELIN-6668] Add notebook route benchmark contract
7f7b995c35 is described below
commit 7f7b995c35978c4a3ef3df31ec8faf206ce179f9
Author: YONGJAE LEE (이용재) <[email protected]>
AuthorDate: Sun Sep 27 17:34:57 2026 +0900
[ZEPPELIN-6668] Add notebook route benchmark contract
### What is this PR for?
Add a reproducible benchmark contract for the notebook route, without
committing baseline numbers (a follow-up records them).
* Fixture: 100 paragraphs (80 TEXT, 10 TABLE, 10 collapsed), pinned by
SHA-256
* Ready condition: action bar visible, 100 paragraph containers, first
Monaco editor attached
* Runs: 10 cold (new context) and 10 warm (after one unrecorded prime),
with raw samples, median, and p95
* Bundles: raw and gzip sizes of the Angular entry chunks and React
`remoteEntry.js`
Runtime metrics cover the Angular route only. The benchmark is excluded
from the normal E2E run.
Most of the diff (3,319 of 3,957 added lines) is the fixture JSON. It is
data, pinned by SHA-256 and checked for composition by `validateFixture`, so it
does not need a line-by-line review. The code to review is about 590 lines
under `e2e/performance/`, `e2e/models/notebook-performance-page.ts`,
`test/notebook-baseline.spec.ts` and `playwright.performance.config.js`.
### What type of PR is it?
Improvement
### Todos
* [x] Add a hash-pinned benchmark fixture
* [x] Add the Playwright performance runner
* [x] Validate the benchmark contract with unit tests
### What is the Jira issue?
ZEPPELIN-6668
### How should this be tested?
```bash
cd zeppelin-web-angular
npm run test:shell -- test/notebook-baseline.spec.ts
# against an isolated Zeppelin serving the `npm run build` output
PLAYWRIGHT_BASE_URL=http://localhost:8080 PERF_NOTEBOOK_DISPOSABLE=1
PERF_NOTEBOOK_DRY_RUN=1 npm run perf:notebook-baseline
```
A local dry run passes (1 cold + 1 warm, every summary field recorded). Use
`localhost`: the server rejects a `127.0.0.1` WebSocket origin unless
`zeppelin.server.allowed.origins` is set.
### Screenshots (if appropriate)
N/A
### Questions:
* Does the license files need to update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? Yes - `e2e/performance/README.md`
Closes #5484 from voidmatcha/ZEPPELIN-6668-notebook-benchmark.
Signed-off-by: ChanHo Lee <[email protected]>
---
.gitattributes | 2 +
zeppelin-web-angular/.gitignore | 1 +
zeppelin-web-angular/.prettierignore | 1 +
.../performance/notebook-route-100-paragraphs.json | 3319 ++++++++++++++++++++
.../e2e/models/notebook-performance-page.ts | 66 +
zeppelin-web-angular/e2e/performance/README.md | 49 +
.../e2e/performance/notebook-baseline.ts | 135 +
.../performance/notebook-route-baseline.spec.ts | 184 ++
zeppelin-web-angular/package.json | 1 +
zeppelin-web-angular/playwright.config.js | 4 +-
.../playwright.performance.config.js | 46 +
.../test/notebook-baseline.spec.ts | 151 +
12 files changed, 3957 insertions(+), 2 deletions(-)
diff --git a/.gitattributes b/.gitattributes
index cbdcbbc258..5d41043928 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,3 @@
*.js text eol=lf
+# Byte-exact: the benchmark pins this fixture's SHA-256.
+zeppelin-web-angular/e2e/fixtures/performance/*.json -text
diff --git a/zeppelin-web-angular/.gitignore b/zeppelin-web-angular/.gitignore
index d0a457873a..bb775e418d 100644
--- a/zeppelin-web-angular/.gitignore
+++ b/zeppelin-web-angular/.gitignore
@@ -51,6 +51,7 @@ Thumbs.db
/test-results-classic/
/playwright/.cache/
/playwright/.auth/
+/e2e/performance/baselines/*.json
#
.env
diff --git a/zeppelin-web-angular/.prettierignore
b/zeppelin-web-angular/.prettierignore
index a16d95f394..ed1a946bfb 100644
--- a/zeppelin-web-angular/.prettierignore
+++ b/zeppelin-web-angular/.prettierignore
@@ -15,5 +15,6 @@ projects/*/coverage/*
playwright-report/*
playwright-coverage/*
test-results/*
+e2e/fixtures/performance/*.json
.angular/*
diff --git
a/zeppelin-web-angular/e2e/fixtures/performance/notebook-route-100-paragraphs.json
b/zeppelin-web-angular/e2e/fixtures/performance/notebook-route-100-paragraphs.json
new file mode 100644
index 0000000000..79fde9f44f
--- /dev/null
+++
b/zeppelin-web-angular/e2e/fixtures/performance/notebook-route-100-paragraphs.json
@@ -0,0 +1,3319 @@
+{
+ "name": "notebook-route-100-paragraphs",
+ "paragraphs": [
+ {
+ "id": "paragraph_perf_001",
+ "title": "Baseline paragraph 001",
+ "text": "%sh\necho baseline-001",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 001\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_002",
+ "title": "Baseline paragraph 002",
+ "text": "%sh\necho baseline-002",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 002\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_003",
+ "title": "Baseline paragraph 003",
+ "text": "%sh\necho baseline-003",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 003\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_004",
+ "title": "Baseline paragraph 004",
+ "text": "%sh\necho baseline-004",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 004\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_005",
+ "title": "Baseline paragraph 005",
+ "text": "%sh\necho baseline-005",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 005\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_006",
+ "title": "Baseline paragraph 006",
+ "text": "%sh\necho baseline-006",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 006\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_007",
+ "title": "Baseline paragraph 007",
+ "text": "%sh\necho baseline-007",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 007\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_008",
+ "title": "Baseline paragraph 008",
+ "text": "%sh\necho baseline-008",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 008\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_009",
+ "title": "Baseline paragraph 009",
+ "text": "%sh\necho baseline-009",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 009\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_010",
+ "title": "Baseline paragraph 010",
+ "text": "%sh\necho baseline-010",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 010\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_011",
+ "title": "Baseline paragraph 011",
+ "text": "%sh\necho baseline-011",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 011\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_012",
+ "title": "Baseline paragraph 012",
+ "text": "%sh\necho baseline-012",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 012\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_013",
+ "title": "Baseline paragraph 013",
+ "text": "%sh\necho baseline-013",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 013\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_014",
+ "title": "Baseline paragraph 014",
+ "text": "%sh\necho baseline-014",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 014\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_015",
+ "title": "Baseline paragraph 015",
+ "text": "%sh\necho baseline-015",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 015\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_016",
+ "title": "Baseline paragraph 016",
+ "text": "%sh\necho baseline-016",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 016\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_017",
+ "title": "Baseline paragraph 017",
+ "text": "%sh\necho baseline-017",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 017\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_018",
+ "title": "Baseline paragraph 018",
+ "text": "%sh\necho baseline-018",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 018\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_019",
+ "title": "Baseline paragraph 019",
+ "text": "%sh\necho baseline-019",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 019\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_020",
+ "title": "Baseline paragraph 020",
+ "text": "%sh\necho baseline-020",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 020\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_021",
+ "title": "Baseline paragraph 021",
+ "text": "%sh\necho baseline-021",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 021\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_022",
+ "title": "Baseline paragraph 022",
+ "text": "%sh\necho baseline-022",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 022\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_023",
+ "title": "Baseline paragraph 023",
+ "text": "%sh\necho baseline-023",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 023\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_024",
+ "title": "Baseline paragraph 024",
+ "text": "%sh\necho baseline-024",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 024\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_025",
+ "title": "Baseline paragraph 025",
+ "text": "%sh\necho baseline-025",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 025\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_026",
+ "title": "Baseline paragraph 026",
+ "text": "%sh\necho baseline-026",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 026\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_027",
+ "title": "Baseline paragraph 027",
+ "text": "%sh\necho baseline-027",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 027\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_028",
+ "title": "Baseline paragraph 028",
+ "text": "%sh\necho baseline-028",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 028\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_029",
+ "title": "Baseline paragraph 029",
+ "text": "%sh\necho baseline-029",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 029\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_030",
+ "title": "Baseline paragraph 030",
+ "text": "%sh\necho baseline-030",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 030\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_031",
+ "title": "Baseline paragraph 031",
+ "text": "%sh\necho baseline-031",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 031\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_032",
+ "title": "Baseline paragraph 032",
+ "text": "%sh\necho baseline-032",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 032\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_033",
+ "title": "Baseline paragraph 033",
+ "text": "%sh\necho baseline-033",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 033\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_034",
+ "title": "Baseline paragraph 034",
+ "text": "%sh\necho baseline-034",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 034\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_035",
+ "title": "Baseline paragraph 035",
+ "text": "%sh\necho baseline-035",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 035\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_036",
+ "title": "Baseline paragraph 036",
+ "text": "%sh\necho baseline-036",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 036\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_037",
+ "title": "Baseline paragraph 037",
+ "text": "%sh\necho baseline-037",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 037\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_038",
+ "title": "Baseline paragraph 038",
+ "text": "%sh\necho baseline-038",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 038\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_039",
+ "title": "Baseline paragraph 039",
+ "text": "%sh\necho baseline-039",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 039\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_040",
+ "title": "Baseline paragraph 040",
+ "text": "%sh\necho baseline-040",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 040\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_041",
+ "title": "Baseline paragraph 041",
+ "text": "%sh\necho baseline-041",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 041\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_042",
+ "title": "Baseline paragraph 042",
+ "text": "%sh\necho baseline-042",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 042\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_043",
+ "title": "Baseline paragraph 043",
+ "text": "%sh\necho baseline-043",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 043\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_044",
+ "title": "Baseline paragraph 044",
+ "text": "%sh\necho baseline-044",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 044\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_045",
+ "title": "Baseline paragraph 045",
+ "text": "%sh\necho baseline-045",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 045\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_046",
+ "title": "Baseline paragraph 046",
+ "text": "%sh\necho baseline-046",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 046\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_047",
+ "title": "Baseline paragraph 047",
+ "text": "%sh\necho baseline-047",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 047\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_048",
+ "title": "Baseline paragraph 048",
+ "text": "%sh\necho baseline-048",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 048\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_049",
+ "title": "Baseline paragraph 049",
+ "text": "%sh\necho baseline-049",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 049\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_050",
+ "title": "Baseline paragraph 050",
+ "text": "%sh\necho baseline-050",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 050\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_051",
+ "title": "Baseline paragraph 051",
+ "text": "%sh\necho baseline-051",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 051\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_052",
+ "title": "Baseline paragraph 052",
+ "text": "%sh\necho baseline-052",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 052\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_053",
+ "title": "Baseline paragraph 053",
+ "text": "%sh\necho baseline-053",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 053\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_054",
+ "title": "Baseline paragraph 054",
+ "text": "%sh\necho baseline-054",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 054\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_055",
+ "title": "Baseline paragraph 055",
+ "text": "%sh\necho baseline-055",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 055\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_056",
+ "title": "Baseline paragraph 056",
+ "text": "%sh\necho baseline-056",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 056\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_057",
+ "title": "Baseline paragraph 057",
+ "text": "%sh\necho baseline-057",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 057\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_058",
+ "title": "Baseline paragraph 058",
+ "text": "%sh\necho baseline-058",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 058\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_059",
+ "title": "Baseline paragraph 059",
+ "text": "%sh\necho baseline-059",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 059\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_060",
+ "title": "Baseline paragraph 060",
+ "text": "%sh\necho baseline-060",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 060\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_061",
+ "title": "Baseline paragraph 061",
+ "text": "%sh\necho baseline-061",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 061\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_062",
+ "title": "Baseline paragraph 062",
+ "text": "%sh\necho baseline-062",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 062\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_063",
+ "title": "Baseline paragraph 063",
+ "text": "%sh\necho baseline-063",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 063\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_064",
+ "title": "Baseline paragraph 064",
+ "text": "%sh\necho baseline-064",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 064\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_065",
+ "title": "Baseline paragraph 065",
+ "text": "%sh\necho baseline-065",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 065\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_066",
+ "title": "Baseline paragraph 066",
+ "text": "%sh\necho baseline-066",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 066\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_067",
+ "title": "Baseline paragraph 067",
+ "text": "%sh\necho baseline-067",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 067\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_068",
+ "title": "Baseline paragraph 068",
+ "text": "%sh\necho baseline-068",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 068\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_069",
+ "title": "Baseline paragraph 069",
+ "text": "%sh\necho baseline-069",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 069\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_070",
+ "title": "Baseline paragraph 070",
+ "text": "%sh\necho baseline-070",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 070\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_071",
+ "title": "Baseline paragraph 071",
+ "text": "%sh\necho baseline-071",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 071\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_072",
+ "title": "Baseline paragraph 072",
+ "text": "%sh\necho baseline-072",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 072\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_073",
+ "title": "Baseline paragraph 073",
+ "text": "%sh\necho baseline-073",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 073\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_074",
+ "title": "Baseline paragraph 074",
+ "text": "%sh\necho baseline-074",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 074\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_075",
+ "title": "Baseline paragraph 075",
+ "text": "%sh\necho baseline-075",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 075\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_076",
+ "title": "Baseline paragraph 076",
+ "text": "%sh\necho baseline-076",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 076\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_077",
+ "title": "Baseline paragraph 077",
+ "text": "%sh\necho baseline-077",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 077\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_078",
+ "title": "Baseline paragraph 078",
+ "text": "%sh\necho baseline-078",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 078\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_079",
+ "title": "Baseline paragraph 079",
+ "text": "%sh\necho baseline-079",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 079\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_080",
+ "title": "Baseline paragraph 080",
+ "text": "%sh\necho baseline-080",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TEXT",
+ "data": "Idle text result 080\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_081",
+ "title": "Baseline paragraph 081",
+ "text": "%sh\necho baseline-081",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TABLE",
+ "data": "key\tvalue\nalpha\t1\nbeta\t2\ngamma\t3\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_082",
+ "title": "Baseline paragraph 082",
+ "text": "%sh\necho baseline-082",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TABLE",
+ "data": "key\tvalue\nalpha\t1\nbeta\t2\ngamma\t3\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_083",
+ "title": "Baseline paragraph 083",
+ "text": "%sh\necho baseline-083",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TABLE",
+ "data": "key\tvalue\nalpha\t1\nbeta\t2\ngamma\t3\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_084",
+ "title": "Baseline paragraph 084",
+ "text": "%sh\necho baseline-084",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TABLE",
+ "data": "key\tvalue\nalpha\t1\nbeta\t2\ngamma\t3\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_085",
+ "title": "Baseline paragraph 085",
+ "text": "%sh\necho baseline-085",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TABLE",
+ "data": "key\tvalue\nalpha\t1\nbeta\t2\ngamma\t3\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_086",
+ "title": "Baseline paragraph 086",
+ "text": "%sh\necho baseline-086",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TABLE",
+ "data": "key\tvalue\nalpha\t1\nbeta\t2\ngamma\t3\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_087",
+ "title": "Baseline paragraph 087",
+ "text": "%sh\necho baseline-087",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TABLE",
+ "data": "key\tvalue\nalpha\t1\nbeta\t2\ngamma\t3\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_088",
+ "title": "Baseline paragraph 088",
+ "text": "%sh\necho baseline-088",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TABLE",
+ "data": "key\tvalue\nalpha\t1\nbeta\t2\ngamma\t3\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_089",
+ "title": "Baseline paragraph 089",
+ "text": "%sh\necho baseline-089",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TABLE",
+ "data": "key\tvalue\nalpha\t1\nbeta\t2\ngamma\t3\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_090",
+ "title": "Baseline paragraph 090",
+ "text": "%sh\necho baseline-090",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": false,
+ "tableHide": false,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {},
+ "results": {
+ "code": "SUCCESS",
+ "msg": [
+ {
+ "type": "TABLE",
+ "data": "key\tvalue\nalpha\t1\nbeta\t2\ngamma\t3\n"
+ }
+ ]
+ }
+ },
+ {
+ "id": "paragraph_perf_091",
+ "title": "Baseline paragraph 091",
+ "text": "%sh\necho baseline-091",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": true,
+ "tableHide": true,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {}
+ },
+ {
+ "id": "paragraph_perf_092",
+ "title": "Baseline paragraph 092",
+ "text": "%sh\necho baseline-092",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": true,
+ "tableHide": true,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {}
+ },
+ {
+ "id": "paragraph_perf_093",
+ "title": "Baseline paragraph 093",
+ "text": "%sh\necho baseline-093",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": true,
+ "tableHide": true,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {}
+ },
+ {
+ "id": "paragraph_perf_094",
+ "title": "Baseline paragraph 094",
+ "text": "%sh\necho baseline-094",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": true,
+ "tableHide": true,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {}
+ },
+ {
+ "id": "paragraph_perf_095",
+ "title": "Baseline paragraph 095",
+ "text": "%sh\necho baseline-095",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": true,
+ "tableHide": true,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {}
+ },
+ {
+ "id": "paragraph_perf_096",
+ "title": "Baseline paragraph 096",
+ "text": "%sh\necho baseline-096",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": true,
+ "tableHide": true,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {}
+ },
+ {
+ "id": "paragraph_perf_097",
+ "title": "Baseline paragraph 097",
+ "text": "%sh\necho baseline-097",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": true,
+ "tableHide": true,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {}
+ },
+ {
+ "id": "paragraph_perf_098",
+ "title": "Baseline paragraph 098",
+ "text": "%sh\necho baseline-098",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": true,
+ "tableHide": true,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {}
+ },
+ {
+ "id": "paragraph_perf_099",
+ "title": "Baseline paragraph 099",
+ "text": "%sh\necho baseline-099",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": true,
+ "tableHide": true,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {}
+ },
+ {
+ "id": "paragraph_perf_100",
+ "title": "Baseline paragraph 100",
+ "text": "%sh\necho baseline-100",
+ "user": "anonymous",
+ "status": "READY",
+ "config": {
+ "colWidth": 12,
+ "fontSize": 9,
+ "enabled": true,
+ "editorHide": true,
+ "tableHide": true,
+ "title": false,
+ "editorSetting": {
+ "language": "sh",
+ "editOnDblClick": false
+ }
+ },
+ "settings": {
+ "params": {},
+ "forms": {}
+ },
+ "apps": [],
+ "runtimeInfos": {}
+ }
+ ],
+ "config": {
+ "isZeppelinNotebook": true
+ },
+ "info": {}
+}
diff --git a/zeppelin-web-angular/e2e/models/notebook-performance-page.ts
b/zeppelin-web-angular/e2e/models/notebook-performance-page.ts
new file mode 100644
index 0000000000..5b2ba38faa
--- /dev/null
+++ b/zeppelin-web-angular/e2e/models/notebook-performance-page.ts
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+import { expect, Page } from '@playwright/test';
+
+// JUSTIFIED: This fixed Angular baseline measures existing hosts and Monaco
attachment,
+// not a cross-framework user flow; these elements have no accessible role or
test ID.
+const selectors = {
+ actionBar: 'zeppelin-notebook-action-bar',
+ paragraphs: 'zeppelin-notebook-paragraph',
+ editor: '.monaco-editor'
+};
+
+export class NotebookPerformancePage {
+ constructor(private readonly page: Page) {}
+
+ async measureReady() {
+ // JUSTIFIED: Evaluate the three readiness signals together on the browser
clock;
+ // separate host-side assertions would add polling/IPC delay to the
measured time.
+ const ready = await this.page.waitForFunction(
+ ({ actionBar, paragraphs, editor }) => {
+ const bar = document.querySelector(actionBar);
+ const style = bar && getComputedStyle(bar);
+ if (
+ !bar ||
+ !bar.getClientRects().length ||
+ style?.visibility === 'hidden' ||
+ style?.display === 'none' ||
+ document.querySelectorAll(paragraphs).length !== 100 ||
+ !document.querySelector(`${paragraphs} ${editor}`)
+ ) {
+ return false;
+ }
+ return performance.now();
+ },
+ selectors,
+ { timeout: 60000, polling: 'raf' }
+ );
+ const notebookReadyMs = (await ready.jsonValue()) as number;
+ await ready.dispose();
+ // Post-measurement sanity check of the ready condition; timing comes from
the in-page wait above.
+ await expect(this.page.locator(selectors.actionBar)).toBeVisible();
+ await expect(this.page.locator(selectors.paragraphs)).toHaveCount(100);
+ // JUSTIFIED: The benchmark explicitly requires the first Monaco editor to
be attached.
+ await expect(this.page.locator(`${selectors.paragraphs}
${selectors.editor}`).first()).toBeAttached();
+ const paint = await this.page.waitForFunction(
+ () => {
+ return
performance.getEntriesByName('first-contentful-paint')[0]?.startTime || false;
+ },
+ undefined,
+ { timeout: 10000 }
+ );
+ const fcpMs = (await paint.jsonValue()) as number;
+ await paint.dispose();
+ return { notebookReadyMs, fcpMs };
+ }
+}
diff --git a/zeppelin-web-angular/e2e/performance/README.md
b/zeppelin-web-angular/e2e/performance/README.md
new file mode 100644
index 0000000000..f1f8b70e0d
--- /dev/null
+++ b/zeppelin-web-angular/e2e/performance/README.md
@@ -0,0 +1,49 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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.
+-->
+
+# Notebook route benchmark contract
+
+ZEPPELIN-6668 defines the fixture and measurement format. It does not
establish a pinned Angular baseline. Generated JSON is ignored by Git.
+
+Build with `npm run build`, then serve `dist/zeppelin` with an isolated local
Zeppelin backend. The benchmark imports one note and deletes that note in
cleanup. Do not point it at a shared notebook store. It checks the served
index's entry script list and the served entry asset hashes against the local
build before importing the fixture; server-injected inline markup does not
affect this check. The normal E2E suite does not run this benchmark; no
development server is started by its conf [...]
+
+To serve the fresh build, start Zeppelin from this source tree after `npm run
build`. In `zeppelin-server`'s `ZeppelinConfiguration`, `zeppelin.default.ui`
defaults to `new` and `zeppelin.angular.war` defaults to
`zeppelin-web-angular/dist/zeppelin`, so the benchmark requests that `dist` at
`/` unless either property is overridden. Use `localhost` in
`PLAYWRIGHT_BASE_URL`: unless `zeppelin.server.allowed.origins` is set, the
server accepts a WebSocket origin only from `localhost` or its [...]
+
+`playwright.performance.config.js` intentionally throws when
`PLAYWRIGHT_BASE_URL` or `PERF_NOTEBOOK_DISPOSABLE=1` is missing, so `npx
playwright test --list --config playwright.performance.config.js` needs them
too.
+
+```sh
+# From zeppelin-web-angular, with the built application served at this origin:
+PLAYWRIGHT_BASE_URL=http://localhost:8080 \
+ PERF_NOTEBOOK_DISPOSABLE=1 \
+ npm run perf:notebook-baseline
+
+# Contract validation only: one cold and one warm sample, plus an unrecorded
prime.
+PLAYWRIGHT_BASE_URL=http://localhost:8080 \
+ PERF_NOTEBOOK_DISPOSABLE=1 \
+ PERF_NOTEBOOK_DRY_RUN=1 \
+ npm run perf:notebook-baseline
+```
+
+The standard Chromium project and its automatic authentication setup are
reused. Traces, screenshots, video, retries, parallel workers and service
workers are disabled for measurement. Measurement contexts inherit the
project's viewport, user agent, device scale factor, mobile/touch, locale,
timezone, color scheme, permissions, HTTPS error and extra HTTP header options.
Each cold run uses a new browser context (empty HTTP cache). Warm runs reuse
one context/page after one unrecorded prim [...]
+
+The fixture is `../fixtures/performance/notebook-route-100-paragraphs.json`:
80 idle TEXT-result paragraphs, 10 idle TABLE-result paragraphs, and 10
collapsed code paragraphs, all in READY status; note import resets paragraph
status to READY. No interpreter executes. The pinned `fixtureSha256` constant
in `notebook-baseline.ts` is checked before import, and the composition is
validated. A deliberate fixture revision must update that constant and be
reviewed as a benchmark contract change.
+
+`notebookReadyMs` is the browser's `performance.now()` when the action bar is
visible, exactly 100 paragraph hosts are attached, and the first Monaco editor
is attached, checked together once per animation frame, so it has roughly
one-frame (about 16 ms at 60 Hz) resolution. It is relative to that document's
navigation start, not the preceding import. `fcpMs` is the browser
`first-contentful-paint` Performance entry. Missing readiness or FCP fails the
run; there is no timeout fallback metric.
+
+Outputs are `baselines/<run-id>.raw.json` and `<run-id>.summary.json`. Both
contain schema version, run ID/time, dry-run flag, Zeppelin commit and
dirty-tree flag, OS/release, CPU model, physical memory bytes, browser/Node
versions, build command, fixture path/SHA-256, base URL, viewport, run counts
and bundle measurements. Raw samples contain `cache` (`cold` or `warm`),
one-based `run`, `notebookReadyMs` and `fcpMs`. Summary groups each metric by
cache mode with count, median and neares [...]
+
+`bundles.angularEntryChunks` lists JavaScript entry scripts from the built
Angular `index.html`. `bundles.reactRemoteEntry` measures the separately served
`assets/react/remoteEntry.js`. Each file records relative path, SHA-256, raw
bytes and gzip bytes. These are entry asset measurements, not the whole `dist`
tree or a claim about the complete notebook route's lazy-loaded bundle size.
+
+Focused static checks: `npm run test:shell -- test/notebook-baseline.spec.ts`
and `npx eslint e2e/performance/*.ts e2e/models/notebook-performance-page.ts`.
diff --git a/zeppelin-web-angular/e2e/performance/notebook-baseline.ts
b/zeppelin-web-angular/e2e/performance/notebook-baseline.ts
new file mode 100644
index 0000000000..f027332f5e
--- /dev/null
+++ b/zeppelin-web-angular/e2e/performance/notebook-baseline.ts
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+import { createHash } from 'node:crypto';
+import { readFileSync } from 'node:fs';
+import { resolve, relative } from 'node:path';
+import { gzipSync } from 'node:zlib';
+
+export const fixturePath =
'e2e/fixtures/performance/notebook-route-100-paragraphs.json';
+const fixtureSha256 =
'7f94de1f9a7e529c7baf473a8bba9ab017f410c896f21bd8357922b63bd81fde';
+export type Sample = { cache: 'cold' | 'warm'; run: number; notebookReadyMs:
number; fcpMs: number };
+
+export const normalizeBundlePath = (path: string): string =>
path.replace(/\\/g, '/');
+
+export const loadFixture = (root: string) => {
+ const bytes = readFileSync(resolve(root, fixturePath));
+ const sha256 = createHash('sha256').update(bytes).digest('hex');
+ if (sha256 !== fixtureSha256) {
+ throw new Error('Benchmark fixture SHA-256 mismatch');
+ }
+ const note = JSON.parse(bytes.toString('utf8'));
+ validateFixture(note);
+ return { note, sha256 };
+};
+
+export const validateFixture = (note: {
+ paragraphs: Array<{
+ id: string;
+ status: string;
+ config: { editorHide: boolean; tableHide: boolean };
+ results?: { code: string; msg: Array<{ type: string; data: string }> };
+ }>;
+}): void => {
+ const paragraphs = note.paragraphs;
+ if (!Array.isArray(paragraphs) || paragraphs.length !== 100 || new
Set(paragraphs.map(p => p.id)).size !== 100) {
+ throw new Error('Benchmark fixture requires 100 distinct paragraphs');
+ }
+ paragraphs.forEach((p, index) => {
+ const collapsed = index >= 90;
+ const result = p.results?.msg;
+ if (
+ p.config.editorHide !== collapsed ||
+ p.config.tableHide !== collapsed ||
+ p.status !== 'READY' ||
+ (collapsed
+ ? p.results !== undefined
+ : p.results?.code !== 'SUCCESS' ||
+ result?.length !== 1 ||
+ result[0].type !== (index < 80 ? 'TEXT' : 'TABLE') ||
+ !result[0].data)
+ ) {
+ throw new Error(
+ `Benchmark fixture paragraph ${index + 1} violates the 80 text / 10
table / 10 collapsed contract`
+ );
+ }
+ });
+};
+
+export const summarize = (samples: Sample[], runs: number) => {
+ return Object.fromEntries(
+ (['cold', 'warm'] as const).map(cache => {
+ const group = samples.filter(sample => sample.cache === cache);
+ if (group.length !== runs || group.some((sample, index) => sample.run
!== index + 1)) {
+ throw new Error(`Expected exactly ${runs} ordered ${cache} samples`);
+ }
+ const metrics = Object.fromEntries(
+ (['notebookReadyMs', 'fcpMs'] as const).map(metric => {
+ const values = group.map(sample => sample[metric]).sort((a, b) => a
- b);
+ if (values.some(value => !Number.isFinite(value) || value <= 0)) {
+ throw new Error(`Missing or invalid ${metric}`);
+ }
+ const middle = Math.floor(values.length / 2);
+ return [
+ metric,
+ {
+ median: values.length % 2 ? values[middle] : (values[middle - 1]
+ values[middle]) / 2,
+ p95: values[Math.ceil(values.length * 0.95) - 1]
+ }
+ ];
+ })
+ );
+ return [cache, { count: group.length, ...metrics }];
+ })
+ );
+};
+
+const angularEntryScripts = (index: string): string[] => {
+ const scripts =
[...index.matchAll(/<script\b[^>]*\bsrc=["']([^"']+)["'][^>]*>/gi)].map(match
=> match[1]);
+ if (!scripts.length || !scripts.some(script =>
/^main[.-].*\.js$/.test(script))) {
+ throw new Error(
+ 'Build output must contain a hashed Angular main entry script; run the
production build (npm run build)'
+ );
+ }
+ for (const script of scripts) {
+ if (!/^[\w.-]+\.js$/.test(script)) {
+ throw new Error(`Unexpected Angular entry script: ${script}`);
+ }
+ }
+ return scripts;
+};
+
+export const validateServedIndex = (root: string, servedIndex: string): void
=> {
+ const expected = angularEntryScripts(readFileSync(resolve(root,
'dist/zeppelin/index.html'), 'utf8'));
+ const actual = angularEntryScripts(servedIndex);
+ if (JSON.stringify(actual) !== JSON.stringify(expected)) {
+ throw new Error(`Served Angular entry scripts do not match the local
build: ${JSON.stringify(actual)}`);
+ }
+};
+
+export const measureBundles = (root: string) => {
+ const angularRoot = resolve(root, 'dist/zeppelin');
+ const scripts = angularEntryScripts(readFileSync(resolve(angularRoot,
'index.html'), 'utf8'));
+ const measure = (path: string) => {
+ const bytes = readFileSync(path);
+ return {
+ path: normalizeBundlePath(relative(root, path)),
+ rawBytes: bytes.length,
+ gzipBytes: gzipSync(bytes).length,
+ sha256: createHash('sha256').update(bytes).digest('hex')
+ };
+ };
+ const angularEntryChunks = [...new Set(scripts)].map(script => {
+ return measure(resolve(angularRoot, script));
+ });
+ return { angularEntryChunks, reactRemoteEntry: measure(resolve(angularRoot,
'assets/react/remoteEntry.js')) };
+};
diff --git
a/zeppelin-web-angular/e2e/performance/notebook-route-baseline.spec.ts
b/zeppelin-web-angular/e2e/performance/notebook-route-baseline.spec.ts
new file mode 100644
index 0000000000..de07da0d10
--- /dev/null
+++ b/zeppelin-web-angular/e2e/performance/notebook-route-baseline.spec.ts
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+import { execFileSync } from 'node:child_process';
+import { createHash, randomUUID } from 'node:crypto';
+import { mkdirSync, writeFileSync } from 'node:fs';
+import { cpus, platform, release, totalmem } from 'node:os';
+import { resolve } from 'node:path';
+import { expect, test, BrowserContextOptions, Page } from '@playwright/test';
+import { NotebookPerformancePage } from '../models/notebook-performance-page';
+import { addPageAnnotationBeforeEach, PAGES, waitForZeppelinReady } from
'../utils';
+import {
+ fixturePath,
+ loadFixture,
+ measureBundles,
+ Sample,
+ summarize,
+ validateFixture,
+ validateServedIndex
+} from './notebook-baseline';
+
+const inheritedContextOptions = [
+ 'viewport',
+ 'userAgent',
+ 'deviceScaleFactor',
+ 'isMobile',
+ 'hasTouch',
+ 'locale',
+ 'timezoneId',
+ 'colorScheme',
+ 'permissions',
+ 'ignoreHTTPSErrors',
+ 'extraHTTPHeaders'
+] as const;
+
+// JUSTIFIED: The issue fixes this path outside tests/; the dedicated config
isolates
+// the benchmark from normal E2E runs and owns the deliberate cold/warm
sequence.
+test.describe('Notebook route performance contract', () => {
+ addPageAnnotationBeforeEach(PAGES.WORKSPACE.NOTEBOOK);
+
+ let importedNoteId: string | undefined;
+
+ test.afterEach(async ({ request }) => {
+ const noteId = importedNoteId;
+ importedNoteId = undefined;
+ if (!noteId) {
+ return;
+ }
+ try {
+ const deleted = await
request.delete(`/api/notebook/${encodeURIComponent(noteId)}`);
+ if (!deleted.ok()) {
+ console.warn(`Benchmark note ${noteId} was not deleted
(${deleted.status()}): ${await deleted.text()}`);
+ }
+ } catch (error) {
+ console.warn(`Benchmark note ${noteId} was not deleted: ${error}`);
+ }
+ });
+
+ test('records every cold and warm sample with readiness, FCP and build
metadata', async ({
+ browser,
+ request,
+ baseURL
+ }, testInfo) => {
+ const root = resolve(__dirname, '../..');
+ const { note, sha256 } = loadFixture(root);
+ const bundles = measureBundles(root);
+ const dryRun = process.env.PERF_NOTEBOOK_DRY_RUN === '1';
+ const runs = dryRun ? 1 : 10;
+ const runId = randomUUID();
+ const metadata = {
+ schemaVersion: 1,
+ runId,
+ generatedAt: new Date().toISOString(),
+ dryRun,
+ zeppelinCommit: execFileSync('git', ['rev-parse', 'HEAD'], { cwd: root,
encoding: 'utf8' }).trim(),
+ workingTreeDirty:
+ execFileSync('git', ['status', '--porcelain'], { cwd: root, encoding:
'utf8' }).trim().length > 0,
+ os: { platform: platform(), release: release() },
+ cpuModel: cpus()[0]?.model ?? 'unknown',
+ memoryBytes: totalmem(),
+ browserVersion: browser.version(),
+ nodeVersion: process.version,
+ buildCommand: 'npm run build',
+ fixture: { path: fixturePath, sha256 },
+ baseURL,
+ viewport: testInfo.project.use.viewport,
+ runsPerCache: runs,
+ warmPrimingNavigations: 1,
+ percentileMethod: 'nearest-rank',
+ bundles
+ };
+
+ await test.step('Given the built assets and the fixed imported note',
async () => {
+ const index = await request.get('/');
+ expect(index.ok()).toBe(true);
+ validateServedIndex(root, await index.text());
+ for (const bundle of [...bundles.angularEntryChunks,
bundles.reactRemoteEntry]) {
+ const response = await
request.get(`/${bundle.path.replace('dist/zeppelin/', '')}`);
+ expect(response.ok()).toBe(true);
+ expect(
+ createHash('sha256')
+ .update(await response.body())
+ .digest('hex')
+ ).toBe(bundle.sha256);
+ }
+ });
+
+ const imported = await request.post('/api/notebook/import', {
+ params: { notePath: `/__performance__/${runId}` },
+ data: note
+ });
+ expect(imported.ok(), `Notebook import failed (${imported.status()}):
${await imported.text()}`).toBe(true);
+ const noteId = (await imported.json()).body;
+ expect(typeof noteId).toBe('string');
+ expect(noteId.length).toBeGreaterThan(0);
+ importedNoteId = noteId;
+ const samples: Sample[] = [];
+ const { use } = testInfo.project;
+ const contextOptions: BrowserContextOptions = {
+ ...Object.fromEntries(inheritedContextOptions.map(key => [key,
use[key]])),
+ baseURL,
+ // browser.newContext resolves a relative storage state path against the
process cwd, not the config.
+ storageState: typeof use.storageState === 'string' ? resolve(root,
use.storageState) : use.storageState,
+ serviceWorkers: 'block'
+ };
+ const navigate = async (page: Page) => {
+ await page.goto('about:blank');
+ const navigation = await
page.goto(`/#/notebook/${encodeURIComponent(noteId)}`, { waitUntil: 'commit' });
+ const metrics = await new NotebookPerformancePage(page).measureReady();
+ if (!navigation) {
+ throw new Error('The benchmark requires a full document navigation
response');
+ }
+ validateServedIndex(root, await navigation.text());
+ await waitForZeppelinReady(page);
+ return metrics;
+ };
+ const persisted = await
request.get(`/api/notebook/${encodeURIComponent(noteId)}`);
+ expect(persisted.ok()).toBe(true);
+ validateFixture((await persisted.json()).body);
+
+ await test.step('When each cold navigation uses a new context with an
empty HTTP cache', async () => {
+ for (let run = 1; run <= runs; run++) {
+ const context = await browser.newContext(contextOptions);
+ try {
+ samples.push({ cache: 'cold', run, ...(await navigate(await
context.newPage())) });
+ } finally {
+ await context.close();
+ }
+ }
+ });
+
+ await test.step('When warm navigations reuse one context after one
unrecorded prime', async () => {
+ const context = await browser.newContext(contextOptions);
+ try {
+ const page = await context.newPage();
+ await navigate(page);
+ for (let run = 1; run <= runs; run++) {
+ samples.push({ cache: 'warm', run, ...(await navigate(page)) });
+ }
+ } finally {
+ await context.close();
+ }
+ });
+
+ await test.step('Then raw samples and median/p95 retain every
measurement', async () => {
+ expect(samples).toHaveLength(runs * 2);
+ const summary = summarize(samples, runs);
+ const output = resolve(root, 'e2e/performance/baselines');
+ mkdirSync(output, { recursive: true });
+ writeFileSync(resolve(output, `${runId}.raw.json`), `${JSON.stringify({
...metadata, samples }, null, 2)}\n`);
+ writeFileSync(resolve(output, `${runId}.summary.json`),
`${JSON.stringify({ ...metadata, summary }, null, 2)}\n`);
+ console.log(`Benchmark outputs:
e2e/performance/baselines/${runId}.{raw,summary}.json`);
+ });
+ });
+});
diff --git a/zeppelin-web-angular/package.json
b/zeppelin-web-angular/package.json
index 0b6cf15458..fe9a70398b 100644
--- a/zeppelin-web-angular/package.json
+++ b/zeppelin-web-angular/package.json
@@ -36,6 +36,7 @@
"check:core-contract-server": "node --test
e2e/core-contract/capture-server.test.mjs",
"e2e:core-contract": "playwright test --config
playwright.core-contract.config.js --project=chromium",
"e2e:core-contract:live": "cross-env ZEPPELIN_E2E_LIVE_CAPTURE=1
playwright test --config playwright.core-contract.config.js --project=chromium",
+ "perf:notebook-baseline": "playwright test --config
playwright.performance.config.js --project chromium",
"e2e:fast": "playwright test --project=chromium",
"e2e:classic": "playwright test --config playwright.classic.config.js",
"e2e:ui": "playwright test --ui",
diff --git a/zeppelin-web-angular/playwright.config.js
b/zeppelin-web-angular/playwright.config.js
index bc4a011261..e8ee9a11bb 100644
--- a/zeppelin-web-angular/playwright.config.js
+++ b/zeppelin-web-angular/playwright.config.js
@@ -19,8 +19,8 @@ process.env.PLAYWRIGHT_BASE_URL =
process.env.PLAYWRIGHT_BASE_URL || defaultBase
// https://playwright.dev/docs/test-configuration
module.exports = defineConfig({
...baseConfig,
- // Classic specs have their own config; Node fixture tests must stay outside
Playwright.
- testIgnore: [/tests\/classic\/.*\.spec\.ts/, /core-contract\/.*\.test\.mjs/],
+ // Classic, core-contract, and performance specs have their own runners.
+ testIgnore: [/tests\/classic\/.*\.spec\.ts/, /core-contract\/.*\.test\.mjs/,
/e2e\/performance\/.*\.spec\.ts$/],
// Live captures run only through playwright.core-contract.config.js.
grepInvert: /@live/,
reporter: [
diff --git a/zeppelin-web-angular/playwright.performance.config.js
b/zeppelin-web-angular/playwright.performance.config.js
new file mode 100644
index 0000000000..05996c61c9
--- /dev/null
+++ b/zeppelin-web-angular/playwright.performance.config.js
@@ -0,0 +1,46 @@
+/*
+ * 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 } = require('@playwright/test');
+const baseURL = process.env.PLAYWRIGHT_BASE_URL;
+if (!baseURL || process.env.PERF_NOTEBOOK_DISPOSABLE !== '1') {
+ throw new Error('Set PLAYWRIGHT_BASE_URL and PERF_NOTEBOOK_DISPOSABLE=1 for
an isolated local Zeppelin backend');
+}
+const target = new URL(baseURL);
+if (
+ !['localhost', '127.0.0.1', '[::1]'].includes(target.hostname) ||
+ target.protocol !== 'http:' ||
+ target.username ||
+ target.password ||
+ target.search ||
+ target.hash ||
+ // Root deployment only: the spec requests '/' and bundle paths relative to
the origin.
+ target.pathname !== '/'
+) {
+ throw new Error('The benchmark requires an explicit loopback HTTP origin
serving npm run build output');
+}
+const standard = require('./playwright.config');
+module.exports = defineConfig({
+ ...standard,
+ testMatch: /performance\/notebook-route-baseline\.spec\.ts/,
+ testIgnore: [],
+ globalSetup: undefined,
+ globalTeardown: undefined,
+ webServer: undefined,
+ fullyParallel: false,
+ workers: 1,
+ retries: 0,
+ timeout: 30 * 60 * 1000,
+ reporter: 'list',
+ use: { ...standard.use, trace: 'off', video: 'off', screenshot: 'off',
serviceWorkers: 'block' },
+ projects: standard.projects.filter(project => ['setup',
'chromium'].includes(project.name))
+});
diff --git a/zeppelin-web-angular/test/notebook-baseline.spec.ts
b/zeppelin-web-angular/test/notebook-baseline.spec.ts
new file mode 100644
index 0000000000..0172f60aea
--- /dev/null
+++ b/zeppelin-web-angular/test/notebook-baseline.spec.ts
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from
'node:fs';
+import { tmpdir } from 'node:os';
+import { dirname, resolve } from 'node:path';
+import { afterEach, describe, expect, it } from 'vitest';
+import {
+ fixturePath,
+ loadFixture,
+ measureBundles,
+ normalizeBundlePath,
+ Sample,
+ summarize,
+ validateFixture,
+ validateServedIndex
+} from '../e2e/performance/notebook-baseline';
+
+describe('Notebook benchmark contract', () => {
+ const temporaryRoots: string[] = [];
+ const tempRoot = () => {
+ const root = mkdtempSync(resolve(tmpdir(), 'zeppelin-perf-contract-'));
+ temporaryRoots.push(root);
+ return root;
+ };
+ afterEach(() => temporaryRoots.splice(0).forEach(root => rmSync(root, {
recursive: true, force: true })));
+
+ it('normalizes native Windows bundle paths for browser requests', () => {
+
expect(normalizeBundlePath('dist\\zeppelin\\assets\\react\\remoteEntry.js')).toBe(
+ 'dist/zeppelin/assets/react/remoteEntry.js'
+ );
+ });
+
+ it('accepts the versioned fixture and rejects changed bytes against its
committed hash', () => {
+ const { note } = loadFixture(process.cwd());
+ expect(note.paragraphs).toHaveLength(100);
+ expect(new Set(note.paragraphs.map((paragraph: { status: string }) =>
paragraph.status))).toEqual(
+ new Set(['READY'])
+ );
+ const root = tempRoot();
+ mkdirSync(dirname(resolve(root, fixturePath)), { recursive: true });
+ writeFileSync(resolve(root, fixturePath), `${readFileSync(fixturePath,
'utf8')}\n`);
+ expect(() => loadFixture(root)).toThrow('SHA-256 mismatch');
+ });
+
+ it.each(['missing', 'duplicate', 'result', 'expanded', 'running'])(
+ 'rejects the %s fixture contract mutation',
+ mutation => {
+ const { note } = loadFixture(process.cwd());
+ if (mutation === 'missing') note.paragraphs.pop();
+ if (mutation === 'duplicate') note.paragraphs[1].id =
note.paragraphs[0].id;
+ if (mutation === 'result') note.paragraphs[80].results.msg[0].type =
'TEXT';
+ if (mutation === 'expanded') note.paragraphs[90].config.editorHide =
false;
+ if (mutation === 'running') note.paragraphs[0].status = 'RUNNING';
+ expect(() => validateFixture(note)).toThrow('Benchmark fixture');
+ }
+ );
+
+ it('retains the outlier and computes median and nearest-rank p95 separately
by cache mode', () => {
+ const samples: Sample[] = (['cold', 'warm'] as const).flatMap(cache =>
+ Array.from({ length: 10 }, (_, index) => ({
+ cache,
+ run: index + 1,
+ notebookReadyMs: index === 9 ? 1000 : index + 1,
+ fcpMs: index + 1
+ }))
+ );
+ expect(summarize(samples, 10)).toEqual({
+ cold: { count: 10, notebookReadyMs: { median: 5.5, p95: 1000 }, fcpMs: {
median: 5.5, p95: 10 } },
+ warm: { count: 10, notebookReadyMs: { median: 5.5, p95: 1000 }, fcpMs: {
median: 5.5, p95: 10 } }
+ });
+ expect(samples).toHaveLength(20);
+ });
+
+ it('distinguishes nearest-rank p95 from the max and from interpolation at
n=20', () => {
+ const samples: Sample[] = (['cold', 'warm'] as const).flatMap(cache =>
+ Array.from({ length: 20 }, (_, index) => ({
+ cache,
+ run: index + 1,
+ notebookReadyMs: (index + 1) * 10,
+ fcpMs: index + 1
+ }))
+ );
+ expect(summarize(samples, 20).cold).toEqual({
+ count: 20,
+ notebookReadyMs: { median: 105, p95: 190 },
+ fcpMs: { median: 10.5, p95: 19 }
+ });
+ });
+
+ it('rejects a missing run or metric instead of publishing an incomplete
summary', () => {
+ const cold: Sample = { cache: 'cold', run: 1, notebookReadyMs: 10, fcpMs:
5 };
+ expect(() => summarize([cold], 1)).toThrow('warm samples');
+ expect(() => summarize([cold, { ...cold, cache: 'warm', fcpMs: NaN }],
1)).toThrow('Missing or invalid fcpMs');
+ expect(summarize([cold, { ...cold, cache: 'warm' }], 1).cold).toEqual({
+ count: 1,
+ notebookReadyMs: { median: 10, p95: 10 },
+ fcpMs: { median: 5, p95: 5 }
+ });
+ });
+
+ it('rejects an old served index even when both builds remain available,
while allowing server-injected markup', () => {
+ const root = tempRoot();
+ const dist = resolve(root, 'dist/zeppelin');
+ mkdirSync(dist, { recursive: true });
+ const current = '<script src="runtime.new.js"></script><script
src="main.new.js"></script>';
+ writeFileSync(resolve(dist, 'index.html'), current);
+ for (const name of ['runtime.new.js', 'main.new.js', 'runtime.old.js',
'main.old.js']) {
+ writeFileSync(resolve(dist, name), name);
+ }
+ expect(() => validateServedIndex(root, current.replace(/\.new\.js/g,
'.old.js'))).toThrow(
+ 'Served Angular entry scripts do not match the local build'
+ );
+ expect(() =>
+ validateServedIndex(root, `<base href="/"><script>window.injected =
true;</script>${current}`)
+ ).not.toThrow();
+ });
+
+ it('measures only Angular index entry scripts and the separate React entry,
and fails if the latter is missing', () => {
+ const root = tempRoot();
+ const dist = resolve(root, 'dist/zeppelin');
+ mkdirSync(resolve(dist, 'assets/react'), { recursive: true });
+ writeFileSync(
+ resolve(dist, 'index.html'),
+ '<script src="runtime.abc.js"></script><script src="main.abc.js"
type="module"></script>'
+ );
+ writeFileSync(resolve(dist, 'runtime.abc.js'), 'runtime');
+ writeFileSync(resolve(dist, 'main.abc.js'), 'application');
+ writeFileSync(resolve(dist, 'lazy.js'), 'unrelated lazy chunk');
+ writeFileSync(resolve(dist, 'assets/react/remoteEntry.js'), 'remote');
+ const result = measureBundles(root);
+ expect(result.angularEntryChunks.map(chunk => chunk.path)).toEqual([
+ 'dist/zeppelin/runtime.abc.js',
+ 'dist/zeppelin/main.abc.js'
+ ]);
+ expect(result.angularEntryChunks.map(chunk => chunk.rawBytes)).toEqual([7,
11]);
+ expect(result.reactRemoteEntry.rawBytes).toBe(6);
+ expect(result.reactRemoteEntry.gzipBytes).toBeGreaterThan(0);
+ rmSync(resolve(dist, 'assets/react/remoteEntry.js'));
+ expect(() => measureBundles(root)).toThrow();
+ });
+});