Skip to content

Commit

Permalink
Merge pull request #1231 from seanpdoyle/link-with-frame-child
Browse files Browse the repository at this point in the history
Resolve Turbo Frame navigation bug
  • Loading branch information
brunoprietog authored Jun 21, 2024
2 parents 1a0aeb6 + 513a0e0 commit 9b604db
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
14 changes: 9 additions & 5 deletions src/core/frames/link_interceptor.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { findLinkFromClickTarget } from "../../util"

export class LinkInterceptor {
constructor(delegate, element) {
this.delegate = delegate
Expand All @@ -17,15 +19,15 @@ export class LinkInterceptor {
}

clickBubbled = (event) => {
if (this.respondsToEventTarget(event.target)) {
if (this.clickEventIsSignificant(event)) {
this.clickEvent = event
} else {
delete this.clickEvent
}
}

linkClicked = (event) => {
if (this.clickEvent && this.respondsToEventTarget(event.target) && event.target instanceof Element) {
if (this.clickEvent && this.clickEventIsSignificant(event)) {
if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url, event.detail.originalEvent)) {
this.clickEvent.preventDefault()
event.preventDefault()
Expand All @@ -39,8 +41,10 @@ export class LinkInterceptor {
delete this.clickEvent
}

respondsToEventTarget(target) {
const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null
return element && element.closest("turbo-frame, html") == this.element
clickEventIsSignificant(event) {
const target = event.composed ? event.target?.parentElement : event.target
const element = findLinkFromClickTarget(target) || target

return element instanceof Element && element.closest("turbo-frame, html") == this.element
}
}
3 changes: 3 additions & 0 deletions src/tests/fixtures/frames.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ <h2>Frames: #frame</h2>
</form>
</turbo-frame>
<a id="outside-frame-form" href="/src/tests/fixtures/frames/form.html" data-turbo-frame="frame">Navigate #frame to /frames/form.html</a>
<a id="outside-frame-link-with-frame-child" href="/src/tests/fixtures/frames/form.html" data-turbo-frame="frame">
<turbo-frame id="ignored-frame">Has a turbo-frame child</turbo-frame>
</a>

<a id="link-outside-frame-action-advance" href="/src/tests/fixtures/frames/frame.html" data-turbo-frame="frame" data-turbo-action="advance">Navigate #frame from outside with a[data-turbo-action="advance"]</a>
<form id="form-get-frame-action-advance" action="/__turbo/redirect" data-turbo-frame="frame" data-turbo-action="advance">
Expand Down
13 changes: 13 additions & 0 deletions src/tests/functional/frame_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,19 @@ test("'turbo:frame-render' is triggered after frame has finished rendering", asy
assert.include(fetchResponse.response.url, "/src/tests/fixtures/frames/part.html")
})

test("navigating a frame from an outer link with a turbo-frame child fires events", async ({ page }) => {
await page.click("#outside-frame-link-with-frame-child")

await nextEventOnTarget(page, "frame", "turbo:before-fetch-request")
await nextEventOnTarget(page, "frame", "turbo:before-fetch-response")
const { fetchResponse } = await nextEventOnTarget(page, "frame", "turbo:frame-render")
expect(fetchResponse.response.url).toContain("/src/tests/fixtures/frames/form.html")

await nextEventOnTarget(page, "frame", "turbo:frame-load")

expect(await readEventLogs(page), "no more events").toHaveLength(0)
})

test("navigating a frame from an outer form fires events", async ({ page }) => {
await page.click("#outside-frame-form")

Expand Down

0 comments on commit 9b604db

Please sign in to comment.