Skip to content

Commit c4d84bb

Browse files
authored
fix(prefetch): Fix "tap" prefetch strategy when view transitions are enabled (#14235)
* add onPageLoad call to tap strategy * add changeset * add tests * format * rename test * fix tests * remove onPageLoad, add event listener directly on the document
1 parent 3bb14b7 commit c4d84bb

File tree

7 files changed

+135
-1
lines changed

7 files changed

+135
-1
lines changed

.changeset/young-hornets-post.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Fixes a bug where the "tap" prefetch strategy worked only on the first clicked link with view transitions enabled
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
import { ClientRouter } from 'astro:transitions';
3+
---
4+
5+
<html>
6+
<head>
7+
<title>Testing</title>
8+
<ClientRouter />
9+
</head>
10+
<body>
11+
<slot />
12+
</body>
13+
</html>
14+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
import ViewTransitionsLayout from "../../components/ViewTransitionsLayout.astro";
3+
---
4+
5+
<ViewTransitionsLayout>
6+
<h1>View Transitions 1</h1>
7+
<br>
8+
<br>
9+
<a href="/view-transitions/2">2</a>
10+
</ViewTransitionsLayout>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
import ViewTransitionsLayout from "../../components/ViewTransitionsLayout.astro";
3+
---
4+
5+
<ViewTransitionsLayout>
6+
<h1>View Transitions 2</h1>
7+
</ViewTransitionsLayout>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
import ViewTransitionsLayout from "../../components/ViewTransitionsLayout.astro";
3+
---
4+
5+
<ViewTransitionsLayout>
6+
<h1>View Transitions index</h1>
7+
<a href="/view-transitions/1">1</a>
8+
</ViewTransitionsLayout>

packages/astro/e2e/prefetch.test.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,24 @@ async function expectUrlNotPrefetched(url, page) {
5656
expect(reqUrls).not.toContainEqual(url);
5757
}
5858

59+
/**
60+
* @param {import('@playwright/test').Page} page
61+
* @param {string} selector
62+
*/
63+
async function mouseDown(page, selector) {
64+
const box = await page.locator(selector).boundingBox();
65+
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
66+
await page.mouse.down();
67+
}
68+
69+
/**
70+
* @param {import('@playwright/test').Page} page
71+
*/
72+
async function waitForPageLoad(page) {
73+
await page.waitForEvent('response');
74+
await new Promise(res => setTimeout(res, 500)); // wait for transition to finish
75+
}
76+
5977
test.describe('Prefetch (default)', () => {
6078
let devServer;
6179

@@ -393,3 +411,75 @@ test.describe('Prefetch (default), Experimental ({ clientPrerender: true })', ()
393411
expect(await scriptIsInHead(page, 'prefetch-load')).toBeTruthy();
394412
});
395413
});
414+
415+
test.describe('Prefetch View Transitions', () => {
416+
let devServer;
417+
418+
test.afterEach(async () => {
419+
await devServer.stop();
420+
});
421+
422+
test('"load" strategy', async ({ page, astro }) => {
423+
devServer = await astro.startDevServer({
424+
prefetch: {
425+
defaultStrategy: 'load',
426+
},
427+
});
428+
await page.goto(astro.resolveUrl('/view-transitions'));
429+
await expectUrlPrefetched('/view-transitions/1', page);
430+
431+
await Promise.all([waitForPageLoad(page), page.click('a')]);
432+
await expectUrlPrefetched('/view-transitions/2', page);
433+
});
434+
435+
test('"viewport" strategy', async ({ page, astro }) => {
436+
devServer = await astro.startDevServer({
437+
prefetch: {
438+
defaultStrategy: 'viewport',
439+
},
440+
});
441+
await page.goto(astro.resolveUrl('/view-transitions'));
442+
await expectUrlPrefetched('/view-transitions/1', page);
443+
444+
await Promise.all([waitForPageLoad(page), page.click('a')]);
445+
await expectUrlPrefetched('/view-transitions/2', page);
446+
});
447+
448+
test('"tap" strategy', async ({ page, astro }) => {
449+
devServer = await astro.startDevServer({
450+
prefetch: {
451+
defaultStrategy: 'tap',
452+
},
453+
});
454+
await page.goto(astro.resolveUrl('/view-transitions'));
455+
456+
await expectUrlNotPrefetched('/view-transitions/1', page);
457+
await mouseDown(page, 'a');
458+
await expectUrlPrefetched('/view-transitions/1', page);
459+
460+
await Promise.all([waitForPageLoad(page), page.mouse.up()]);
461+
462+
await expectUrlNotPrefetched('/view-transitions/2', page);
463+
await mouseDown(page, 'a')
464+
await expectUrlPrefetched('/view-transitions/2', page);
465+
});
466+
467+
test('"hover" strategy', async ({ page, astro }) => {
468+
devServer = await astro.startDevServer({
469+
prefetch: {
470+
defaultStrategy: 'hover',
471+
},
472+
});
473+
await page.goto(astro.resolveUrl('/view-transitions'));
474+
475+
await expectUrlNotPrefetched('/view-transitions/1', page);
476+
await page.locator('a').hover();
477+
await expectUrlPrefetched('/view-transitions/1', page);
478+
479+
await Promise.all([waitForPageLoad(page), page.click('a')]);
480+
481+
await expectUrlNotPrefetched('/view-transitions/2', page);
482+
await page.locator('a').hover();
483+
await expectUrlPrefetched('/view-transitions/2', page);
484+
});
485+
});

packages/astro/src/prefetch/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export function init(defaultOpts?: InitOptions) {
5454
*/
5555
function initTapStrategy() {
5656
for (const event of ['touchstart', 'mousedown']) {
57-
document.body.addEventListener(
57+
document.addEventListener(
5858
event,
5959
(e) => {
6060
if (elMatchesStrategy(e.target, 'tap')) {

0 commit comments

Comments
 (0)