Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/tests/fixtures/navigation.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ <h1>Navigation</h1>
<p><a id="bare-target-link" href="/src/tests/fixtures/one.html" target>Bare target attribute link</a></p>
<p><a id="same-origin-download-link" href="/intentionally_missing_fake_download.html" download="x.html">Same-origin download link</a></p>
<svg width="600" height="100" viewbox="-300 -50 600 100"><text><a id="same-origin-link-inside-svg-element" href="/src/tests/fixtures/one.html">Same-origin link inside SVG element</a></text></svg>
<svg width="600" height="100" viewbox="-300 -50 600 100"><text><a id="same-origin-targeted-link-inside-svg-element" href="/src/tests/fixtures/one.html" target="_blank">Same-origin targeted link inside SVG element</a></text></svg>
<svg width="600" height="100" viewbox="-300 -50 600 100"><text><a id="same-page-link-inside-svg-element" href="#main">Same-page link inside SVG element</a></text></svg>
<svg width="600" height="100" viewbox="-300 -50 600 100"><text><a id="cross-origin-link-inside-svg-element" href="about:blank">Cross-origin link inside SVG element</a></text></svg>
<p><a id="same-origin-get-link-form" href="/src/tests/fixtures/navigation.html?a=one&b=two" data-turbo-method="get">Same-origin data-turbo-method=get link</a></p>
<p><a id="same-origin-replace-post-link" href="/__turbo/redirect" data-turbo-method="post" data-turbo-action="replace">Same-origin data-turbo-action=replace link with post method</a></p>
Expand Down
45 changes: 44 additions & 1 deletion src/tests/functional/navigation_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,18 @@ test("following a same-origin [target] link", async ({ page }) => {
expect(await visitAction(page)).toEqual("load")
})

test("following a same-origin [target] link inside an SVG", async ({ page }) => {
const errors = []
await page.on("pageerror", e => errors.push(e))
const link = page.locator("#same-origin-targeted-link-inside-svg-element")
await link.focus()
const [popup] = await Promise.all([page.waitForEvent("popup"), page.keyboard.press("Enter")])

expect(pathname(popup.url())).toEqual("/src/tests/fixtures/one.html")
expect(await visitAction(page)).toEqual("load")
expect(errors, "raised an error").toHaveLength(0)
})

test("following a _self [target] link", async ({ page }) => {
await page.click("#self-targeted-link")

Expand Down Expand Up @@ -298,7 +310,19 @@ test("following a same-origin link inside an SVG element", async ({ page }) => {
await page.keyboard.press("Enter")

await expect(page).toHaveURL(withPathname("/src/tests/fixtures/one.html"))
expect(await visitAction(page)).toEqual("load")
expect(await visitAction(page)).toEqual("advance")
})

test("following a same-page link inside an SVG element", async ({ page }) => {
const errors = []
await page.on("pageerror", e => errors.push(e))
const link = page.locator("#same-page-link-inside-svg-element")
await link.focus()
await page.keyboard.press("Enter")

await expect(page).toHaveURL(withHash("#main"))
expect(await isScrolledToSelector(page, "#main"), "scrolled to #main").toEqual(true)
expect(errors, "raised an error").toHaveLength(0)
})

test("following a cross-origin link inside an SVG element", async ({ page }) => {
Expand Down Expand Up @@ -425,6 +449,25 @@ test("same-page anchor visits do not trigger visit events", async ({ page }) =>
}
})

test("same-page anchor visits within SVG elements do not trigger visit events", async ({ page }) => {
const events = [
"turbo:before-visit",
"turbo:visit",
"turbo:before-cache",
"turbo:before-render",
"turbo:render",
"turbo:load"
]

for (const eventName in events) {
await page.goto("/src/tests/fixtures/navigation.html")
const link = page.locator("#same-origin-link-inside-svg-element")
await link.focus()
await page.keyboard.press("Enter")
expect(await noNextEventNamed(page, eventName), `same-page links do not trigger ${eventName} events`).toEqual(true)
}
})

test("correct referrer header", async ({ page }) => {
page.click("#headers-link")
await nextEventNamed(page, "turbo:load")
Expand Down
4 changes: 3 additions & 1 deletion src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,14 @@ export function findLinkFromClickTarget(target) {
const link = findClosestRecursively(target, "a[href], a[xlink\\:href]")

if (!link) return null
if (link.href.startsWith("#")) return null
if (link.hasAttribute("download")) return null

const linkTarget = link.getAttribute("target")
if (linkTarget && linkTarget !== "_self") return null

const linkHref = link.getAttribute("href")
if (linkHref && linkHref.startsWith("#")) return null

return link
}

Expand Down