Skip to content

Commit

Permalink
Merge branch 'main' into mt/preventDefault
Browse files Browse the repository at this point in the history
  • Loading branch information
martrapp authored Dec 20, 2023
2 parents 453b9f9 + 5062d27 commit 3c5edd6
Show file tree
Hide file tree
Showing 15 changed files with 184 additions and 56 deletions.
11 changes: 11 additions & 0 deletions .changeset/eleven-hairs-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@astrojs/tailwind': patch
'@astrojs/markdoc': patch
'@astrojs/svelte': patch
'@astrojs/react': patch
'@astrojs/mdx': patch
'@astrojs/vue': patch
'astro': patch
---

Upgrades vite to latest
5 changes: 5 additions & 0 deletions .changeset/rude-geckos-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Updates view transitions `form` handling with logic for the [`enctype`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/enctype) attribute
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
---
import Layout from '../components/Layout.astro';
const method = Astro.url.searchParams.get('method') ?? 'POST';
const enctype = Astro.url.searchParams.get('enctype');
const postShowThrow = Astro.url.searchParams.has('throw') ?? false;
---

<Layout>
<h2>Contact Form</h2>
<form action="/contact" method={method}>
<input type="hidden" name="name" value="Testing">
{postShowThrow ? <input type="hidden" name="throw" value="true"> : ''}
<input type="submit" value="Submit" id="submit">
<form action="/contact" method={method} {...enctype ? { enctype } : {}}>
<input type="hidden" name="name" value="Testing" />
{postShowThrow ? <input type="hidden" name="throw" value="true" /> : ''}
<input type="submit" value="Submit" id="submit" />
</form>
</Layout>
77 changes: 77 additions & 0 deletions packages/astro/e2e/view-transitions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,83 @@ test.describe('View Transitions', () => {
).toEqual(1);
});

test('form POST defaults to multipart/form-data (Astro 4.x compatibility)', async ({
page,
astro,
}) => {
const loads = [];

page.addListener('load', async (p) => {
loads.push(p);
});

const postedEncodings = [];

await page.route('**/contact', async (route) => {
const request = route.request();

if (request.method() === 'POST') {
postedEncodings.push(request.headers()['content-type'].split(';')[0]);
}

await route.continue();
});

await page.goto(astro.resolveUrl('/form-one'));

// Submit the form
await page.click('#submit');

expect(
loads.length,
'There should be only 1 page load. No additional loads for the form submission'
).toEqual(1);

expect(
postedEncodings,
'There should be 1 POST, with encoding set to `multipart/form-data`'
).toEqual(['multipart/form-data']);
});

test('form POST respects enctype attribute', async ({ page, astro }) => {
const loads = [];

page.addListener('load', async (p) => {
loads.push(p);
});

const postedEncodings = [];

await page.route('**/contact', async (route) => {
const request = route.request();

if (request.method() === 'POST') {
postedEncodings.push(request.headers()['content-type'].split(';')[0]);
}

await route.continue();
});

await page.goto(
astro.resolveUrl(
`/form-one?${new URLSearchParams({ enctype: 'application/x-www-form-urlencoded' })}`
)
);

// Submit the form
await page.click('#submit');

expect(
loads.length,
'There should be only 1 page load. No additional loads for the form submission'
).toEqual(1);

expect(
postedEncodings,
'There should be 1 POST, with encoding set to `multipart/form-data`'
).toEqual(['application/x-www-form-urlencoded']);
});

test('Route announcer is invisible on page transition', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/no-directive-one'));

Expand Down
2 changes: 1 addition & 1 deletion packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@
"tsconfck": "^3.0.0",
"unist-util-visit": "^5.0.0",
"vfile": "^6.0.1",
"vite": "^5.0.0",
"vite": "^5.0.10",
"vitefu": "^0.2.5",
"which-pm": "^2.1.1",
"yargs-parser": "^21.1.1",
Expand Down
20 changes: 19 additions & 1 deletion packages/astro/src/transitions/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,25 @@ async function transition(
const init: RequestInit = {};
if (preparationEvent.formData) {
init.method = 'POST';
init.body = preparationEvent.formData;
const form =
preparationEvent.sourceElement instanceof HTMLFormElement
? preparationEvent.sourceElement
: preparationEvent.sourceElement instanceof HTMLElement &&
'form' in preparationEvent.sourceElement
? (preparationEvent.sourceElement.form as HTMLFormElement)
: preparationEvent.sourceElement?.closest('form');
// Form elements without enctype explicitly set default to application/x-www-form-urlencoded.
// In order to maintain compatibility with Astro 4.x, we need to check the value of enctype
// on the attributes property rather than accessing .enctype directly. Astro 5.x may
// introduce defaulting to application/x-www-form-urlencoded as a breaking change, and then
// we can access .enctype directly.
//
// Note: getNamedItem can return null in real life, even if TypeScript doesn't think so, hence
// the ?.
init.body =
form?.attributes.getNamedItem('enctype')?.value === 'application/x-www-form-urlencoded'
? new URLSearchParams(preparationEvent.formData as any)
: preparationEvent.formData;
}
const response = await fetchHTML(href, init);
// If there is a problem fetching the new page, just do an MPA navigation to it.
Expand Down
8 changes: 5 additions & 3 deletions packages/astro/test/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,11 @@ describe('astro cli', () => {
const proc = cli('dev', '--root', fileURLToPath(projectRootURL));
const { messages } = await parseCliDevStart(proc);

expect(messages[0]).to.contain('astro');
expect(messages[0]).to.contain(pkgVersion);
expect(messages[0]).to.contain('ready in');
const index = messages[0].includes('[vite]') ? 1 : 0;

expect(messages[index]).to.contain('astro');
expect(messages[index]).to.contain(pkgVersion);
expect(messages[index]).to.contain('ready in');
});

['dev', 'preview'].forEach((cmd) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/markdoc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
"devalue": "^4.3.2",
"linkedom": "^0.16.4",
"mocha": "^10.2.0",
"vite": "^5.0.0"
"vite": "^5.0.10"
},
"engines": {
"node": ">=18.14.1"
Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/mdx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"remark-shiki-twoslash": "^3.1.3",
"remark-toc": "^9.0.0",
"unified": "^11.0.4",
"vite": "^5.0.0"
"vite": "^5.0.10"
},
"engines": {
"node": ">=18.14.1"
Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
"cheerio": "1.0.0-rc.12",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"vite": "^5.0.0",
"vite": "^5.0.10",
"mocha": "^10.2.0"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"svelte": "^4.2.5",
"vite": "^5.0.0"
"vite": "^5.0.10"
},
"peerDependencies": {
"astro": "^4.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/tailwind/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"tailwindcss": "^3.3.5",
"vite": "^5.0.0"
"vite": "^5.0.10"
},
"peerDependencies": {
"astro": "^3.0.0 || ^4.0.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/integrations/tailwind/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async function getPostCssConfig(
async function getViteConfiguration(
tailwindConfigPath: string | undefined,
viteConfig: UserConfig
) {
): Promise<Partial<UserConfig>> {
// We need to manually load postcss config files because when inlining the tailwind and autoprefixer plugins,
// that causes vite to ignore postcss config files
const postcssConfigResult = await getPostCssConfig(viteConfig.root, viteConfig.css?.postcss);
Expand All @@ -38,7 +38,7 @@ async function getViteConfiguration(
return {
css: {
postcss: {
options: postcssOptions,
...postcssOptions,
plugins: postcssPlugins,
},
},
Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"cheerio": "1.0.0-rc.12",
"linkedom": "^0.16.4",
"mocha": "^10.2.0",
"vite": "^5.0.0",
"vite": "^5.0.10",
"vue": "^3.3.8"
},
"peerDependencies": {
Expand Down
Loading

0 comments on commit 3c5edd6

Please sign in to comment.