-
diff --git a/src/tests/functional/autofocus_tests.js b/src/tests/functional/autofocus_tests.js
index 9cc49afe3..726ef8307 100644
--- a/src/tests/functional/autofocus_tests.js
+++ b/src/tests/functional/autofocus_tests.js
@@ -59,7 +59,9 @@ test("autofocus from a Turbo Stream message does not leak a placeholder [id]", a
`)
})
+
await expect(page.locator("#container-from-stream input")).toBeFocused()
+
})
test("receiving a Turbo Stream message with an [autofocus] element when an element within the document has focus", async ({ page }) => {
diff --git a/src/tests/server.mjs b/src/tests/server.mjs
index 10eab3abb..76cdaf464 100644
--- a/src/tests/server.mjs
+++ b/src/tests/server.mjs
@@ -61,6 +61,13 @@ router.post("/reject/tall", (request, response) => {
response.status(parseInt(status || "422", 10)).sendFile(fixture)
})
+router.post("/reject/morph", (request, response) => {
+ const { status } = request.body
+ const fixture = path.join(__dirname, `../../src/tests/fixtures/422_morph.html`)
+
+ response.status(parseInt(status || "422", 10)).sendFile(fixture)
+})
+
router.post("/reject", (request, response) => {
const { status } = request.body
const fixture = path.join(__dirname, `../../src/tests/fixtures/${status}.html`)
From 8c706bb894e05ea14448f0098aa32a7446836332 Mon Sep 17 00:00:00 2001
From: David Alejandro
<15317732+davidalejandroaguilar@users.noreply.github.com>
Date: Mon, 20 May 2024 11:11:02 +0200
Subject: [PATCH 11/20] Fix test to verify no network request on prefetched
link click (#1257)
* Fix test not making a network request after prefetch click
The test was supposed to assert that a network
request was not made when clicking on a link that
had been prefetched by hovering over it. However,
the test was not actually making the click, just
trying to hover over an already hovered link, so
this wasn't really testing what it was supposed to.
* assertRequestMade and assertRequestNotMade take functions as arguments
These functions are called to perform the action that should trigger the
network request. This allows us to test different scenarios without
repeating the same code.
It also allows us to pass a callback that will be called with the request
object when the request is made. This is useful for testing the request
object itself.
---
.../link_prefetch_observer_tests.js | 99 +++++++++----------
1 file changed, 48 insertions(+), 51 deletions(-)
diff --git a/src/tests/functional/link_prefetch_observer_tests.js b/src/tests/functional/link_prefetch_observer_tests.js
index 735efb7fb..361c8b020 100644
--- a/src/tests/functional/link_prefetch_observer_tests.js
+++ b/src/tests/functional/link_prefetch_observer_tests.js
@@ -195,35 +195,28 @@ test("doesn't include a turbo-frame header when the link is inside a turbo frame
test("it prefetches links with a delay", async ({ page }) => {
await goTo({ page, path: "/hover_to_prefetch.html" })
- let requestMade = false
- page.on("request", async (request) => (requestMade = true))
-
- await page.hover("#anchor_for_prefetch")
- await sleep(75)
-
- assertRequestNotMade(requestMade)
-
- await sleep(100)
+ await assertRequestNotMade(page, async () => {
+ await page.hover("#anchor_for_prefetch")
+ await sleep(75)
+ })
- assertRequestMade(requestMade)
+ await assertRequestMade(page, async () => {
+ await sleep(100)
+ })
})
test("it cancels the prefetch request if the link is no longer hovered", async ({ page }) => {
await goTo({ page, path: "/hover_to_prefetch.html" })
- let requestMade = false
- page.on("request", async (request) => (requestMade = true))
-
- await page.hover("#anchor_for_prefetch")
- await sleep(75)
-
- assertRequestNotMade(requestMade)
-
- await page.mouse.move(0, 0)
-
- await sleep(100)
+ await assertRequestNotMade(page, async () => {
+ await page.hover("#anchor_for_prefetch")
+ await sleep(75)
+ })
- assertRequestNotMade(requestMade)
+ await assertRequestNotMade(page, async () => {
+ await page.mouse.move(0, 0)
+ await sleep(100)
+ })
})
test("it resets the cache when a link is hovered", async ({ page }) => {
@@ -246,11 +239,8 @@ test("it resets the cache when a link is hovered", async ({ page }) => {
test("it does not make a network request when clicking on a link that has been prefetched", async ({ page }) => {
await goTo({ page, path: "/hover_to_prefetch.html" })
- await hoverSelector({ page, selector: "#anchor_for_prefetch" })
-
- await sleep(100)
-
- await assertNotPrefetchedOnHover({ page, selector: "#anchor_for_prefetch" })
+ await assertPrefetchedOnHover({ page, selector: "#anchor_for_prefetch" })
+ await assertRequestNotMadeOnClick({ page, selector: "#anchor_for_prefetch" })
})
test("it follows the link using the cached response when clicking on a link that has been prefetched", async ({
@@ -264,44 +254,51 @@ test("it follows the link using the cached response when clicking on a link that
})
const assertPrefetchedOnHover = async ({ page, selector, callback }) => {
- let requestMade = false
+ await assertRequestMade(page, async () => {
+ await hoverSelector({ page, selector })
+
+ await sleep(100)
+ }, callback)
+}
- page.on("request", (request) => {
- requestMade = request
+const assertNotPrefetchedOnHover = async ({ page, selector, callback }) => {
+ await assertRequestNotMade(page, async () => {
+ await hoverSelector({ page, selector })
+
+ await sleep(100)
+ }, callback)
+}
+
+const assertRequestNotMadeOnClick = async ({ page, selector }) => {
+ await assertRequestNotMade(page, async () => {
+ await clickSelector({ page, selector })
})
+}
- await hoverSelector({ page, selector })
+const assertRequestMade = async (page, action, callback) => {
+ let requestMade = false
+ page.on("request", async (request) => requestMade = request)
- await sleep(100)
+ await action()
+
+ assert.equal(!!requestMade, true, "Network request wasn't made when it should have been.")
if (callback) {
await callback(requestMade)
}
-
- assertRequestMade(!!requestMade)
}
-const assertNotPrefetchedOnHover = async ({ page, selector, callback }) => {
+const assertRequestNotMade = async (page, action, callback) => {
let requestMade = false
+ page.on("request", async (request) => requestMade = request)
- page.on("request", (request) => {
- callback && callback(request)
- requestMade = true
- })
-
- await hoverSelector({ page, selector })
-
- await sleep(100)
-
- assert.equal(requestMade, false, "Network request was made when it should not have been.")
-}
+ await action()
-const assertRequestMade = (requestMade) => {
- assert.equal(requestMade, true, "Network request wasn't made when it should have been.")
-}
+ assert.equal(!!requestMade, false, "Network request was made when it should not have been.")
-const assertRequestNotMade = (requestMade) => {
- assert.equal(requestMade, false, "Network request was made when it should not have been.")
+ if (callback) {
+ await callback(requestMade)
+ }
}
const goTo = async ({ page, path }) => {
From 89be8e4c206ea877183b7ac4a89f898363a14f0f Mon Sep 17 00:00:00 2001
From: Tom Pietrosanti
Date: Tue, 21 May 2024 10:07:27 -0400
Subject: [PATCH 12/20] style: align prettier trailing comma with eslint
(#1260)
---
.prettierrc.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.prettierrc.json b/.prettierrc.json
index db5bf647b..ec8e5e030 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -1,5 +1,6 @@
{
"singleQuote": false,
"printWidth": 120,
- "semi": false
+ "semi": false,
+ "trailingComma" : "none"
}
From c81830783eb498a3732a8248353146e262378532 Mon Sep 17 00:00:00 2001
From: Jorge Manrubia
Date: Thu, 30 May 2024 13:05:39 +0200
Subject: [PATCH 13/20] Don't autofocus when rendering page refreshes with
morphing
Before this change, Turbo would always focus on the first element with `[autofocus]` when a page refresh
with morphing happened (default behavior inherited from `PageRenderer`). With this change, it will never
autofocus when a page refresh with morphing happens.
This is meant to solve the problem where you are writing on a form, and it loses the focus because a
broadcasted page refresh arrives.
---
src/core/drive/morph_renderer.js | 4 ++++
src/core/renderer.js | 12 +++++++++---
src/tests/fixtures/autofocus.html | 9 +++++++++
src/tests/functional/autofocus_tests.js | 22 ++++++++++++++++++++++
src/tests/functional/page_refresh_tests.js | 2 +-
5 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/src/core/drive/morph_renderer.js b/src/core/drive/morph_renderer.js
index 2c5d14874..11142463e 100644
--- a/src/core/drive/morph_renderer.js
+++ b/src/core/drive/morph_renderer.js
@@ -11,6 +11,10 @@ export class MorphRenderer extends PageRenderer {
return "morph"
}
+ get shouldAutofocus() {
+ return false
+ }
+
// Private
async #morphBody() {
diff --git a/src/core/renderer.js b/src/core/renderer.js
index 56e73983e..f0a02f581 100644
--- a/src/core/renderer.js
+++ b/src/core/renderer.js
@@ -16,6 +16,10 @@ export class Renderer {
return true
}
+ get shouldAutofocus() {
+ return true
+ }
+
get reloadReason() {
return
}
@@ -40,9 +44,11 @@ export class Renderer {
}
focusFirstAutofocusableElement() {
- const element = this.connectedSnapshot.firstAutofocusableElement
- if (element) {
- element.focus()
+ if (this.shouldAutofocus) {
+ const element = this.connectedSnapshot.firstAutofocusableElement
+ if (element) {
+ element.focus()
+ }
}
}
diff --git a/src/tests/fixtures/autofocus.html b/src/tests/fixtures/autofocus.html
index a0d55fa0d..8d49539cb 100644
--- a/src/tests/fixtures/autofocus.html
+++ b/src/tests/fixtures/autofocus.html
@@ -5,6 +5,8 @@
Autofocus
+
+
Autofocus
@@ -22,5 +24,12 @@ Autofocus
#drives-frame link to frames/form.html
+
+