Skip to content

[#75318] Upgrade Turbo to 8.0.23 with proper event types#21816

Merged
myabc merged 18 commits into
devfrom
dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23
May 27, 2026
Merged

[#75318] Upgrade Turbo to 8.0.23 with proper event types#21816
myabc merged 18 commits into
devfrom
dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23

Conversation

@dependabot
Copy link
Copy Markdown
Contributor

@dependabot dependabot Bot commented on behalf of github Jan 30, 2026

Ticket

https://community.openproject.org/wp/75318

What are you trying to accomplish?

Update Turbo packages and make the application/test suite compatible with the newer Turbo behavior. Introduce proper types for Turbo events throughout the frontend.

This PR includes:

  • Bumped @hotwired/turbo and @hotwired/turbo-rails from 8.0.20 to 8.0.23.
  • Bumped @types/hotwired__turbo from 8.0.5 to 8.0.10.
  • Removed obsolete custom Turbo typings from shims.d.ts.
  • Replaced generic CustomEvent handling with typed Turbo events, removing eslint-disable suppressions and ad-hoc interface definitions.
  • Fixed Turbo frame ViewChild typing (HTMLIFrameElementFrameElement).
  • Removed unnecessary casts in Turbo global listeners.
  • Used the ProgressBar API directly in helpers instead of faking FormSubmission arguments.
  • Added compile-time exhaustiveness guard for Turbo event names (utils.ts).
  • Fixed the work package query history regression where opening the filters pane could leave browser history in the wrong state.
  • Fixed canceled work package edit Back navigation: restored the canceled Back URL through Turbo's history wrapper without triggering stale snapshot restoration.
  • Reverted the parallel_tests / turbo_tests bump that broke CI seed/process logging.

What approach did you choose and why?

Kept the dependency update and compatibility fixes scoped to Turbo integration points instead of adding broad retries. The canceled edit Back fix restores Turbo/UI-Router history state without triggering a second browser navigation, avoiding stale split-view snapshot restoration while preserving Turbo's restoration index.

Verification performed:

  • TZ=UTC npm run test -- --browsers=chromium
  • npx tsc -p tsconfig.app.json --noEmit
  • npx eslint src/app/shared/components/fields/edit/edit-form/edit-form.component.spec.ts

Upstream Turbo changelog analysis (8.0.20 → 8.0.23)

Commits relevant to this PR's behavioral changes:

1. 600617c — Tidy history popstate handling

Removed shouldHandlePopState() / pageLoaded guard. In 8.0.20, popstate events were ignored until the page's load event fired (a Safari workaround from ~2016). In 8.0.23, ALL popstate events are processed immediately. This affects timing of restoration visits during Angular bootstrap.

2. 50ff9c7 — Handle same-page anchor clicks via popstate

Added historyPoppedWithEmptyState() — popstate events WITHOUT event.state.turbo now trigger #reconcileEmptyHistoryEntry which caches a snapshot. Previously these were ignored. OpenProject's UI-Router changes URL via pushState/replaceState without Turbo state, so Turbo now reconciles those as empty-state popstates.

3. e591ea9 — Cleanup after same-page anchor handling

Removed locationWithActionIsSamePage from allowsVisitingLocationWithAction. In 8.0.20, same-page visits bypassed turbo:before-visit. In 8.0.23, they don't — but same-page clicks are now handled outside the Visit flow entirely.

4. bfc700e — Navigator destructuring fix

Fixed window.navigator being clobbered by Turbo's internal Navigator instance when Rollup's output changed to ESM format.

5. 5eca98f — Prevent noscript style evaluation

Removes <noscript> elements during snapshot creation and page rendering. Changes snapshot content.

Key finding: restoration visit path

The restoration visit path (navigator.startVisit) does NOT fire turbo:before-visit — in either 8.0.20 or 8.0.23:

popstate → History.onPopState
  → session.historyPoppedToLocationWithRestorationIdentifierAndDirection
    → navigator.startVisit(location, ..., { action: "restore" })
      → new Visit(...).start()
        → adapter.visitStarted(visit) → visit.loadCachedSnapshot() → renderPageSnapshot()

Only the proposeVisit path (link clicks) fires turbo:before-visit via applicationAllowsVisitingLocation. Restoration visits bypass it entirely and render cached snapshots unconditionally.

Merge checklist

  • Added/updated tests
  • Tested major browsers (Chrome, Firefox, Edge, ...)

Note
Automatic rebases have been disabled on this pull request as it has been open for over 30 days.

@dependabot dependabot Bot added dependencies Pull requests that update a dependency file javascript Pull requests that update Javascript code labels Jan 30, 2026
@cbliard
Copy link
Copy Markdown
Member

cbliard commented Feb 3, 2026

This upgrade comes with regressions, as shown by the failing tests.

I've only looked at ./spec/features/work_packages/cancel_editing_spec.rb:138.

It opens a wp in split view and tries to edit a description field of a work package, then clicks back. A dialog appears with text "Are you sure you want to cancel editing the work package?".
Then the test clicks "Cancel" and the page is supposed to stay the same.
It fails because the page gets reloaded, even if "Cancel" is clicked.
This was not the case before upgrading.

I tried in a local env as well, and yes, even after clicking Cancel, the page is reloaded and the content is lost.

@myabc myabc force-pushed the dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23 branch from 76b09e4 to 4762388 Compare March 1, 2026 18:57
@myabc myabc requested a review from Copilot March 1, 2026 19:01
@myabc myabc removed the DO NOT MERGE label Mar 1, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the frontend Turbo (Hotwire) dependency set to the latest 8.0.23 patch release, aligning runtime and TypeScript typings, and adjusts a feature spec to accommodate resulting UI behavior changes.

Changes:

  • Bump @hotwired/turbo and @hotwired/turbo-rails from 8.0.20 to 8.0.23 (and @types/hotwired__turbo to 8.0.6).
  • Remove the custom declare module '@hotwired/turbo' shim from frontend typings.
  • Stabilize the query history feature spec by explicitly opening the filters panel before asserting filter details.

Reviewed changes

Copilot reviewed 2 out of 4 changed files in this pull request and generated no comments.

File Description
spec/features/work_packages/table/queries/query_history_spec.rb Opens filters before checking filter UI after browser history navigation.
frontend/src/typings/shims.d.ts Removes local Turbo module type shim (relying on upstream/package typings).
frontend/package.json Bumps Turbo and its related typings versions.
frontend/package-lock.json Updates lockfile to Turbo 8.0.23 / turbo-rails 8.0.23 and typings 8.0.6.
Files not reviewed (1)
  • frontend/package-lock.json: Language not supported

@myabc myabc requested review from HDinger and cbliard March 2, 2026 01:35
@myabc myabc force-pushed the dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23 branch from 6dc8caa to 0938624 Compare March 2, 2026 12:37
@myabc myabc force-pushed the dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23 branch from 0938624 to 9499b6f Compare March 3, 2026 12:54
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 9, 2026

Deploying openproject with PullPreview

Field Value
Latest commit 2935a93
Job deploy
Status ✅ Deploy successful
Preview URL https://pr-21816-turbo-8-0-23-ip-178-105-209-47.my.opf.run:443

View logs

Copy link
Copy Markdown
Member

@akabiru akabiru left a comment

Choose a reason for hiding this comment

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

Top work, Alex! 👏🏾 👏🏾 🤩

@akabiru
Copy link
Copy Markdown
Member

akabiru commented Mar 9, 2026

👷🏾 @myabc there's one failing unit test. https://github.com/opf/openproject/actions/runs/22623904699/job/65555464579

@myabc
Copy link
Copy Markdown
Contributor

myabc commented Mar 9, 2026

👷🏾 @myabc there's one failing unit test. https://github.com/opf/openproject/actions/runs/22623904699/job/65555464579

@akabiru that should now be fixed (see #21934).

@myabc myabc force-pushed the dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23 branch 2 times, most recently from b5ead8f to f560a3e Compare March 9, 2026 18:51
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 8, 2026

Dependency Review

The following issues were found:

  • ❌ 2 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 2 package(s) with unknown licenses.

View full job summary

@myabc myabc force-pushed the dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23 branch from 7a31aae to 8103174 Compare May 25, 2026 11:19
myabc added 10 commits May 26, 2026 17:18
Replaces loose `CustomEvent` parameter types with typed equivalents
from `@hotwired/turbo`. Removes `eslint-disable` suppressions and
ad-hoc interface definitions that were only needed due to the loose
typing.
`<turbo-frame>` elements are instances of Turbo's `FrameElement`,
not `HTMLIFrameElement`. Corrects `@ViewChild` type annotations in
`wp-relations`, `wp-reminder`, and `wp-share` modals.
Uses TS compile-time checks to ensure all events are logged.
Adds missing events:

  - turbo:before-morph-attribute
  - turbo:before-morph-element
  - turbo:frame-missing
  - turbo:morph-element
Replaces the `formSubmissionStarted`/`formSubmissionFinished` calls
that required faking a `FormSubmission` argument with direct
`ProgressBar` method calls. Uses `??=` with `window.setTimeout` to
defer `show()` by `Turbo.config.drive.progressBarDelay`, matching
the internal `BrowserAdapter` pattern. Adds Vitest spec covering
the delay, idempotent show, timeout cleanup on hide, and full
show/hide cycle.
Use Turbo's history wrapper to restore the canceled Back URL without
triggering a real forward navigation. This preserves Turbo's restoration
index while avoiding stale split-view snapshot restoration.
Let the global Turbo before-visit guard consult the Angular edit form
tracker instead of relying only on OpenProject.pageState. This keeps
split-create frame navigation unblocked while still warning for
top-level navigation when an edit form is active or dirty.
@myabc myabc force-pushed the dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23 branch from 030e3e6 to 1d8515d Compare May 26, 2026 15:18
New resources can need a leave warning even before their change set contains model changes. Keep suppressing prompts while a save is in flight, but let split work package creation trigger the native beforeunload guard.
@myabc myabc force-pushed the dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23 branch from 1d8515d to f61a534 Compare May 26, 2026 16:47
@myabc myabc requested a review from Copilot May 26, 2026 19:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 27 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • frontend/package-lock.json: Language not supported

Comment thread frontend/src/stimulus/controllers/beforeunload.controller.ts
Turbo can restore the query filter pane as either open or closed during
browser history traversal. Use an idempotent helper before asserting
restored filters so the spec checks the query state instead of depending
on the current pane visibility.
@myabc myabc force-pushed the dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23 branch from 9ccc1b5 to 635ea68 Compare May 26, 2026 21:18
@myabc myabc requested a review from Copilot May 26, 2026 21:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 27 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • frontend/package-lock.json: Language not supported

Comment thread frontend/src/stimulus/controllers/beforeunload.controller.ts
Turbo's restoration visit path (`navigator.startVisit`) bypasses
`turbo:before-visit`, so the Stimulus leave guard never fires for
Back/Forward navigation.  Cancels `turbo:before-render` when edit
forms have unsaved changes and the visit action is `restore`.
Derives the decision from `turbo:visit` (which only fires for
visits that actually started) rather than `turbo:before-visit`
(which fires before cancellation is known).  Uses AbortController
so event listeners are properly cleaned up between tests.
@myabc myabc force-pushed the dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23 branch from 635ea68 to 3866b33 Compare May 26, 2026 22:15
Wait for the Turbo visit to finish before the Selenium example resets.
@myabc myabc merged commit 4fdd0c6 into dev May 27, 2026
21 checks passed
@myabc myabc deleted the dependabot/npm_and_yarn/frontend/dev/hotwired/turbo-8.0.23 branch May 27, 2026 07:08
@github-actions github-actions Bot locked and limited conversation to collaborators May 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

dependencies Pull requests that update a dependency file javascript Pull requests that update Javascript code needs review

Development

Successfully merging this pull request may close these issues.

5 participants