mirror of
https://github.com/oven-sh/bun
synced 2026-02-15 21:32:05 +00:00
163 lines
4.4 KiB
TypeScript
163 lines
4.4 KiB
TypeScript
import { Subprocess } from "bun";
|
|
import { install_test_helpers } from "bun:internal-for-testing";
|
|
import { afterAll, beforeAll, expect, test } from "bun:test";
|
|
import { copyFileSync } from "fs";
|
|
import { cp, rm } from "fs/promises";
|
|
import { join } from "path";
|
|
import { StringDecoder } from "string_decoder";
|
|
import { bunEnv, bunExe, isCI, isWindows, tmpdirSync, toMatchNodeModulesAt } from "../../../harness";
|
|
const { parseLockfile } = install_test_helpers;
|
|
|
|
expect.extend({ toMatchNodeModulesAt });
|
|
|
|
let root = tmpdirSync();
|
|
|
|
beforeAll(async () => {
|
|
await rm(root, { recursive: true, force: true });
|
|
await cp(join(import.meta.dir, "../"), root, { recursive: true, force: true });
|
|
await rm(join(root, ".next"), { recursive: true, force: true });
|
|
console.log("Copied to:", root);
|
|
});
|
|
|
|
let dev_server: undefined | Subprocess<"ignore", "pipe", "inherit">;
|
|
let baseUrl: string;
|
|
let dev_server_pid: number | undefined = undefined;
|
|
async function getDevServerURL() {
|
|
console.log("Starting Next.js dev server");
|
|
dev_server = Bun.spawn([bunExe(), "--bun", "run", "next", "dev", "--port=0"], {
|
|
cwd: root,
|
|
env: {
|
|
...bunEnv,
|
|
NEXT_TELEMETRY_DISABLED: "1",
|
|
// Print lots of debug logs in next.js:
|
|
// "DEBUG": "*",
|
|
},
|
|
stdio: ["ignore", "pipe", "inherit"],
|
|
});
|
|
dev_server.stdout?.unref?.();
|
|
var hasLoaded = false;
|
|
dev_server_pid = dev_server.pid;
|
|
|
|
const { resolve: loaded, promise, reject } = Promise.withResolvers();
|
|
dev_server.exited
|
|
.catch(e => {
|
|
dev_server_pid = undefined;
|
|
dev_server = undefined;
|
|
|
|
if (hasLoaded) {
|
|
reportError(e);
|
|
} else {
|
|
reject(e);
|
|
}
|
|
})
|
|
.finally(() => {
|
|
console.log("Closing Next.js dev server");
|
|
dev_server = undefined;
|
|
dev_server_pid = undefined;
|
|
});
|
|
|
|
async function readStream() {
|
|
const string_decoder = new StringDecoder("utf-8");
|
|
const stdout = dev_server!.stdout!;
|
|
for await (const chunk of stdout) {
|
|
const str = string_decoder.write(chunk);
|
|
console.error(str);
|
|
|
|
if (!hasLoaded) {
|
|
let match = str.match(/http:\/\/localhost:\d+/);
|
|
if (match) {
|
|
baseUrl = match[0];
|
|
}
|
|
if (str.toLowerCase().includes("ready")) {
|
|
hasLoaded = true;
|
|
loaded();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
readStream()
|
|
.catch(e => reject(e))
|
|
.finally(() => {
|
|
dev_server?.unref?.();
|
|
});
|
|
await promise;
|
|
return baseUrl;
|
|
}
|
|
|
|
beforeAll(async () => {
|
|
copyFileSync(join(root, "src/Counter1.txt"), join(root, "src/Counter.tsx"));
|
|
|
|
const install = Bun.spawnSync([bunExe(), "i"], {
|
|
cwd: root,
|
|
env: { ...bunEnv, BUN_INSTALL_CACHE_DIR: join(root, ".bun-install") },
|
|
stdout: "inherit",
|
|
stderr: "inherit",
|
|
stdin: "inherit",
|
|
});
|
|
if (!install.success) {
|
|
const reason = install.signalCode || `code ${install.exitCode}`;
|
|
throw new Error(`Failed to install dependencies: ${reason}`);
|
|
}
|
|
|
|
try {
|
|
await getDevServerURL();
|
|
} catch (e) {
|
|
console.error("Failed to start dev server :/");
|
|
dev_server?.kill?.();
|
|
dev_server = undefined;
|
|
}
|
|
});
|
|
|
|
afterAll(() => {
|
|
if (dev_server_pid) {
|
|
process?.kill?.(dev_server_pid);
|
|
dev_server_pid = undefined;
|
|
}
|
|
});
|
|
|
|
// Chrome for Testing doesn't support arm64 yet
|
|
//
|
|
// https://github.com/GoogleChromeLabs/chrome-for-testing/issues/1
|
|
// https://github.com/puppeteer/puppeteer/issues/7740
|
|
const puppeteer_unsupported = process.platform === "linux" && process.arch === "arm64";
|
|
|
|
// https://github.com/oven-sh/bun/issues/11255
|
|
test.skipIf(puppeteer_unsupported || (isWindows && isCI))(
|
|
"hot reloading works on the client (+ tailwind hmr)",
|
|
async () => {
|
|
expect(dev_server).not.toBeUndefined();
|
|
expect(baseUrl).not.toBeUndefined();
|
|
|
|
const lockfile = parseLockfile(root);
|
|
expect(lockfile).toMatchNodeModulesAt(root);
|
|
expect(lockfile).toMatchSnapshot();
|
|
|
|
var pid: number, exited;
|
|
let timeout = setTimeout(() => {
|
|
if (timeout && pid) {
|
|
process.kill?.(pid);
|
|
pid = 0;
|
|
|
|
if (dev_server_pid) {
|
|
process?.kill?.(dev_server_pid);
|
|
dev_server_pid = undefined;
|
|
}
|
|
}
|
|
}, 30000).unref();
|
|
|
|
({ exited, pid } = Bun.spawn([bunExe(), "test/dev-server-puppeteer.ts", baseUrl], {
|
|
cwd: root,
|
|
env: bunEnv,
|
|
stdio: ["ignore", "inherit", "inherit"],
|
|
}));
|
|
|
|
expect(await exited).toBe(0);
|
|
pid = 0;
|
|
clearTimeout(timeout);
|
|
// @ts-expect-error
|
|
timeout = undefined;
|
|
},
|
|
100_000,
|
|
);
|