Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 45 additions & 120 deletions integration/bug-report-test.ts
Original file line number Diff line number Diff line change
@@ -1,127 +1,52 @@
import { test, expect } from "@playwright/test";

import { PlaywrightFixture } from "./helpers/playwright-fixture.js";
import type { Fixture, AppFixture } from "./helpers/create-fixture.js";
import {
createAppFixture,
createFixture,
js,
} from "./helpers/create-fixture.js";

let fixture: Fixture;
let appFixture: AppFixture;

////////////////////////////////////////////////////////////////////////////////
// 👋 Hola! I'm here to help you write a great bug report pull request.
//
// You don't need to fix the bug, this is just to report one.
//
// The pull request you are submitting is supposed to fail when created, to let
// the team see the erroneous behavior, and understand what's going wrong.
//
// If you happen to have a fix as well, it will have to be applied in a subsequent
// commit to this pull request, and your now-succeeding test will have to be moved
// to the appropriate file.
//
// First, make sure to install dependencies and build React Router. From the root of
// the project, run this:
//
// ```
// pnpm install && pnpm build
// ```
//
// If you have never installed playwright on your system before, you may also need
// to install a browser engine:
//
// ```
// pnpm exec playwright install chromium
// ```
//
// Now try running this test:
//
// ```
// pnpm test:integration bug-report --project chromium
// ```
//
// You can add `--watch` to the end to have it re-run on file changes:
//
// ```
// pnpm test:integration bug-report --project chromium --watch
// ```
////////////////////////////////////////////////////////////////////////////////

test.beforeEach(async ({ context }) => {
await context.route(/\.data$/, async (route) => {
await new Promise((resolve) => setTimeout(resolve, 50));
route.continue();
});
});

test.beforeAll(async () => {
fixture = await createFixture({
////////////////////////////////////////////////////////////////////////////
// 💿 Next, add files to this object, just like files in a real app,
// `createFixture` will make an app and run your tests against it.
////////////////////////////////////////////////////////////////////////////
files: {
"app/routes/_index.tsx": js`
import { useLoaderData, Link } from "react-router";

export function loader() {
return "pizza";
}

export default function Index() {
let data = useLoaderData();
return (
<div>
{data}
<Link to="/burgers">Other Route</Link>
</div>
)
}
import { expect, test } from "@playwright/test";
import getPort from "get-port";

import { build, createProject, dev } from "./helpers/vite.js";

test("splitRouteModules enforce accepts JSX exports in Vite dev", async ({
page,
}) => {
let port = await getPort();
let cwd = await createProject(
{
"react-router.config.ts": `
import type { Config } from "@react-router/dev/config";

export default {
splitRouteModules: "enforce",
} satisfies Config;
`,
"vite.config.ts": `
import { reactRouter } from "@react-router/dev/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

export default defineConfig({
plugins: [reactRouter(), react()],
server: { port: ${port}, strictPort: true },
});
`,
"app/routes/_index.tsx": `
export function HydrateFallback() {
return <p>Loading...</p>;
}

"app/routes/burgers.tsx": js`
export default function Index() {
return <div>cheeseburger</div>;
return <h1>Ready</h1>;
}
`,
},
});

// This creates an interactive app using playwright.
appFixture = await createAppFixture(fixture);
});

test.afterAll(() => {
appFixture.close();
"rsc-vite-framework",
);

let buildResult = build({ cwd });
expect(buildResult.status).toBe(0);

let stop = await dev({ cwd, port });
try {
await page.goto(`http://localhost:${port}`);
await expect(page.getByRole("heading", { name: "Ready" })).toBeVisible();
} finally {
stop();
}
});

////////////////////////////////////////////////////////////////////////////////
// 💿 Almost done, now write your failing test case(s) down here Make sure to
// add a good description for what you expect React Router to do 👇🏽
////////////////////////////////////////////////////////////////////////////////

test("[description of what you expect it to do]", async ({ page }) => {
let app = new PlaywrightFixture(appFixture, page);
// You can test any request your app might get using `fixture`.
let response = await fixture.requestDocument("/");
expect(await response.text()).toMatch("pizza");

// If you need to test interactivity use the `app`
await app.goto("/");
await app.clickLink("/burgers");
await page.waitForSelector("text=cheeseburger");

// If you're not sure what's going on, you can "poke" the app, it'll
// automatically open up in your browser for 20 seconds, so be quick!
// await app.poke(20);

// Go check out the other tests to see what else you can do.
});

////////////////////////////////////////////////////////////////////////////////
// 💿 Finally, push your changes to your fork of React Router
// and open a pull request!
////////////////////////////////////////////////////////////////////////////////
30 changes: 0 additions & 30 deletions packages/react-router-dev/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1079,16 +1079,11 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
ctx,
);

let enforceSplitRouteModules =
ctx.reactRouterConfig.splitRouteModules === "enforce";

for (let [key, route] of Object.entries(ctx.reactRouterConfig.routes)) {
let routeFile = route.file;
let sourceExports = routeManifestExports[key];
let hasClientAction = sourceExports.includes("clientAction");
let hasClientLoader = sourceExports.includes("clientLoader");
let hasClientMiddleware = sourceExports.includes("clientMiddleware");
let hasHydrateFallback = sourceExports.includes("HydrateFallback");
let routeModulePath = combineURLs(
ctx.publicPath,
`${resolveFileUrl(
Expand All @@ -1097,31 +1092,6 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
)}`,
);

if (enforceSplitRouteModules) {
let { hasRouteChunkByExportName } = await detectRouteChunksIfEnabled(
cache,
ctx,
routeFile,
{ routeFile, viteChildCompiler },
);

validateRouteChunks({
ctx,
id: route.file,
valid: {
clientAction:
!hasClientAction || hasRouteChunkByExportName.clientAction,
clientLoader:
!hasClientLoader || hasRouteChunkByExportName.clientLoader,
clientMiddleware:
!hasClientMiddleware ||
hasRouteChunkByExportName.clientMiddleware,
HydrateFallback:
!hasHydrateFallback || hasRouteChunkByExportName.HydrateFallback,
},
});
}

routes[key] = {
id: route.id,
parentId: route.parentId,
Expand Down