Skip to content

Conversation

@jeremy
Copy link
Member

@jeremy jeremy commented May 25, 2025

Clicking a data-turbo-method link submits an ephemeral form. The form is removed synchronously in a turbo:submit-end handler, blocking propagation to parent elements.

This causes issues for ancestors that act on turbo:submit-end, like closing a dialog on redirect responses.

To fix, defer form removal to allow the event to fully propagate.

Clicking a `data-turbo-method` link submits an ephemeral form.
The form is removed synchronously in a `turbo:submit-end` handler,
blocking propagation to parent elements.

This causes issues for ancestors that act on turbo:submit-end,
like closing a dialog on redirect responses.

To fix, defer form removal to allow the event to fully propagate.
Comment on lines +1260 to +1276
await page.evaluate(() => {
let eventPropagatedPastForm = false

// Listen on document to verify event propagates beyond the form element
document.addEventListener("turbo:submit-end", (event) => {
if (event.target.tagName === "FORM") {
eventPropagatedPastForm = true
}
})

window.eventPropagatedPastForm = () => eventPropagatedPastForm
})

await page.click("#turbo-method-post-to-targeted-frame")
await nextEventNamed(page, "turbo:submit-end")

assert.ok(await page.evaluate(() => window.eventPropagatedPastForm()), "turbo:submit-end propagated past the form element")
Copy link
Contributor

Choose a reason for hiding this comment

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

Could this test be re-written to utilize Playwright's retrying assertions?:

Suggested change
await page.evaluate(() => {
let eventPropagatedPastForm = false
// Listen on document to verify event propagates beyond the form element
document.addEventListener("turbo:submit-end", (event) => {
if (event.target.tagName === "FORM") {
eventPropagatedPastForm = true
}
})
window.eventPropagatedPastForm = () => eventPropagatedPastForm
})
await page.click("#turbo-method-post-to-targeted-frame")
await nextEventNamed(page, "turbo:submit-end")
assert.ok(await page.evaluate(() => window.eventPropagatedPastForm()), "turbo:submit-end propagated past the form element")
const html = page.locator("html")
await html.evaluate((documentElement) => {
documentElement.addEventListener("turbo:submit-end", ({ target }) => {
if (target instanceof HTMLFormElement) {
documentElement.toggleAttribute("data-turbo-submit-end", true)
}
})
})
await page.click("#turbo-method-post-to-targeted-frame")
await nextEventNamed(page, "turbo:submit-end")
await expect(html, "turbo:submit-end propagated past the form element").toHaveAttribute("data-turbo-submit-end")

@brunoprietog
Copy link
Collaborator

This came up while debugging an error that was actually associated with another cause, and ultimately we agreed at that point to Stop fixing bugs around data-turbo-method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants