From fbe4ed206a5dfd36bcf5c924a23f02c06ff8b293 Mon Sep 17 00:00:00 2001 From: Dylan Conway <35280289+dylan-conway@users.noreply.github.com> Date: Thu, 11 Jan 2024 16:57:24 -0800 Subject: [PATCH] More bun install hoisting tests (#8112) * hoisting tests * more comments on hoistDependency * fix test --- src/install/lockfile.zig | 14 +- .../registry/bun-install-registry.test.ts | 196 ++++++++++++++++++ 2 files changed, 203 insertions(+), 7 deletions(-) diff --git a/src/install/lockfile.zig b/src/install/lockfile.zig index d745ec86c9..9335458e7c 100644 --- a/src/install/lockfile.zig +++ b/src/install/lockfile.zig @@ -526,9 +526,9 @@ pub const Tree = struct { } // This function does one of three things: - // - de-duplicate (skip) the package - // - move the package to the top directory - // - leave the package at the same (relative) directory + // 1 (return hoisted) - de-duplicate (skip) the package + // 2 (return id) - move the package to the top directory + // 3 (return dependency_loop) - leave the package at the same (relative) directory fn hoistDependency( this: *Tree, comptime as_defined: bool, @@ -556,9 +556,9 @@ pub const Tree = struct { return error.DependencyLoop; } // ignore versioning conflicts caused by peer dependencies - return dependency_loop; + return dependency_loop; // 3 } - return hoisted; + return hoisted; // 1 } if (this.parent < error_id) { @@ -571,10 +571,10 @@ pub const Tree = struct { trees, builder, ) catch unreachable; - if (!as_defined or id != dependency_loop) return id; + if (!as_defined or id != dependency_loop) return id; // 1 or 2 } - return this.id; + return this.id; // 2 } }; diff --git a/test/cli/install/registry/bun-install-registry.test.ts b/test/cli/install/registry/bun-install-registry.test.ts index c7c575dd0d..49aaae269c 100644 --- a/test/cli/install/registry/bun-install-registry.test.ts +++ b/test/cli/install/registry/bun-install-registry.test.ts @@ -930,6 +930,202 @@ describe("hoisting", async () => { }); } }); + + test("hoisting/using incorrect peer dep after install", async () => { + await writeFile( + join(packageDir, "package.json"), + JSON.stringify({ + name: "foo", + dependencies: { + "peer-deps-fixed": "1.0.0", + "no-deps": "1.0.0", + }, + }), + ); + + var { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "install"], + cwd: packageDir, + stdout: "pipe", + stdin: "pipe", + stderr: "pipe", + env, + }); + + var err = await new Response(stderr).text(); + var out = await new Response(stdout).text(); + expect(err).toContain("Saved lockfile"); + expect(err).not.toContain("not found"); + expect(err).not.toContain("error:"); + expect(err).not.toContain("incorrect peer dependency"); + + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + "", + " + no-deps@1.0.0", + " + peer-deps-fixed@1.0.0", + "", + " 2 packages installed", + ]); + + expect(await exited).toBe(0); + expect(await file(join(packageDir, "node_modules", "no-deps", "package.json")).json()).toEqual({ + name: "no-deps", + version: "1.0.0", + } as any); + expect(await file(join(packageDir, "node_modules", "peer-deps-fixed", "package.json")).json()).toEqual({ + name: "peer-deps-fixed", + version: "1.0.0", + peerDependencies: { + "no-deps": "^1.0.0", + }, + } as any); + expect(await exists(join(packageDir, "node_modules", "peer-deps-fixed", "node_modules"))).toBeFalse(); + + await writeFile( + join(packageDir, "package.json"), + JSON.stringify({ + name: "foo", + dependencies: { + "peer-deps-fixed": "1.0.0", + "no-deps": "2.0.0", + }, + }), + ); + + ({ stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "install"], + cwd: packageDir, + stdout: "pipe", + stdin: "pipe", + stderr: "pipe", + env, + })); + + err = await new Response(stderr).text(); + out = await new Response(stdout).text(); + expect(err).toContain("Saved lockfile"); + expect(err).not.toContain("not found"); + expect(err).not.toContain("error:"); + + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + "", + " + no-deps@2.0.0", + "", + " 1 package installed", + ]); + + expect(await exited).toBe(0); + expect(await file(join(packageDir, "node_modules", "no-deps", "package.json")).json()).toEqual({ + name: "no-deps", + version: "2.0.0", + } as any); + expect(await file(join(packageDir, "node_modules", "peer-deps-fixed", "package.json")).json()).toEqual({ + name: "peer-deps-fixed", + version: "1.0.0", + peerDependencies: { + "no-deps": "^1.0.0", + }, + } as any); + expect(await exists(join(packageDir, "node_modules", "peer-deps-fixed", "node_modules"))).toBeFalse(); + }); + + test("hoisting/using incorrect peer dep on initial install", async () => { + await writeFile( + join(packageDir, "package.json"), + JSON.stringify({ + name: "foo", + dependencies: { + "peer-deps-fixed": "1.0.0", + "no-deps": "2.0.0", + }, + }), + ); + + var { stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "install"], + cwd: packageDir, + stdout: "pipe", + stdin: "pipe", + stderr: "pipe", + env, + }); + + var err = await new Response(stderr).text(); + var out = await new Response(stdout).text(); + expect(err).toContain("Saved lockfile"); + expect(err).not.toContain("not found"); + expect(err).not.toContain("error:"); + expect(err).toContain("incorrect peer dependency"); + + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + "", + " + no-deps@2.0.0", + " + peer-deps-fixed@1.0.0", + "", + " 2 packages installed", + ]); + + expect(await exited).toBe(0); + expect(await file(join(packageDir, "node_modules", "no-deps", "package.json")).json()).toEqual({ + name: "no-deps", + version: "2.0.0", + } as any); + expect(await file(join(packageDir, "node_modules", "peer-deps-fixed", "package.json")).json()).toEqual({ + name: "peer-deps-fixed", + version: "1.0.0", + peerDependencies: { + "no-deps": "^1.0.0", + }, + } as any); + expect(await exists(join(packageDir, "node_modules", "peer-deps-fixed", "node_modules"))).toBeFalse(); + + await writeFile( + join(packageDir, "package.json"), + JSON.stringify({ + name: "foo", + dependencies: { + "peer-deps-fixed": "1.0.0", + "no-deps": "1.0.0", + }, + }), + ); + + ({ stdout, stderr, exited } = spawn({ + cmd: [bunExe(), "install"], + cwd: packageDir, + stdout: "pipe", + stdin: "pipe", + stderr: "pipe", + env, + })); + + err = await new Response(stderr).text(); + out = await new Response(stdout).text(); + expect(err).toContain("Saved lockfile"); + expect(err).not.toContain("not found"); + expect(err).not.toContain("error:"); + + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + "", + " + no-deps@1.0.0", + "", + " 1 package installed", + ]); + + expect(await exited).toBe(0); + expect(await file(join(packageDir, "node_modules", "no-deps", "package.json")).json()).toEqual({ + name: "no-deps", + version: "1.0.0", + } as any); + expect(await file(join(packageDir, "node_modules", "peer-deps-fixed", "package.json")).json()).toEqual({ + name: "peer-deps-fixed", + version: "1.0.0", + peerDependencies: { + "no-deps": "^1.0.0", + }, + } as any); + expect(await exists(join(packageDir, "node_modules", "peer-deps-fixed", "node_modules"))).toBeFalse(); + }); }); describe("workspaces", async () => {