Repository: remix-run/react-router
File: integration/single-fetch-test.ts (TypeScript)

Code before:
    let appFixture = await createAppFixture(fixture);
    let app = new PlaywrightFixture(appFixture, page);
    await app.goto("/base/");
    await app.clickLink("/base/data");
    await page.waitForSelector("#target");
    expect(await app.getHtml("#target")).toContain("Target");
  });

  test("processes redirects returned outside of react router", async ({
    page,
  }) => {
    let port = await getPort();
    let cwd = await createProject({
      "vite.config.js": await viteConfig.basic({ port }),
      "server.mjs": EXPRESS_SERVER({
        port,
        customLogic: js`
          app.use(async (req, res, next) => {
            if (req.url === "/page.data") {
              let { dataRedirect } = await import("react-router");
              let response = dataRedirect("/target");
              res.statusMessage = response.statusText;
              res.status(response.status);
              for (let [key, value] of response.headers.entries()) {
                res.append(key, value);
              }
              res.end();
            } else {
              next();
            }
          });
        `,
      }),
      "app/routes/_index.tsx": js`
        import { Link } from "react-router";
        export default function Component() {
          return <Link to="/page">Go to /page</Link>
        }
      `,
      "app/routes/page.tsx": js`
        export function loader() {
          return null
        }
        export default function Component() {
          return <p>Should not see me</p>
        }
      `,
      "app/routes/target.tsx": js`
        export default function Component() {
          return <h1 id="target">Target</h1>
        }

Review comment (suggestion):
We don't export our internal logic for converting a fetch `Response` to an express `res` so for now it's assumed that the application has to do that adapter logic on their own.  I think this is ok since status/headers are all that matter?  There isn't a body on these responses

Code after:
        `,
        "react-router.config.ts": reactRouterConfig({
          basename: "/base/",
        }),
        ...files,
      },
      useReactRouterServe: true,
    });

    let appFixture = await createAppFixture(fixture);

    let requests: string[] = [];
    page.on("request", (req) => {
      let url = new URL(req.url());
      if (url.pathname.endsWith(".data")) {
        requests.push(url.pathname + url.search);
      }
    });

    let app = new PlaywrightFixture(appFixture, page);
    await app.goto("/base/");
    await app.clickLink("/base/data");
    await expect(page.getByText("Data Route")).toBeVisible();
    await app.clickLink("/base/");
    await expect(page.getByText("Index")).toBeVisible();

    expect(requests).toEqual(["/base/data.data", "/base/_root.data"]);
  });

  test("processes redirects when a basename is present", async ({ page }) => {
    let fixture = await createFixture({
      files: {
        ...files,
        "react-router.config.ts": reactRouterConfig({
          basename: "/base",
        }),
        "app/routes/data.tsx": js`
          import { redirect } from 'react-router';
          export function loader() {
            throw redirect('/target');
          }
          export default function Component() {
            return null
          }
        `,
        "app/routes/target.tsx": js`
          export default function Component() {
            return <h1 id="target">Target</h1>
          }
        `,
      },