mirror of
https://github.com/cloudflare/vinext.git
synced 2026-09-14 19:04:59 +08:00
123 lines
4.9 KiB
TypeScript
123 lines
4.9 KiB
TypeScript
import path from "node:path";
|
|
import os from "node:os";
|
|
import fs from "node:fs/promises";
|
|
import { describe, expect, it } from "vite-plus/test";
|
|
import { appRouter, invalidateAppRouteCache } from "../packages/vinext/src/routing/app-router.js";
|
|
import {
|
|
apiRouter,
|
|
invalidateRouteCache,
|
|
pagesRouter,
|
|
} from "../packages/vinext/src/routing/pages-router.js";
|
|
|
|
async function makeTempDir(prefix: string): Promise<string> {
|
|
return fs.mkdtemp(path.join(os.tmpdir(), prefix));
|
|
}
|
|
|
|
describe("pageExtensions route discovery", () => {
|
|
it("discovers app/page.mdx routes when pageExtensions includes mdx", async () => {
|
|
// Ported from Next.js MDX e2e setup:
|
|
// test/e2e/app-dir/mdx/next.config.ts
|
|
// https://github.com/vercel/next.js/blob/canary/test/e2e/app-dir/mdx/next.config.ts
|
|
const tmpRoot = await makeTempDir("vinext-app-ext-mdx-");
|
|
const appDir = path.join(tmpRoot, "app");
|
|
try {
|
|
await fs.mkdir(path.join(appDir, "about"), { recursive: true });
|
|
await fs.writeFile(
|
|
path.join(appDir, "layout.tsx"),
|
|
"export default function Layout({ children }: { children: React.ReactNode }) { return <html><body>{children}</body></html>; }",
|
|
);
|
|
await fs.writeFile(
|
|
path.join(appDir, "page.tsx"),
|
|
"export default function Page() { return <div>home</div>; }",
|
|
);
|
|
await fs.writeFile(path.join(appDir, "about", "page.mdx"), "# About");
|
|
|
|
invalidateAppRouteCache();
|
|
const routes = await appRouter(appDir, ["tsx", "ts", "jsx", "js", "mdx"]);
|
|
const patterns = routes.filter((r) => r.pagePath).map((r) => r.pattern);
|
|
expect(patterns).toContain("/about");
|
|
} finally {
|
|
await fs.rm(tmpRoot, { recursive: true, force: true });
|
|
invalidateAppRouteCache();
|
|
}
|
|
});
|
|
|
|
it("does not discover app/page.mdx routes when mdx is not configured", async () => {
|
|
const tmpRoot = await makeTempDir("vinext-app-ext-no-mdx-");
|
|
const appDir = path.join(tmpRoot, "app");
|
|
try {
|
|
await fs.mkdir(path.join(appDir, "about"), { recursive: true });
|
|
await fs.writeFile(
|
|
path.join(appDir, "layout.tsx"),
|
|
"export default function Layout({ children }: { children: React.ReactNode }) { return <html><body>{children}</body></html>; }",
|
|
);
|
|
await fs.writeFile(
|
|
path.join(appDir, "page.tsx"),
|
|
"export default function Page() { return <div>home</div>; }",
|
|
);
|
|
await fs.writeFile(path.join(appDir, "about", "page.mdx"), "# About");
|
|
|
|
invalidateAppRouteCache();
|
|
const routes = await appRouter(appDir, ["tsx", "ts", "jsx", "js"]);
|
|
const patterns = routes.filter((r) => r.pagePath).map((r) => r.pattern);
|
|
expect(patterns).not.toContain("/about");
|
|
} finally {
|
|
await fs.rm(tmpRoot, { recursive: true, force: true });
|
|
invalidateAppRouteCache();
|
|
}
|
|
});
|
|
|
|
it("serves _ prefixed files in api routes", async () => {
|
|
// Next.js does NOT ignore _-prefixed files in pages/api/ — the private-
|
|
// folder underscore rule is App Router only. Pages Router serves them.
|
|
// Ported from Next.js: test/e2e/app-dir/underscore-ignore-app-paths
|
|
const tmpRoot = await makeTempDir("vinext-api-underscore-");
|
|
const pagesDir = path.join(tmpRoot, "pages");
|
|
try {
|
|
await fs.mkdir(path.join(pagesDir, "api"), { recursive: true });
|
|
await fs.writeFile(
|
|
path.join(pagesDir, "api", "hello.ts"),
|
|
"export async function GET() { return Response.json({}); }",
|
|
);
|
|
await fs.writeFile(path.join(pagesDir, "api", "_helpers.ts"), "// internal helper");
|
|
|
|
invalidateRouteCache(pagesDir);
|
|
const apiRoutes = await apiRouter(pagesDir);
|
|
const patterns = apiRoutes.map((r) => r.pattern);
|
|
|
|
expect(patterns).toContain("/api/hello");
|
|
expect(patterns).toContain("/api/_helpers");
|
|
} finally {
|
|
await fs.rm(tmpRoot, { recursive: true, force: true });
|
|
invalidateRouteCache(pagesDir);
|
|
}
|
|
});
|
|
|
|
it("discovers pages and api files using configured pageExtensions", async () => {
|
|
const tmpRoot = await makeTempDir("vinext-pages-ext-mdx-");
|
|
const pagesDir = path.join(tmpRoot, "pages");
|
|
try {
|
|
await fs.mkdir(path.join(pagesDir, "api"), { recursive: true });
|
|
await fs.writeFile(
|
|
path.join(pagesDir, "index.tsx"),
|
|
"export default function Page() { return <div>home</div>; }",
|
|
);
|
|
await fs.writeFile(path.join(pagesDir, "about.mdx"), "# About");
|
|
await fs.writeFile(
|
|
path.join(pagesDir, "api", "hello.mdx"),
|
|
"export default function handler() {}",
|
|
);
|
|
|
|
invalidateRouteCache(pagesDir);
|
|
const pageRoutes = await pagesRouter(pagesDir, ["tsx", "ts", "jsx", "js", "mdx"]);
|
|
const apiRoutes = await apiRouter(pagesDir, ["tsx", "ts", "jsx", "js", "mdx"]);
|
|
|
|
expect(pageRoutes.map((r) => r.pattern)).toContain("/about");
|
|
expect(apiRoutes.map((r) => r.pattern)).toContain("/api/hello");
|
|
} finally {
|
|
await fs.rm(tmpRoot, { recursive: true, force: true });
|
|
invalidateRouteCache(pagesDir);
|
|
}
|
|
});
|
|
});
|