-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add integration tests for request structures #4829
Changes from all commits
ebd39db
cdacee5
4373bb9
1e1b7d8
d8c78ba
a7e9b36
7a3c205
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@remix-run/server-runtime": patch | ||
--- | ||
|
||
- Ensure `loader` `request`'s proxy headers on document `action` submissions | ||
- Fix an issue where loader `request`'s reflected `method: "POST"` on document submissions |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@remix-run/server-runtime": patch | ||
--- | ||
|
||
Fix error boundary tracking for multiple errors bubbling to the same boundary |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
import { test, expect } from "@playwright/test"; | ||
|
||
import { PlaywrightFixture } from "./helpers/playwright-fixture"; | ||
import type { Fixture, AppFixture } from "./helpers/create-fixture"; | ||
import { createAppFixture, createFixture, js } from "./helpers/create-fixture"; | ||
|
||
let fixture: Fixture; | ||
let appFixture: AppFixture; | ||
|
||
test.beforeAll(async () => { | ||
fixture = await createFixture({ | ||
files: { | ||
"app/routes/index.jsx": js` | ||
import { json } from "@remix-run/node"; | ||
import { Form, useLoaderData, useActionData } from "@remix-run/react"; | ||
export async function loader({ request }) { | ||
let text = (await request.text()); | ||
return json({ | ||
method: request.method, | ||
url: request.url, | ||
headers: Object.fromEntries(request.headers.entries()), | ||
text, | ||
}); | ||
} | ||
export async function action({ request }) { | ||
let text = (await request.text()); | ||
return json({ | ||
method: request.method, | ||
url: request.url, | ||
headers: Object.fromEntries(request.headers.entries()), | ||
text, | ||
}); | ||
} | ||
export default function Index() { | ||
let loaderData = useLoaderData(); | ||
let actionData = useActionData(); | ||
return ( | ||
<div> | ||
<button id="set-cookie" onClick={() => { | ||
document.cookie = 'cookie=nomnom; path=/'; | ||
}}> | ||
Set Cookie | ||
</button> | ||
<Form method="get" reloadDocument> | ||
<button type="submit" id="submit-get-ssr" name="type" value="ssr" /> | ||
</Form> | ||
<Form method="get"> | ||
<button type="submit" id="submit-get-csr" name="type" value="csr" /> | ||
</Form> | ||
<Form method="post" reloadDocument> | ||
<button type="submit" id="submit-post-ssr" name="type" value="ssr" /> | ||
</Form> | ||
<Form method="post"> | ||
<button type="submit" id="submit-post-csr" name="type" value="csr" /> | ||
</Form> | ||
<pre id="loader-data">{JSON.stringify(loaderData)}</pre> | ||
{actionData ? | ||
<pre id="action-data">{JSON.stringify(actionData)}</pre> : | ||
null} | ||
</div> | ||
) | ||
} | ||
`, | ||
}, | ||
}); | ||
|
||
appFixture = await createAppFixture(fixture); | ||
}); | ||
|
||
test.afterAll(() => appFixture.close()); | ||
|
||
test("loader request on SSR GET requests", async ({ page }) => { | ||
let app = new PlaywrightFixture(appFixture, page); | ||
await app.goto("/"); | ||
await app.clickElement("#set-cookie"); | ||
|
||
let loaderData = JSON.parse(await page.locator("#loader-data").innerHTML()); | ||
expect(loaderData.method).toEqual("GET"); | ||
expect(loaderData.url).toMatch(/^http:\/\/localhost:\d+\/$/); | ||
expect(loaderData.headers.cookie).toEqual(undefined); | ||
expect(loaderData.text).toEqual(""); | ||
|
||
await app.clickElement("#submit-get-ssr"); | ||
|
||
loaderData = JSON.parse(await page.locator("#loader-data").innerHTML()); | ||
expect(loaderData.method).toEqual("GET"); | ||
expect(loaderData.url).toMatch(/^http:\/\/localhost:\d+\/\?type=ssr$/); | ||
expect(loaderData.headers.cookie).toEqual("cookie=nomnom"); | ||
expect(loaderData.text).toEqual(""); | ||
}); | ||
|
||
test("loader request on CSR GET requests", async ({ page }) => { | ||
let app = new PlaywrightFixture(appFixture, page); | ||
await app.goto("/"); | ||
await app.clickElement("#set-cookie"); | ||
|
||
let loaderData = JSON.parse(await page.locator("#loader-data").innerHTML()); | ||
expect(loaderData.method).toEqual("GET"); | ||
expect(loaderData.url).toMatch(/^http:\/\/localhost:\d+\/$/); | ||
expect(loaderData.headers.cookie).toEqual(undefined); | ||
expect(loaderData.text).toEqual(""); | ||
|
||
await app.clickElement("#submit-get-csr"); | ||
|
||
loaderData = JSON.parse(await page.locator("#loader-data").innerHTML()); | ||
expect(loaderData.method).toEqual("GET"); | ||
expect(loaderData.url).toMatch(/^http:\/\/localhost:\d+\/\?type=csr$/); | ||
expect(loaderData.headers.cookie).toEqual("cookie=nomnom"); | ||
expect(loaderData.text).toEqual(""); | ||
}); | ||
|
||
test("action + loader requests SSR POST requests", async ({ page }) => { | ||
let app = new PlaywrightFixture(appFixture, page); | ||
await app.goto("/"); | ||
await app.clickElement("#set-cookie"); | ||
|
||
let loaderData = JSON.parse(await page.locator("#loader-data").innerHTML()); | ||
expect(loaderData.method).toEqual("GET"); | ||
expect(loaderData.url).toMatch(/^http:\/\/localhost:\d+\/$/); | ||
expect(loaderData.headers.cookie).toEqual(undefined); | ||
expect(loaderData.text).toEqual(""); | ||
|
||
await app.clickElement("#submit-post-ssr"); | ||
|
||
let actionData = JSON.parse(await page.locator("#action-data").innerHTML()); | ||
expect(actionData.method).toEqual("POST"); | ||
expect(actionData.url).toMatch(/^http:\/\/localhost:\d+\/$/); | ||
expect(actionData.headers.cookie).toEqual("cookie=nomnom"); | ||
expect(actionData.text).toEqual("type=ssr"); | ||
|
||
loaderData = JSON.parse(await page.locator("#loader-data").innerHTML()); | ||
expect(loaderData.method).toEqual("GET"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Loaders receive |
||
expect(loaderData.url).toMatch(/^http:\/\/localhost:\d+\/$/); | ||
expect(loaderData.headers.cookie).toEqual("cookie=nomnom"); | ||
expect(loaderData.text).toEqual(""); | ||
}); | ||
|
||
test("action + loader requests on CSR POST requests", async ({ page }) => { | ||
let app = new PlaywrightFixture(appFixture, page); | ||
await app.goto("/"); | ||
await app.clickElement("#set-cookie"); | ||
|
||
let loaderData = JSON.parse(await page.locator("#loader-data").innerHTML()); | ||
expect(loaderData.method).toEqual("GET"); | ||
expect(loaderData.url).toMatch(/^http:\/\/localhost:\d+\/$/); | ||
expect(loaderData.headers.cookie).toEqual(undefined); | ||
expect(loaderData.text).toEqual(""); | ||
|
||
await app.clickElement("#submit-post-csr"); | ||
|
||
let actionData = JSON.parse(await page.locator("#action-data").innerHTML()); | ||
expect(actionData.method).toEqual("POST"); | ||
expect(actionData.url).toMatch(/^http:\/\/localhost:\d+\/$/); | ||
expect(actionData.headers.cookie).toEqual("cookie=nomnom"); | ||
expect(actionData.text).toEqual("type=csr"); | ||
|
||
loaderData = JSON.parse(await page.locator("#loader-data").innerHTML()); | ||
expect(loaderData.method).toEqual("GET"); | ||
expect(loaderData.url).toMatch(/^http:\/\/localhost:\d+\/$/); | ||
expect(loaderData.headers.cookie).toEqual("cookie=nomnom"); | ||
expect(loaderData.text).toEqual(""); | ||
Comment on lines
+157
to
+161
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. During SPA submissions, the loader is called through separate revalidation I think this all makes sense given how Remix is executing loaders differently in MPA/SPA calls, even if it introduces a slight different between them from a DX standpoint. Users shouldn't be branching on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic is implemented in the router here: remix-run/react-router#9721 |
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2174,6 +2174,11 @@ | |
resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.0.5.tgz#d5c65626add4c3c185a89aa5bd38b1e42daec075" | ||
integrity sha512-my0Mycd+jruq/1lQuO5LBB6WTlL/e8DTCYWp44DfMTDcXz8DcTlgF0ISaLsGewt+ctHN+yA8xMq3q/N7uWJPug== | ||
|
||
"@remix-run/[email protected]": | ||
version "1.1.0-pre.0" | ||
resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.1.0-pre.0.tgz#c33db6bd13c6d3847f73f618008ebecdaec237c7" | ||
integrity sha512-FFa1aGAYUZm+PdOO2a7r/4gxLqSIOq1Qav3g6wwRgWj28PNyO7CjdUNER4O4DSKVVyob21mhZHvTe25z+2xnZw== | ||
|
||
"@remix-run/web-blob@^3.0.3", "@remix-run/web-blob@^3.0.4": | ||
version "3.0.4" | ||
resolved "https://registry.npmjs.org/@remix-run/web-blob/-/web-blob-3.0.4.tgz" | ||
|
@@ -10722,20 +10727,20 @@ react-is@^17.0.1: | |
resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" | ||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== | ||
|
||
react-router-dom@6.4.5: | ||
version "6.4.5" | ||
resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.5.tgz#4fdb12efef4f3848c693a76afbeaed1f6ca02047" | ||
integrity sha512-a7HsgikBR0wNfroBHcZUCd9+mLRqZS8R5U1Z1mzLWxFXEkUT3vR1XXmSIVoVpxVX8Bar0nQYYYc9Yipq8dWwAA== | ||
react-router-dom@6.5.0-pre.0: | ||
version "6.5.0-pre.0" | ||
resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.5.0-pre.0.tgz#73dc3861f43b1bc83a854bd5d3d3ab4d7beb1710" | ||
integrity sha512-Hq8lhsAqLH4LDewj6OeDCiEel5RP6El1DsxohxwgOctt+xq4Q6kGiiuVnLA+eHl2wXFCEF8ZSK/kOddGKfLWYA== | ||
dependencies: | ||
"@remix-run/router" "1.0.5" | ||
react-router "6.4.5" | ||
"@remix-run/router" "1.1.0-pre.0" | ||
react-router "6.5.0-pre.0" | ||
|
||
react-router@6.4.5: | ||
version "6.4.5" | ||
resolved "https://registry.npmjs.org/react-router/-/react-router-6.4.5.tgz#73f382af2c8b9a86d74e761a7c5fc3ce7cb0024d" | ||
integrity sha512-1RQJ8bM70YEumHIlNUYc6mFfUDoWa5EgPDenK/fq0bxD8DYpQUi/S6Zoft+9DBrh2xmtg92N5HMAJgGWDhKJ5Q== | ||
react-router@6.5.0-pre.0: | ||
version "6.5.0-pre.0" | ||
resolved "https://registry.npmjs.org/react-router/-/react-router-6.5.0-pre.0.tgz#513b2fe858736443082a33a7a9d2f728b2bd7fe4" | ||
integrity sha512-JqRGYSGzySjcqVMkgCa+1i3zvXiH2IHUfEPac71sJn5ArH5tvR5GmraWUn+D5t7Yzq2dz11is4u2SzHiT0pGdg== | ||
dependencies: | ||
"@remix-run/router" "1.0.5" | ||
"@remix-run/router" "1.1.0-pre.0" | ||
|
||
react@^18.2.0: | ||
version "18.2.0" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parent throws 401, child throws 404