diff --git a/src/observers/link_prefetch_observer.js b/src/observers/link_prefetch_observer.js index de08e05da..d204cb2a5 100644 --- a/src/observers/link_prefetch_observer.js +++ b/src/observers/link_prefetch_observer.js @@ -100,14 +100,11 @@ export class LinkPrefetchObserver { request.headers["Sec-Purpose"] = "prefetch" - if (link.dataset.turboFrame && link.dataset.turboFrame !== "_top") { - request.headers["Turbo-Frame"] = link.dataset.turboFrame - } else if (link.dataset.turboFrame !== "_top") { - const turboFrame = link.closest("turbo-frame") + const turboFrame = link.closest("turbo-frame") + const turboFrameTarget = link.getAttribute("data-turbo-frame") || turboFrame?.getAttribute("target") || turboFrame?.id - if (turboFrame) { - request.headers["Turbo-Frame"] = turboFrame.id - } + if (turboFrameTarget && turboFrameTarget !== "_top") { + request.headers["Turbo-Frame"] = turboFrameTarget } if (link.hasAttribute("data-turbo-stream")) { diff --git a/src/tests/fixtures/hover_to_prefetch.html b/src/tests/fixtures/hover_to_prefetch.html index e0748fe0e..89b94f1bb 100644 --- a/src/tests/fixtures/hover_to_prefetch.html +++ b/src/tests/fixtures/hover_to_prefetch.html @@ -41,5 +41,13 @@ Won't prefetch when hovering me + + + Hover to prefetch me + + + + Hover to prefetch me + diff --git a/src/tests/functional/link_prefetch_observer_tests.js b/src/tests/functional/link_prefetch_observer_tests.js index 1d0139986..584d673ef 100644 --- a/src/tests/functional/link_prefetch_observer_tests.js +++ b/src/tests/functional/link_prefetch_observer_tests.js @@ -153,6 +153,25 @@ test("it prefetches links with inner elements", async ({ page }) => { await assertPrefetchedOnHover({ page, selector: "#anchor_with_inner_elements" }) }) +test("it prefetches links inside a turbo frame", async ({ page }) => { + await goTo({ page, path: "/hover_to_prefetch.html" }) + + await assertPrefetchedOnHover({ page, selector: "#anchor_for_prefetch_in_frame", callback: (request) => { + const turboFrameHeader = request.headers()["turbo-frame"] + assert.equal(turboFrameHeader, "frame_for_prefetch") + }}) +}) + + +test("doesn't include a turbo-frame header when the link is inside a turbo frame with a target=_top", async ({ page}) => { + await goTo({ page, path: "/hover_to_prefetch.html" }) + + await assertPrefetchedOnHover({ page, selector: "#anchor_for_prefetch_in_frame_target_top", callback: (request) => { + const turboFrameHeader = request.headers()["turbo-frame"] + assert.equal(undefined, turboFrameHeader) + }}) +}) + test("it prefetches links with a delay", async ({ page }) => { await goTo({ page, path: "/hover_to_prefetch.html" }) @@ -253,15 +272,18 @@ const assertPrefetchedOnHover = async ({ page, selector, callback }) => { let requestMade = false page.on("request", (request) => { - callback && callback(request) - requestMade = true + requestMade = request }) await hoverSelector({ page, selector }) await sleep(100) - assertRequestMade(requestMade) + if (callback) { + await callback(requestMade) + } + + assertRequestMade(!!requestMade) } const assertNotPrefetchedOnHover = async ({ page, selector, callback }) => {