Files
bun.sh/test/cli/install/overrides.test.ts
Dylan Conway aad4d800ff add "configVersion" to bun.lock(b) (#24236)
### What does this PR do?

Adds `"configVersion"` to bun.lock(b). The version will be used to keep
default settings the same if they would be breaking across bun versions.

fixes ENG-21389
fixes ENG-21388
### How did you verify your code works?
TODO:
- [ ] new project
- [ ] existing project without configVersion
- [ ] existing project with configVersion
- [ ] same as above but with bun.lockb
- [ ] configVersion@0 defaults to hoisted linker
- [ ] new projects use isolated linker

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2025-11-03 22:20:07 -08:00

250 lines
6.1 KiB
TypeScript

import { write } from "bun";
import { beforeAll, expect, setDefaultTimeout, test } from "bun:test";
import { readFileSync, writeFileSync } from "fs";
import { bunEnv, bunExe, tmpdirSync } from "harness";
import { join } from "path";
beforeAll(() => {
setDefaultTimeout(1000 * 60 * 5);
});
function install(cwd: string, args: string[]) {
const exec = Bun.spawnSync({
cmd: [bunExe(), ...args, "--linker=hoisted"],
cwd,
stdout: "inherit",
stdin: "inherit",
stderr: "inherit",
env: bunEnv,
});
if (exec.exitCode !== 0) {
throw new Error(`bun install exited with code ${exec.exitCode}`);
}
return exec;
}
function installExpectFail(cwd: string, args: string[]) {
const exec = Bun.spawnSync({
cmd: [bunExe(), ...args],
cwd,
stdout: "inherit",
stdin: "inherit",
stderr: "inherit",
env: bunEnv,
});
if (exec.exitCode === 0) {
throw new Error(`bun install exited with code ${exec.exitCode}, (expected failure)`);
}
return exec;
}
function versionOf(cwd: string, path: string) {
const data = readFileSync(join(cwd, path));
const json = JSON.parse(data.toString());
return json.version;
}
function ensureLockfileDoesntChangeOnBunI(cwd: string) {
install(cwd, ["install"]);
const lockb1 = readFileSync(join(cwd, "bun.lock"));
install(cwd, ["install", "--frozen-lockfile"]);
install(cwd, ["install", "--force"]);
const lockb2 = readFileSync(join(cwd, "bun.lock"));
expect(lockb1.toString("hex")).toEqual(lockb2.toString("hex"));
}
test("overrides affect your own packages", async () => {
const tmp = tmpdirSync();
writeFileSync(
join(tmp, "package.json"),
JSON.stringify({
dependencies: {},
overrides: {
lodash: "4.0.0",
},
}),
);
install(tmp, ["install", "lodash"]);
expect(versionOf(tmp, "node_modules/lodash/package.json")).toBe("4.0.0");
ensureLockfileDoesntChangeOnBunI(tmp);
});
test("overrides affects all dependencies", async () => {
const tmp = tmpdirSync();
writeFileSync(
join(tmp, "package.json"),
JSON.stringify({
dependencies: {},
overrides: {
bytes: "1.0.0",
},
}),
);
install(tmp, ["install", "express@4.18.2"]);
expect(versionOf(tmp, "node_modules/bytes/package.json")).toBe("1.0.0");
ensureLockfileDoesntChangeOnBunI(tmp);
});
test("overrides being set later affects all dependencies", async () => {
const tmp = tmpdirSync();
writeFileSync(
join(tmp, "package.json"),
JSON.stringify({
dependencies: {},
}),
);
install(tmp, ["install", "express@4.18.2"]);
expect(versionOf(tmp, "node_modules/bytes/package.json")).not.toBe("1.0.0");
ensureLockfileDoesntChangeOnBunI(tmp);
writeFileSync(
join(tmp, "package.json"),
JSON.stringify({
...JSON.parse(readFileSync(join(tmp, "package.json")).toString()),
overrides: {
bytes: "1.0.0",
},
}),
);
install(tmp, ["install"]);
expect(versionOf(tmp, "node_modules/bytes/package.json")).toBe("1.0.0");
ensureLockfileDoesntChangeOnBunI(tmp);
});
test("overrides to npm specifier", async () => {
const tmp = tmpdirSync();
writeFileSync(
join(tmp, "package.json"),
JSON.stringify({
dependencies: {},
overrides: {
bytes: "npm:lodash@4.0.0",
},
}),
);
install(tmp, ["install", "express@4.18.2"]);
const bytes = JSON.parse(readFileSync(join(tmp, "node_modules/bytes/package.json"), "utf-8"));
expect(bytes.name).toBe("lodash");
expect(bytes.version).toBe("4.0.0");
ensureLockfileDoesntChangeOnBunI(tmp);
});
test("changing overrides makes the lockfile changed, prevent frozen install", async () => {
const tmp = tmpdirSync();
writeFileSync(
join(tmp, "package.json"),
JSON.stringify({
dependencies: {},
overrides: {
bytes: "1.0.0",
},
}),
);
install(tmp, ["install", "express@4.18.2"]);
writeFileSync(
join(tmp, "package.json"),
JSON.stringify({
...JSON.parse(readFileSync(join(tmp, "package.json")).toString()),
overrides: {
bytes: "1.0.1",
},
}),
);
installExpectFail(tmp, ["install", "--frozen-lockfile"]);
});
test("overrides reset when removed", async () => {
const tmp = tmpdirSync();
writeFileSync(
join(tmp, "package.json"),
JSON.stringify({
overrides: {
bytes: "1.0.0",
},
}),
);
install(tmp, ["install", "express@4.18.2"]);
expect(versionOf(tmp, "node_modules/bytes/package.json")).toBe("1.0.0");
writeFileSync(
join(tmp, "package.json"),
JSON.stringify({
...JSON.parse(readFileSync(join(tmp, "package.json")).toString()),
overrides: undefined,
}),
);
install(tmp, ["install"]);
expect(versionOf(tmp, "node_modules/bytes/package.json")).not.toBe("1.0.0");
ensureLockfileDoesntChangeOnBunI(tmp);
});
test("overrides do not apply to workspaces", async () => {
const tmp = tmpdirSync();
await Promise.all([
write(
join(tmp, "package.json"),
JSON.stringify({ name: "monorepo-root", workspaces: ["packages/*"], overrides: { "pkg1": "file:pkg2" } }),
),
write(
join(tmp, "packages", "pkg1", "package.json"),
JSON.stringify({
name: "pkg1",
version: "1.1.1",
}),
),
write(
join(tmp, "pkg2", "package.json"),
JSON.stringify({
name: "pkg2",
version: "2.2.2",
}),
),
]);
let { exited, stderr } = Bun.spawn({
cmd: [bunExe(), "install"],
cwd: tmp,
env: bunEnv,
stderr: "pipe",
stdout: "inherit",
});
expect(await exited).toBe(0);
expect(await stderr.text()).toContain("Saved lockfile");
// --frozen-lockfile works
({ exited, stderr } = Bun.spawn({
cmd: [bunExe(), "install", "--frozen-lockfile"],
cwd: tmp,
env: bunEnv,
stderr: "pipe",
stdout: "inherit",
}));
expect(await exited).toBe(0);
expect(await stderr.text()).not.toContain("Frozen lockfile");
// lockfile is not changed
({ exited, stderr } = Bun.spawn({
cmd: [bunExe(), "install"],
cwd: tmp,
env: bunEnv,
stderr: "pipe",
stdout: "inherit",
}));
expect(await exited).toBe(0);
expect(await stderr.text()).not.toContain("Saved lockfile");
});