mirror of
https://github.com/withastro/astro.git
synced 2025-02-10 22:38:53 -05:00
Makes view transition e2e tests compatible with Firefox (#11093)
This commit is contained in:
parent
bfe9c73536
commit
a514bbe992
3 changed files with 80 additions and 120 deletions
|
@ -6,7 +6,7 @@ import { ViewTransitions, fade } from 'astro:transitions';
|
|||
<ViewTransitions />
|
||||
</head>
|
||||
<body>
|
||||
<h1 transition:name="h1" transition:animate={fade({duration:10000})}>Abort</h1>
|
||||
<h1 transition:name="h1" transition:animate={fade({duration:500})}>Abort</h1>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -15,11 +15,10 @@ import { ViewTransitions, fade } from 'astro:transitions';
|
|||
import {navigate } from 'astro:transitions/client';
|
||||
|
||||
setTimeout(()=>{
|
||||
[...document.getAnimations()].forEach((a) => a.addEventListener('cancel',
|
||||
(e) => console.log("[test]",e.type, a.animationName)));
|
||||
console.log("[test] navigate to /one")
|
||||
[...document.getAnimations()].forEach((a) => a.addEventListener('cancel', (e) => console.log("[test]", e.type, a.animationName)));
|
||||
console.log("[test] navigate to /one");
|
||||
navigate("/one");
|
||||
}, 1000);
|
||||
}, 200);
|
||||
console.log('[test] navigate to "."')
|
||||
navigate("/abort2");
|
||||
</script>
|
||||
|
|
|
@ -13,6 +13,14 @@ test.afterAll(async () => {
|
|||
await devServer.stop();
|
||||
});
|
||||
|
||||
function collectLoads(page) {
|
||||
const loads = [];
|
||||
page.on('load', async () => {
|
||||
const url = page.url();
|
||||
if (url !== 'about:blank') loads.push(await page.title());
|
||||
});
|
||||
return loads;
|
||||
}
|
||||
function scrollToBottom(page) {
|
||||
return page.evaluate(() => {
|
||||
window.scrollY = document.documentElement.scrollHeight;
|
||||
|
@ -34,12 +42,13 @@ function collectPreloads(page) {
|
|||
});
|
||||
}
|
||||
|
||||
async function nativeViewTransition(page) {
|
||||
return page.evaluate(() => document.startViewTransition !== undefined)
|
||||
}
|
||||
|
||||
test.describe('View Transitions', () => {
|
||||
test('Moving from page 1 to page 2', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
|
@ -55,10 +64,7 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('Back button is captured', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
|
@ -79,11 +85,7 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('Clicking on a link with nested content', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
|
||||
const loads = collectLoads(page);
|
||||
// Go to page 4
|
||||
await page.goto(astro.resolveUrl('/four'));
|
||||
let p = page.locator('#four');
|
||||
|
@ -98,11 +100,7 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('Clicking on a link to a page with non-recommended headers', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
|
||||
const loads = collectLoads(page);
|
||||
// Go to page 4
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
let p = page.locator('#one');
|
||||
|
@ -120,10 +118,7 @@ test.describe('View Transitions', () => {
|
|||
page,
|
||||
astro,
|
||||
}) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
|
@ -145,10 +140,7 @@ test.describe('View Transitions', () => {
|
|||
page,
|
||||
astro,
|
||||
}) => {
|
||||
const loads = [];
|
||||
page.addListener('load', async (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
let p = page.locator('#one');
|
||||
|
@ -176,10 +168,7 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('Moving from a page without ViewTransitions w/ back button', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
|
@ -250,7 +239,7 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('No page rendering during swap()', async ({ page, astro }) => {
|
||||
// This has been a problem with theme switchers (e.g. for drakmode)
|
||||
// This has been a problem with theme switchers (e.g. for darkmode)
|
||||
// Swap() should not trigger any page renders and give users the chance to
|
||||
// correct attributes in the astro:after-swap handler before they become visible
|
||||
|
||||
|
@ -258,6 +247,10 @@ test.describe('View Transitions', () => {
|
|||
// The test succeeds if no additional animation beside those of the
|
||||
// view transition is triggered during swap()
|
||||
|
||||
// Only works for browsers with native view transitions
|
||||
if (!await nativeViewTransition(page)) return;
|
||||
|
||||
|
||||
await page.goto(astro.resolveUrl('/listener-one'));
|
||||
let p = page.locator('#totwo');
|
||||
await expect(p, 'should have content').toHaveText('Go to listener two');
|
||||
|
@ -295,10 +288,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('click self link (w/o hash) does not do navigation', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
const p = page.locator('#one');
|
||||
|
@ -596,10 +587,8 @@ test.describe('View Transitions', () => {
|
|||
page,
|
||||
astro,
|
||||
}) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/query'));
|
||||
|
@ -618,10 +607,8 @@ test.describe('View Transitions', () => {
|
|||
page,
|
||||
astro,
|
||||
}) => {
|
||||
const loads = [];
|
||||
page.addListener('load', async (p) => {
|
||||
loads.push(p);
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
// Go to the half bakeed page
|
||||
await page.goto(astro.resolveUrl('/half-baked'));
|
||||
let p = page.locator('#half-baked');
|
||||
|
@ -669,10 +656,8 @@ test.describe('View Transitions', () => {
|
|||
page,
|
||||
astro,
|
||||
}) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
|
||||
// Go to page 4
|
||||
await page.goto(astro.resolveUrl('/four'));
|
||||
|
@ -684,6 +669,9 @@ test.describe('View Transitions', () => {
|
|||
p = page.locator('#two');
|
||||
await expect(p, 'should have content').toHaveText('Page 2');
|
||||
|
||||
// go to next page
|
||||
await page.click('#click-longpage');
|
||||
|
||||
expect(loads.length, 'There should be 2 page load').toEqual(2);
|
||||
});
|
||||
|
||||
|
@ -703,10 +691,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('data-astro-reload not required for non-html content', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
// Go to page 4
|
||||
await page.goto(astro.resolveUrl('/four'));
|
||||
let p = page.locator('#four');
|
||||
|
@ -765,10 +751,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('Moving to a page which redirects to another', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
|
@ -792,10 +776,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('Redirect to external site causes page load', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
|
@ -805,11 +787,9 @@ test.describe('View Transitions', () => {
|
|||
// go to external page
|
||||
await page.click('#click-redirect-external');
|
||||
// doesn't work for playwright when we are too fast
|
||||
p = page.locator('h1');
|
||||
|
||||
await expect(p, 'should have content').toBeVisible();
|
||||
await page.waitForURL('http://example.com');
|
||||
await page.waitForFunction((arr) => arr.length === 2, loads);
|
||||
await expect(page.locator("h1"), 'should have content').toHaveText('Example Domain');
|
||||
expect(loads.length, 'There should be 2 page loads').toEqual(2);
|
||||
});
|
||||
|
||||
|
@ -1019,10 +999,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('form POST that redirects to another page is handled', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', async (p) => {
|
||||
loads.push(p);
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
|
||||
await page.goto(astro.resolveUrl('/form-one'));
|
||||
|
||||
|
@ -1048,10 +1026,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('form GET that redirects to another page is handled', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', async (p) => {
|
||||
loads.push(p);
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
|
||||
await page.goto(astro.resolveUrl('/form-one?method=get'));
|
||||
|
||||
|
@ -1070,10 +1046,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('form POST when there is an error shows the error', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', async (p) => {
|
||||
loads.push(p);
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
|
||||
await page.goto(astro.resolveUrl('/form-one?throw'));
|
||||
|
||||
|
@ -1095,11 +1069,8 @@ test.describe('View Transitions', () => {
|
|||
page,
|
||||
astro,
|
||||
}) => {
|
||||
const loads = [];
|
||||
const loads = collectLoads(page);
|
||||
|
||||
page.addListener('load', async (p) => {
|
||||
loads.push(p);
|
||||
});
|
||||
|
||||
const postedEncodings = [];
|
||||
|
||||
|
@ -1130,11 +1101,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('form POST respects enctype attribute', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
const loads = collectLoads(page);
|
||||
|
||||
page.addListener('load', async (p) => {
|
||||
loads.push(p);
|
||||
});
|
||||
|
||||
const postedEncodings = [];
|
||||
|
||||
|
@ -1222,10 +1190,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('form POST with no action handler', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', async (p) => {
|
||||
loads.push(p);
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
|
||||
await page.goto(astro.resolveUrl('/form-two'));
|
||||
|
||||
|
@ -1256,10 +1222,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('click on an svg anchor should trigger navigation', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
|
||||
await page.goto(astro.resolveUrl('/non-html-anchor'));
|
||||
let locator = page.locator('#insidesvga');
|
||||
|
@ -1271,10 +1235,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('click inside an svg anchor should trigger navigation', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
await page.goto(astro.resolveUrl('/non-html-anchor'));
|
||||
let locator = page.locator('#insidesvga');
|
||||
await expect(locator, 'should have content').toHaveText('text within a svga');
|
||||
|
@ -1285,10 +1247,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('click on an area in an image map should trigger navigation', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
await page.goto(astro.resolveUrl('/non-html-anchor'));
|
||||
let locator = page.locator('#area');
|
||||
await expect(locator, 'should have attribute').toHaveAttribute('shape', 'default');
|
||||
|
@ -1328,10 +1288,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('view transition should also work with 404 page', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
|
||||
// Go to page 1
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
|
@ -1347,10 +1305,8 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('custom elements can trigger a view transition', async ({ page, astro }) => {
|
||||
const loads = [];
|
||||
page.addListener('load', (p) => {
|
||||
loads.push(p.title());
|
||||
});
|
||||
const loads = collectLoads(page);
|
||||
|
||||
await page.goto(astro.resolveUrl('/one'));
|
||||
await expect(page.locator('#one'), 'should have content').toHaveText('Page 1');
|
||||
// go to page 2
|
||||
|
@ -1361,6 +1317,9 @@ test.describe('View Transitions', () => {
|
|||
});
|
||||
|
||||
test('transition:name should be escaped correctly', async ({ page, astro }) => {
|
||||
|
||||
// view-transition-name errors on browser w/o native support
|
||||
if (!await nativeViewTransition(page)) return;
|
||||
const expectedAnimations = new Set();
|
||||
const checkName = async (selector, name) => {
|
||||
expectedAnimations.add(name);
|
||||
|
@ -1518,7 +1477,6 @@ test.describe('View Transitions', () => {
|
|||
// clicks on slow loading page two
|
||||
// after short delay clicks on fast loading page one
|
||||
// even after some delay /two should not show up
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000)); // wait is part of the test
|
||||
let p = page.locator('#one');
|
||||
await expect(p, 'should have content').toHaveText('Page 1');
|
||||
});
|
||||
|
@ -1533,16 +1491,19 @@ test.describe('View Transitions', () => {
|
|||
// Navigate to self with a 10 second animation
|
||||
// shortly after starting that, change your mind an navigate to /one
|
||||
// check that animations got canceled
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000)); // wait is part of the test
|
||||
let p = page.locator('#one');
|
||||
await expect(p, 'should have content').toHaveText('Page 1');
|
||||
|
||||
// This test would be more important for a browser without native view transitions
|
||||
// as those do not have automatic cancelation of transitions.
|
||||
// For simulated view transitions, the last line would be missing as enter and exit animations
|
||||
// don't run in parallel.
|
||||
expect(lines.join('\n')).toBe(
|
||||
'[test] navigate to "."\n[test] navigate to /one\n[test] cancel astroFadeOut\n[test] cancel astroFadeIn'
|
||||
);
|
||||
// For simulated view transitions, the last line would be missing
|
||||
// as enter and exit animations don't run in parallel.
|
||||
|
||||
let expected = '[test] navigate to "."\n[test] navigate to /one\n[test] cancel astroFadeOut';
|
||||
const native = await nativeViewTransition(page);
|
||||
if (native) {
|
||||
expected += '\n[test] cancel astroFadeIn';
|
||||
}
|
||||
await page.click('#click-two');
|
||||
expect(lines.join('\n')).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@ process.stdout.isTTY = false;
|
|||
|
||||
const config = {
|
||||
// TODO: add more tests like view transitions and audits, and fix them. Some of them are failing.
|
||||
testMatch: ['e2e/css.test.js', 'e2e/prefetch.test.js'],
|
||||
testMatch: ['e2e/css.test.js', 'e2e/prefetch.test.js', 'e2e/view-transitions.test.js'],
|
||||
/* Maximum time one test can run for. */
|
||||
timeout: 40 * 1000,
|
||||
expect: {
|
||||
|
|
Loading…
Add table
Reference in a new issue