Vt follow redirects (#8522)
* View Transitions redirects WIP * transition across redirects * added changeset --------- Co-authored-by: Matthew Phillips <matthew@skypack.dev>
This commit is contained in:
parent
2db9762eb0
commit
43bc5f2a55
5 changed files with 78 additions and 6 deletions
5
.changeset/warm-windows-occur.md
Normal file
5
.changeset/warm-windows-occur.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
let view transitions handle same origin redirects
|
|
@ -65,9 +65,19 @@ const { fallback = 'animate' } = Astro.props as Props;
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getHTML(href: string) {
|
async function getHTML(href: string) {
|
||||||
const res = await fetch(href);
|
let res;
|
||||||
|
try {
|
||||||
|
res = await fetch(href);
|
||||||
|
} catch (err) {
|
||||||
|
return { ok: false };
|
||||||
|
}
|
||||||
const html = await res.text();
|
const html = await res.text();
|
||||||
return { ok: res.ok, html };
|
return {
|
||||||
|
ok: res.ok,
|
||||||
|
html,
|
||||||
|
redirected: res.redirected ? res.url : undefined,
|
||||||
|
contentType: res.headers.get('content-type'),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFallback(): Fallback {
|
function getFallback(): Fallback {
|
||||||
|
@ -280,13 +290,16 @@ const { fallback = 'animate' } = Astro.props as Props;
|
||||||
async function navigate(dir: Direction, loc: URL, state?: State) {
|
async function navigate(dir: Direction, loc: URL, state?: State) {
|
||||||
let finished: Promise<void>;
|
let finished: Promise<void>;
|
||||||
const href = loc.href;
|
const href = loc.href;
|
||||||
const { html, ok } = await getHTML(href);
|
const { html, ok, contentType, redirected } = await getHTML(href);
|
||||||
|
// if there was a redirection, show the final URL in the browser's address bar
|
||||||
|
redirected && (loc = new URL(redirected));
|
||||||
// If there is a problem fetching the new page, just do an MPA navigation to it.
|
// If there is a problem fetching the new page, just do an MPA navigation to it.
|
||||||
if (!ok) {
|
if (!ok || contentType !== 'text/html') {
|
||||||
location.href = href;
|
location.href = href;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const doc = parser.parseFromString(html, 'text/html');
|
|
||||||
|
const doc = parser.parseFromString(html, contentType);
|
||||||
if (!doc.querySelector('[name="astro-view-transitions-enabled"]')) {
|
if (!doc.querySelector('[name="astro-view-transitions-enabled"]')) {
|
||||||
location.href = href;
|
location.href = href;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -7,6 +7,10 @@ export default defineConfig({
|
||||||
output: 'server',
|
output: 'server',
|
||||||
adapter: nodejs({ mode: 'standalone' }),
|
adapter: nodejs({ mode: 'standalone' }),
|
||||||
integrations: [react()],
|
integrations: [react()],
|
||||||
|
redirects: {
|
||||||
|
'/redirect-two': '/two',
|
||||||
|
'/redirect-external': 'http://example.com/',
|
||||||
|
},
|
||||||
vite: {
|
vite: {
|
||||||
build: {
|
build: {
|
||||||
assetsInlineLimit: 0,
|
assetsInlineLimit: 0,
|
||||||
|
|
|
@ -8,6 +8,8 @@ import Layout from '../components/Layout.astro';
|
||||||
<a id="click-three" href="/three">go to 3</a>
|
<a id="click-three" href="/three">go to 3</a>
|
||||||
<a id="click-longpage" href="/long-page">go to long page</a>
|
<a id="click-longpage" href="/long-page">go to long page</a>
|
||||||
<a id="click-self" href="">go to top</a>
|
<a id="click-self" href="">go to top</a>
|
||||||
|
<a id="click-redirect-two" href="/redirect-two">go to redirect 2</a>
|
||||||
|
<a id="click-redirect-external" href="/redirect-external">go to a redirect external</a>
|
||||||
|
|
||||||
<div id="test">test content</div>
|
<div id="test">test content</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
@ -566,7 +566,55 @@ test.describe('View Transitions', () => {
|
||||||
await expect(p, 'should have content').toHaveText('Page 1');
|
await expect(p, 'should have content').toHaveText('Page 1');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('client:only styles are retained on transition', async ({ page, astro }) => {
|
test('Moving to a page which redirects to another', async ({ page, astro }) => {
|
||||||
|
const loads = [];
|
||||||
|
page.addListener('load', (p) => {
|
||||||
|
loads.push(p.title());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Go to page 1
|
||||||
|
await page.goto(astro.resolveUrl('/one'));
|
||||||
|
let p = page.locator('#one');
|
||||||
|
await expect(p, 'should have content').toHaveText('Page 1');
|
||||||
|
|
||||||
|
// go to page 2
|
||||||
|
await page.click('#click-redirect-two');
|
||||||
|
p = page.locator('#two');
|
||||||
|
await expect(p, 'should have content').toHaveText('Page 2');
|
||||||
|
|
||||||
|
// go back
|
||||||
|
await page.goBack();
|
||||||
|
p = page.locator('#one');
|
||||||
|
await expect(p, 'should have content').toHaveText('Page 1');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
loads.length,
|
||||||
|
'There should only be the initial page load and two normal transitions'
|
||||||
|
).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Redirect to external site causes page load', async ({ page, astro }) => {
|
||||||
|
const loads = [];
|
||||||
|
page.addListener('load', (p) => {
|
||||||
|
loads.push(p.title());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Go to page 1
|
||||||
|
await page.goto(astro.resolveUrl('/one'));
|
||||||
|
let p = page.locator('#one');
|
||||||
|
await expect(p, 'should have content').toHaveText('Page 1');
|
||||||
|
|
||||||
|
// go to external page
|
||||||
|
await page.click('#click-redirect-external');
|
||||||
|
// doesn't work for playwright when we are too fast
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
|
p = page.locator('h1');
|
||||||
|
await expect(p, 'should have content').toBeVisible();
|
||||||
|
|
||||||
|
expect(loads.length, 'There should be 2 page loads').toEqual(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('client:only styles are retained on transition', async ({ page, astro }) => {
|
||||||
const totalExpectedStyles = 8;
|
const totalExpectedStyles = 8;
|
||||||
|
|
||||||
// Go to page 1
|
// Go to page 1
|
||||||
|
|
Loading…
Reference in a new issue