Skip to content

[DREAM-967] Pin the table paths DREAM-874 changed - #26512

Merged
myabc merged 12 commits into
release/18.0from
code-maintenance/dream-959-fast-table-cleanup-4
Nov 11, 2026
Merged

myabc merged 12 commits into
release/18.0from
code-maintenance/dream-959-fast-table-cleanup-4

Conversation

@myabc

@myabc myabc commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Ticket

https://community.openproject.org/wp/DREAM-967

What are you trying to accomplish?

tl;dr for humans: Adds unit specs that lock in how the work package table behaves on paths the DREAM-874 keyboard and accessibility work changed but no spec exercised, so regressions show up before DREAM-897 verification. Spec-only apart from deleting dead code and two redundant guards; no behaviour change.

First slice of DREAM-967. Uncovered code was attributed with git blame to the epic's tickets; this slice pins the reachable epic paths plus grouped row matching.

Metric (production wp-fast-table) Before After
Statements 95.9% 97.0%
Branches 88.9% 91.4%
Functions 97.2% 98.0%
Lines 96.4% 97.3%
Uncovered points in DREAM-874 code 136 94

What approach did you choose and why?

  • Delete WorkPackageTableEditingContext.stopEditing and TimelineRowBuilder.insert, which have no callers
  • Pin PageUp/PageDown by viewport rows, Enter on a group sums row, and focus that rests on the scroll container or an unlisted row
  • Pin Tab inside multi-control editors and overlay re-entry
  • Pin pure movement edges in focus-position.ts
  • Pin details-pane switching on row click (keeps the tab) and edit activation abandoned on teardown
  • Pin mutate after destroy, row positions with an unset groups state, and the grouped position check
  • Pin child-relation retry after a failed load, grouped highlighting, unchanged baseline cells and deferred hierarchy parents
  • Pin grouped row matching by href, multi-value length, % progress values and missing properties
  • Drop two guards their callers already rule out

Every new spec was checked by breaking the line it pins and watching it fail.

Behaviour notes for reviewers

These specs pin today's behaviour where it is an open question rather than a decision; the questions go to DREAM-967:

  • Hierarchy mode renders a leaf before its filtered-out parent when the leaf comes before its in-window grandparent (currently renders a deferred leaf before its filtered-out parent). This looks like a bug.
  • A cell position without a desired column lands in column 0, Tab from a non-walk control in a cell stays native, and an editor overlay without a usable control receives focus itself.

Not pinned: HierarchyTransformer's reset of collapsed classes uses [class^="__hierarchy-group-"], which never matches a table row, so it never runs. Fixing the selector would change behaviour, so it is left for DREAM-967.

Hints for dev review

Each commit is green on its own (typecheck plus the wp-fast-table specs). The full Chromium suite and the keyboard specs on Firefox pass.

AI involvement

Directed – I specified the requirements and AI implemented most of it; I validated via testing rather than a full line-by-line review.

Merge checklist

  • Added/updated tests
  • Added/updated documentation in Lookbook (patterns, previews, etc)
  • Tested major browsers (Chrome, Firefox, Edge, ...)

@myabc myabc added javascript Pull requests that update Javascript code ai: Directed 🪄 A human specified the requirements and AI implemented most of it; They validated via testing. labels Nov 1, 2026
@myabc myabc self-assigned this Nov 1, 2026
@myabc
myabc added this pull request to stack #26508 November 1, 2026 02:01
@myabc
myabc marked this pull request as ready for review November 1, 2026 02:02
Copilot AI balanced review requested due to automatic review settings November 1, 2026 02:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The console.warn spy is not restored, so it can hide warnings from subsequent tests in the file.

1 open issue
What changed in this PR

Adds regression coverage for work package table paths affected by DREAM-874, building on the DREAM-959 refactors before DREAM-897 verification. Existing behavior is preserved, including explicitly documented edge cases.

Changes:

  • Covers keyboard navigation, editor focus, teardown, and details-pane switching.
  • Adds rendering checks for grouping, hierarchy, relations, baseline cells, and row positions.
  • Removes unused methods, a redundant guard, and an unused constructor default.

All paths below are relative to frontend/src/app/features/work-packages/components/wp-fast-table/.

File Description
wp-table-editing.ts Removes unused stopEditing method.
wp-fast-table-lifecycle.spec.ts Tests mutation after destruction.
testing/​work-package-fixture.ts Supports unchanged baseline fixtures.
semantics/​table-row-positions.spec.ts Tests positions with unset groups state.
semantics/​body-row-positions.spec.ts Covers empty groups and missing headers.
row-mutations.ts Requires the render-pending callback explicitly.
handlers/​state/​keyboard/​keyboard-navigation-transformer.ts Removes redundant destruction guard.
handlers/​state/​keyboard/​keyboard-navigation-transformer.spec.ts Covers paging and focus-recovery edges.
handlers/​state/​keyboard/​focus-position.spec.ts Tests movement boundary cases.
handlers/​state/​keyboard/​cell-interaction.spec.ts Covers editor Tab behavior and overlay re-entry.
handlers/​row/​click-handler.spec.ts Tests details-pane switching and tab preservation.
handlers/​cell/​edit-cell-entry.spec.ts Tests activation cancellation during teardown.
builders/​timeline/​timeline-row-builder.ts Removes unused insert method.
builders/​rows/​single-row-builder.spec.ts Tests unchanged baseline presentation.
builders/​relations/​relations-render-pass.spec.ts Tests retry after child-loading failure.
builders/​modes/​hierarchy/​hierarchy-order.spec.ts Records current deferred-leaf ordering.
builders/​modes/​grouped/​grouped-render-pass.spec.ts Covers group matching and member highlighting.

Review effort: Balanced

@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch 2 times, most recently from a760c2e to 82cc331 Compare November 1, 2026 13:50
@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch 2 times, most recently from 0af0dc2 to 8c49d33 Compare November 1, 2026 14:19
@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch 3 times, most recently from 041292c to 5f7c9b3 Compare November 2, 2026 21:01
@myabc myabc mentioned this pull request Nov 3, 2026
2 of 3 tasks
@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch from 5f7c9b3 to bc4275b Compare November 3, 2026 17:05
@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch from bc4275b to 448a246 Compare November 3, 2026 22:34
@myabc
myabc requested a review from planktonic November 3, 2026 22:45
@myabc myabc removed their assignment Nov 3, 2026
@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch 2 times, most recently from 982b7fa to ab64c9c Compare November 4, 2026 21:57
@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch from a108add to f1f43ec Compare November 6, 2026 04:29
@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch from f1f43ec to 1747170 Compare November 6, 2026 23:29
@myabc myabc added this to the 18.0.x milestone Nov 7, 2026
@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch from 1747170 to f742be6 Compare November 7, 2026 22:39
@myabc myabc added the spec coverage Pull requests that primarily update specs – with few or no production changes label Nov 7, 2026
await harness.render();

const highlighted = (row:Element) => Array.from(row.classList).some((name) => name.startsWith('__hl_'));
expect(highlighted(harness.row('1'))).toBe(true);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is every row expected to be highlighted with this class individually? Perhaps it would make the test more robust to build a table with multiple rows, and check that they all have the highlight.

Nothing to do with these tests: if they’re all highlighted, what does the highlight mean? :D Does it have some semantic meaning that we could indicate using an (aria-)attribute, or is it purely aesthetic?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enabling highlighting does this btw (using status as an example):

Image

If this were phrasal content, then we would have <mark> in our toolbox. For rows, I'm really not sure how to handle. I'm also quite sure that colour highlighting flagrantly disregards WCAG colour contrast guidelines. / @bsatarnejad

aria-describedby referencing the column used for highlighting might be one option.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec now renders two rather than one row .. does that suffice?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(sorry, that was meant flippantly. I confess that I didn't put enough thought into how extensive the assertions should be with this particular case)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes two rows works 👍

For the highlighted rows, possible alternative aria attributes would be aria-selected (suitable for gridcell, option, row, and tab roles), or perhaps aria-current (“indicates that this element represents the current item within a container or set of related elements.”, from mdn). But does either of those fit the meaning of the highlight? It looks like this highlighting is indicating something else.

(And to be clear, that’s not a suggestion to do it here, just asking for possible future improvements)

Base automatically changed from code-maintenance/dream-959-fast-table-cleanup-3 to release/18.0 November 9, 2026 13:58
@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch from f742be6 to 484d275 Compare November 9, 2026 13:58
myabc added 12 commits November 10, 2026 22:08
Removes WorkPackageTableEditingContext.stopEditing and
TimelineRowBuilder.insert. Nothing calls either of them, specs
included; the other stopEditing calls in the app belong to the
resource editing service, and the timeline render pass only uses
build.

https://community.openproject.org/wp/DREAM-967
Pins keyboard paths that no unit or feature spec covered: PageUp and
PageDown move by the rows that fit the viewport, and by one row when
every group is collapsed; Enter on a group sums row is not consumed;
an overlay that already holds focus keeps the return path; focus on
an unlisted grid row counts as at rest, while focus on the scroll
container itself does not; repainting before any focus keeps the
first row as the Tab stop; and focusing an unrendered cell leaves
focus and scroll alone.

Each spec fails when the line it pins is broken.

https://community.openproject.org/wp/DREAM-967
Pins how Tab and re-entry behave around open editors: Tab between
controls inside a multi-control editor stays native and does not
park it, and re-engaging a parked editor restores its overlay root's
own tabindex.

Also pins two behaviours that are still open questions rather than
settled decisions: an overlay without a usable control receives
focus itself, and Tab from a control in a cell that is not a walk
target stays native and leaves the grid.

Each spec fails when the line it pins is broken.

https://community.openproject.org/wp/DREAM-967
Pins three edges of the pure movement model: ArrowRight on a row
without cells does nothing, a position on a row that is not rendered
moves nowhere, and a cell position without a desired column lands
in the first cell of the next row. The last one is an open question
rather than a decision: the current cell may be the better fallback.

Each spec fails when the line it pins is broken.

https://community.openproject.org/wp/DREAM-967
Pins that clicking another row while the details pane is open
switches the pane to that row and keeps its tab, and that clicking
the row already shown leaves it alone. Also pins that an edit
activation abandoned because the table was torn down mid-load marks
nothing read-only and opens no editor.

Each spec fails when the line it pins is broken.

https://community.openproject.org/wp/DREAM-967
Pins that a destroyed table runs no further mutation, and that row
positions are still painted when the groups state is unset, as it can
be when a response carries no groups. Also pins two behaviours of the
grouped position check that are still open questions: a zero-count
group is skipped, and member rows drawn without their group header
are rejected.

Each spec fails when the line it pins is broken.

https://community.openproject.org/wp/DREAM-967
Pins four render-pass paths: child relation targets are requested
again on the next redraw after a failed load, row highlighting skips
group headers, an unchanged work package leaves its baseline cell
empty, and a deferred filtered-out parent is taken from the cache
when it is not in the result window.

The hierarchy case pins the order DREAM-959 settled: the
filtered-out parent renders before its deferred leaf.

Each spec fails when the line it pins is broken.

https://community.openproject.org/wp/DREAM-967
Pins how rows find their group: a linked value matches by href, a
multi-value property with a different number of values matches no
group, a progress group shown with a percent sign matches the bare
number, and a work package without the property lands in the empty
group.

https://community.openproject.org/wp/DREAM-967
Removes the destroyed check in keyboard navigation's recover, whose
only caller rowsChanged already returns early on a destroyed table,
and makes RowMutations' renderPending callback required, since both
constructions pass it. No behaviour change.

https://community.openproject.org/wp/DREAM-967
Asserts the "All rows should have a group" warning the multi-value
mismatch spec expects instead of silencing it, passes group hrefs as a
plain array so the matching specs need no cast, types the
renderedUnder helper's boolean return, and highlights two member rows
so the spec covers every member rather than one.

https://community.openproject.org/wp/DREAM-967
Adds TableHarness#groupSums, which finds a group's sums row by its
group class the way groupHeader finds the header, and uses it in place
of the selector strings the keyboard navigation and roving tabindex
specs repeated.

https://community.openproject.org/wp/DREAM-967
Renames three keyboard specs so their titles state the expected
outcome: Tab before an editor's last control stays with the browser
and parks nothing, Enter on a group sums row is left to the browser,
and returnFocus takes focus back from a row the table did not render.

https://community.openproject.org/wp/DREAM-967
@myabc
myabc force-pushed the code-maintenance/dream-959-fast-table-cleanup-4 branch from 484d275 to c5d98a8 Compare November 10, 2026 23:08
@github-actions

Copy link
Copy Markdown

Caution

The provided work package version does not match the core version

Details:

Please make sure that:

  • The work package version OR your pull request target branch is correct

@github-actions

Copy link
Copy Markdown

Warning

Flaky specs

  • rspec ./modules/backlogs/spec/features/work_packages/batch_destination_menu_spec.rb[1:2:3]
  • rspec ./modules/backlogs/spec/features/work_packages/create_work_package_spec.rb[1:5:1]
🤖 Ask Copilot to investigate

Copy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer.

@copilot The following spec(s) are flaky in CI (first seen on PR #26512, linked for reference only):

- `rspec ./modules/backlogs/spec/features/work_packages/batch_destination_menu_spec.rb[1:2:3]`
- `rspec ./modules/backlogs/spec/features/work_packages/create_work_package_spec.rb[1:5:1]`

Treat this as a standalone task, unrelated to PR #26512. Create a new branch from origin/dev and open a new pull request targeting dev — do not stack it on PR #26512 or reuse that branch.

Follow the playbook in docs/development/testing/handling-flaky-tests/README.md to find the root cause and fix the underlying race — do not skip, delete, or weaken the spec to make it pass; disabling is a last resort per the playbook, and only with a bug ticket. Verify the fix by running the spec(s) repeatedly (e.g. `script/bulk_run_rspec --run-count 10`).

If you cannot reproduce the flake or are not confident in a fix after reasonable investigation, do not fabricate a change or skip the spec to force CI green. Instead, leave the pull request in draft and document what you tried, the suspected cause, and any leads in its description, then assign @myabc to take over.

Once the fix is verified, title the PR after the spec(s) it fixes, and use the PR description to explain the root cause, how the change resolves it, and the before/after results. Label the PR `flaky-spec`, assign @myabc, and request a review from @myabc.
On every commit, set @myabc as the sole co-author with a `Co-authored-by:` trailer (use their GitHub no-reply email so it links to their account), so it is traceable who dispatched the fix.

@myabc
myabc enabled stacked auto-merge November 11, 2026 14:05

@planktonic planktonic left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. My remaining unresolved thread is a question for me to understand the UI here better, it’s not something that’s related to/blocking this PR

@myabc
myabc merged commit 34c0864 into release/18.0 Nov 11, 2026
21 checks passed
@myabc
myabc deleted the code-maintenance/dream-959-fast-table-cleanup-4 branch November 11, 2026 14:18
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 11, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

ai: Directed 🪄 A human specified the requirements and AI implemented most of it; They validated via testing. feature javascript Pull requests that update Javascript code needs review spec coverage Pull requests that primarily update specs – with few or no production changes

Development

Successfully merging this pull request may close these issues.

3 participants