124 lines
4.4 KiB
TypeScript
124 lines
4.4 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { mkdirSync } from "fs";
|
|
import { bunEnv, bunExe, tempDir, tmpdirSync } from "harness";
|
|
import { join } from "path";
|
|
|
|
// --install=<val> Configure auto-install behavior. One of "auto" (default, auto-installs when no node_modules), "fallback" (missing packages only), "force" (always).
|
|
// -i Auto-install dependencies during execution. Equivalent to --install=fallback.
|
|
|
|
describe("basic autoinstall", () => {
|
|
for (const install of ["", "-i", "--install=auto", "--install=fallback", "--install=force"]) {
|
|
for (const has_node_modules of [true, false]) {
|
|
let should_install = false;
|
|
if (has_node_modules) {
|
|
if (install === "" || install === "--install=auto") {
|
|
should_install = false;
|
|
} else {
|
|
should_install = true;
|
|
}
|
|
} else {
|
|
should_install = true;
|
|
}
|
|
|
|
test(`${install || "<no flag>"} ${has_node_modules ? "with" : "without"} node_modules ${should_install ? "should" : "should not"} autoinstall`, async () => {
|
|
const dir = tmpdirSync();
|
|
mkdirSync(dir, { recursive: true });
|
|
await Bun.write(join(dir, "index.js"), "import isEven from 'is-even'; console.log(isEven(2));");
|
|
const env = bunEnv;
|
|
env.BUN_INSTALL = install;
|
|
if (has_node_modules) {
|
|
mkdirSync(join(dir, "node_modules/abc"), { recursive: true });
|
|
}
|
|
const { stdout, stderr } = Bun.spawnSync({
|
|
cmd: [bunExe(), ...(install === "" ? [] : [install]), join(dir, "index.js")],
|
|
cwd: dir,
|
|
env,
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
});
|
|
|
|
if (should_install) {
|
|
expect(stderr?.toString("utf8")).not.toContain("error: Cannot find package 'is-even'");
|
|
expect(stdout?.toString("utf8")).toBe("true\n");
|
|
} else {
|
|
expect(stderr?.toString("utf8")).toContain("error: Cannot find package 'is-even'");
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// In auto-install mode the project's own package.json is the lockfile's root
|
|
// package (resolution tag `root`, not `npm`). With a name and an exact version
|
|
// present, resolving any missing bare specifier used to read that resolution
|
|
// through the npm union accessor: "assertion failed: self.tag == Tag::Npm".
|
|
test("auto-install in a project whose package.json has a name and version", async () => {
|
|
const requests: string[] = [];
|
|
using registry = Bun.serve({
|
|
port: 0,
|
|
fetch(req) {
|
|
requests.push(new URL(req.url).pathname);
|
|
return new Response("not found", { status: 404 });
|
|
},
|
|
});
|
|
|
|
using dir = tempDir("autoinstall-root-name-version", {
|
|
"package.json": JSON.stringify({ name: "myapp", version: "1.0.0" }),
|
|
"index.js": `import "pkg-that-does-not-exist-anywhere";\n`,
|
|
"bunfig.toml": `[install]\nregistry = "http://127.0.0.1:${registry.port}/"\n`,
|
|
});
|
|
|
|
await using proc = Bun.spawn({
|
|
cmd: [bunExe(), "index.js"],
|
|
cwd: String(dir),
|
|
env: { ...bunEnv, BUN_INSTALL_CACHE_DIR: join(String(dir), ".bun-cache") },
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
});
|
|
const [, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
|
|
|
// The resolver must get as far as asking the (local) registry for the
|
|
// missing package, then report it as missing instead of dying while
|
|
// re-parsing the project's own package.json.
|
|
expect(requests).toContain("/pkg-that-does-not-exist-anywhere");
|
|
expect(stderr).toContain("Cannot find package 'pkg-that-does-not-exist-anywhere'");
|
|
expect(exitCode).toBe(1);
|
|
});
|
|
|
|
test("--install=fallback to install missing packages", async () => {
|
|
const dir = tmpdirSync();
|
|
mkdirSync(dir, { recursive: true });
|
|
await Promise.all([
|
|
Bun.write(
|
|
join(dir, "index.js"),
|
|
"import isEven from 'is-even'; import isOdd from 'is-odd'; console.log(isEven(2), isOdd(2));",
|
|
),
|
|
Bun.write(
|
|
join(dir, "package.json"),
|
|
JSON.stringify({
|
|
name: "test",
|
|
dependencies: {
|
|
"is-odd": "1.0.0",
|
|
},
|
|
}),
|
|
),
|
|
]);
|
|
|
|
Bun.spawnSync({
|
|
cmd: [bunExe(), "install"],
|
|
cwd: dir,
|
|
env: bunEnv,
|
|
});
|
|
|
|
const { stdout, stderr } = Bun.spawnSync({
|
|
cmd: [bunExe(), "--install=fallback", join(dir, "index.js")],
|
|
cwd: dir,
|
|
env: bunEnv,
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
});
|
|
|
|
expect(stderr?.toString("utf8")).not.toContain("error: Cannot find package 'is-odd'");
|
|
expect(stdout?.toString("utf8")).toBe("true false\n");
|
|
});
|