diff --git a/integration/form-test.ts b/integration/form-test.ts index c94560c9d35..c1da0f99f88 100644 --- a/integration/form-test.ts +++ b/integration/form-test.ts @@ -308,9 +308,9 @@ test.describe("Forms", () => { } `, - "app/routes/submitter-formmethod.jsx": js` - import { useActionData, useLoaderData, Form } from "@remix-run/react"; - import { json } from '@remix-run/node' + "app/routes/form-method.jsx": js` + import { Form, useActionData, useLoaderData, useSearchParams } from "@remix-run/react"; + import { json } from "@remix-run/node"; export function action({ request }) { return json(request.method) @@ -320,94 +320,94 @@ test.describe("Forms", () => { return json(request.method) } - export default function Index() { + export default function() { let actionData = useActionData(); let loaderData = useLoaderData(); + let [searchParams] = useSearchParams(); + let formMethod = searchParams.get('method') || 'GET'; + let submitterFormMethod = searchParams.get('submitterFormMethod') || 'GET'; return ( <> -
- - -{actionData || loaderData}> ) } `, - "app/routes/form-method.jsx": js` - import { Form, useActionData, useSearchParams } from "@remix-run/react"; - import { json } from "@remix-run/node"; + "app/routes/submitter.jsx": js` + import { Form } from "@remix-run/react"; - export function action({ request }) { - return json(request.method) - } export default function() { - let actionData = useActionData(); - let [searchParams] = useSearchParams(); - let formMethod = searchParams.get('method') || 'post'; return ( <> - -
{actionData}> ) } `, - "app/routes/button-form-method.jsx": js` - import { Form, useActionData, useSearchParams } from "@remix-run/react"; - import { json } from "@remix-run/node"; + "app/routes/file-upload.jsx": js` + import { Form, useSearchParams } from "@remix-run/react"; - export function action({ request }) { - return json(request.method) - } export default function() { - let actionData = useActionData(); - let [searchParams] = useSearchParams(); - let formMethod = searchParams.get('method') || 'post'; + const [params] = useSearchParams(); return ( - <> - -
{actionData}- > + ) } `, - "app/routes/submitter.jsx": js` - import { useLoaderData, Form } from "@remix-run/react"; + // Generic route for outputting url-encoded form data (either from the request body or search params) + // + // TODO: refactor other tests to use this + "app/routes/outputFormData.jsx": js` + import { useActionData, useSearchParams } from "@remix-run/react"; - export function loader({ request }) { - let url = new URL(request.url); - return url.searchParams.toString() + export async function action({ request }) { + const formData = await request.formData(); + const body = new URLSearchParams(); + for (let [key, value] of formData) { + body.append( + key, + value instanceof File ? await streamToString(value.stream()) : value + ); + } + return body.toString(); } - export default function() { - let data = useLoaderData(); - return ( - - ) + export default function OutputFormData() { + const requestBody = useActionData(); + const searchParams = useSearchParams()[0]; + return ; } `, + "myfile.txt": "stuff", + "app/routes/pathless-layout-parent.jsx": js` import { json } from '@remix-run/server-runtime' import { Form, Outlet, useActionData } from '@remix-run/react' @@ -460,572 +460,607 @@ test.describe("Forms", () => { test.describe("without JavaScript", () => { test.use({ javaScriptEnabled: false }); - test("posts to a loader", async ({ page }) => { - let app = new PlaywrightFixture(appFixture, page); - await app.goto("/get-submission"); - await Promise.all([ - page.waitForNavigation(), - app.clickSubmitButton("/get-submission", { wait: false }), - ]); - await page.waitForSelector(`pre:has-text("${CHEESESTEAK}")`); - }); + + runFormTests(); }); test.describe("with JavaScript", () => { + test.use({ javaScriptEnabled: true }); // explicitly set so we don't have to check against undefined + + runFormTests(); + }); + + function runFormTests() { test("posts to a loader", async ({ page }) => { let app = new PlaywrightFixture(appFixture, page); // this indirectly tests that clicking SVG children in buttons works await app.goto("/get-submission"); - await app.clickSubmitButton("/get-submission"); + await app.clickSubmitButton("/get-submission", { wait: true }); await page.waitForSelector(`pre:has-text("${CHEESESTEAK}")`); }); - }); - - test("posts to a loader with an ", async ({ - page, - }) => { - let app = new PlaywrightFixture(appFixture, page); - await app.goto("/get-submission"); - await app.clickElement(`#${FORM_WITH_ACTION_INPUT} button`); - await page.waitForLoadState("load"); - await page.waitForSelector(`pre:has-text("${EAT}")`); - }); - - test("posts to a loader with button data with click", async ({ page }) => { - let app = new PlaywrightFixture(appFixture, page); - await app.goto("/get-submission"); - await Promise.all([ - page.waitForNavigation(), - app.clickElement("#buttonWithValue"), - ]); - await page.waitForSelector(`pre:has-text("${LAKSA}")`); - }); - - test("posts to a loader with button data with keyboard", async ({ page }) => { - let app = new PlaywrightFixture(appFixture, page); - await app.goto("/get-submission"); - await page.focus(`#${KEYBOARD_INPUT}`); - await page.keyboard.press("Enter"); - await page.waitForLoadState("networkidle"); - await page.waitForSelector(`pre:has-text("${LAKSA}")`); - }); - - test("posts with the correct checkbox data", async ({ page }) => { - let app = new PlaywrightFixture(appFixture, page); - await app.goto("/get-submission"); - await app.clickElement(`#${CHECKBOX_BUTTON}`); - await page.waitForSelector(`pre:has-text("${LAKSA}")`); - await page.waitForSelector(`pre:has-text("${CHEESESTEAK}")`); - }); - - test("posts button data from outside the form", async ({ page }) => { - let app = new PlaywrightFixture(appFixture, page); - await app.goto("/get-submission"); - await app.clickElement(`#${ORPHAN_BUTTON}`); - await page.waitForSelector(`pre:has-text("${SQUID_INK_HOTDOG}")`); - }); - - test("when clicking on a submit button as a descendant of an element that stops propagation on click, still passes the clicked submit button's `name` and `value` props to the request payload", async ({ - page, - }) => { - let app = new PlaywrightFixture(appFixture, page); - await app.goto("/stop-propagation"); - await app.clickSubmitButton("/stop-propagation"); - expect(await app.getHtml()).toMatch('{"action":"add"}'); - }); - - test.describe("