diff --git a/src/core/frames/frame_controller.ts b/src/core/frames/frame_controller.ts index 5a29907c3..0f49ef0f3 100644 --- a/src/core/frames/frame_controller.ts +++ b/src/core/frames/frame_controller.ts @@ -431,11 +431,11 @@ export class FrameController } } - if (!session.elementDriveEnabled(element)) { + if (!session.elementIsNavigatable(element)) { return false } - if (submitter && !session.elementDriveEnabled(submitter)) { + if (submitter && !session.elementIsNavigatable(submitter)) { return false } diff --git a/src/core/session.ts b/src/core/session.ts index a6d53540c..4e7baa081 100644 --- a/src/core/session.ts +++ b/src/core/session.ts @@ -175,7 +175,7 @@ export class Session willFollowLinkToLocation(link: Element, location: URL, event: MouseEvent) { return ( - this.elementDriveEnabled(link) && + this.elementIsNavigatable(link) && locationIsVisitable(location, this.snapshot.rootLocation) && this.applicationAllowsFollowingLinkToLocation(link, location, event) ) @@ -222,8 +222,8 @@ export class Session const action = getAction(form, submitter) return ( - this.elementDriveEnabled(form) && - (!submitter || this.formElementDriveEnabled(submitter)) && + this.elementIsNavigatable(form) && + (!submitter || this.formElementIsNavigatable(submitter)) && locationIsVisitable(expandURL(action), this.snapshot.rootLocation) ) } @@ -375,7 +375,7 @@ export class Session // Helpers - formElementDriveEnabled(element?: Element) { + formElementIsNavigatable(element?: Element) { if (this.formMode == "off") { return false } @@ -383,22 +383,23 @@ export class Session const form = element?.closest("form[data-turbo]") return form?.getAttribute("data-turbo") == "true" } - return this.elementDriveEnabled(element) + return this.elementIsNavigatable(element) } - elementDriveEnabled(element?: Element) { + elementIsNavigatable(element?: Element) { const container = element?.closest("[data-turbo]") + const withinFrame = element?.closest("turbo-frame") - // Check if Drive is enabled on the session. - if (this.drive) { - // Drive should be enabled by default, unless `data-turbo="false"`. + // Check if Drive is enabled on the session or we're within a Frame. + if (this.drive || withinFrame) { + // Element is navigatable by default, unless `data-turbo="false"`. if (container) { return container.getAttribute("data-turbo") != "false" } else { return true } } else { - // Drive should be disabled by default, unless `data-turbo="true"`. + // Element isn't navigatable by default, unless `data-turbo="true"`. if (container) { return container.getAttribute("data-turbo") == "true" } else { diff --git a/src/tests/fixtures/drive_disabled.html b/src/tests/fixtures/drive_disabled.html index 8be3904cf..99e85be61 100644 --- a/src/tests/fixtures/drive_disabled.html +++ b/src/tests/fixtures/drive_disabled.html @@ -34,5 +34,14 @@

Drive (Disabled by Default)

Drive enabled submit via JS + + +

Hello from a frame

+ + Navigate #frame +
+ +
+
diff --git a/src/tests/functional/drive_disabled_tests.ts b/src/tests/functional/drive_disabled_tests.ts index b8a422636..e27f6c300 100644 --- a/src/tests/functional/drive_disabled_tests.ts +++ b/src/tests/functional/drive_disabled_tests.ts @@ -3,6 +3,7 @@ import { assert } from "chai" import { getFromLocalStorage, nextBody, + nextEventOnTarget, pathname, searchParams, setLocalStorageFromEvent, @@ -42,3 +43,13 @@ test("test drive disabled by default; submit form inside data-turbo='true'", asy assert.equal(await visitAction(page), "advance") assert.equal(await searchParams(page.url()).get("greeting"), "Hello from a redirect") }) + +test("test drive disabled by default; links within navigate with Turbo", async ({ page }) => { + await page.click("#frame a") + await nextEventOnTarget(page, "frame", "turbo:frame-render") +}) + +test("test drive disabled by default; forms within navigate with Turbo", async ({ page }) => { + await page.click("#frame button") + await nextEventOnTarget(page, "frame", "turbo:frame-render") +})