Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
# node-runtime @abap2ui5/node-runtime + the ABAP apps, transpiled in the job
# (open-abap-core fetched with git, cached by its commit)
# cap2ui5 a CAP project + @cap2ui5/cds-plugin + the JS apps
# plus abaplint over the ABAP apps, and the frontend suite against the two
# in-process frontends: the agent client and the Adaptive Cards renderer
# (renderers/adaptive-cards/, with its golden cards). Each backend run takes
# seconds; the install dominates.
# plus abaplint over the ABAP apps, and the frontend suite against the three
# in-process frontends: the agent client, the Adaptive Cards renderer
# (renderers/adaptive-cards/, with its golden cards) and the terminal
# renderer (renderers/terminal/, golden screens, and end to end against the
# node-runtime host). Each backend run takes seconds; the install dominates.
# The frontend job runs the frontend suite against the UI5 SPA of abap2UI5
# (the commit the spec is derived from, app/webapp only) in Chromium - the
# test job skips that test, it has no browser and no checkout - and records
# the reports of the UI5 SPA, the agent client and the Adaptive Cards renderer.
# the reports of the UI5 SPA, the agent client and the Adaptive Cards and
# terminal renderers.
name: ci

on:
Expand Down Expand Up @@ -58,7 +60,7 @@ jobs:
run: npm ci --prefix conformance/hosts/cap2ui5 --no-audit --no-fund
- name: abaplint (ABAP conformance apps)
run: npm run lint:abap
- name: npm test (both backends, agent client, Adaptive Cards renderer)
- name: npm test (both backends, agent client, Adaptive Cards and terminal renderers)
run: npm test
- name: generated sections are up to date
run: npm run generate && git diff --exit-code
Expand Down Expand Up @@ -108,6 +110,9 @@ jobs:
- name: frontend suite report - Adaptive Cards renderer
if: ${{ !cancelled() }}
run: node conformance/backend/bin/abap2ui5-conformance.mjs frontend --adapter adaptive-cards --json > report-frontend-adaptive-cards.json || true
- name: frontend suite report - terminal renderer
if: ${{ !cancelled() }}
run: node conformance/backend/bin/abap2ui5-conformance.mjs frontend --adapter terminal --json > report-frontend-terminal.json || true
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: ${{ !cancelled() }}
with:
Expand Down
15 changes: 10 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ down, and the spec records what the implementations do.
- **Generated sections are generated.** `conformance/backend/README.md`
(check list), `profiles/portable.md` (between the `portable:*` markers,
from `profiles/portable-v1.json`), `renderers/adaptive-cards/README.md`
(the mapping table, from `mapping.mjs`) - run `npm run generate`.
and `renderers/terminal/README.md` (the mapping tables, from each
renderer's `mapping.mjs`) - run `npm run generate`.
- **Known failures of a reference are pinned, not hidden.** A backend check
the reference backends fail goes into `test/lib/expected.mjs` with the
place of its fix; the tests fail when it starts to pass (unpin it, record
Expand All @@ -72,8 +73,10 @@ down, and the spec records what the implementations do.
| `profiles/` | UI5, portable (v1 + `portable-v1.json` + coverage) and semantic profiles |
| `schema/` | JSON Schemas 2020-12 |
| `conformance/backend/` | the backend suite - the published package's entry (`index.mjs`, `bin/`) |
| `conformance/frontend/` | the frontend suite - `lib/` (scripted backend `mock.mjs`, runner, response builders, `checks/`), `adapters/` (`ui5` Playwright + the boot page, `agent` + the vendored mcp-server client, `webcomponent`, `adaptive-cards` (in process, the renderer below), `headless` stub) |
| `conformance/frontend/` | the frontend suite - `lib/` (scripted backend `mock.mjs`, runner, response builders, `checks/`), `adapters/` (`ui5` Playwright + the boot page, `agent` + the vendored mcp-server client, `webcomponent`, `adaptive-cards` and `terminal` (in process, the renderers below), `headless` stub) |
| `renderers/adaptive-cards/` | a prototype portable renderer: response -> Adaptive Card 1.5 and `Action.Submit` payload -> request (`render.mjs`, `mapping.mjs` - the control table the README's mapping section is generated from, `submit.mjs`, `host.mjs`, `demo.mjs`), golden cards in `golden/` (`UPDATE_GOLDEN=1 node --test test/adaptive-cards.test.mjs` rewrites them) |
| `renderers/terminal/` | a portable renderer for the terminal: keys in, a text screen out, the CLI `abap2ui5-tui` (`bin/`), `session.mjs` (the protocol over HTTP: transport rules, basic auth, cookies, follow-up actions, the hash history), `app.mjs` (the state machine: focus, edits, keys; `frame()`, `print()`), `render.mjs` + `mapping.mjs` (the control table the README's mapping section is generated from), `layout.mjs`, `text.mjs`, `tty.mjs`; golden screens in `golden/` (`UPDATE_GOLDEN=1 node --test test/terminal.test.mjs` rewrites them) |
| `renderers/common/` | what the renderers share: `view.mjs` (bindings, aggregations, list bindings, event wires over the vendored `viewxml`/`snapshot` modules) and `request.mjs` (an action payload -> the next request, the model delta) |
| `conformance/apps/` | the conformance apps (ABAP + cap2UI5) and their abaplint config |
| `conformance/hosts/` | `node-runtime` (build + serve) and `cap2ui5` (a CAP project) reference hosts |
| `traffic/` | recorded traffic per backend: `suite.json`, `ui5-frontend.json`, `agent-client.json` |
Expand All @@ -88,9 +91,11 @@ recorded traffic, cross-backend equality, docs links and anchors, the
portable profile, the conformance apps' abapGit format, the CLI, the
full backend suite against both reference backends (`PROTOCOL_SKIP_BACKENDS=1`
skips those; the cap2UI5 run skips itself when its host is not installed),
and the frontend suite against the agent client and the Adaptive Cards
renderer (always, golden cards included) and the UI5 SPA
(when an abap2UI5 checkout and a Chromium are there;
and the frontend suite against the agent client, the Adaptive Cards
renderer and the terminal renderer (always, golden cards and screens
included; the terminal also end to end against the node-runtime host,
inside the backend run) and the UI5 SPA (when an abap2UI5 checkout and a
Chromium are there;
`PROTOCOL_SKIP_BROWSER=1` skips it, `PROTOCOL_REQUIRE_BROWSER=1` fails
without them). CI runs the same on Node 22 and 24, and the UI5 SPA in a
job of its own with Chromium. Never `playwright install` in a sandbox that
Expand Down
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,39 @@

## Unreleased

- **Terminal renderer** (`renderers/terminal/`, export
`@abap2ui5/protocol/renderers/terminal`, CLI `abap2ui5-tui <url> [--app
<CLASS>] [--user u --password p | --cookie c] [--print] [--no-color]`):
an abap2UI5 app in a terminal. Its session speaks the protocol to any
backend - the node runtime, cap2UI5, an SAP system's ICF node (basic
auth, cookies, the CSRF token handshake, `sap-contextid`, the terminate
HEAD) - and keeps a hash history synchronised like the UI5 router, so
Back restores routes. All 65 portable controls as keyboard widgets
(fields edited in place, toggles, pick lists, buttons and links, tables
with row selection and row actions, banners, overlay frames for dialogs,
popovers and message boxes), unknown controls as visible placeholders;
edits travel as the UI5 frontend's delta, field events (`change`,
`select`, `submit`, ...) are raised. Respects the width (wrapping,
ellipsis, wide characters), colors only when wanted (`NO_COLOR`,
`--no-color`), `--print` renders once as plain text. Text from the
backend is sanitised of control characters. Pure Node, no dependencies.
The README's mapping table is generated from `mapping.mjs`
(`scripts/render-terminal.mjs`, part of `npm run generate`).
- **Frontend adapter `terminal`** (in process, driven with keys through the
renderer's state machine): 72 pass, 0 fail, 9 skip (a DOM, a programmatic
model edit; the UI5 and semantic profiles) - the router checks included.
Pinned in `test/frontend.test.mjs`; `test/terminal.test.mjs` holds golden
screens, the keys down to the request body, width, colors, sanitising
and the CLI; `test/backends.test.mjs` drives the renderer against the
node-runtime host after the backend suite.
- **`renderers/common/`**: the render-agnostic half of the Adaptive Cards
renderer (view helpers over the vendored `viewxml` / `snapshot` modules,
the payload -> request step) moved out for both renderers; the card
renderer re-exports it unchanged (its golden cards are byte-identical).
- **`portable.box-details` no longer asks for a DOM** - it reads only the
text on screen. The Adaptive Cards renderer now runs and passes it (66
pass, 15 skip).

- **Specification revision 0.3 - the maintainer's decisions** on the ten
open questions ([spec/open-questions.md](spec/open-questions.md), each now
"Decided (revision 0.3)" with its rationale):
Expand Down
38 changes: 31 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@ repository writes it down.
backend the backend suite - plays the frontend over HTTP (implemented)
frontend the frontend suite - plays the backend, adapters for (implemented)
the UI5 SPA (Playwright), the agent client, the
Web Components frontend, the Adaptive Cards renderer
Web Components frontend, the Adaptive Cards and the
terminal renderer
apps the conformance apps: ABAP classes + cap2UI5 twins
hosts the two reference backends, started with the apps deployed
renderers/
adaptive-cards a portable renderer without a browser: response -> Adaptive
Card 1.5, Action.Submit -> request (prototype)
terminal an abap2UI5 app in a terminal: keys in, text screen out,
the CLI abap2ui5-tui (node runtime, cap2UI5, SAP systems)
common what both renderers share: view helpers, payload -> request
traffic/ real traffic of both reference backends and three frontends
```

Expand All @@ -64,12 +68,20 @@ source file and method it was derived from ([spec/README.md](spec/README.md#sour
- **Frontend suite: 81 checks** (66 MUST, 15 SHOULD; 66 core, 8 portable,
4 UI5, 3 semantic), scripted from the recorded traffic. The official UI5
SPA passes every MUST but one - message box details stay empty on OpenUI5
>= 1.120 (fix under way); the agent client (mcp-server `a4d9f07`) and the
Adaptive Cards renderer pass every check that applies to them (61 and 65);
the Web Components frontend 68 of 68, with one intermittent failure ([conformance/RESULTS.md](conformance/RESULTS.md#frontend-suite)).
>= 1.120 (fix under way); the agent client (mcp-server `a4d9f07`), the
Adaptive Cards renderer and the terminal renderer pass every check that
applies to them (61, 66 and 72 - the terminal's include the router
checks); the Web Components frontend 68 of 68, with one intermittent
failure ([conformance/RESULTS.md](conformance/RESULTS.md#frontend-suite)).
- **Adaptive Cards renderer** (prototype, [renderers/adaptive-cards/](renderers/adaptive-cards/README.md)):
all 65 portable controls mapped onto Adaptive Cards 1.5, the way back from
an `Action.Submit` to the next request, golden cards of recorded traffic.
- **Terminal renderer** ([renderers/terminal/](renderers/terminal/README.md)):
an abap2UI5 app in a terminal - `npx abap2ui5-tui <url> --app <CLASS>`
against the node runtime, cap2UI5 or an SAP system (basic auth, cookies,
CSRF, `sap-contextid`), all 65 portable controls as keyboard-driven
widgets, a hash history so Back works, `--print` for logs, CI and screen
readers; pure Node, no dependencies.
- Not yet run against an ABAP system.

## Run the backend suite
Expand Down Expand Up @@ -97,22 +109,34 @@ Options, the library API and the check list:
npx abap2ui5-conformance frontend --adapter ui5 # the UI5 SPA (ABAP2UI5_HOME=<abap2UI5 checkout>) in Chromium
npx abap2ui5-conformance frontend --adapter agent # the agent client of abap2UI5/mcp-server
npx abap2ui5-conformance frontend --adapter adaptive-cards # the Adaptive Cards renderer of this package
npx abap2ui5-conformance frontend --adapter terminal # the terminal renderer of this package
```

## Run an app in the terminal

```bash
npm run serve:node-runtime & # the conformance apps on http://localhost:3000/
npx abap2ui5-tui http://localhost:3000/ --app Z2UI5_CL_CONF_BIND
npx abap2ui5-tui "https://host/sap/bc/z2ui5?sap-client=100" --app Z2UI5_CL_MY_APP --user ME --print
```

Keys, options and the control mapping: [renderers/terminal/README.md](renderers/terminal/README.md).

Adapters, options and the check list:
[conformance/frontend/README.md](conformance/frontend/README.md).

## Develop

```bash
npm test # schemas, traffic, docs, portable profile, CLI, both backends,
# the frontend suite (agent client, Adaptive Cards renderer;
# UI5 SPA with a checkout + Chromium), the golden cards
# the frontend suite (agent client, Adaptive Cards and terminal
# renderer; UI5 SPA with a checkout + Chromium), the golden
# cards and screens, the terminal against the node runtime
# (PROTOCOL_SKIP_BACKENDS=1 / PROTOCOL_SKIP_BROWSER=1 skip the slow parts)
npm run record # re-record traffic/ from both backends
npm run lint:abap # abaplint over the ABAP conformance apps
npm run generate # regenerate the check lists, the portable-profile sections and
# the Adaptive Cards mapping table
# the Adaptive Cards and terminal mapping tables
npm run demo:adaptive-cards -- slots.popup-destroy 0 1 # a recorded response as card JSON
```

Expand Down
Loading
Loading