diff --git a/src/tests/fixtures/frame_navigation.html b/src/tests/fixtures/frame_navigation.html
index 50020cb79..83be7e993 100644
--- a/src/tests/fixtures/frame_navigation.html
+++ b/src/tests/fixtures/frame_navigation.html
@@ -10,6 +10,10 @@
Outside Frame
+
+ Outside Frame in Shadow DOM
+
+
Frame Navigation
diff --git a/src/tests/fixtures/navigation.html b/src/tests/fixtures/navigation.html
index 0f63df4de..4dbd8c4af 100644
--- a/src/tests/fixtures/navigation.html
+++ b/src/tests/fixtures/navigation.html
@@ -6,22 +6,6 @@
Turbo
-
diff --git a/src/tests/fixtures/test.js b/src/tests/fixtures/test.js
index 80a2557a3..1820466cc 100644
--- a/src/tests/fixtures/test.js
+++ b/src/tests/fixtures/test.js
@@ -66,3 +66,17 @@
"turbo:frame-missing",
"turbo:reload"
])
+
+window.customElements.define('custom-link-element', class extends HTMLElement {
+ constructor() {
+ super()
+ this.attachShadow({ mode: 'open' })
+ }
+ connectedCallback() {
+ this.shadowRoot.innerHTML = `
+
+ ${this.getAttribute('text')}
+
+ `
+ }
+})
diff --git a/src/tests/functional/frame_navigation_tests.ts b/src/tests/functional/frame_navigation_tests.ts
index 3a2fadde1..99fe6c388 100644
--- a/src/tests/functional/frame_navigation_tests.ts
+++ b/src/tests/functional/frame_navigation_tests.ts
@@ -23,6 +23,13 @@ test("test frame navigation with exterior link", async ({ page }) => {
await nextEventOnTarget(page, "frame", "turbo:frame-load")
})
+test("test frame navigation with exterior link in Shadow DOM", async ({ page }) => {
+ await page.goto("/src/tests/fixtures/frame_navigation.html")
+ await page.click("#outside-in-shadow-dom")
+
+ await nextEventOnTarget(page, "frame", "turbo:frame-load")
+})
+
test("test frame navigation emits fetch-request-error event when offline", async ({ page }) => {
await page.goto("/src/tests/fixtures/tabs.html")
await page.context().setOffline(true)
diff --git a/src/util.ts b/src/util.ts
index 9d15aa505..4e83d264f 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -41,6 +41,7 @@ export function dispatch(
const event = new CustomEvent(eventName, {
cancelable,
bubbles: true,
+ composed: true,
detail,
})