summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Martin Trapp <94928215+martrapp@users.noreply.github.com> 2023-09-12 18:54:32 +0200
committerGravatar GitHub <noreply@github.com> 2023-09-12 12:54:32 -0400
commit43bc5f2a55173218bcfeec50242b72ae999930e2 (patch)
tree1d747d741a00ff82149a70d40d5489ddca5ac95d
parent2db9762eb06d8a95021556c64e0cbb56c61352d5 (diff)
downloadastro-43bc5f2a55173218bcfeec50242b72ae999930e2.tar.gz
astro-43bc5f2a55173218bcfeec50242b72ae999930e2.tar.zst
astro-43bc5f2a55173218bcfeec50242b72ae999930e2.zip
Vt follow redirects (#8522)
* View Transitions redirects WIP * transition across redirects * added changeset --------- Co-authored-by: Matthew Phillips <matthew@skypack.dev>
-rw-r--r--.changeset/warm-windows-occur.md5
-rw-r--r--packages/astro/components/ViewTransitions.astro23
-rw-r--r--packages/astro/e2e/fixtures/view-transitions/astro.config.mjs4
-rw-r--r--packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro2
-rw-r--r--packages/astro/e2e/view-transitions.test.js50
5 files changed, 78 insertions, 6 deletions
diff --git a/.changeset/warm-windows-occur.md b/.changeset/warm-windows-occur.md
new file mode 100644
index 000000000..47c797f2f
--- /dev/null
+++ b/.changeset/warm-windows-occur.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+let view transitions handle same origin redirects
diff --git a/packages/astro/components/ViewTransitions.astro b/packages/astro/components/ViewTransitions.astro
index 6ae8f3592..77d56e652 100644
--- a/packages/astro/components/ViewTransitions.astro
+++ b/packages/astro/components/ViewTransitions.astro
@@ -65,9 +65,19 @@ const { fallback = 'animate' } = Astro.props as Props;
};
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();
- 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 {
@@ -280,13 +290,16 @@ const { fallback = 'animate' } = Astro.props as Props;
async function navigate(dir: Direction, loc: URL, state?: State) {
let finished: Promise<void>;
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 (!ok) {
+ if (!ok || contentType !== 'text/html') {
location.href = href;
return;
}
- const doc = parser.parseFromString(html, 'text/html');
+
+ const doc = parser.parseFromString(html, contentType);
if (!doc.querySelector('[name="astro-view-transitions-enabled"]')) {
location.href = href;
return;
diff --git a/packages/astro/e2e/fixtures/view-transitions/astro.config.mjs b/packages/astro/e2e/fixtures/view-transitions/astro.config.mjs
index 02dc2043d..68fdc8e2e 100644
--- a/packages/astro/e2e/fixtures/view-transitions/astro.config.mjs
+++ b/packages/astro/e2e/fixtures/view-transitions/astro.config.mjs
@@ -7,6 +7,10 @@ export default defineConfig({
output: 'server',
adapter: nodejs({ mode: 'standalone' }),
integrations: [react()],
+ redirects: {
+ '/redirect-two': '/two',
+ '/redirect-external': 'http://example.com/',
+ },
vite: {
build: {
assetsInlineLimit: 0,
diff --git a/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro b/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro
index 3f9666c1d..cc57e76d8 100644
--- a/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro
+++ b/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro
@@ -8,6 +8,8 @@ import Layout from '../components/Layout.astro';
<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-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>
</Layout>
diff --git a/packages/astro/e2e/view-transitions.test.js b/packages/astro/e2e/view-transitions.test.js
index 6421b5fc3..f1c1c4ef8 100644
--- a/packages/astro/e2e/view-transitions.test.js
+++ b/packages/astro/e2e/view-transitions.test.js
@@ -566,7 +566,55 @@ test.describe('View Transitions', () => {
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;
// Go to page 1