diff options
author | 2024-04-23 22:52:55 +0200 | |
---|---|---|
committer | 2024-04-23 16:52:55 -0400 | |
commit | 30cf82ac3e970a6a3c0f07db1340dd7152d1c35d (patch) | |
tree | b7d54fdb5a90752aca4017f6fd47651d39341420 | |
parent | d7dff648241b23b235f7060249de0fe015411bc3 (diff) | |
download | astro-30cf82ac3e970a6a3c0f07db1340dd7152d1c35d.tar.gz astro-30cf82ac3e970a6a3c0f07db1340dd7152d1c35d.tar.zst astro-30cf82ac3e970a6a3c0f07db1340dd7152d1c35d.zip |
Prevents inputs from changing ViewTransitions' form method or action (#10856)
* Prevents inputs from changing ViewTransitions' form method or action. Fixes #10849
* Consistency 🧘♂️
5 files changed, 55 insertions, 2 deletions
diff --git a/.changeset/tasty-swans-refuse.md b/.changeset/tasty-swans-refuse.md new file mode 100644 index 000000000..8a8d6dde5 --- /dev/null +++ b/.changeset/tasty-swans-refuse.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Prevents inputs with a name attribute of action or method to break ViewTransitions' form submission diff --git a/packages/astro/components/ViewTransitions.astro b/packages/astro/components/ViewTransitions.astro index c33d9a3f5..84a68d61e 100644 --- a/packages/astro/components/ViewTransitions.astro +++ b/packages/astro/components/ViewTransitions.astro @@ -108,9 +108,16 @@ const { fallback = 'animate' } = Astro.props; const form = el as HTMLFormElement; const submitter = ev.submitter; const formData = new FormData(form, submitter); + // form.action and form.method can point to an <input name="action"> or <input name="method"> + // in which case should fallback to the form attribute + const formAction = + typeof form.action === 'string' ? form.action : form.getAttribute('action'); + const formMethod = + typeof form.method === 'string' ? form.method : form.getAttribute('method'); // Use the form action, if defined, otherwise fallback to current path. - let action = submitter?.getAttribute('formaction') ?? form.action ?? location.pathname; - const method = submitter?.getAttribute('formmethod') ?? form.method; + let action = submitter?.getAttribute('formaction') ?? formAction ?? location.pathname; + // Use the form method, if defined, otherwise fallback to "get" + const method = submitter?.getAttribute('formmethod') ?? formMethod ?? 'get'; // the "dialog" method is a special keyword used within <dialog> elements // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fs-method diff --git a/packages/astro/e2e/fixtures/view-transitions/src/pages/form-seven.astro b/packages/astro/e2e/fixtures/view-transitions/src/pages/form-seven.astro new file mode 100644 index 000000000..71befd924 --- /dev/null +++ b/packages/astro/e2e/fixtures/view-transitions/src/pages/form-seven.astro @@ -0,0 +1,11 @@ +--- +import Layout from '../components/Layout.astro'; + +--- +<Layout> + <form> + <p>This form has an no method defined, but input with `name=method`</p> + <input type="text" name="method" value="POST" /> + <button id="submit">Submit</button> + </form> +</Layout> diff --git a/packages/astro/e2e/fixtures/view-transitions/src/pages/form-six.astro b/packages/astro/e2e/fixtures/view-transitions/src/pages/form-six.astro new file mode 100644 index 000000000..699fb1842 --- /dev/null +++ b/packages/astro/e2e/fixtures/view-transitions/src/pages/form-six.astro @@ -0,0 +1,11 @@ +--- +import Layout from '../components/Layout.astro'; + +--- +<Layout> + <form method="POST" action="bar"> + <p>This form has an input with `name=action`</p> + <input type="text" name="action" value="foo" /> + <button id="submit">Submit</button> + </form> +</Layout> diff --git a/packages/astro/e2e/view-transitions.test.js b/packages/astro/e2e/view-transitions.test.js index ef76010a5..5e2ea0ace 100644 --- a/packages/astro/e2e/view-transitions.test.js +++ b/packages/astro/e2e/view-transitions.test.js @@ -1168,6 +1168,25 @@ test.describe('View Transitions', () => { ).toEqual(['application/x-www-form-urlencoded']); }); + + test('form POST that includes an input with name action should not override action', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/form-six')); + page.on('request', (request) => { + expect(request.url()).toContain('/bar') + }); + // Submit the form + await page.click('#submit'); + }); + + test('form without method that includes an input with name method should not override default method', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/form-seven')); + page.on('request', (request) => { + expect(request.method()).toBe('GET') + }); + // Submit the form + await page.click('#submit'); + }); + test('Route announcer is invisible on page transition', async ({ page, astro }) => { await page.goto(astro.resolveUrl('/no-directive-one')); |