From bbd65cc23dcff968a6452af0543b766c5c66187d Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Thu, 16 Feb 2023 20:14:39 +0100 Subject: [PATCH] Fix `data-turbo-confirm` on `` without `data-turbo-method` --- src/core/confirmation.js | 5 +++++ src/core/drive/form_submission.js | 7 ++----- src/core/index.js | 2 ++ src/core/session.js | 11 ++++++++++- src/tests/functional/visit_tests.js | 25 +++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/core/confirmation.js diff --git a/src/core/confirmation.js b/src/core/confirmation.js new file mode 100644 index 000000000..d78cad82b --- /dev/null +++ b/src/core/confirmation.js @@ -0,0 +1,5 @@ +export class Confirmation { + static confirmMethod(message, _element, _submitter) { + return Promise.resolve(confirm(message)) + } +} diff --git a/src/core/drive/form_submission.js b/src/core/drive/form_submission.js index c31d8ce60..2bb39088f 100644 --- a/src/core/drive/form_submission.js +++ b/src/core/drive/form_submission.js @@ -2,6 +2,7 @@ import { FetchRequest, FetchMethod, fetchMethodFromString, fetchEnctypeFromStrin import { expandURL } from "../url" import { clearBusyState, dispatch, getAttribute, getMetaContent, hasAttribute, markAsBusy } from "../../util" import { StreamMessage } from "../streams/stream_message" +import { Confirmation } from "../confirmation" import { prefetchCache } from "./prefetch_cache" import { config } from "../config" @@ -23,10 +24,6 @@ export const FormEnctype = { export class FormSubmission { state = FormSubmissionState.initialized - static confirmMethod(message) { - return Promise.resolve(confirm(message)) - } - constructor(delegate, formElement, submitter, mustRedirect = false) { const method = getMethod(formElement, submitter) const action = getAction(getFormAction(formElement, submitter), method) @@ -81,7 +78,7 @@ export class FormSubmission { if (typeof confirmationMessage === "string") { const confirmMethod = typeof config.forms.confirm === "function" ? config.forms.confirm : - FormSubmission.confirmMethod + Confirmation.confirmMethod const answer = await confirmMethod(confirmationMessage, this.formElement, this.submitter) if (!answer) { diff --git a/src/core/index.js b/src/core/index.js index 17f804bcf..f4bcaa5b9 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -2,6 +2,7 @@ import { Session } from "./session" import { PageRenderer } from "./drive/page_renderer" import { PageSnapshot } from "./drive/page_snapshot" import { FrameRenderer } from "./frames/frame_renderer" +import { Confirmation } from "./confirmation" import { fetch, recentRequests } from "../http/fetch" import { config } from "./config" @@ -108,6 +109,7 @@ export function setConfirmMethod(confirmMethod) { "Please replace `Turbo.setConfirmMethod(confirmMethod)` with `Turbo.config.forms.confirm = confirmMethod`. The top-level function is deprecated and will be removed in a future version of Turbo.`" ) config.forms.confirm = confirmMethod + Confirmation.confirmMethod = confirmMethod } export function setFormMode(mode) { diff --git a/src/core/session.js b/src/core/session.js index 181b6b2a2..3c8161189 100644 --- a/src/core/session.js +++ b/src/core/session.js @@ -18,6 +18,7 @@ import { PageView } from "./drive/page_view" import { FrameElement } from "../elements/frame_element" import { Preloader } from "./drive/preloader" import { Cache } from "./cache" +import { Confirmation } from "./confirmation" import { config } from "./config" export class Session { @@ -229,9 +230,17 @@ export class Session { ) } - followedLinkToLocation(link, location) { + async followedLinkToLocation(link, location) { const action = this.getActionForLink(link) const acceptsStreamResponse = link.hasAttribute("data-turbo-stream") + const confirmationMessage = link.getAttribute("data-turbo-confirm") + + if (typeof confirmationMessage === "string") { + const answer = await Confirmation.confirmMethod(confirmationMessage, link, link) + if (!answer) { + return + } + } this.visit(location.href, { action, acceptsStreamResponse }) } diff --git a/src/tests/functional/visit_tests.js b/src/tests/functional/visit_tests.js index dd0b97968..a05d0df5d 100644 --- a/src/tests/functional/visit_tests.js +++ b/src/tests/functional/visit_tests.js @@ -267,6 +267,31 @@ test("Turbo history state after a reload", async ({ page }) => { ) }) +test("test data-turbo-confirm on anchor element without data-turbo-method", async ({ page }) => { + let confirmed = false + + page.on("dialog", (alert) => { + assert.equal(alert.message(), "Are you sure?") + alert.accept() + confirmed = true + }) + + await page.evaluate(() => { + const link = document.querySelector("#same-origin-link") + + if (link) link.dataset.turboConfirm = "Are you sure?" + }) + + assert.equal(await page.locator("#same-origin-link[data-turbo-confirm]:not([data-turbo-method])").count(), 1) + assert.equal(pathname(page.url()), "/src/tests/fixtures/visit.html") + + await page.click("#same-origin-link") + await nextEventNamed(page, "turbo:load") + + assert.isTrue(confirmed) + assert.equal(pathname(page.url()), "/src/tests/fixtures/one.html") +}) + async function visitLocation(page, location) { return page.evaluate((location) => window.Turbo.visit(location), location) }