|
| 1 | +You are helping the developer edit a Mendix test project (.mpr file) to support a new or updated Playwright e2e test in the web-widgets monorepo. |
| 2 | + |
| 3 | +## Context |
| 4 | + |
| 5 | +- Test projects live at: `packages/pluggableWidgets/<widget>/tests/testProject/<Name>.mpr` |
| 6 | +- `mxcli` reads/writes `.mpr` files via MDL (Mendix Definition Language) |
| 7 | +- Binary: `automation/tools/mxcli` — gitignored, install with `bash automation/mxcli/setup.sh` |
| 8 | +- The `.mpr` **must be closed in Studio Pro** before mxcli can edit it |
| 9 | +- mxcli is **alpha software** — ensure `.mendix-cache/backup/AppBackup.mpr` exists before bulk edits |
| 10 | +- For Playwright rules that new pages must satisfy, see `mendix:e2e-spec` and `docs/requirements/e2e-test-guidelines.md` |
| 11 | + |
| 12 | +--- |
| 13 | + |
| 14 | +## Step 1 — Identify widget and goal |
| 15 | + |
| 16 | +Ask the user (or infer from context): which widget, and what scenario requires a test project change? |
| 17 | + |
| 18 | +## Step 2 — Check prerequisites |
| 19 | + |
| 20 | +```bash |
| 21 | +[[ -x automation/tools/mxcli ]] && echo "OK" || bash automation/mxcli/setup.sh |
| 22 | +ls packages/pluggableWidgets/<widget>/tests/testProject/*.mpr | grep -v backup |
| 23 | +``` |
| 24 | + |
| 25 | +Verify Studio Pro is **not** holding the project open before any mxcli writes: |
| 26 | + |
| 27 | +```bash |
| 28 | +ls packages/pluggableWidgets/<widget>/tests/testProject/.mendix-cache/lock 2>/dev/null \ |
| 29 | + && echo "⚠️ Studio Pro lock file present — close the project first" \ |
| 30 | + || echo "OK — no lock file" |
| 31 | +``` |
| 32 | + |
| 33 | +## Step 3 — Inspect current state |
| 34 | + |
| 35 | +```bash |
| 36 | +# Full overview: modules, pages, entities, navigation |
| 37 | +bash automation/mxcli/mx-testproject.sh inspect <widget> |
| 38 | + |
| 39 | +# Targeted queries: |
| 40 | +automation/tools/mxcli -p <MPR_PATH> -c "SHOW PAGES IN <Module>" |
| 41 | +automation/tools/mxcli -p <MPR_PATH> -c "SHOW ENTITIES IN <Module>" |
| 42 | +automation/tools/mxcli -p <MPR_PATH> -c "SHOW MICROFLOWS IN <Module>" |
| 43 | +automation/tools/mxcli -p <MPR_PATH> -c "DESCRIBE PAGE <Module>.<PageName>" |
| 44 | +bash automation/mxcli/mx-testproject.sh search <widget> 'keyword' |
| 45 | +``` |
| 46 | + |
| 47 | +> **`DESCRIBE PAGE` caveat**: pages containing only pluggable widgets (no built-in widgets like `DATAVIEW`, `LAYOUTGRID`, etc.) may render as an empty body even when widget content exists in the MPR. Use `automation/tools/mxcli bson dump -p <MPR> --type page --object <Module>.<Page>` and grep for widget names to verify content was written. |
| 48 | +
|
| 49 | +> **`SEARCH` quoting**: use single-quoted strings — `SEARCH 'keyword'`, not `SEARCH "keyword"`. Double quotes cause a parse error. |
| 50 | +
|
| 51 | +> **`SHOW ROLES IN <Module>`** — this MDL statement does not exist. Use `SHOW MODULES` output to see module source; roles are returned inline. To query roles programmatically use the catalog: `SELECT Name FROM CATALOG.USER_ROLES`. |
| 52 | +
|
| 53 | +Run a baseline lint before editing: |
| 54 | + |
| 55 | +```bash |
| 56 | +bash automation/mxcli/mx-testproject.sh lint <widget> |
| 57 | +``` |
| 58 | + |
| 59 | +## Step 4 — Plan and execute MDL changes |
| 60 | + |
| 61 | +#### ⚠️ `CREATE OR MODIFY PAGE ... {}` wipes page content |
| 62 | + |
| 63 | +Never use it on a page that already has widgets — the empty body replaces all content. Restore from `tests/testProject/.mendix-cache/backup/AppBackup.mpr` if this happens. |
| 64 | + |
| 65 | +#### Safety flow: validate → diff → apply |
| 66 | + |
| 67 | +```bash |
| 68 | +# 1. Validate MDL syntax and references: |
| 69 | +bash automation/mxcli/mx-testproject.sh check <widget> changes.mdl |
| 70 | + |
| 71 | +# 2. Preview as a diff (no writes): |
| 72 | +bash automation/mxcli/mx-testproject.sh diff <widget> changes.mdl |
| 73 | + |
| 74 | +# 3. Apply: |
| 75 | +bash automation/mxcli/mx-testproject.sh exec <widget> "$(cat changes.mdl)" |
| 76 | +``` |
| 77 | + |
| 78 | +#### Creating a new page |
| 79 | + |
| 80 | +``` |
| 81 | +CREATE PAGE Module.PageName ( |
| 82 | + Title: 'Page Title', |
| 83 | + Layout: Atlas_Core.Atlas_Default |
| 84 | +) |
| 85 | +``` |
| 86 | + |
| 87 | +Always include `Layout: Atlas_Core.Atlas_Default` — omitting it causes mxbuild to fail with exit code 3. |
| 88 | + |
| 89 | +After creating, grant page access or mxbuild fails: |
| 90 | + |
| 91 | +```bash |
| 92 | +automation/tools/mxcli -p <MPR_PATH> -c "GRANT VIEW ON PAGE <Module>.<PageName> TO <Module>.<RoleName>" |
| 93 | +``` |
| 94 | + |
| 95 | +#### Navigating to pages from Playwright |
| 96 | + |
| 97 | +For **existing pages** with widget content — use menu traversal (no mxcli changes needed). Get labels from `inspect` output: |
| 98 | + |
| 99 | +```js |
| 100 | +test.beforeEach(async ({ page }) => { |
| 101 | + await page.goto("/"); |
| 102 | + await page.getByRole("menuitem", { name: "Menu Label" }).click(); |
| 103 | + await page.getByRole("menuitem", { name: "Page Label" }).click(); |
| 104 | +}); |
| 105 | +``` |
| 106 | + |
| 107 | +For **brand-new empty pages** created by mxcli, the URL is auto-generated from the page name. Discover it with: |
| 108 | + |
| 109 | +```bash |
| 110 | +automation/tools/mxcli -p <MPR_PATH> -c "DESCRIBE PAGE <Module>.<PageName>" |
| 111 | +# Look for the `url:` field in the output, e.g. url: 'my-page-name' |
| 112 | +``` |
| 113 | + |
| 114 | +Then navigate directly in the spec: |
| 115 | + |
| 116 | +```js |
| 117 | +await page.goto("/p/my-page-name"); |
| 118 | +``` |
| 119 | + |
| 120 | +## Step 5 — Rebuild and validate |
| 121 | + |
| 122 | +Continue with `mendix:e2e-workflow` from Phase 4 (build → run → validate). |
| 123 | + |
| 124 | +--- |
| 125 | + |
| 126 | +## MDL Quick Reference |
| 127 | + |
| 128 | +| Goal | MDL / Command | |
| 129 | +| -------------------------- | ----------------------------------------------------------------------------- | |
| 130 | +| List modules | `SHOW MODULES` | |
| 131 | +| List pages | `SHOW PAGES IN Module` | |
| 132 | +| List entities | `SHOW ENTITIES IN Module` | |
| 133 | +| List microflows | `SHOW MICROFLOWS IN Module` | |
| 134 | +| List nanoflows | `SHOW NANOFLOWS IN Module` | |
| 135 | +| Describe page widgets | `DESCRIBE PAGE Module.PageName` | |
| 136 | +| Describe navigation menu | `DESCRIBE NAVIGATION Responsive` | |
| 137 | +| Search project strings | `SEARCH 'keyword'` | |
| 138 | +| Show callers of microflow | `SHOW CALLERS OF Module.MicroflowName` | |
| 139 | +| Show callers (transitive) | `SHOW CALLERS OF Module.MicroflowName TRANSITIVE` | |
| 140 | +| Show references to element | `SHOW REFERENCES TO Module.ElementName` | |
| 141 | +| Show impact of element | `SHOW IMPACT OF Module.ElementName` | |
| 142 | +| Show context for AI | `SHOW CONTEXT OF Module.ElementName DEPTH 3` | |
| 143 | +| Create page | `CREATE PAGE Module.Name (Title: 'Title', Layout: Atlas_Core.Atlas_Default)` | |
| 144 | +| Grant page access | `GRANT VIEW ON PAGE Module.Page TO Module.Role` | |
| 145 | +| Create entity | `CREATE ENTITY Module.Name (Attr: String(200))` | |
| 146 | +| Discover widgets by type | `SHOW WIDGETS WHERE widgettype LIKE '%combobox%'` | |
| 147 | +| Bulk-update widget props | `UPDATE WIDGETS SET 'showLabel' = false WHERE widgettype LIKE '%X%' DRY RUN` | |
| 148 | +| Populate catalog tables | `REFRESH CATALOG FULL` | |
| 149 | +| Catalog SQL query | `SELECT Name, ActivityCount FROM CATALOG.MICROFLOWS WHERE ActivityCount > 10` | |
| 150 | +| Validate MDL syntax + refs | `mxcli check changes.mdl -p app.mpr --references` | |
| 151 | +| Preview changes as diff | `mxcli diff -p app.mpr changes.mdl` | |
| 152 | + |
| 153 | +## Pluggable widget limitations |
| 154 | + |
| 155 | +mxcli can only create pluggable widget instances (`PLUGGABLEWIDGET '...' name (...)`) when the MPR **already contains an existing instance** of that widget type (Studio Pro registers the BSON template the first time the widget is imported). If no instance exists yet, mxcli fails with `template not found: <widgetname>`. |
| 156 | + |
| 157 | +**Workaround for a brand-new widget in a new test project:** |
| 158 | + |
| 159 | +1. Create the page with **named containers** and placeholder `DYNAMICTEXT` widgets (these are built-in and always work). |
| 160 | +2. Open the `.mpr` in Studio Pro — it will register the widget type from the `.mpk` in `tests/testProject/widgets/`. |
| 161 | +3. Inside each container, replace the placeholder with the actual pluggable widget instance. |
| 162 | +4. After Studio Pro saves, run `automation/tools/mxcli widget init -p <MPR>` to cache the widget definition. |
| 163 | +5. Future `PLUGGABLEWIDGET` statements for that widget will then work via mxcli. |
| 164 | + |
| 165 | +**Widget management commands:** |
| 166 | + |
| 167 | +```bash |
| 168 | +# Register widget definitions from all .mpk files in the project's widgets/ dir |
| 169 | +automation/tools/mxcli widget init -p <MPR_PATH> |
| 170 | + |
| 171 | +# Extract a .def.json skeleton from a specific .mpk (does not bootstrap the BSON template) |
| 172 | +automation/tools/mxcli widget extract --mpk <path>.mpk |
| 173 | + |
| 174 | +# List all registered widget definitions and their MDL keywords |
| 175 | +automation/tools/mxcli widget list -p <MPR_PATH> |
| 176 | + |
| 177 | +# Generate MDL syntax docs for a specific widget |
| 178 | +automation/tools/mxcli widget docs -p <MPR_PATH> <mdl-name> |
| 179 | +``` |
| 180 | + |
| 181 | +The `widget list` output shows the MDL keyword (e.g. `bubblechart`) needed in `PLUGGABLEWIDGET` blocks. The keyword lookup is case-insensitive but the widget ID string is exact. |
| 182 | + |
| 183 | +## Warnings |
| 184 | + |
| 185 | +- Do NOT run mxcli while Studio Pro has the project open — check for the lock file (Step 2) |
| 186 | +- New pages need `GRANT VIEW ON PAGE` — missing it causes mxbuild exit code 3 |
| 187 | +- `automation/tools/mxcli` is gitignored — run `bash automation/mxcli/setup.sh` on first checkout |
| 188 | +- `PLUGGABLEWIDGET` requires an existing instance in the MPR — use named containers as placeholders for brand-new widgets and configure them in Studio Pro first |
| 189 | +- Test project changes may require updating the `testProjects` repo branch for CI — flag this to the user |
0 commit comments