Skip to content

Test Specification Editor

opencode CI edited this page Sep 15, 2026 · 5 revisions

Test Specification — Tree & Editor (editTc) — Modernized Screen

Path: ASIDE → Test Specification URL: gui/templates/testcases/testSpec.html?tproject_id=<id>[&tcase_id=<id>][&locale=<loc>] BFF API: api/testcases/index.php (action=tree, action=get; POST create, update, delete, create_version, suite_create, suite_update, suite_delete — session-based auth, JSON I/O) Rights: mgt_view_tc to browse; mgt_modify_tc for every write action; editing an executed version additionally requires testproject_edit_executed_testcases (or canEditExecuted config), same as legacy tcEdit.php. Replaces: legacy workarea launcher lib/general/frmWorkArea.php?feature=editTc → tree frame + lib/testcases/tcEdit.php editor forms.

Test Specification screen


What it does

Single-page replacement of the 1.9.20 Test Specification two-frame layout:

  • Left pane — test case tree: full project subtree (suites at any depth + test cases) rendered from one BFF call; suite count pills; expand/collapse toggles; live name filter box; inactive test cases dimmed.
  • Right pane — context panel, three states:
    • Suite selected: path, sub-suite / test-case counters, "New Test Case Here", "New Sub-Suite", "Rename Suite", "Delete Suite".
    • Test case selected: identity header (name, version badge, external id badge, executed/inactive badges), meta grid (status, importance, execution type, internal id), summary and preconditions blocks, numbered steps table, assigned keywords chips and the action bar.
    • Editor form (create or edit): name, status (workflow domain draft..final), importance, execution type, summary, preconditions, steps editor (add/remove rows, auto renumbering), project keywords checkboxes.

Actions

Button Behavior
New Test Case opens create form targeted at the selected suite
New Test Suite modal → POST suite_create under selection (or project root)
Rename Suite modal prefilled → POST suite_update
Delete Suite confirm modal (warns when non-empty) → POST suite_delete
Edit Test Case pre-filled form → POST update (latest version, legacy doUpdate semantics)
Create New Version confirm modal → POST create_version, view reloads on VER n+1
Full Viewer opens the modernized read-only tcView.html?tcase_id=… in a new tab
Delete Test Case confirm modal → POST delete (removes ALL versions)

Editor form

New suite modal

Errors & warnings

Situation Message
Not authenticated BFF returns HTTP 401 JSON error
Missing right on write action HTTP 403 "Requires permission: modify test cases"
Executed latest version without special right HTTP 403, save blocked (legacy parity)
Empty name on save/create/rename toast "Name is required"
Unknown node id (deep link) panel shows the BFF error text

i18n

All labels/toasts/placeholders come from the tspec.* block — 62 keys added to all 10 locale bundles (en, de, es, fr, it, ja, pt, ro, ru, zh), verified valid JSON. Runtime switch via ?locale= verified (e.g. RO).

Bugs found & fixed while testing

  1. Wrong column name tcexternalid (real schema: tc_external_id) broke the tree aggregates and get action — SQL error was captured by the Event Viewer.
  2. Create form crashed on Object.keys(undefined) when no keywords were assigned yet (guard added).
  3. TC name/suite parent were read from tcversions which has no name column — get action now joins nodes_hierarchy twice.
  4. PHP 8 warning "Undefined property: stdClass::$canEditExecuted" logged in the Event Viewer on every context/update call — now null-safe.

All four fixed and re-verified; Event Viewer clean afterwards.

Test case STATUS field (workflow domain) — Refs #908

Gap: the 1.9.20 design-time editor rendered a Status select (attributesLinear.inc.tpl, <select name="tc_status"> bound to $gui->domainTCStatus) and persisted it via setStatus; the modernized screen had dropped the field entirely (create/update never wrote status, detail view hid it).

Implemented (already modernized minus this gap):

  • Editor form (create + edit) shows a Status select with the full workflow domain: Draft (default), Ready for review, Review in progress, Rework, Obsolete, Future, Final. Domain + order come from the BFF (statusDomain, derived from $tlCfg->testCaseStatus); labels are the existing tcview.status1..7 i18n keys (all locales).
  • Persistence: BFF create/update read status from the POST body, validate it against the domain and persist it through the existing testcase::create(options['status']) / testcase::update($attrib['status']) path (same tcversions.status column the legacy setStatus() wrote; modification_ts/updater_id are updated by update() as usual). Absent / invalid value on create falls back to Draft (1); on update the current value is kept.
  • Detail view adds a Status meta-item with the current workflow label.

Editor Status select

Detail view Status badge

Editor Status select — ro locale

Verified live (project "Demo Project", TC "Login with valid credentials"): create with "Ready for review" → tcversions.status=2; edit to "Final" → tcversions.status=7 with refreshed modification_ts; detail view badge tracks the value; RO locale renders all 7 workflow labels (Ciornă … Final). Event Viewer: no new ERROR/WARNING rows. Test suite: Task — Issue #908 in tmp/TLU_Test_Cases.md (PASS).

Estimated Execution Duration field — Refs #911

Gap: the 1.9.20 design-time editor rendered an Estimated Execution Duration (min) input (attributesLinear.inc.tpl, gated as mandatory by $tlCfg->testcase_cfg->estimated_execution_duration->required, persisted via setEstimatedExecDuration → tcversions.estimated_exec_duration); the modernized screen had no field and the BFF silently dropped the value on create/update.

Implemented:

  • BFF (api/testcases/index.php): new isDurationRequired() helper reads the config flag; context/get/keywords responses expose estimateDurationRequired; create/update accept estimated_execution_duration, validate it (is_numeric; 400 Invalid estimated duration), enforce it when configured as required (400 Estimated execution duration is required), and persist it through testcase::create/update options (estimatedExecDuration). Empty string on update writes NULL — the legacy always-write semantics.
  • Editor (testSpec.html): create + edit form gain the decimal input #tcDurationInput (red * + required attribute only when the config flag is set); saveForm() blocks non-numeric values (toast) and empty-when-required (toast); the detail view meta-grid shows the value ("… min") when set.
  • i18n: tspec.estimatedDuration, tspec.estimatedDurationHint, tspec.errDurationInvalid, tspec.errDurationRequired in all 10 bundles.

Detail view duration meta-item

Editor — estimated execution duration input

Verified live (project "TestSpec Fixture", suite "Suite Alpha"): create with 7.5 → 7.50; edit 42.75 → 55 → view + DB updated; abc blocked client-side and 400 server-side; with required='required' (temp config) empty save blocked both client + server; clearing → NULL; tcView.html shows the value. Event Viewer: no new ERROR/WARNING rows. Test suite: Task — Issue #911 in tmp/TLU_Test_Cases.md (12/12 PASS).

Version selector + version lifecycle actions — Refs #914

The legacy per-version controls (freeze/unfreeze, activate/deactivate, delete-this-version) and the version dropdown are ported to the modern screen.

BFF (api/testcases/index.php):

  • get accepts optional tcversion_id (edit/view a SPECIFIC version; default latest). A requested version that does not exist returns 404 "Test case version not found" instead of the old silent fallback + E_WARNING ("Trying to access array offset on false" — root cause: fetchFirstRow() returns boolean false when no rows, is_null() never fired; all BFF row checks now use empty()).
  • GET version_list → versions[] (tcversion_id, version, active, is_open, has_been_executed, is_latest) + grants (mgt_modify_tc, testcase_freeze, delete_frozen_tcversion, testproject_delete_executed_testcases).
  • POST delete_version → legacy gates (frozen ⇒ needs delete_frozen_tcversion; executed ⇒ testproject_delete_executed_testcases/canDeleteExecuted); when the last version is removed the now-empty test-case nodes_hierarchy row is deleted too (no ghost nodes in the tree).
  • POST freeze / unfreeze (needs testcase_freeze) → tcversions.is_open.
  • POST activate / deactivate → tcversions.active (legacy setActiveAttr semantics: toggles the viewed tcversion, mirrored by testcase.class.php).

UI (gui/templates/testcases/testSpec.html): version selector in the viewer + editor (Ver. N (current|latest), ❄ frozen marker, "(inactive)"), per-version Freeze/Unfreeze, Activate/Deactivate (hint "latest only" on old versions of a multi-version TC), Delete-this-version, askConfirm OK-button label now dynamic. Editor save sends tcversion_id so updates hit exactly the edited version.

i18n: 20 new tspec.* keys across all 9 locale bundles.

Issue 914 — version selector + lifecycle buttons

Verified live (project "Version Lifecycle Test", MultiVer Demo v1=21/v2=23): get-by-version, 404-on-missing-version, freeze→403-delete-frozen, unfreeze, deactivate/activate with correct "latest only" hint, per-version edit precision, delete v1→1 left, delete last→ghost node removed. Event Viewer: no new ERROR/WARNING rows after the fix. Test suite: Task — Issue #914 in tmp/TLU_Test_Cases.md (15/15 PASS).

Clone this wiki locally