This commit is contained in:
2026-03-23 07:42:00 +01:00
parent 567fb4f746
commit 4b8b610e32
43 changed files with 635 additions and 169 deletions
+65 -23
View File
@@ -1,21 +1,60 @@
import { describe, expect, test, beforeAll, afterAll } from "bun:test";
import startServer from "../../../src/functions/server/start-server";
import bunextInit from "../../../src/functions/bunext-init";
import rewritePagesModule from "../../../src/utils/rewrite-pages-module";
import pagePathTransform from "../../../src/utils/page-path-transform";
import path from "path";
import fs from "fs";
// Fixture lives under test/ so the framework's directory guard allows it
const fixtureDir = path.resolve(__dirname, "../../../test/e2e-fixture");
const fixturePagesDir = path.join(fixtureDir, "src", "pages");
const fixtureIndexPage = path.join(fixturePagesDir, "index.tsx");
// The rewritten page path (inside .bunext/pages, stripped of server logic)
const rewrittenIndexPage = pagePathTransform({ page_path: fixtureIndexPage });
let originalCwd = process.cwd();
let originalPort: string | undefined;
describe("E2E Integration", () => {
let server: any;
beforeAll(async () => {
// Change to the fixture directory to simulate actual user repo
const fixtureDir = path.resolve(__dirname, "../__fixtures__/app");
originalPort = process.env.PORT;
// Use port 0 so Bun.serve picks a random available port
process.env.PORT = "0";
process.chdir(fixtureDir);
// Mock grabAppPort to assign dynamically to avoid port conflicts
global.CONFIG = { development: true };
global.HMR_CONTROLLERS = [];
global.BUNDLER_REBUILDS = 0;
global.PAGE_FILES = [];
// Set up router pointing at the fixture's pages directory
global.ROUTER = new Bun.FileSystemRouter({
style: "nextjs",
dir: fixturePagesDir,
});
// Rewrite the fixture page (strips server logic) into .bunext/pages
// so that grab-page-react-component-string can resolve the import
await rewritePagesModule({ page_file_path: fixtureIndexPage });
// Pre-populate the bundler context map so grab-page-component can
// look up the compiled path. The `path` value only needs to be
// present for the guard check; SSR does not require the file to exist.
global.BUNDLER_CTX_MAP = {
[fixtureIndexPage]: {
path: ".bunext/public/pages/index.js",
hash: "index",
type: "text/javascript",
entrypoint: fixtureIndexPage,
local_path: fixtureIndexPage,
url_path: "/",
file_name: "index",
},
};
});
afterAll(async () => {
@@ -23,32 +62,35 @@ describe("E2E Integration", () => {
server.stop(true);
}
process.chdir(originalCwd);
// Ensure to remove the dummy generated .bunext folder
const dotBunext = path.resolve(__dirname, "../__fixtures__/app/.bunext");
// Restore PORT env variable
if (originalPort !== undefined) {
process.env.PORT = originalPort;
} else {
delete process.env.PORT;
}
// Remove the rewritten page created during setup
const rewrittenDir = path.dirname(rewrittenIndexPage);
if (fs.existsSync(rewrittenDir)) {
fs.rmSync(rewrittenDir, { recursive: true, force: true });
}
// Remove any generated .bunext artifacts from the fixture
const dotBunext = path.join(fixtureDir, ".bunext");
if (fs.existsSync(dotBunext)) {
fs.rmSync(dotBunext, { recursive: true, force: true });
}
const pubBunext = path.resolve(__dirname, "../__fixtures__/app/public/__bunext");
if (fs.existsSync(pubBunext)) {
fs.rmSync(pubBunext, { recursive: true, force: true });
}
});
test("boots up the server and correctly routes to index.tsx page", async () => {
// Mock to randomize port
// Note: Bun test runs modules in isolation but startServer imports grab-app-port
// If we can't easily mock we can set PORT env
process.env.PORT = "0"; // Let Bun.serve pick port
await bunextInit();
server = await startServer();
expect(server).toBeDefined();
// Fetch the index page
expect(server.port).toBeGreaterThan(0);
const response = await fetch(`http://localhost:${server.port}/`);
expect(response.status).toBe(200);
const html = await response.text();
expect(html).toContain("Hello E2E");
});
@@ -57,7 +99,7 @@ describe("E2E Integration", () => {
const response = await fetch(`http://localhost:${server.port}/unknown-foo-bar123`);
expect(response.status).toBe(404);
const text = await response.text();
// Assume default 404 preset component is rendered
// Default 404 component is rendered
expect(text).toContain("404");
});
});
@@ -10,9 +10,9 @@ describe("handle-hmr", () => {
}
} as any;
global.HMR_CONTROLLERS = [];
global.BUNDLER_CTX_MAP = [
{ local_path: "/test-file" } as any
];
global.BUNDLER_CTX_MAP = {
"/test-file": { local_path: "/test-file" } as any,
};
});
afterEach(() => {
@@ -40,11 +40,11 @@ describe("handle-routes", () => {
mock.restore();
});
test("returns 401 for unknown route", async () => {
test("returns 404 for unknown route", async () => {
const req = new Request("http://localhost/api/unknown");
const res = await handleRoutes({ req });
expect(res.status).toBe(401);
expect(res.status).toBe(404);
const json = await res.json();
expect(json.success).toBe(false);
expect(json.msg).toContain("not found");
+4 -4
View File
@@ -14,17 +14,17 @@ describe("grabDirNames", () => {
expect(dirs.PUBLIC_DIR).toBe(path.join(cwd, "public"));
});
it("nests HYDRATION_DST_DIR under public/__bunext/pages", () => {
it("nests HYDRATION_DST_DIR under .bunext/public/pages", () => {
const dirs = grabDirNames();
expect(dirs.HYDRATION_DST_DIR).toBe(
path.join(dirs.PUBLIC_DIR, "__bunext", "pages"),
path.join(dirs.BUNX_CWD_DIR, "public", "pages"),
);
});
it("nests BUNEXT_CACHE_DIR under public/__bunext/cache", () => {
it("nests BUNEXT_CACHE_DIR under .bunext/public/cache", () => {
const dirs = grabDirNames();
expect(dirs.BUNEXT_CACHE_DIR).toBe(
path.join(dirs.PUBLIC_DIR, "__bunext", "cache"),
path.join(dirs.BUNX_CWD_DIR, "public", "cache"),
);
});