Skip to content

Commit

Permalink
fix(remix-react): Form's method shouldn't be ignored (#4413)
Browse files Browse the repository at this point in the history
  • Loading branch information
maxschwarzmueller authored Oct 26, 2022
1 parent 4beb7c9 commit 4e8cbd8
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 11 deletions.
1 change: 1 addition & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -444,3 +444,4 @@
- zachdtaylor
- zainfathoni
- zhe
- maxschwarzmueller
45 changes: 35 additions & 10 deletions integration/form-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,13 @@ test.describe("Forms", () => {
return (
<>
<Form method="post">
<button type="submit" formMethod="get">Submit with GET</button>
<button type="submit" formMethod="get">Replace POST with GET</button>
</Form>
<Form method="get">
<button type="submit" formMethod="post">Submit with POST</button>
<button type="submit" formMethod="post">Replace GET with POST</button>
</Form>
<Form method="delete">
<button type="submit" formMethod="post">Replace DELETE with POST</button>
</Form>
<pre>{actionData || loaderData}</pre>
Expand All @@ -339,17 +342,19 @@ test.describe("Forms", () => {
`,

"app/routes/form-method.jsx": js`
import { Form, useActionData } from "@remix-run/react";
import { Form, useActionData, useSearchParams } from "@remix-run/react";
import { json } from "@remix-run/node";
export function action({ request }) {
return json(request.method)
}
export default function() {
let actionData = useActionData();
let [searchParams] = useSearchParams();
let formMethod = searchParams.get('method') || 'post';
return (
<>
<Form method="post">
<Form method={formMethod}>
<button type="submit">Submit</button>
</Form>
<pre>{actionData}</pre>
Expand All @@ -359,17 +364,19 @@ test.describe("Forms", () => {
`,

"app/routes/button-form-method.jsx": js`
import { Form, useActionData } from "@remix-run/react";
import { Form, useActionData, useSearchParams } from "@remix-run/react";
import { json } from "@remix-run/node";
export function action({ request }) {
return json(request.method)
}
export default function() {
let actionData = useActionData();
let [searchParams] = useSearchParams();
let formMethod = searchParams.get('method') || 'post';
return (
<>
<Form>
<Form method={formMethod}>
<button type="submit" formMethod="post">Submit</button>
</Form>
<pre>{actionData}</pre>
Expand Down Expand Up @@ -933,31 +940,49 @@ test.describe("Forms", () => {
test("submits with GET instead of POST", async ({ page }) => {
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/submitter-formmethod");
await app.clickElement("text=Submit with GET");
await app.clickElement("text=Replace POST with GET");
await page.waitForLoadState("load");
expect(await app.getHtml("pre")).toBe("<pre>GET</pre>");
});

test("submits with POST instead of GET", async ({ page }) => {
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/submitter-formmethod");
await app.clickElement("text=Submit with POST");
await app.clickElement("text=Replace GET with POST");
await page.waitForLoadState("load");
expect(await app.getHtml("pre")).toBe("<pre>POST</pre>");
});

test("submits with POST instead of DELETE", async ({ page }) => {
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/submitter-formmethod");
await app.clickElement("text=Replace DELETE with POST");
await page.waitForLoadState("load");
expect(await app.getHtml("pre")).toBe("<pre>POST</pre>");
});
});

test("uses the form `method` attribute", async ({ page }) => {
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/form-method");
await app.goto("/form-method?method=delete");
await app.clickElement("button");
await page.waitForLoadState("load");
expect(await app.getHtml("pre")).toMatch("DELETE");

await app.goto("/form-method?method=post");
await app.clickElement("button");
await page.waitForLoadState("load");
expect(await app.getHtml("pre")).toMatch("POST");
});

test("uses the button `formmethod` attribute", async ({ page }) => {
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/button-form-method");
await app.goto("/button-form-method?method=get");
await app.clickElement("button");
await page.waitForLoadState("load");
expect(await app.getHtml("pre")).toMatch("POST");

await app.goto("/button-form-method?method=delete");
await app.clickElement("button");
await page.waitForLoadState("load");
expect(await app.getHtml("pre")).toMatch("POST");
Expand Down
8 changes: 7 additions & 1 deletion packages/remix-react/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,13 @@ let FormImpl = React.forwardRef<HTMLFormElement, FormImplProps>(
let submitter = (event as unknown as HTMLSubmitEvent)
.nativeEvent.submitter as HTMLFormSubmitter | null;

submit(submitter || event.currentTarget, { replace });
let submitMethod =
(submitter?.formMethod as FormMethod | undefined) || method;

submit(submitter || event.currentTarget, {
method: submitMethod,
replace,
});
}
}
{...props}
Expand Down

0 comments on commit 4e8cbd8

Please sign in to comment.