mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
434 lines
13 KiB
TypeScript
434 lines
13 KiB
TypeScript
import { file, write } from "bun";
|
|
import { afterAll, beforeAll, describe, expect, setDefaultTimeout, test } from "bun:test";
|
|
import { existsSync, readlinkSync } from "fs";
|
|
import { VerdaccioRegistry, bunEnv, readdirSorted, runBunInstall } from "harness";
|
|
import { join } from "path";
|
|
|
|
const registry = new VerdaccioRegistry();
|
|
|
|
beforeAll(async () => {
|
|
setDefaultTimeout(10 * 60 * 1000);
|
|
await registry.start();
|
|
});
|
|
|
|
afterAll(() => {
|
|
registry.stop();
|
|
});
|
|
|
|
describe("basic", () => {
|
|
test("single dependency", async () => {
|
|
const { packageJson, packageDir } = await registry.createTestDir();
|
|
|
|
await write(
|
|
packageJson,
|
|
JSON.stringify({
|
|
name: "test-pkg-1",
|
|
workspaces: {
|
|
nodeLinker: "isolated",
|
|
},
|
|
dependencies: {
|
|
"no-deps": "1.0.0",
|
|
},
|
|
}),
|
|
);
|
|
|
|
await runBunInstall(bunEnv, packageDir);
|
|
|
|
expect(readlinkSync(join(packageDir, "node_modules", "no-deps"))).toBe(
|
|
join(".bun", "no-deps@1.0.0", "node_modules", "no-deps"),
|
|
);
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "node_modules", "no-deps"))).toBe(
|
|
join("..", "no-deps@1.0.0", "node_modules", "no-deps"),
|
|
);
|
|
expect(
|
|
await file(
|
|
join(packageDir, "node_modules", ".bun", "no-deps@1.0.0", "node_modules", "no-deps", "package.json"),
|
|
).json(),
|
|
).toEqual({
|
|
name: "no-deps",
|
|
version: "1.0.0",
|
|
});
|
|
});
|
|
|
|
test("scope package", async () => {
|
|
const { packageJson, packageDir } = await registry.createTestDir();
|
|
|
|
await write(
|
|
packageJson,
|
|
JSON.stringify({
|
|
name: "test-pkg-2",
|
|
workspaces: {
|
|
nodeLinker: "isolated",
|
|
},
|
|
dependencies: {
|
|
"@types/is-number": "1.0.0",
|
|
},
|
|
}),
|
|
);
|
|
|
|
await runBunInstall(bunEnv, packageDir);
|
|
|
|
expect(readlinkSync(join(packageDir, "node_modules", "@types", "is-number"))).toBe(
|
|
join("..", ".bun", "@types+is-number@1.0.0", "node_modules", "@types", "is-number"),
|
|
);
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "node_modules", "@types", "is-number"))).toBe(
|
|
join("..", "..", "@types+is-number@1.0.0", "node_modules", "@types", "is-number"),
|
|
);
|
|
expect(
|
|
await file(
|
|
join(
|
|
packageDir,
|
|
"node_modules",
|
|
".bun",
|
|
"@types+is-number@1.0.0",
|
|
"node_modules",
|
|
"@types",
|
|
"is-number",
|
|
"package.json",
|
|
),
|
|
).json(),
|
|
).toEqual({
|
|
name: "@types/is-number",
|
|
version: "1.0.0",
|
|
});
|
|
});
|
|
|
|
test("transitive dependencies", async () => {
|
|
const { packageJson, packageDir } = await registry.createTestDir();
|
|
|
|
await write(
|
|
packageJson,
|
|
JSON.stringify({
|
|
name: "test-pkg-3",
|
|
workspaces: {
|
|
nodeLinker: "isolated",
|
|
},
|
|
dependencies: {
|
|
"two-range-deps": "1.0.0",
|
|
},
|
|
}),
|
|
);
|
|
|
|
await runBunInstall(bunEnv, packageDir);
|
|
|
|
expect(await readdirSorted(join(packageDir, "node_modules"))).toEqual([".bun", "two-range-deps"]);
|
|
expect(readlinkSync(join(packageDir, "node_modules", "two-range-deps"))).toBe(
|
|
join(".bun", "two-range-deps@1.0.0", "node_modules", "two-range-deps"),
|
|
);
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "node_modules", "two-range-deps"))).toBe(
|
|
join("..", "two-range-deps@1.0.0", "node_modules", "two-range-deps"),
|
|
);
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "node_modules", "no-deps"))).toBe(
|
|
join("..", "no-deps@1.1.0", "node_modules", "no-deps"),
|
|
);
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "node_modules", "@types", "is-number"))).toBe(
|
|
join("..", "..", "@types+is-number@2.0.0", "node_modules", "@types", "is-number"),
|
|
);
|
|
expect(
|
|
await file(
|
|
join(
|
|
packageDir,
|
|
"node_modules",
|
|
".bun",
|
|
"two-range-deps@1.0.0",
|
|
"node_modules",
|
|
"two-range-deps",
|
|
"package.json",
|
|
),
|
|
).json(),
|
|
).toEqual({
|
|
name: "two-range-deps",
|
|
version: "1.0.0",
|
|
dependencies: {
|
|
"no-deps": "^1.0.0",
|
|
"@types/is-number": ">=1.0.0",
|
|
},
|
|
});
|
|
expect(
|
|
await readdirSorted(join(packageDir, "node_modules", ".bun", "two-range-deps@1.0.0", "node_modules")),
|
|
).toEqual(["@types", "no-deps", "two-range-deps"]);
|
|
expect(
|
|
readlinkSync(
|
|
join(packageDir, "node_modules", ".bun", "two-range-deps@1.0.0", "node_modules", "@types", "is-number"),
|
|
),
|
|
).toBe(join("..", "..", "..", "@types+is-number@2.0.0", "node_modules", "@types", "is-number"));
|
|
expect(
|
|
readlinkSync(join(packageDir, "node_modules", ".bun", "two-range-deps@1.0.0", "node_modules", "no-deps")),
|
|
).toBe(join("..", "..", "no-deps@1.1.0", "node_modules", "no-deps"));
|
|
expect(
|
|
await file(
|
|
join(packageDir, "node_modules", ".bun", "no-deps@1.1.0", "node_modules", "no-deps", "package.json"),
|
|
).json(),
|
|
).toEqual({
|
|
name: "no-deps",
|
|
version: "1.1.0",
|
|
});
|
|
expect(
|
|
await file(
|
|
join(
|
|
packageDir,
|
|
"node_modules",
|
|
".bun",
|
|
"@types+is-number@2.0.0",
|
|
"node_modules",
|
|
"@types",
|
|
"is-number",
|
|
"package.json",
|
|
),
|
|
).json(),
|
|
).toEqual({
|
|
name: "@types/is-number",
|
|
version: "2.0.0",
|
|
});
|
|
});
|
|
});
|
|
|
|
test("handles cyclic dependencies", async () => {
|
|
const { packageJson, packageDir } = await registry.createTestDir();
|
|
|
|
await write(
|
|
packageJson,
|
|
JSON.stringify({
|
|
name: "test-pkg-cyclic",
|
|
workspaces: {
|
|
nodeLinker: "isolated",
|
|
},
|
|
dependencies: {
|
|
"a-dep-b": "1.0.0",
|
|
},
|
|
}),
|
|
);
|
|
|
|
await runBunInstall(bunEnv, packageDir);
|
|
|
|
expect(readlinkSync(join(packageDir, "node_modules", "a-dep-b"))).toBe(
|
|
join(".bun", "a-dep-b@1.0.0", "node_modules", "a-dep-b"),
|
|
);
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "node_modules", "a-dep-b"))).toBe(
|
|
join("..", "a-dep-b@1.0.0", "node_modules", "a-dep-b"),
|
|
);
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "node_modules", "b-dep-a"))).toBe(
|
|
join("..", "b-dep-a@1.0.0", "node_modules", "b-dep-a"),
|
|
);
|
|
expect(
|
|
await file(
|
|
join(packageDir, "node_modules", ".bun", "a-dep-b@1.0.0", "node_modules", "a-dep-b", "package.json"),
|
|
).json(),
|
|
).toEqual({
|
|
name: "a-dep-b",
|
|
version: "1.0.0",
|
|
dependencies: {
|
|
"b-dep-a": "1.0.0",
|
|
},
|
|
});
|
|
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "a-dep-b@1.0.0", "node_modules", "b-dep-a"))).toBe(
|
|
join("..", "..", "b-dep-a@1.0.0", "node_modules", "b-dep-a"),
|
|
);
|
|
expect(
|
|
await file(
|
|
join(packageDir, "node_modules", ".bun", "a-dep-b@1.0.0", "node_modules", "b-dep-a", "package.json"),
|
|
).json(),
|
|
).toEqual({
|
|
name: "b-dep-a",
|
|
version: "1.0.0",
|
|
dependencies: {
|
|
"a-dep-b": "1.0.0",
|
|
},
|
|
});
|
|
});
|
|
|
|
test("can install folder dependencies", async () => {
|
|
const { packageJson, packageDir } = await registry.createTestDir();
|
|
|
|
await write(
|
|
packageJson,
|
|
JSON.stringify({
|
|
name: "test-pkg-folder-deps",
|
|
workspaces: {
|
|
nodeLinker: "isolated",
|
|
},
|
|
dependencies: {
|
|
"folder-dep": "file:./pkg-1",
|
|
},
|
|
}),
|
|
);
|
|
|
|
await write(join(packageDir, "pkg-1", "package.json"), JSON.stringify({ name: "folder-dep", version: "1.0.0" }));
|
|
|
|
await runBunInstall(bunEnv, packageDir);
|
|
|
|
expect(readlinkSync(join(packageDir, "node_modules", "folder-dep"))).toBe(
|
|
join(".bun", "folder-dep@file+pkg-1", "node_modules", "folder-dep"),
|
|
);
|
|
expect(
|
|
await file(
|
|
join(packageDir, "node_modules", ".bun", "folder-dep@file+pkg-1", "node_modules", "folder-dep", "package.json"),
|
|
).json(),
|
|
).toEqual({
|
|
name: "folder-dep",
|
|
version: "1.0.0",
|
|
});
|
|
|
|
await write(join(packageDir, "pkg-1", "index.js"), "module.exports = 'hello from pkg-1';");
|
|
|
|
await runBunInstall(bunEnv, packageDir, { savesLockfile: false });
|
|
expect(readlinkSync(join(packageDir, "node_modules", "folder-dep"))).toBe(
|
|
join(".bun", "folder-dep@file+pkg-1", "node_modules", "folder-dep"),
|
|
);
|
|
expect(
|
|
await file(
|
|
join(packageDir, "node_modules", ".bun", "folder-dep@file+pkg-1", "node_modules", "folder-dep", "index.js"),
|
|
).text(),
|
|
).toBe("module.exports = 'hello from pkg-1';");
|
|
});
|
|
|
|
describe("isolated workspaces", () => {
|
|
test("basic", async () => {
|
|
const { packageJson, packageDir } = await registry.createTestDir();
|
|
|
|
await Promise.all([
|
|
write(
|
|
packageJson,
|
|
JSON.stringify({
|
|
name: "test-pkg-workspaces",
|
|
workspaces: {
|
|
nodeLinker: "isolated",
|
|
packages: ["pkg-1", "pkg-2"],
|
|
},
|
|
dependencies: {
|
|
"no-deps": "1.0.0",
|
|
},
|
|
}),
|
|
),
|
|
write(
|
|
join(packageDir, "pkg-1", "package.json"),
|
|
JSON.stringify({
|
|
name: "pkg-1",
|
|
version: "1.0.0",
|
|
dependencies: {
|
|
"a-dep": "1.0.1",
|
|
"pkg-2": "workspace:",
|
|
"@types/is-number": "1.0.0",
|
|
},
|
|
}),
|
|
),
|
|
write(
|
|
join(packageDir, "pkg-2", "package.json"),
|
|
JSON.stringify({
|
|
name: "pkg-2",
|
|
version: "1.0.0",
|
|
dependencies: {
|
|
"b-dep-a": "1.0.0",
|
|
},
|
|
}),
|
|
),
|
|
]);
|
|
|
|
await runBunInstall(bunEnv, packageDir);
|
|
|
|
expect(existsSync(join(packageDir, "node_modules", "pkg-1"))).toBeFalse();
|
|
expect(readlinkSync(join(packageDir, "pkg-1", "node_modules", "pkg-2"))).toBe(join("..", "..", "pkg-2"));
|
|
expect(await readdirSorted(join(packageDir, "node_modules"))).toEqual([".bun", "no-deps"]);
|
|
expect(readlinkSync(join(packageDir, "node_modules", "no-deps"))).toBe(
|
|
join(".bun", "no-deps@1.0.0", "node_modules", "no-deps"),
|
|
);
|
|
|
|
expect(await readdirSorted(join(packageDir, "pkg-1", "node_modules"))).toEqual(["@types", "a-dep", "pkg-2"]);
|
|
expect(await readdirSorted(join(packageDir, "pkg-2", "node_modules"))).toEqual(["b-dep-a"]);
|
|
expect(await readdirSorted(join(packageDir, "node_modules", ".bun"))).toEqual([
|
|
"@types+is-number@1.0.0",
|
|
"a-dep-b@1.0.0",
|
|
"a-dep@1.0.1",
|
|
"b-dep-a@1.0.0",
|
|
"no-deps@1.0.0",
|
|
"node_modules",
|
|
]);
|
|
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "node_modules", "no-deps"))).toBe(
|
|
join("..", "no-deps@1.0.0", "node_modules", "no-deps"),
|
|
);
|
|
expect(
|
|
await file(
|
|
join(packageDir, "node_modules", ".bun", "no-deps@1.0.0", "node_modules", "no-deps", "package.json"),
|
|
).json(),
|
|
).toEqual({
|
|
name: "no-deps",
|
|
version: "1.0.0",
|
|
});
|
|
});
|
|
});
|
|
|
|
test("many transitive dependencies", async () => {
|
|
const { packageJson, packageDir } = await registry.createTestDir();
|
|
|
|
await write(
|
|
packageJson,
|
|
JSON.stringify({
|
|
name: "test-pkg-many-transitive-deps",
|
|
workspaces: {
|
|
nodeLinker: "isolated",
|
|
},
|
|
dependencies: {
|
|
"alias-loop-1": "1.0.0",
|
|
"alias-loop-2": "1.0.0",
|
|
"1-peer-dep-a": "1.0.0",
|
|
"basic-1": "1.0.0",
|
|
"is-number": "1.0.0",
|
|
},
|
|
}),
|
|
);
|
|
|
|
await runBunInstall(bunEnv, packageDir);
|
|
|
|
expect(await readdirSorted(join(packageDir, "node_modules"))).toEqual([
|
|
".bun",
|
|
"1-peer-dep-a",
|
|
"alias-loop-1",
|
|
"alias-loop-2",
|
|
"basic-1",
|
|
"is-number",
|
|
]);
|
|
expect(readlinkSync(join(packageDir, "node_modules", "alias-loop-1"))).toBe(
|
|
join(".bun", "alias-loop-1@1.0.0", "node_modules", "alias-loop-1"),
|
|
);
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "node_modules", "alias-loop-1"))).toBe(
|
|
join("..", "alias-loop-1@1.0.0", "node_modules", "alias-loop-1"),
|
|
);
|
|
expect(readlinkSync(join(packageDir, "node_modules", ".bun", "node_modules", "alias-loop-2"))).toBe(
|
|
join("..", "alias-loop-2@1.0.0", "node_modules", "alias-loop-2"),
|
|
);
|
|
expect(
|
|
await file(
|
|
join(packageDir, "node_modules", ".bun", "alias-loop-1@1.0.0", "node_modules", "alias-loop-1", "package.json"),
|
|
).json(),
|
|
).toEqual({
|
|
name: "alias-loop-1",
|
|
version: "1.0.0",
|
|
dependencies: {
|
|
"alias1": "npm:alias-loop-2@*",
|
|
},
|
|
});
|
|
expect(
|
|
await file(
|
|
join(packageDir, "node_modules", ".bun", "alias-loop-2@1.0.0", "node_modules", "alias-loop-2", "package.json"),
|
|
).json(),
|
|
).toEqual({
|
|
name: "alias-loop-2",
|
|
version: "1.0.0",
|
|
dependencies: {
|
|
"alias2": "npm:alias-loop-1@*",
|
|
},
|
|
});
|
|
// expect(await readdirSorted(join(packageDir, "node_modules", ".bun", "alias-loop-1@1.0.0", "node_modules"))).toEqual([
|
|
// "alias1",
|
|
// "alias-loop-1",
|
|
// ]);
|
|
// expect(readlinkSync(join(packageDir, "node_modules", ".bun", "alias-loop-1@1.0.0", "node_modules", "alias1"))).toBe(
|
|
// join("..", "..", "alias-loop-2@1.0.0", "node_modules", "alias-loop-2"),
|
|
// );
|
|
// expect(readlinkSync(join(packageDir, "node_modules", ".bun", "alias-loop-2@1.0.0", "node_modules", "alias2"))).toBe(
|
|
// join("..", "..", "alias-loop-1@1.0.0", "node_modules", "alias-loop-1"),
|
|
// );
|
|
});
|