diff --git a/src/core/frames/link_interceptor.js b/src/core/frames/link_interceptor.js index 9b9249544..56ec4e8cd 100644 --- a/src/core/frames/link_interceptor.js +++ b/src/core/frames/link_interceptor.js @@ -1,3 +1,5 @@ +import { findLinkFromClickTarget } from "../../util" + export class LinkInterceptor { constructor(delegate, element) { this.delegate = delegate @@ -17,7 +19,7 @@ export class LinkInterceptor { } clickBubbled = (event) => { - if (this.respondsToEventTarget(event.target)) { + if (this.clickEventIsSignificant(event)) { this.clickEvent = event } else { delete this.clickEvent @@ -25,7 +27,7 @@ export class LinkInterceptor { } 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() @@ -39,8 +41,10 @@ export class LinkInterceptor { delete this.clickEvent } - respondsToEventTarget(target) { - const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null + clickEventIsSignificant(event) { + const target = event.composed ? event.target?.parentElement : event.target + const element = findLinkFromClickTarget(target) || target + return element && element.closest("turbo-frame, html") == this.element } } diff --git a/src/tests/fixtures/frames.html b/src/tests/fixtures/frames.html index 24c3272b9..0513e911a 100644 --- a/src/tests/fixtures/frames.html +++ b/src/tests/fixtures/frames.html @@ -37,6 +37,9 @@

Frames: #frame

Navigate #frame to /frames/form.html + + Has a turbo-frame child + Navigate #frame from outside with a[data-turbo-action="advance"]
diff --git a/src/tests/functional/frame_tests.js b/src/tests/functional/frame_tests.js index f1925908b..3b0770c39 100644 --- a/src/tests/functional/frame_tests.js +++ b/src/tests/functional/frame_tests.js @@ -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")