From 25083a425270e06d591fc71b35c993bcb4e733f4 Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Wed, 2 Oct 2024 02:24:37 -0700 Subject: [PATCH] pm: print command name to stdout (#14266) --- packages/bun-types/bun.d.ts | 6 + src/bun.js/bindings/BunObject.cpp | 6 + src/bun.js/bindings/headers-handwritten.h | 1 + src/bun.js/node/types.zig | 1 + src/cli.zig | 4 +- src/cli/outdated_command.zig | 2 +- src/cli/pack_command.zig | 2 +- src/cli/test_command.zig | 2 +- src/install/install.zig | 10 +- .../__snapshots__/bun-install.test.ts.snap | 15 +- test/cli/install/bun-add.test.ts | 52 ++- test/cli/install/bun-install-retry.test.ts | 1 + test/cli/install/bun-install.test.ts | 329 ++++++++++--- test/cli/install/bun-link.test.ts | 48 +- test/cli/install/bun-remove.test.ts | 24 +- test/cli/install/bun-update.test.ts | 6 + test/cli/install/bun-workspaces.test.ts | 19 +- .../registry/bun-install-registry.test.ts | 433 ++++++++++++++---- test/cli/run/env.test.ts | 26 +- .../resolve/import-custom-condition.test.ts | 4 +- test/js/bun/shell/bunshell-default.test.ts | 2 + test/js/bun/test/test-test.test.ts | 24 +- test/js/node/stream/node-stream.test.js | 2 +- test/regression/issue/08964/08964.test.ts | 2 +- 24 files changed, 781 insertions(+), 240 deletions(-) diff --git a/packages/bun-types/bun.d.ts b/packages/bun-types/bun.d.ts index fccf64a4479a25..4b92de08e579d9 100644 --- a/packages/bun-types/bun.d.ts +++ b/packages/bun-types/bun.d.ts @@ -5260,6 +5260,12 @@ declare module "bun" { */ const version: string; + /** + * The current version of Bun with the shortened commit sha of the build + * @example "v1.1.30 (d09df1af)" + */ + const version_with_sha: string; + /** * The git sha at the time the currently-running version of Bun was compiled * @example diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index 7be836dc1404aa..54bbc9be0d2184 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -259,6 +259,11 @@ static JSValue constructBunRevision(VM& vm, JSObject*) return JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__version_sha))); } +static JSValue constructBunVersionWithSha(VM& vm, JSObject*) +{ + return JSC::jsString(vm, makeString(ASCIILiteral::fromLiteralUnsafe(Bun__version_with_sha))); +} + static JSValue constructIsMainThread(VM&, JSObject* object) { return jsBoolean(jsCast(object->globalObject())->scriptExecutionContext()->isMainThread()); @@ -608,6 +613,7 @@ JSC_DEFINE_HOST_FUNCTION(functionFileURLToPath, (JSC::JSGlobalObject * globalObj nanoseconds functionBunNanoseconds DontDelete|Function 0 openInEditor BunObject_callback_openInEditor DontDelete|Function 1 origin BunObject_getter_wrap_origin DontDelete|PropertyCallback + version_with_sha constructBunVersionWithSha ReadOnly|DontDelete|PropertyCallback password constructPasswordObject DontDelete|PropertyCallback pathToFileURL functionPathToFileURL DontDelete|Function 1 peek constructBunPeekObject DontDelete|PropertyCallback diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index 6e6b60a95db606..f21fc27bf9834e 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -345,6 +345,7 @@ extern "C" bool Bun__fetchBuiltinModule( // Used in process.version extern "C" const char* Bun__version; +extern "C" const char* Bun__version_with_sha; // Used in process.versions extern "C" const char* Bun__versions_boringssl; diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 9489c2ed4667d4..36785b05960a7d 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -2116,6 +2116,7 @@ pub const Process = struct { } pub export const Bun__version: [*:0]const u8 = "v" ++ bun.Global.package_json_version; + pub export const Bun__version_with_sha: [*:0]const u8 = "v" ++ bun.Global.package_json_version_with_sha; pub export const Bun__versions_boringssl: [*:0]const u8 = bun.Global.versions.boringssl; pub export const Bun__versions_libarchive: [*:0]const u8 = bun.Global.versions.libarchive; pub export const Bun__versions_mimalloc: [*:0]const u8 = bun.Global.versions.mimalloc; diff --git a/src/cli.zig b/src/cli.zig index 199ccf85e72614..6e30b2b95c4f27 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -1014,8 +1014,8 @@ pub const Arguments = struct { if (cmd == .BuildCommand) { if (opts.entry_points.len == 0) { - Output.prettyErrorln("bun build v" ++ Global.package_json_version_with_sha ++ "", .{}); - Output.prettyError("error: Missing entrypoints. What would you like to bundle?\n\n", .{}); + Output.prettyln("bun build v" ++ Global.package_json_version_with_sha ++ "", .{}); + Output.pretty("error: Missing entrypoints. What would you like to bundle?\n\n", .{}); Output.flush(); Output.pretty("Usage:\n $ bun build \\ [...\\] [...flags] \n", .{}); Output.pretty("\nTo see full documentation:\n $ bun build --help\n", .{}); diff --git a/src/cli/outdated_command.zig b/src/cli/outdated_command.zig index a786e3afbb6ded..4c8745823e2fa7 100644 --- a/src/cli/outdated_command.zig +++ b/src/cli/outdated_command.zig @@ -21,7 +21,7 @@ const Table = bun.fmt.Table; pub const OutdatedCommand = struct { pub fn exec(ctx: Command.Context) !void { - Output.prettyErrorln("bun outdated v" ++ Global.package_json_version_with_sha ++ "", .{}); + Output.prettyln("bun outdated v" ++ Global.package_json_version_with_sha ++ "", .{}); Output.flush(); const cli = try PackageManager.CommandLineArguments.parse(ctx.allocator, .outdated); diff --git a/src/cli/pack_command.zig b/src/cli/pack_command.zig index ee41c8ddaac5a0..c36df036b697f1 100644 --- a/src/cli/pack_command.zig +++ b/src/cli/pack_command.zig @@ -109,7 +109,7 @@ pub const PackCommand = struct { }; pub fn execWithManager(ctx: Command.Context, manager: *PackageManager) !void { - Output.prettyErrorln("bun pack v" ++ Global.package_json_version_with_sha ++ "", .{}); + Output.prettyln("bun pack v" ++ Global.package_json_version_with_sha ++ "", .{}); Output.flush(); var lockfile: Lockfile = undefined; diff --git a/src/cli/test_command.zig b/src/cli/test_command.zig index a6ccf6f4ad81fa..51de17c555e345 100644 --- a/src/cli/test_command.zig +++ b/src/cli/test_command.zig @@ -729,7 +729,7 @@ pub const TestCommand = struct { Output.is_github_action = Output.isGithubAction(); // print the version so you know its doing stuff if it takes a sec - Output.prettyErrorln("bun test v" ++ Global.package_json_version_with_sha ++ "", .{}); + Output.prettyln("bun test v" ++ Global.package_json_version_with_sha ++ "", .{}); Output.flush(); var env_loader = brk: { diff --git a/src/install/install.zig b/src/install/install.zig index 72efc9d97bdfa9..dd27ed84b0261b 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -8838,7 +8838,7 @@ pub const PackageManager = struct { defer ctx.allocator.free(original_cwd); if (manager.options.shouldPrintCommandName()) { - Output.prettyErrorln("bun link v" ++ Global.package_json_version_with_sha ++ "\n", .{}); + Output.prettyln("bun link v" ++ Global.package_json_version_with_sha ++ "\n", .{}); Output.flush(); } @@ -9021,7 +9021,7 @@ pub const PackageManager = struct { defer ctx.allocator.free(original_cwd); if (manager.options.shouldPrintCommandName()) { - Output.prettyErrorln("bun unlink v" ++ Global.package_json_version_with_sha ++ "\n", .{}); + Output.prettyln("bun unlink v" ++ Global.package_json_version_with_sha ++ "\n", .{}); Output.flush(); } @@ -9985,7 +9985,7 @@ pub const PackageManager = struct { defer ctx.allocator.free(original_cwd); if (manager.options.shouldPrintCommandName()) { - Output.prettyErrorln("bun {s} v" ++ Global.package_json_version_with_sha ++ "\n", .{@tagName(subcommand)}); + Output.prettyln("bun {s} v" ++ Global.package_json_version_with_sha ++ "\n", .{@tagName(subcommand)}); Output.flush(); } @@ -11724,7 +11724,7 @@ pub const PackageManager = struct { // switch to `bun add ` if (manager.options.positionals.len > 1) { if (manager.options.shouldPrintCommandName()) { - Output.prettyErrorln("bun add v" ++ Global.package_json_version_with_sha ++ "\n", .{}); + Output.prettyln("bun add v" ++ Global.package_json_version_with_sha ++ "\n", .{}); Output.flush(); } manager.subcommand = .add; @@ -11734,7 +11734,7 @@ pub const PackageManager = struct { } if (manager.options.shouldPrintCommandName()) { - Output.prettyErrorln("bun install v" ++ Global.package_json_version_with_sha ++ "\n", .{}); + Output.prettyln("bun install v" ++ Global.package_json_version_with_sha ++ "\n", .{}); Output.flush(); } diff --git a/test/cli/install/__snapshots__/bun-install.test.ts.snap b/test/cli/install/__snapshots__/bun-install.test.ts.snap index 90a7a79e081013..bd375763acd18a 100644 --- a/test/cli/install/__snapshots__/bun-install.test.ts.snap +++ b/test/cli/install/__snapshots__/bun-install.test.ts.snap @@ -1,8 +1,7 @@ // Bun Snapshot v1, https://goo.gl/fbAQLP exports[`should report error on invalid format for package.json 1`] = ` -"bun install -1 | foo +"1 | foo ^ error: Unexpected foo at [dir]/package.json:1:1 @@ -11,8 +10,7 @@ ParserError parsing package.json in "[dir]/" `; exports[`should report error on invalid format for dependencies 1`] = ` -"bun install -1 | {"name":"foo","version":"0.0.1","dependencies":[]} +"1 | {"name":"foo","version":"0.0.1","dependencies":[]} ^ error: dependencies expects a map of specifiers, e.g. "dependencies": { @@ -23,8 +21,7 @@ error: dependencies expects a map of specifiers, e.g. `; exports[`should report error on invalid format for optionalDependencies 1`] = ` -"bun install -1 | {"name":"foo","version":"0.0.1","optionalDependencies":"bar"} +"1 | {"name":"foo","version":"0.0.1","optionalDependencies":"bar"} ^ error: optionalDependencies expects a map of specifiers, e.g. "optionalDependencies": { @@ -35,8 +32,7 @@ error: optionalDependencies expects a map of specifiers, e.g. `; exports[`should report error on invalid format for workspaces 1`] = ` -"bun install -1 | {"name":"foo","version":"0.0.1","workspaces":{"packages":{"bar":true}}} +"1 | {"name":"foo","version":"0.0.1","workspaces":{"packages":{"bar":true}}} ^ error: Workspaces expects an array of strings, e.g. "workspaces": [ @@ -47,8 +43,7 @@ error: Workspaces expects an array of strings, e.g. `; exports[`should report error on duplicated workspace packages 1`] = ` -"bun install -1 | {"name":"moo","version":"0.0.3"} +"1 | {"name":"moo","version":"0.0.3"} ^ error: Workspace name "moo" already exists at [dir]/baz/package.json:1:9 diff --git a/test/cli/install/bun-add.test.ts b/test/cli/install/bun-add.test.ts index 385a14f28337c0..52540dbcd6f8b1 100644 --- a/test/cli/install/bun-add.test.ts +++ b/test/cli/install/bun-add.test.ts @@ -67,10 +67,10 @@ it("should add existing package", async () => { }); const err = await new Response(stderr).text(); expect(err).not.toContain("error:"); - expect(err).toContain("bun add"); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", `installed foo@${add_path.replace(/\\/g, "/")}`, "", @@ -111,12 +111,11 @@ it("should reject missing package", async () => { env, }); const err = await new Response(stderr).text(); - expect(err).toContain("bun add"); expect(err).toContain("error: MissingPackageJSON"); expect(err).toContain(`note: error occured while resolving file:${add_path}`); const out = await new Response(stdout).text(); - expect(out).toBe(""); + expect(out).toEqual(expect.stringContaining("bun add v1.")); expect(await exited).toBe(1); expect(await file(join(package_dir, "package.json")).text()).toEqual( JSON.stringify({ @@ -164,6 +163,7 @@ for (const pathType of ["absolute", "relative"]) { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", `installed foo@${add_path_rel.replace(/\\/g, "/")}`, "", @@ -201,11 +201,10 @@ it.each(["fileblah://"])("should reject invalid path without segfault: %s", asyn env, }); const err = await new Response(stderr).text(); - expect(err).toContain("bun add"); expect(err).toContain(`error: unrecognised dependency format: ${dep}`); const out = await new Response(stdout).text(); - expect(out).toBe(""); + expect(out).toEqual(expect.stringContaining("bun add v1.")); expect(await exited).toBe(1); expect(await file(join(package_dir, "package.json")).text()).toEqual( JSON.stringify({ @@ -244,7 +243,7 @@ it("should handle semver-like names", async () => { }); const err = await new Response(stderr).text(); expect(err.split(/\r?\n/)).toContain(`error: GET http://localhost:${port}/1.2.3 - 404`); - expect(await new Response(stdout).text()).toBe(""); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun add v1.")); expect(await exited).toBe(1); expect(urls.sort()).toEqual([`${root_url}/1.2.3`]); expect(requested).toBe(1); @@ -285,7 +284,7 @@ it("should handle @scoped names", async () => { }); const err = await new Response(stderr).text(); expect(err.split(/\r?\n/)).toContain(`error: GET http://localhost:${port}/@bar%2fbaz - 404`); - expect(await new Response(stdout).text()).toBe(""); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun add v1.")); expect(await exited).toBe(1); expect(urls.sort()).toEqual([`${root_url}/@bar%2fbaz`]); expect(requested).toBe(1); @@ -320,6 +319,7 @@ it("should add dependency with capital letters", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed BaR@0.0.2", "", @@ -373,6 +373,7 @@ it("should add exact version with --exact", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed BaR@0.0.2", "", @@ -427,6 +428,7 @@ it("should add exact version with install.exact", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed BaR@0.0.2", "", @@ -479,6 +481,7 @@ it("should add exact version with -E", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed BaR@0.0.2", "", @@ -540,6 +543,7 @@ it("should add dependency with specified semver", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed baz@0.0.3 with binaries:", " - baz-run", @@ -599,6 +603,7 @@ it("should add dependency (GitHub)", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed uglify-js@github:mishoo/UglifyJS#e219a9a with binaries:", " - uglifyjs", @@ -684,6 +689,7 @@ it("should add dependency alongside workspaces", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed baz@0.0.3 with binaries:", " - baz-run", @@ -754,6 +760,7 @@ it("should add aliased dependency (npm)", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed bar@0.0.3 with binaries:", " - baz-run", @@ -813,6 +820,7 @@ it("should add aliased dependency (GitHub)", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed uglify@github:mishoo/UglifyJS#e219a9a with binaries:", " - uglifyjs", @@ -961,6 +969,7 @@ it("should let you add the same package twice", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed baz@0.0.3", "", @@ -1010,7 +1019,14 @@ it("should let you add the same package twice", async () => { expect(err2).not.toContain("error:"); expect(err2).toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); - expect(out2.replace(/\[[0-9\.]+m?s\]/, "[]").split(/\r?\n/)).toEqual(["", "installed baz@0.0.3", "", "[] done", ""]); + expect(out2.replace(/\[[0-9\.]+m?s\]/, "[]").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), + "", + "installed baz@0.0.3", + "", + "[] done", + "", + ]); expect(await exited2).toBe(0); expect(urls.sort()).toEqual([`${root_url}/baz`]); expect(requested).toBe(3); @@ -1074,6 +1090,7 @@ it("should install version tagged with `latest` by default", async () => { expect(err1).not.toContain("error:"); expect(err1).toContain("Saved lockfile"); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed baz@0.0.3", "", @@ -1124,6 +1141,7 @@ it("should install version tagged with `latest` by default", async () => { expect(err2).toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@0.0.3", "", @@ -1185,6 +1203,7 @@ it("should handle Git URL in dependencies (SCP-style)", async () => { out1 = out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, ""); out1 = out1.replace(/(\.git)#[a-f0-9]+/, "$1"); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed uglify-js@git+ssh://bun@github.com:mishoo/UglifyJS.git with binaries:", " - uglifyjs", @@ -1247,6 +1266,7 @@ it("should handle Git URL in dependencies (SCP-style)", async () => { expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 1 install across 2 packages (no changes)", ]); @@ -1327,6 +1347,7 @@ it("should prefer optionalDependencies over dependencies of the same name", asyn expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed bar@0.0.2", "", @@ -1385,6 +1406,7 @@ it("should prefer dependencies over peerDependencies of the same name", async () expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed bar@0.0.2", "", @@ -1441,6 +1463,7 @@ it("should add dependency without duplication", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed bar@0.0.2", "", @@ -1492,7 +1515,11 @@ it("should add dependency without duplication", async () => { // The meta-hash didn't change, but we do save everytime you do "bun add ". expect(err2).toContain("Saved lockfile"); - expect(out2.replace(/\s*\[[0-9\.]+m?s\] done\s*$/, "").split(/\r?\n/)).toEqual(["", "installed bar@0.0.2"]); + expect(out2.replace(/\s*\[[0-9\.]+m?s\] done\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), + "", + "installed bar@0.0.2", + ]); expect(await exited2).toBe(0); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(2); @@ -1543,6 +1570,7 @@ it("should add dependency without duplication (GitHub)", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed uglify-js@github:mishoo/UglifyJS#e219a9a with binaries:", " - uglifyjs", @@ -1605,6 +1633,7 @@ it("should add dependency without duplication (GitHub)", async () => { const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\] done\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed uglify-js@github:mishoo/UglifyJS#e219a9a with binaries:", " - uglifyjs", @@ -1683,6 +1712,7 @@ it("should add dependencies to workspaces directly", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", `installed foo@${relative(package_dir, add_dir).replace(/\\/g, "/")}`, "", @@ -1747,10 +1777,10 @@ async function installRedirectsToAdd(saveFlagFirst: boolean) { }); const err = await new Response(stderr).text(); expect(err).not.toContain("error:"); - expect(err).toContain("bun add"); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", `installed foo@${add_path.replace(/\\/g, "/")}`, "", @@ -1785,6 +1815,7 @@ it("should add dependency alongside peerDependencies", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed bar@0.0.2", "", @@ -1833,6 +1864,7 @@ it("should add local tarball dependency", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed baz@baz-0.0.3.tgz with binaries:", " - baz-run", diff --git a/test/cli/install/bun-install-retry.test.ts b/test/cli/install/bun-install-retry.test.ts index 27f3f70522f2cd..842691bb0b9eef 100644 --- a/test/cli/install/bun-install-retry.test.ts +++ b/test/cli/install/bun-install-retry.test.ts @@ -63,6 +63,7 @@ it("retries on 500", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed BaR@0.0.2", "", diff --git a/test/cli/install/bun-install.test.ts b/test/cli/install/bun-install.test.ts index 591f03fc5cc1f8..088199222accde 100644 --- a/test/cli/install/bun-install.test.ts +++ b/test/cli/install/bun-install.test.ts @@ -86,7 +86,7 @@ it("should not error when package.json has comments and trailing commas", async }); const err = await new Response(stderr).text(); expect(err).toContain('error: No version matching "^1" found for specifier "bar" (but package exists)'); - expect(await new Response(stdout).text()).toBeEmpty(); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); expect(urls.sort()).toEqual([`${root_url}/bar`]); expect(requested).toBe(1); @@ -145,6 +145,7 @@ describe("chooses", () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ baz@${chosen}`, "", @@ -233,7 +234,7 @@ registry = "http://${server.hostname}:${server.port}/" }); const err = await new Response(stderr).text(); expect(err).toMatch(/error: (ConnectionRefused|ConnectionClosed) downloading package manifest bar/gm); - expect(await new Response(stdout).text()).toBeEmpty(); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); try { await access(join(package_dir, "bun.lockb")); @@ -292,7 +293,7 @@ registry = "https://badssl.com:bad" }); const err = await new Response(stderr).text(); expect(err).toMatch(/error: (ConnectionRefused|ConnectionClosed) downloading package manifest bar/gm); - expect(await new Response(stdout).text()).toBeEmpty(); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); try { await access(join(package_dir, "bun.lockb")); @@ -475,7 +476,7 @@ it("should handle missing package", async () => { }); const err = await new Response(stderr).text(); expect(err.split(/\r?\n/)).toContain(`error: GET http://localhost:${new URL(root_url).port}/foo - 404`); - expect(await new Response(stdout).text()).toBeEmpty(); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun add v1.")); expect(await exited).toBe(1); expect(urls.sort()).toEqual([`${root_url}/foo`]); expect(requested).toBe(1); @@ -525,7 +526,7 @@ foo = { token = "bar" } }); const err = await new Response(stderr).text(); expect(err.split(/\r?\n/)).toContain(`error: GET ${url} - 422`); - expect(await new Response(stdout).text()).toBeEmpty(); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun add v1.")); expect(await exited).toBe(1); expect(urls.sort()).toEqual([url]); expect(seen_token).toBe(true); @@ -563,6 +564,7 @@ it("should handle empty string in dependencies", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -640,7 +642,11 @@ it("should handle workspaces", async () => { const err1 = await new Response(stderr1).text(); expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); - expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "4 packages installed"]); + expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "4 packages installed", + ]); expect(await exited1).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ @@ -674,7 +680,11 @@ it("should handle workspaces", async () => { const err2 = await new Response(stderr2).text(); expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); - expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "4 packages installed"]); + expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "4 packages installed", + ]); expect(await exited2).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([ @@ -726,6 +736,7 @@ it("should handle `workspace:` specifier", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ Bar@workspace:path/to/bar`, "", @@ -754,6 +765,7 @@ it("should handle `workspace:` specifier", async () => { expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ Bar@workspace:path/to/bar`, "", @@ -796,7 +808,11 @@ it("should handle workspaces with packages array", async () => { const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar"]); @@ -846,7 +862,11 @@ it("should handle inter-dependency between workspaces", async () => { const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); expect(await exited).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar", "Baz"]); @@ -897,7 +917,11 @@ it("should handle inter-dependency between workspaces (devDependencies)", async const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); expect(await exited).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar", "Baz"]); @@ -948,7 +972,11 @@ it("should handle inter-dependency between workspaces (optionalDependencies)", a const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); expect(await exited).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar", "Baz"]); @@ -998,7 +1026,11 @@ it("should ignore peerDependencies within workspaces", async () => { const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual(["Baz"]); @@ -1036,6 +1068,7 @@ it("should handle installing the same peerDependency with different versions", a expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ peer@0.0.2", "+ boba@0.0.2", @@ -1075,6 +1108,7 @@ it("should handle installing the same peerDependency with the same version", asy expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ boba@0.0.2", "", @@ -1121,7 +1155,11 @@ it("should handle life-cycle scripts within workspaces", async () => { env, }); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar"]); @@ -1181,6 +1219,7 @@ it("should handle life-cycle scripts during re-installation", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ qux@0.0.2", "", @@ -1212,6 +1251,7 @@ it("should handle life-cycle scripts during re-installation", async () => { expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ qux@0.0.2", "", @@ -1243,6 +1283,7 @@ it("should handle life-cycle scripts during re-installation", async () => { expect(err3).not.toContain("Saved lockfile"); const out3 = await new Response(stdout3).text(); expect(out3.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ qux@0.0.2", "", @@ -1299,7 +1340,11 @@ it("should use updated life-cycle scripts in root during re-installation", async expect(err1).not.toContain("error:"); expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); - expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited1).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar"]); @@ -1342,7 +1387,11 @@ it("should use updated life-cycle scripts in root during re-installation", async expect(err2).not.toContain("error:"); expect(err2).toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); - expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited2).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar"]); @@ -1372,7 +1421,11 @@ it("should use updated life-cycle scripts in root during re-installation", async expect(err3).not.toContain("Saved lockfile"); const out3 = await new Response(stdout3).text(); - expect(out3.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out3.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited3).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar"]); @@ -1425,7 +1478,11 @@ it("should use updated life-cycle scripts in dependency during re-installation", expect(err1).not.toContain("error:"); expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); - expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited1).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar"]); @@ -1471,7 +1528,11 @@ it("should use updated life-cycle scripts in dependency during re-installation", expect(err2).not.toContain("error:"); expect(err2).toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); - expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited2).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar"]); @@ -1503,7 +1564,11 @@ it("should use updated life-cycle scripts in dependency during re-installation", expect(err3).not.toContain("error:"); expect(err3).not.toContain("Saved lockfile"); const out3 = await new Response(stdout3).text(); - expect(out3.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out3.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited3).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "Bar"]); @@ -1543,7 +1608,11 @@ it("should ignore workspaces within workspaces", async () => { const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited).toBe(0); expect(requested).toBe(0); expect(await readdirSorted(join(package_dir, "node_modules"))).toEqual([".cache", "bar"]); @@ -1576,6 +1645,7 @@ it("should handle ^0 in dependencies", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -1616,7 +1686,7 @@ it("should handle ^1 in dependencies", async () => { }); const err = await new Response(stderr).text(); expect(err).toContain('error: No version matching "^1" found for specifier "bar" (but package exists)'); - expect(await new Response(stdout).text()).toBeEmpty(); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); expect(urls.sort()).toEqual([`${root_url}/bar`]); expect(requested).toBe(1); @@ -1653,6 +1723,7 @@ it("should handle ^0.0 in dependencies", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -1693,7 +1764,7 @@ it("should handle ^0.1 in dependencies", async () => { }); const err = await new Response(stderr).text(); expect(err).toContain('error: No version matching "^0.1" found for specifier "bar" (but package exists)'); - expect(await new Response(stdout).text()).toBeEmpty(); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); expect(urls.sort()).toEqual([`${root_url}/bar`]); expect(requested).toBe(1); @@ -1728,7 +1799,7 @@ it("should handle ^0.0.0 in dependencies", async () => { }); const err = await new Response(stderr).text(); expect(err).toContain('error: No version matching "^0.0.0" found for specifier "bar" (but package exists)'); - expect(await new Response(stdout).text()).toBeEmpty(); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); expect(urls.sort()).toEqual([`${root_url}/bar`]); expect(requested).toBe(1); @@ -1766,6 +1837,7 @@ it("should handle ^0.0.2 in dependencies", async () => { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -1831,7 +1903,11 @@ it("should handle matching workspaces from dependencies", async () => { expect(err).not.toContain("error:"); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "3 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "3 packages installed", + ]); expect(await exited).toBe(0); await access(join(package_dir, "bun.lockb")); }); @@ -1953,6 +2029,7 @@ it("should handle ^0.0.2-rc in dependencies", async () => { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2-rc", "", @@ -1996,6 +2073,7 @@ it("should handle ^0.0.2-alpha.3+b4d in dependencies", async () => { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2-alpha.3", "", @@ -2039,6 +2117,7 @@ it("should choose the right version with prereleases", async () => { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2-alpha.3", "", @@ -2082,6 +2161,7 @@ it("should handle ^0.0.2rc1 in dependencies", async () => { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2-rc1", "", @@ -2125,6 +2205,7 @@ it("should handle caret range in dependencies when the registry has prereleased expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@6.3.0", "", @@ -2181,6 +2262,7 @@ it("should prefer latest-tagged dependency", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@0.0.3", "", @@ -2232,6 +2314,7 @@ it("should install latest with prereleases", async () => { expect(err).toContain("Saved lockfile"); var out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed baz@1.0.0-0", "", @@ -2263,6 +2346,7 @@ it("should install latest with prereleases", async () => { expect(err).toContain("Saved lockfile"); out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@1.0.0-0", "", @@ -2293,6 +2377,7 @@ it("should install latest with prereleases", async () => { expect(err).toContain("Saved lockfile"); out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@1.0.0-8", "", @@ -2324,6 +2409,7 @@ it("should install latest with prereleases", async () => { expect(err).toContain("Saved lockfile"); out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@1.0.0-0", "", @@ -2366,6 +2452,7 @@ it("should handle dependency aliasing", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ Bar@0.0.3", "", @@ -2421,6 +2508,7 @@ it("should handle dependency aliasing (versioned)", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ Bar@0.0.3", "", @@ -2476,6 +2564,7 @@ it("should handle dependency aliasing (dist-tagged)", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ Bar@0.0.3", "", @@ -2535,6 +2624,7 @@ it("should not reinstall aliased dependencies", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ Bar@0.0.3", "", @@ -2573,6 +2663,7 @@ it("should not reinstall aliased dependencies", async () => { expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 1 install across 2 packages (no changes)", ]); @@ -2638,6 +2729,7 @@ it("should handle aliased & direct dependency references", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@0.0.3", "", @@ -2716,6 +2808,7 @@ it("should not hoist if name collides with alias", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.3", "", @@ -2793,6 +2886,7 @@ it("should get npm alias with matching version", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ boba@0.0.5", "", @@ -2845,6 +2939,7 @@ it("should not apply overrides to package name of aliased package", async () => expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.3", "", @@ -2889,6 +2984,7 @@ it("should handle unscoped alias on scoped dependency", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @barn/moo@0.1.0", "+ moo@0.1.0", @@ -2948,6 +3044,7 @@ it("should handle scoped alias on unscoped dependency", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @baz/bar@0.0.2", "+ bar@0.0.2", @@ -3017,6 +3114,7 @@ it("should handle aliased dependency with existing lockfile", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ moz@0.1.0", "", @@ -3077,6 +3175,7 @@ it("should handle aliased dependency with existing lockfile", async () => { expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ moz@0.1.0", "", @@ -3143,7 +3242,13 @@ it("should handle GitHub URL in dependencies (user/repo)", async () => { let out = await new Response(stdout).text(); out = out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, ""); out = out.replace(/(github:[^#]+)#[a-f0-9]+/, "$1"); - expect(out.split(/\r?\n/)).toEqual(["", "+ uglify@github:mishoo/UglifyJS", "", "1 package installed"]); + expect(out.split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "+ uglify@github:mishoo/UglifyJS", + "", + "1 package installed", + ]); expect(await exited).toBe(0); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -3193,6 +3298,7 @@ it("should handle GitHub URL in dependencies (user/repo#commit-id)", async () => expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uglify@github:mishoo/UglifyJS#e219a9a", "", @@ -3258,6 +3364,7 @@ it("should handle GitHub URL in dependencies (user/repo#tag)", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uglify@github:mishoo/UglifyJS#e219a9a", "", @@ -3331,6 +3438,7 @@ it("should handle bitbucket git dependencies", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ public-install-test@git+ssh://${dep}#79265e2d9754c60b60f97cc8d859fb6da073b5d2`, "", @@ -3366,6 +3474,7 @@ it("should handle bitbucket git dependencies", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", `installed publicinstalltest@git+ssh://${dep}#79265e2d9754c60b60f97cc8d859fb6da073b5d2`, "", @@ -3406,6 +3515,7 @@ it("should handle gitlab git dependencies", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ public-install-test@git+ssh://${dep}#93f3aa4ec9ca8a0bacc010776db48bfcd915c44c`, "", @@ -3441,6 +3551,7 @@ it("should handle gitlab git dependencies", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", `installed public-install-test@git+ssh://${dep}#93f3aa4ec9ca8a0bacc010776db48bfcd915c44c`, "", @@ -3478,6 +3589,7 @@ it("should handle GitHub URL in dependencies (github:user/repo#tag)", async () = expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uglify@github:mishoo/UglifyJS#e219a9a", "", @@ -3545,7 +3657,13 @@ it("should handle GitHub URL in dependencies (https://github.com/user/repo.git)" let out = await new Response(stdout).text(); out = out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, ""); out = out.replace(/(github:[^#]+)#[a-f0-9]+/, "$1"); - expect(out.split(/\r?\n/)).toEqual(["", "+ uglify@github:mishoo/UglifyJS", "", "1 package installed"]); + expect(out.split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "+ uglify@github:mishoo/UglifyJS", + "", + "1 package installed", + ]); expect(await exited).toBe(0); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -3595,6 +3713,7 @@ it("should handle GitHub URL in dependencies (git://github.com/user/repo.git#com expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uglify@github:mishoo/UglifyJS#e219a9a", "", @@ -3662,7 +3781,13 @@ it("should handle GitHub URL in dependencies (git+https://github.com/user/repo.g let out = await new Response(stdout).text(); out = out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, ""); out = out.replace(/(github:[^#]+)#[a-f0-9]+/, "$1"); - expect(out.split(/\r?\n/)).toEqual(["", "+ uglify@github:mishoo/UglifyJS", "", "1 package installed"]); + expect(out.split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "+ uglify@github:mishoo/UglifyJS", + "", + "1 package installed", + ]); expect(await exited).toBe(0); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -3714,6 +3839,7 @@ it("should handle GitHub tarball URL in dependencies (https://github.com/user/re out = out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, ""); out = out.replace(/(github:[^#]+)#[a-f0-9]+/, "$1"); expect(out.split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ when@https://github.com/cujojs/when/tarball/1.0.2", "", @@ -3772,6 +3898,7 @@ it("should handle GitHub tarball URL in dependencies (https://github.com/user/re out = out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, ""); out = out.replace(/(github:[^#]+)#[a-f0-9]+/, "$1"); expect(out.split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ when@https://github.com/cujojs/when/tarball/1.0.2", "", @@ -3832,6 +3959,7 @@ it("should treat non-GitHub http(s) URLs as tarballs (https://some.url/path?stuf out = out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, ""); out = out.replace(/(github:[^#]+)#[a-f0-9]+/, "$1"); expect(out.split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @vercel/turbopack-node@https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230922.2", "", @@ -3886,6 +4014,7 @@ cache = false expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ html-minifier@github:kangax/html-minifier#4beb325", "", @@ -3942,6 +4071,7 @@ cache = false expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ html-minifier@github:kangax/html-minifier#4beb325", "", @@ -4042,6 +4172,7 @@ it("should consider peerDependencies during hoisting", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@0.0.5", "", @@ -4139,6 +4270,7 @@ it("should install peerDependencies when needed", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@0.0.5", "", @@ -4201,6 +4333,7 @@ it("should not regard peerDependencies declarations as duplicates", async () => expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -4229,9 +4362,9 @@ it("should report error on invalid format for package.json", async () => { env, }); const err = await new Response(stderr).text(); - expect(err.replace(/^bun install v.+\n/, "bun install\n").replaceAll(package_dir + sep, "[dir]/")).toMatchSnapshot(); + expect(err.replaceAll(package_dir + sep, "[dir]/")).toMatchSnapshot(); const out = await new Response(stdout).text(); - expect(out).toEqual(""); + expect(out).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); }); @@ -4253,9 +4386,9 @@ it("should report error on invalid format for dependencies", async () => { env, }); const err = await new Response(stderr).text(); - expect(err.replace(/^bun install v.+\n/, "bun install\n").replaceAll(package_dir + sep, "[dir]/")).toMatchSnapshot(); + expect(err.replaceAll(package_dir + sep, "[dir]/")).toMatchSnapshot(); const out = await new Response(stdout).text(); - expect(out).toEqual(""); + expect(out).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); }); @@ -4278,10 +4411,9 @@ it("should report error on invalid format for optionalDependencies", async () => }); let err = await new Response(stderr).text(); - err = err.replace(/^bun install v.+\n/, "bun install\n").replaceAll(package_dir + sep, "[dir]/"); + err = err.replaceAll(package_dir + sep, "[dir]/"); err = err.substring(0, err.indexOf("\n", err.lastIndexOf("[dir]/package.json:"))).trim(); expect(err.split("\n")).toEqual([ - `bun install`, `1 | {"name":"foo","version":"0.0.1","optionalDependencies":"bar"}`, ` ^`, `error: optionalDependencies expects a map of specifiers, e.g.`, @@ -4291,7 +4423,7 @@ it("should report error on invalid format for optionalDependencies", async () => ` at [dir]/package.json:1:33`, ]); const out = await new Response(stdout).text(); - expect(out).toEqual(""); + expect(out).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); }); @@ -4315,9 +4447,9 @@ it("should report error on invalid format for workspaces", async () => { env, }); const err = await new Response(stderr).text(); - expect(err.replace(/^bun install v.+\n/, "bun install\n").replaceAll(package_dir + sep, "[dir]/")).toMatchSnapshot(); + expect(err.replaceAll(package_dir + sep, "[dir]/")).toMatchSnapshot(); const out = await new Response(stdout).text(); - expect(out).toEqual(""); + expect(out).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); }); @@ -4355,11 +4487,9 @@ it("should report error on duplicated workspace packages", async () => { env, }); let err = await new Response(stderr).text(); - err = err.replace(/^bun install v.+\n/, "bun install\n"); err = err.replaceAll(package_dir, "[dir]"); err = err.replaceAll(sep, "/"); expect(err.trim().split("\n")).toEqual([ - `bun install`, `1 | {"name":"moo","version":"0.0.3"}`, ` ^`, `error: Workspace name "moo" already exists`, @@ -4371,7 +4501,7 @@ it("should report error on duplicated workspace packages", async () => { ` at [dir]/bar/package.json:1:9`, ]); const out = await new Response(stdout).text(); - expect(out).toEqual(""); + expect(out).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); }); @@ -4402,6 +4532,7 @@ it("should handle Git URL in dependencies", async () => { out = out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, ""); out = out.replace(/(\.git)#[a-f0-9]+/, "$1"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uglify-js@git+https://git@github.com/mishoo/UglifyJS.git", "", @@ -4462,6 +4593,7 @@ it("should handle Git URL in dependencies (SCP-style)", async () => { out = out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, ""); out = out.replace(/(\.git)#[a-f0-9]+/, "$1"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uglify@git+ssh://github.com:mishoo/UglifyJS.git", "", @@ -4518,6 +4650,7 @@ it("should handle Git URL with committish in dependencies", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uglify@git+https://git@github.com/mishoo/UglifyJS.git#e219a9a78a0d2251e4dcbd4bb9034207eb484fe8", "", @@ -4577,7 +4710,7 @@ it("should fail on invalid Git URL", async () => { const err = await new Response(stderr).text(); expect(err.split(/\r?\n/)).toContain('error: "git clone" for "uglify" failed'); const out = await new Response(stdout).text(); - expect(out).toBeEmpty(); + expect(out).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -4613,7 +4746,7 @@ it("should fail on ssh Git URL if invalid credentials", async () => { const err = await new Response(stderr).text(); expect(err.split(/\r?\n/)).toContain('error: "git clone" for "private-install" failed'); const out = await new Response(stdout).text(); - expect(out).toBeEmpty(); + expect(out).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -4651,7 +4784,7 @@ it("should fail on Git URL with invalid committish", async () => { 'error: no commit matching "404-no_such_tag" found for "uglify" (but repository exists)', ); const out = await new Response(stdout).text(); - expect(out).toBeEmpty(); + expect(out).toEqual(expect.stringContaining("bun install v1.")); expect(await exited).toBe(1); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -4689,6 +4822,7 @@ it("should de-duplicate committish in Git URLs", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uglify-hash@git+https://git@github.com/mishoo/UglifyJS.git#e219a9a78a0d2251e4dcbd4bb9034207eb484fe8", "+ uglify-ver@git+https://git@github.com/mishoo/UglifyJS.git#e219a9a78a0d2251e4dcbd4bb9034207eb484fe8", @@ -4785,6 +4919,7 @@ cache = false expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ html-minifier@git+https://git@github.com/kangax/html-minifier#4beb325eb01154a40c0cbebff2e5737bbd7071ab", "", @@ -4841,6 +4976,7 @@ cache = false expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ html-minifier@git+https://git@github.com/kangax/html-minifier#4beb325eb01154a40c0cbebff2e5737bbd7071ab", "", @@ -4914,6 +5050,7 @@ cache = false expect(err3).not.toContain("Saved lockfile"); const out3 = await new Response(stdout3).text(); expect(out3.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ html-minifier@git+https://git@github.com/kangax/html-minifier#4beb325eb01154a40c0cbebff2e5737bbd7071ab", "", @@ -4986,6 +5123,7 @@ it("should prefer optionalDependencies over dependencies of the same name", asyn expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@0.0.3", "", @@ -5038,6 +5176,7 @@ it("should prefer dependencies over peerDependencies of the same name", async () expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@0.0.5", "", @@ -5082,6 +5221,7 @@ it("should handle tarball URL", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ baz@${root_url}/baz-0.0.3.tgz`, "", @@ -5129,6 +5269,7 @@ it("should handle tarball path", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ baz@${join(import.meta.dir, "baz-0.0.3.tgz").replace(/\\/g, "/")}`, "", @@ -5175,6 +5316,7 @@ it("should handle tarball URL with aliasing", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ bar@${root_url}/baz-0.0.3.tgz`, "", @@ -5222,6 +5364,7 @@ it("should handle tarball path with aliasing", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ bar@${join(import.meta.dir, "baz-0.0.3.tgz").replace(/\\/g, "/")}`, "", @@ -5278,6 +5421,7 @@ it("should de-duplicate dependencies alongside tarball URL", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ @barn/moo@${root_url}/moo-0.1.0.tgz`, "+ bar@0.0.2", @@ -5360,6 +5504,7 @@ it("should handle tarball URL with existing lockfile", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ @barn/moo@${root_url}/moo-0.1.0.tgz`, "", @@ -5420,6 +5565,7 @@ it("should handle tarball URL with existing lockfile", async () => { expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ @barn/moo@${root_url}/moo-0.1.0.tgz`, "", @@ -5501,6 +5647,7 @@ it("should handle tarball path with existing lockfile", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ @barn/moo@${join(import.meta.dir, "moo-0.1.0.tgz").replace(/\\/g, "/")}`, "", @@ -5560,6 +5707,7 @@ it("should handle tarball path with existing lockfile", async () => { expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ @barn/moo@${join(import.meta.dir, "moo-0.1.0.tgz").replace(/\\/g, "/")}`, "", @@ -5636,6 +5784,7 @@ it("should handle devDependencies from folder", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ moo@moo", "", @@ -5690,6 +5839,7 @@ it("should deduplicate devDependencies from folder", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "+ moo@moo", @@ -5742,6 +5892,7 @@ it("should install dependencies in root package of workspace", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -5793,6 +5944,7 @@ it("should install dependencies in root package of workspace (*)", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -5843,6 +5995,7 @@ it("should ignore invalid workspaces from parent directory", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -5898,6 +6051,7 @@ it("should handle --cwd", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -6057,6 +6211,7 @@ cache = false expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ conditional-type-checks@1.0.6", "+ prettier@2.8.8", @@ -6197,7 +6352,12 @@ cache = false expect(err2).not.toContain("Saved lockfile"); expect(err2).not.toContain("error:"); const out2 = await new Response(stdout2).text(); - expect(out2.replace(/\[[0-9\.]+m?s\]/, "[]").split(/\r?\n/)).toEqual(["", "[] done", ""]); + expect(out2.replace(/\[[0-9\.]+m?s\]/, "[]").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "[] done", + "", + ]); expect(await exited2).toBe(0); expect(await readdirSorted(package_dir)).toEqual(["bun.lockb", "bunfig.toml", "node_modules", "package.json"]); expect(await file(join(package_dir, "package.json")).text()).toEqual(foo_package); @@ -6253,12 +6413,13 @@ it("should handle trustedDependencies", async () => { expect(err).not.toContain("error:"); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@bar", "+ moo@moo", "", - expect.stringContaining("2 packages installed"), + "2 packages installed", "", "Blocked 3 postinstalls. Run `bun pm untrusted` for details.", "", @@ -6305,6 +6466,7 @@ it("should handle `workspaces:*` and `workspace:*` gracefully", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@workspace:bar", "", @@ -6334,6 +6496,7 @@ it("should handle `workspaces:*` and `workspace:*` gracefully", async () => { expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@workspace:bar", "", @@ -6376,6 +6539,7 @@ it("should handle `workspaces:bar` and `workspace:*` gracefully", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@workspace:bar", "", @@ -6418,6 +6582,7 @@ it("should handle `workspaces:*` and `workspace:bar` gracefully", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@workspace:bar", "", @@ -6460,6 +6625,7 @@ it("should handle `workspaces:bar` and `workspace:bar` gracefully", async () => expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@workspace:bar", "", @@ -6513,6 +6679,7 @@ it("should handle installing packages from inside a workspace with `*`", async ( expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ swag@workspace:packages/swag`, "", @@ -6591,6 +6758,7 @@ it("should handle installing packages from inside a workspace without prefix", a expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ p2@workspace:packages/p2`, "", @@ -6674,9 +6842,8 @@ it("should handle installing workspaces with more complicated globs", async () = stdout .toString() .replace(/\s*\[[0-9\.]+m?s\]\s*$/, "") - .split(/\r?\n/) - .sort(), - ).toEqual(["", "4 packages installed"].sort()); + .split(/\r?\n/), + ).toEqual([expect.stringContaining("bun install v1."), "", "4 packages installed"]); }); it("should handle installing workspaces with multiple glob patterns", async () => { @@ -6738,9 +6905,8 @@ it("should handle installing workspaces with multiple glob patterns", async () = stdout .toString() .replace(/\s*\[[0-9\.]+m?s\]\s*$/, "") - .split(/\r?\n/) - .sort(), - ).toEqual(["", "4 packages installed"].sort()); + .split(/\r?\n/), + ).toEqual([expect.stringContaining("bun install v1."), "", "4 packages installed"]); }); it.todo("should handle installing workspaces with absolute glob patterns", async () => { @@ -6798,9 +6964,8 @@ it.todo("should handle installing workspaces with absolute glob patterns", async stdout .toString() .replace(/\s*\[[0-9\.]+m?s\]\s*$/, "") - .split(/\r?\n/) - .sort(), - ).toEqual(["", "4 packages installed"].sort()); + .split(/\r?\n/), + ).toEqual([expect.stringContaining("bun install v1."), "", "4 packages installed"]); }); it("should handle installing packages inside workspaces with difference versions", async () => { @@ -6941,6 +7106,7 @@ it("should handle installing packages inside workspaces with difference versions expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ package1@workspace:packages/package1`, "", @@ -6991,6 +7157,7 @@ it("should handle installing packages inside workspaces with difference versions expect(err2).toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ package1@workspace:packages/package1`, "", @@ -7036,6 +7203,7 @@ it("should handle installing packages inside workspaces with difference versions expect(err3).toContain("Saved lockfile"); const out3 = await new Response(stdout3).text(); expect(out3.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ package1@workspace:packages/package1`, "", @@ -7081,6 +7249,7 @@ it("should handle installing packages inside workspaces with difference versions expect(err4).toContain("Saved lockfile"); const out4 = await new Response(stdout4).text(); expect(out4.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ package1@workspace:packages/package1`, "", @@ -7126,7 +7295,11 @@ it("should handle installing packages inside workspaces with difference versions const err5 = await new Response(stderr5).text(); expect(err5).toContain("Saved lockfile"); const out5 = await new Response(stdout5).text(); - expect(out5.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "6 packages installed"]); + expect(out5.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "6 packages installed", + ]); expect(await exited5).toBe(0); const { @@ -7185,6 +7358,7 @@ it("should override npm dependency by matching workspace", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@workspace:bar", "", @@ -7230,6 +7404,7 @@ it("should not override npm dependency by workspace with mismatched version", as expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -7271,6 +7446,7 @@ it("should override @scoped npm dependency by matching workspace", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ @bar/baz@workspace:packages/bar-baz`, "", @@ -7319,6 +7495,7 @@ it("should override aliased npm dependency by matching workspace", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@workspace:baz", "", @@ -7371,7 +7548,11 @@ it("should override child npm dependency by matching workspace", async () => { const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); expect(await exited).toBe(0); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -7421,7 +7602,11 @@ it("should not override child npm dependency by workspace with mismatched versio const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "3 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "3 packages installed", + ]); expect(await exited).toBe(0); expect(urls.sort()).toEqual([`${root_url}/bar`, `${root_url}/bar-0.0.2.tgz`]); expect(requested).toBe(2); @@ -7477,7 +7662,11 @@ it("should override @scoped child npm dependency by matching workspace", async ( const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); expect(await exited).toBe(0); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -7532,7 +7721,11 @@ it("should override aliased child npm dependency by matching workspace", async ( const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); expect(await exited).toBe(0); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -7586,7 +7779,11 @@ it("should handle `workspace:` with semver range", async () => { const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); expect(await exited).toBe(0); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -7635,7 +7832,11 @@ it("should handle `workspace:` with alias & @scope", async () => { const err = await new Response(stderr).text(); expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); expect(await exited).toBe(0); expect(urls.sort()).toBeEmpty(); expect(requested).toBe(0); @@ -7701,6 +7902,7 @@ it("should handle `workspace:*` on both root & child", async () => { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ bar@workspace:packages/bar`, "", @@ -7736,6 +7938,7 @@ it("should handle `workspace:*` on both root & child", async () => { expect(err2).not.toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ bar@workspace:packages/bar`, "", @@ -7778,6 +7981,7 @@ it("should install peer dependencies from root package", async () => { expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@0.0.2", "", @@ -7822,6 +8026,7 @@ it("should install correct version of peer dependency from root package", async expect(err).toContain("Saved lockfile"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@0.0.3", "", @@ -7889,7 +8094,7 @@ describe("Registry URLs", () => { stderr: "pipe", env, }); - expect(await new Response(stdout).text()).toBeEmpty(); + expect(await new Response(stdout).text()).toEqual(expect.stringContaining("bun install v1.")); const err = await new Response(stderr).text(); diff --git a/test/cli/install/bun-link.test.ts b/test/cli/install/bun-link.test.ts index 713088fe04ccac..20be3e14207f69 100644 --- a/test/cli/install/bun-link.test.ts +++ b/test/cli/install/bun-link.test.ts @@ -56,8 +56,12 @@ it("should link and unlink workspace package", async () => { }), ); let { out, err } = await runBunInstall(env, link_dir); - expect(err.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun install", "Saved lockfile", ""]); - expect(out.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(err.split(/\r?\n/)).toEqual(["Saved lockfile", ""]); + expect(out.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); let { stdout, stderr, exited } = spawn({ cmd: [bunExe(), "link"], @@ -69,7 +73,7 @@ it("should link and unlink workspace package", async () => { }); err = await new Response(stderr).text(); - expect(err.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun link", ""]); + expect(err.split(/\r?\n/)).toEqual([""]); expect(await new Response(stdout).text()).toContain(`Success! Registered "moo"`); expect(await exited).toBe(0); @@ -83,8 +87,9 @@ it("should link and unlink workspace package", async () => { })); err = await new Response(stderr).text(); - expect(err.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun link", ""]); + expect(err.split(/\r?\n/)).toEqual([""]); expect((await new Response(stdout).text()).replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun link v1."), "", `installed moo@link:moo`, "", @@ -106,7 +111,7 @@ it("should link and unlink workspace package", async () => { })); err = await new Response(stderr).text(); - expect(err.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun unlink", ""]); + expect(err.split(/\r?\n/)).toEqual([""]); expect(await new Response(stdout).text()).toContain(`success: unlinked package "moo"`); expect(await exited).toBe(0); @@ -121,7 +126,7 @@ it("should link and unlink workspace package", async () => { })); err = await new Response(stderr).text(); - expect(err.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun link", ""]); + expect(err.split(/\r?\n/)).toEqual([""]); expect(await new Response(stdout).text()).toContain(`Success! Registered "foo"`); expect(await exited).toBe(0); @@ -135,8 +140,9 @@ it("should link and unlink workspace package", async () => { })); err = await new Response(stderr).text(); - expect(err.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun link", ""]); + expect(err.split(/\r?\n/)).toEqual([""]); expect((await new Response(stdout).text()).replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun link v1."), "", `installed foo@link:foo`, "", @@ -159,7 +165,7 @@ it("should link and unlink workspace package", async () => { })); err = await new Response(stderr).text(); - expect(err.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun unlink", ""]); + expect(err.split(/\r?\n/)).toEqual([""]); expect(await new Response(stdout).text()).toContain(`success: unlinked package "foo"`); expect(await exited).toBe(0); }); @@ -194,7 +200,7 @@ it("should link package", async () => { env, }); const err1 = await new Response(stderr1).text(); - expect(err1.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun link", ""]); + expect(err1.split(/\r?\n/)).toEqual([""]); expect(await new Response(stdout1).text()).toContain(`Success! Registered "${link_name}"`); expect(await exited1).toBe(0); @@ -211,9 +217,10 @@ it("should link package", async () => { env, }); const err2 = await new Response(stderr2).text(); - expect(err2.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun link", ""]); + expect(err2.split(/\r?\n/)).toEqual([""]); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun link v1."), "", `installed ${link_name}@link:${link_name}`, "", @@ -234,7 +241,7 @@ it("should link package", async () => { env, }); const err3 = await new Response(stderr3).text(); - expect(err3.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun unlink", ""]); + expect(err3.split(/\r?\n/)).toEqual([""]); expect(await new Response(stdout3).text()).toContain(`success: unlinked package "${link_name}"`); expect(await exited3).toBe(0); @@ -252,7 +259,7 @@ it("should link package", async () => { }); const err4 = await new Response(stderr4).text(); expect(err4).toContain(`error: Package "${link_name}" is not linked`); - expect(await new Response(stdout4).text()).toBe(""); + expect(await new Response(stdout4).text()).toEqual(expect.stringContaining("bun link v1.")); expect(await exited4).toBe(1); }); @@ -286,7 +293,7 @@ it("should link scoped package", async () => { env, }); const err1 = await new Response(stderr1).text(); - expect(err1.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun link", ""]); + expect(err1.split(/\r?\n/)).toEqual([""]); expect(await new Response(stdout1).text()).toContain(`Success! Registered "${link_name}"`); expect(await exited1).toBe(0); @@ -303,9 +310,10 @@ it("should link scoped package", async () => { env, }); const err2 = await new Response(stderr2).text(); - expect(err2.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun link", ""]); + expect(err2.split(/\r?\n/)).toEqual([""]); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun link v1."), "", `installed ${link_name}@link:${link_name}`, "", @@ -326,7 +334,7 @@ it("should link scoped package", async () => { env, }); const err3 = await new Response(stderr3).text(); - expect(err3.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun unlink", ""]); + expect(err3.split(/\r?\n/)).toEqual([""]); expect(await new Response(stdout3).text()).toContain(`success: unlinked package "${link_name}"`); expect(await exited3).toBe(0); @@ -344,7 +352,7 @@ it("should link scoped package", async () => { }); const err4 = await new Response(stderr4).text(); expect(err4).toContain(`error: Package "${link_name}" is not linked`); - expect(await new Response(stdout4).text()).toBe(""); + expect((await new Response(stdout4).text()).split(/\r?\n/)).toEqual([expect.stringContaining("bun link v1."), ""]); expect(await exited4).toBe(1); }); @@ -385,7 +393,7 @@ it("should link dependency without crashing", async () => { env, }); const err1 = await new Response(stderr1).text(); - expect(err1.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun link", ""]); + expect(err1.split(/\r?\n/)).toEqual([""]); expect(await new Response(stdout1).text()).toContain(`Success! Registered "${link_name}"`); expect(await exited1).toBe(0); @@ -402,9 +410,10 @@ it("should link dependency without crashing", async () => { env, }); const err2 = await new Response(stderr2).text(); - expect(err2.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun install", "Saved lockfile", ""]); + expect(err2.split(/\r?\n/)).toEqual(["Saved lockfile", ""]); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+ms\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ ${link_name}@link:${link_name}`, "", @@ -432,7 +441,7 @@ it("should link dependency without crashing", async () => { env, }); const err3 = await new Response(stderr3).text(); - expect(err3.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun unlink", ""]); + expect(err3.split(/\r?\n/)).toEqual([""]); expect(await new Response(stdout3).text()).toContain(`success: unlinked package "${link_name}"`); expect(await exited3).toBe(0); @@ -452,6 +461,7 @@ it("should link dependency without crashing", async () => { expect(err4).toContain(`error: FileNotFound installing ${link_name}`); const out4 = await new Response(stdout4).text(); expect(out4.replace(/\[[0-9\.]+m?s\]/, "[]").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Failed to install 1 package", "[] done", diff --git a/test/cli/install/bun-remove.test.ts b/test/cli/install/bun-remove.test.ts index c7ae73618df916..c6e272cd1e774d 100644 --- a/test/cli/install/bun-remove.test.ts +++ b/test/cli/install/bun-remove.test.ts @@ -98,6 +98,7 @@ it("should remove existing package", async () => { const err1 = await new Response(stderr1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun remove v1."), "", `+ pkg2@${pkg2_path.replace(/\\/g, "/")}`, "", @@ -105,7 +106,7 @@ it("should remove existing package", async () => { "Removed: 1", "", ]); - expect(err1.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual(["bun remove", "Saved lockfile", ""]); + expect(err1.split(/\r?\n/)).toEqual(["Saved lockfile", ""]); expect(await file(join(package_dir, "package.json")).text()).toEqual( JSON.stringify( { @@ -136,13 +137,14 @@ it("should remove existing package", async () => { const out2 = await new Response(stdout2).text(); const err2 = await new Response(stderr2).text(); - expect(out2.replace(/\s*\[[0-9\.]+m?s\]/, "").split(/\r?\n/)).toEqual(["", "- pkg2", "1 package removed", ""]); - expect(err2.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual([ - "bun remove", + expect(out2.replace(/ \[[0-9\.]+m?s\]/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun remove v1."), "", - "package.json has no dependencies! Deleted empty lockfile", + "- pkg2", + "1 package removed", "", ]); + expect(err2.split(/\r?\n/)).toEqual(["", "package.json has no dependencies! Deleted empty lockfile", ""]); expect(await file(join(package_dir, "package.json")).text()).toEqual( JSON.stringify( { @@ -211,10 +213,9 @@ it("should not affect if package is not installed", async () => { }); expect(await exited).toBe(0); const out = await new Response(stdout).text(); - expect(out).toEqual(""); + expect(out.split("\n")).toEqual([expect.stringContaining("bun remove v1."), ""]); const err = await new Response(stderr).text(); - expect(err.replace(/^(.*?) v[^\n]+/, "$1").split(/\r?\n/)).toEqual([ - "bun remove", + expect(err.replace(/ \[[0-9\.]+m?s\]/, "").split(/\r?\n/)).toEqual([ "package.json doesn't have dependencies, there's nothing to remove!", "", ]); @@ -306,7 +307,12 @@ it("should remove peerDependencies", async () => { const err = await new Response(stderr).text(); expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]/, "").split(/\r?\n/)).toEqual([" done", ""]); + expect(out.replace(/\[[0-9\.]+m?s\]/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun remove v1."), + "", + " done", + "", + ]); expect(await exited).toBe(0); expect(await file(join(package_dir, "package.json")).json()).toEqual({ name: "foo", diff --git a/test/cli/install/bun-update.test.ts b/test/cli/install/bun-update.test.ts index 9b6575a73b0d26..64d7ffd7cc99f0 100644 --- a/test/cli/install/bun-update.test.ts +++ b/test/cli/install/bun-update.test.ts @@ -70,6 +70,7 @@ for (const { input } of [{ input: { baz: "~0.0.3", moo: "~0.1.0" } }, { input: { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@0.0.3", "", @@ -112,6 +113,7 @@ for (const { input } of [{ input: { baz: "~0.0.3", moo: "~0.1.0" } }, { input: { expect(err2).toContain("Saved lockfile"); const out2 = await new Response(stdout2).text(); expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun update v1."), "", `installed baz@${tilde ? "0.0.5" : "0.0.3"} with binaries:`, ` - ${tilde ? "baz-exec" : "baz-run"}`, @@ -188,6 +190,7 @@ for (const { input } of [{ input: { baz: "~0.0.3", moo: "~0.1.0" } }, { input: { expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout1).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @barn/moo@0.1.0", "+ baz@0.0.3", @@ -239,6 +242,7 @@ for (const { input } of [{ input: { baz: "~0.0.3", moo: "~0.1.0" } }, { input: { const out2 = await new Response(stdout2).text(); if (tilde) { expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun update v1."), "", "^ baz 0.0.3 -> 0.0.5", "", @@ -248,6 +252,7 @@ for (const { input } of [{ input: { baz: "~0.0.3", moo: "~0.1.0" } }, { input: { ]); } else { expect(out2.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun update v1."), "", "+ @barn/moo@0.1.0", "+ baz@0.0.3", @@ -324,6 +329,7 @@ it("lockfile should not be modified when there are no version changes, issue#588 expect(err1).toContain("Saved lockfile"); const out1 = await new Response(stdout).text(); expect(out1.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ baz@0.0.3", "", diff --git a/test/cli/install/bun-workspaces.test.ts b/test/cli/install/bun-workspaces.test.ts index c5e8804d77f681..f692c7221563eb 100644 --- a/test/cli/install/bun-workspaces.test.ts +++ b/test/cli/install/bun-workspaces.test.ts @@ -83,7 +83,11 @@ test("dependency on workspace without version in package.json", async () => { const lockfile = parseLockfile(packageDir); expect(lockfile).toMatchNodeModulesAt(packageDir); expect(lockfile).toMatchSnapshot(`version: ${version}`); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); rmSync(join(packageDir, "node_modules"), { recursive: true, force: true }); rmSync(join(packageDir, "bun.lockb"), { recursive: true, force: true }); } @@ -106,7 +110,11 @@ test("dependency on workspace without version in package.json", async () => { const lockfile = parseLockfile(packageDir); expect(lockfile).toMatchNodeModulesAt(packageDir); expect(lockfile).toMatchSnapshot(`version: ${version}`); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "3 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "3 packages installed", + ]); rmSync(join(packageDir, "node_modules"), { recursive: true, force: true }); rmSync(join(packageDir, "packages", "bar", "node_modules"), { recursive: true, force: true }); rmSync(join(packageDir, "bun.lockb"), { recursive: true, force: true }); @@ -147,7 +155,11 @@ test("dependency on same name as workspace and dist-tag", async () => { const lockfile = parseLockfile(packageDir); expect(lockfile).toMatchSnapshot("with version"); expect(lockfile).toMatchNodeModulesAt(packageDir); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "3 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "3 packages installed", + ]); }); test("successfully installs workspace when path already exists in node_modules", async () => { @@ -218,6 +230,7 @@ test("adding workspace in workspace edits package.json with correct version (wor const out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed pkg2@workspace:apps/pkg2", "", diff --git a/test/cli/install/registry/bun-install-registry.test.ts b/test/cli/install/registry/bun-install-registry.test.ts index 75254b29c5c684..8966e19116c44c 100644 --- a/test/cli/install/registry/bun-install-registry.test.ts +++ b/test/cli/install/registry/bun-install-registry.test.ts @@ -871,6 +871,7 @@ test("hardlinks on windows dont fail with long paths", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@a-package", "", @@ -905,6 +906,7 @@ test("basic 1", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ basic-1@1.0.0", "", @@ -935,6 +937,7 @@ test("basic 1", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ basic-1@1.0.0", "", @@ -1027,6 +1030,7 @@ test("dependency from root satisfies range from dependency", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "+ one-range-dep@1.0.0", @@ -1057,6 +1061,7 @@ test("dependency from root satisfies range from dependency", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "+ one-range-dep@1.0.0", @@ -1263,6 +1268,7 @@ test("peerDependency in child npm dependency should not maintain old version whe expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "+ peer-deps-fixed@1.0.0", @@ -1307,6 +1313,7 @@ test("peerDependency in child npm dependency should not maintain old version whe } as any); expect(await exists(join(packageDir, "node_modules", "peer-deps-fixed", "node_modules"))).toBeFalse(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.1", "", @@ -1343,6 +1350,7 @@ test("package added after install", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ one-range-dep@1.0.0", "", @@ -1384,6 +1392,7 @@ test("package added after install", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "", @@ -1419,6 +1428,7 @@ test("package added after install", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "+ one-range-dep@1.0.0", @@ -1479,6 +1489,7 @@ test("--production excludes devDependencies in workspaces", async () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "", @@ -1498,6 +1509,7 @@ test("--production excludes devDependencies in workspaces", async () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ a1@1.0.0", "+ no-deps@1.0.0", @@ -1509,6 +1521,7 @@ test("--production excludes devDependencies in workspaces", async () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "", @@ -1549,6 +1562,7 @@ test("--production without a lockfile will install and not save lockfile", async expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "", @@ -1611,12 +1625,13 @@ describe("binaries", () => { 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([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uses-what-bin@1.5.0", "+ what-bin@1.0.0", "", - expect.stringContaining("3 packages installed"), + "3 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -1640,12 +1655,13 @@ describe("binaries", () => { expect(err).not.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([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uses-what-bin@1.5.0", "+ what-bin@1.0.0", "", - expect.stringContaining("3 packages installed"), + "3 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -1734,6 +1750,7 @@ describe("binaries", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bin-change-dir@1.0.0", "", @@ -1774,6 +1791,7 @@ describe("binaries", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bin-change-dir@1.0.1", "", @@ -1921,7 +1939,8 @@ test("it should install with missing bun.lockb, node_modules, and/or cache", asy 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([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ dep-loop-entry@1.0.0", "+ dep-with-tags@3.0.0", @@ -1936,7 +1955,7 @@ test("it should install with missing bun.lockb, node_modules, and/or cache", asy "+ uses-what-bin@1.5.0", "+ what-bin@1.0.0", "", - expect.stringContaining("19 packages installed"), + "19 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -1964,7 +1983,8 @@ test("it should install with missing bun.lockb, node_modules, and/or cache", asy expect(err).not.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([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ dep-loop-entry@1.0.0", "+ dep-with-tags@3.0.0", @@ -1979,7 +1999,7 @@ test("it should install with missing bun.lockb, node_modules, and/or cache", asy "+ uses-what-bin@1.5.0", "+ what-bin@1.0.0", "", - expect.stringContaining("19 packages installed"), + "19 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -2021,6 +2041,7 @@ test("it should install with missing bun.lockb, node_modules, and/or cache", asy expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", expect.stringContaining("Checked 19 installs across 23 packages (no changes)"), ]); @@ -2047,6 +2068,7 @@ test("it should install with missing bun.lockb, node_modules, and/or cache", asy expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", expect.stringContaining("Checked 19 installs across 23 packages (no changes)"), ]); @@ -2075,6 +2097,7 @@ test("it should install with missing bun.lockb, node_modules, and/or cache", asy expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", expect.stringContaining("Checked 19 installs across 23 packages (no changes)"), ]); @@ -2431,6 +2454,7 @@ describe("hoisting", async () => { expect(err).not.toContain("incorrect peer dependency"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "+ peer-deps-fixed@1.0.0", @@ -2481,6 +2505,7 @@ describe("hoisting", async () => { expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@2.0.0", "", @@ -2534,7 +2559,11 @@ describe("hoisting", async () => { }); let out = await Bun.readableStreamToText(stdout); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "3 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "3 packages installed", + ]); expect(await exited).toBe(0); // now run the install again but from the workspace and with `no-deps@2.0.0` @@ -2559,6 +2588,7 @@ describe("hoisting", async () => { out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@2.0.0", "", @@ -2600,6 +2630,7 @@ describe("hoisting", async () => { expect(err).toContain("incorrect peer dependency"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@2.0.0", "+ peer-deps-fixed@1.0.0", @@ -2650,6 +2681,7 @@ describe("hoisting", async () => { expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "", @@ -2929,6 +2961,7 @@ describe("workspaces", async () => { }); let out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed no-deps@2.0.0", "", @@ -2955,6 +2988,7 @@ describe("workspaces", async () => { })); out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed what-bin@1.5.0 with binaries:", " - what-bin", @@ -2984,6 +3018,7 @@ describe("workspaces", async () => { })); out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@2.0.0", "", @@ -3006,6 +3041,7 @@ describe("workspaces", async () => { })); out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ what-bin@1.5.0", "", @@ -3058,6 +3094,7 @@ describe("workspaces", async () => { let out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bar@workspace:packages/bar", "", @@ -3081,6 +3118,7 @@ describe("workspaces", async () => { out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed no-deps@2.0.0", "", @@ -3109,6 +3147,7 @@ describe("workspaces", async () => { out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed two-range-deps@1.0.0", "", @@ -3145,6 +3184,7 @@ describe("workspaces", async () => { out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed bar@0.0.7", "", @@ -3270,6 +3310,7 @@ describe("workspaces", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ pkg2@workspace:packages/pkg2`, "", @@ -3293,6 +3334,7 @@ describe("workspaces", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 2 installs across 3 packages (no changes)", ]); @@ -3317,6 +3359,7 @@ describe("workspaces", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ pkg2@workspace:packages/pkg2`, "", @@ -3340,6 +3383,7 @@ describe("workspaces", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 2 installs across 3 packages (no changes)", ]); @@ -3389,6 +3433,7 @@ describe("workspaces", async () => { expect(err).not.toContain('workspace dependency "workspace-1" not found'); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ workspace-1@workspace:packages/workspace-1`, "", @@ -3420,6 +3465,7 @@ describe("workspaces", async () => { expect(err).not.toContain('workspace dependency "workspace-1" not found'); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 1 install across 2 packages (no changes)", ]); @@ -3452,7 +3498,11 @@ describe("workspaces", async () => { expect(err).not.toContain("Duplicate dependency"); expect(err).not.toContain('workspace dependency "workspace-1" not found'); expect(err).not.toContain("error:"); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited).toBe(0); expect(await file(join(packageDir, "node_modules", "workspace-1", "package.json")).json()).toEqual({ name: "workspace-1", @@ -3477,6 +3527,7 @@ describe("workspaces", async () => { expect(err).not.toContain('workspace dependency "workspace-1" not found'); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 1 install across 2 packages (no changes)", ]); @@ -3640,7 +3691,11 @@ describe("transitive file dependencies", () => { var { out } = await runBunInstall(env, packageDir); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "14 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "14 packages installed", + ]); await checkHoistedFiles(); expect(await exists(join(packageDir, "pkg1", "node_modules"))).toBeFalse(); @@ -3651,14 +3706,22 @@ describe("transitive file dependencies", () => { ({ out } = await runBunInstall(env, packageDir, { savesLockfile: false })); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "14 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "14 packages installed", + ]); await checkHoistedFiles(); ({ out } = await runBunInstall(env, packageDir, { savesLockfile: false })); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); await checkHoistedFiles(); @@ -3670,6 +3733,7 @@ describe("transitive file dependencies", () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @another-scope/file-dep@1.0.0", "+ @scoped/file-dep@1.0.0", @@ -3688,7 +3752,11 @@ describe("transitive file dependencies", () => { ({ out } = await runBunInstall(env, join(packageDir, "pkg1"), { savesLockfile: false })); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); await rm(join(packageDir, "node_modules"), { recursive: true, force: true }); @@ -3696,6 +3764,7 @@ describe("transitive file dependencies", () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @another-scope/file-dep@1.0.0", "+ @scoped/file-dep@1.0.0", @@ -3757,6 +3826,7 @@ describe("transitive file dependencies", () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @another-scope/file-dep@1.0.1", "+ @scoped/file-dep@1.0.1", @@ -3779,6 +3849,7 @@ describe("transitive file dependencies", () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @another-scope/file-dep@1.0.1", "+ @scoped/file-dep@1.0.1", @@ -3796,7 +3867,11 @@ describe("transitive file dependencies", () => { ({ out } = await runBunInstall(env, packageDir, { savesLockfile: false })); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); await checkUnhoistedFiles(); @@ -3809,6 +3884,7 @@ describe("transitive file dependencies", () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @another-scope/file-dep@1.0.0", "+ @scoped/file-dep@1.0.0", @@ -3826,7 +3902,11 @@ describe("transitive file dependencies", () => { ({ out } = await runBunInstall(env, join(packageDir, "pkg1"), { savesLockfile: false })); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); await rm(join(packageDir, "node_modules"), { recursive: true, force: true }); await rm(join(packageDir, "pkg1", "node_modules"), { recursive: true, force: true }); @@ -3835,6 +3915,7 @@ describe("transitive file dependencies", () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @another-scope/file-dep@1.0.0", "+ @scoped/file-dep@1.0.0", @@ -3889,6 +3970,7 @@ describe("transitive file dependencies", () => { expect(err).not.toContain("error:"); expect(err).not.toContain("panic:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ @another-scope/file-dep@1.0.0", "+ @scoped/file-dep@1.0.0", @@ -3930,7 +4012,11 @@ describe("transitive file dependencies", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(err).not.toContain("panic:"); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "1 package installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "1 package installed", + ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -4013,6 +4099,7 @@ describe("transitive file dependencies", () => { expect(err).not.toContain("error:"); expect(err).not.toContain("panic:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ pkg0@pkg0", "+ pkg1@pkg1", @@ -4213,7 +4300,11 @@ describe("update", () => { let { out } = await runBunUpdate(env, packageDir); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "Checked 1 install across 2 packages (no changes)"]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + "Checked 1 install across 2 packages (no changes)", + ]); expect(await file(join(packageDir, "package.json")).json()).toEqual({ name: "foo", dependencies: { @@ -4225,7 +4316,11 @@ describe("update", () => { ({ out } = await runBunUpdate(env, packageDir)); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "Checked 1 install across 2 packages (no changes)"]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + "Checked 1 install across 2 packages (no changes)", + ]); expect(await file(join(packageDir, "package.json")).json()).toEqual({ name: "foo", dependencies: { @@ -4363,7 +4458,14 @@ describe("update", () => { let { out } = await runBunUpdate(env, packageDir, ["no-deps"]); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "installed no-deps@1.0.1", "", expect.stringContaining("done"), ""]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + "installed no-deps@1.0.1", + "", + expect.stringContaining("done"), + "", + ]); expect(await file(join(packageDir, "package.json")).json()).toEqual({ name: "foo", dependencies: { @@ -4376,7 +4478,13 @@ describe("update", () => { ({ out } = await runBunUpdate(env, packageDir, ["no-deps", "--latest"])); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "installed no-deps@2.0.0", "", "1 package installed"]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + "installed no-deps@2.0.0", + "", + "1 package installed", + ]); expect(await file(join(packageDir, "package.json")).json()).toEqual({ name: "foo", dependencies: { @@ -4466,7 +4574,13 @@ describe("update", () => { const { out } = await runBunUpdate(env, packageDir, ["--latest"]); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "^ aliased-dep 5.0.0-alpha.150 -> 5.0.0-alpha.153", "", "1 package installed"]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + "^ aliased-dep 5.0.0-alpha.150 -> 5.0.0-alpha.153", + "", + "1 package installed", + ]); expect(await file(join(packageDir, "package.json")).json()).toMatchObject({ name: "foo", dependencies: { @@ -4489,7 +4603,7 @@ describe("update", () => { let { out } = await runBunUpdate(env, packageDir, ["--no-save"]); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "+ a-dep@1.0.1", "", "1 package installed"]); + expect(out).toEqual([expect.stringContaining("bun update v1."), "", "+ a-dep@1.0.1", "", "1 package installed"]); expect(await file(join(packageDir, "package.json")).json()).toEqual({ name: "foo", dependencies: { @@ -4510,7 +4624,7 @@ describe("update", () => { ({ out } = await runBunUpdate(env, packageDir, ["--no-save"])); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "+ a-dep@1.0.10", "", "1 package installed"]); + expect(out).toEqual([expect.stringContaining("bun update v1."), "", "+ a-dep@1.0.10", "", "1 package installed"]); expect(await file(join(packageDir, "package.json")).json()).toEqual({ name: "foo", dependencies: { @@ -4522,7 +4636,11 @@ describe("update", () => { ({ out } = await runBunUpdate(env, packageDir)); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "Checked 1 install across 2 packages (no changes)"]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + "Checked 1 install across 2 packages (no changes)", + ]); expect(await file(join(packageDir, "package.json")).json()).toEqual({ name: "foo", dependencies: { @@ -4632,6 +4750,7 @@ describe("update", () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out).toEqual([ + expect.stringContaining("bun update v1."), "", "+ a-dep@1.0.10", "+ dep-loop-entry@1.0.0", @@ -4688,6 +4807,7 @@ describe("update", () => { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); expect(out).toEqual([ + expect.stringContaining("bun update v1."), "", "installed what-bin@1.5.0 with binaries:", " - what-bin", @@ -4733,7 +4853,14 @@ describe("update", () => { ({ out } = await runBunUpdate(env, join(packageDir, "packages", "pkg1"), ["a-dep@^1.0.5"])); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "installed a-dep@1.0.10", "", expect.stringMatching(/(\[\d+\.\d+m?s\])/), ""]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + "installed a-dep@1.0.10", + "", + expect.stringMatching(/(\[\d+\.\d+m?s\])/), + "", + ]); expect(await file(join(packageDir, "node_modules", "a-dep", "package.json")).json()).toMatchObject({ name: "a-dep", version: "1.0.10", @@ -4772,7 +4899,13 @@ describe("update", () => { const { out } = args ? await runBunUpdate(env, packageDir, ["a-dep"]) : await runBunUpdate(env, packageDir); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", args ? "installed a-dep@1.0.10" : "+ a-dep@1.0.10", "", "1 package installed"]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + args ? "installed a-dep@1.0.10" : "+ a-dep@1.0.10", + "", + "1 package installed", + ]); expect(await file(join(packageDir, "package.json")).json()).toEqual({ name: "foo", [group]: { @@ -4836,7 +4969,14 @@ describe("update", () => { let { out } = await runBunUpdate(env, packageDir, ["no-deps"]); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "installed no-deps@1.0.0", "", expect.stringMatching(/(\[\d+\.\d+m?s\])/), ""]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + "installed no-deps@1.0.0", + "", + expect.stringMatching(/(\[\d+\.\d+m?s\])/), + "", + ]); expect(await file(join(packageDir, "node_modules", "no-deps", "package.json")).json()).toMatchObject({ version: "1.0.0", }); @@ -4845,7 +4985,13 @@ describe("update", () => { ({ out } = await runBunUpdate(env, join(packageDir, "packages", "pkg1"), ["no-deps"])); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "installed no-deps@2.0.0", "", "1 package installed"]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + "installed no-deps@2.0.0", + "", + "1 package installed", + ]); expect(await file(join(packageDir, "node_modules", "no-deps", "package.json")).json()).toMatchObject({ version: "1.0.0", }); @@ -4873,7 +5019,13 @@ describe("update", () => { ({ out } = await runBunUpdate(env, packageDir, ["no-deps"])); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toEqual(["", "installed no-deps@1.1.0", "", "1 package installed"]); + expect(out).toEqual([ + expect.stringContaining("bun update v1."), + "", + "installed no-deps@1.1.0", + "", + "1 package installed", + ]); expect(await file(join(packageDir, "node_modules", "no-deps", "package.json")).json()).toMatchObject({ version: "1.1.0", }); @@ -4957,6 +5109,7 @@ test("it should re-populate .bin folder if package is reinstalled", async () => expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ what-bin@1.5.0", "", @@ -4993,10 +5146,11 @@ test("it should re-populate .bin folder if package is reinstalled", async () => expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ what-bin@1.5.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -5036,6 +5190,7 @@ test("one version with binary map", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ map-bin@1.0.2", "", @@ -5075,6 +5230,7 @@ test("multiple versions with binary map", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ map-bin-multiple@1.0.2", "", @@ -5165,7 +5321,8 @@ test("missing package on reinstall, some with binaries", async () => { 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([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ dep-loop-entry@1.0.0", "+ dep-with-tags@3.0.0", @@ -5180,7 +5337,7 @@ test("missing package on reinstall, some with binaries", async () => { "+ uses-what-bin@1.5.0", "+ what-bin@1.0.0", "", - expect.stringContaining("19 packages installed"), + "19 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -5219,6 +5376,7 @@ test("missing package on reinstall, some with binaries", async () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ dep-loop-entry@1.0.0", "+ left-pad@1.0.0", @@ -5226,7 +5384,7 @@ test("missing package on reinstall, some with binaries", async () => { "+ one-fixed-dep@2.0.0", "+ peer-deps-too@1.0.0", "", - expect.stringContaining("7 packages installed"), + "7 packages installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -5358,10 +5516,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ all-lifecycle-scripts@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -5414,10 +5573,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ all-lifecycle-scripts@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await file(join(packageDir, "preinstall.txt")).text()).toBe("preinstall!"); @@ -5501,7 +5661,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); expect(err).toContain("Saved lockfile"); var out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "2 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "2 packages installed", + ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -5599,11 +5763,12 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { 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([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ all-lifecycle-scripts@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", "", "Blocked 3 postinstalls. Run `bun pm untrusted` for details.", "", @@ -5648,6 +5813,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", expect.stringContaining("Checked 1 install across 2 packages (no changes)"), ]); @@ -5692,6 +5858,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ what-bin@1.0.0", "", @@ -5721,6 +5888,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 1 install across 2 packages (no changes)", ]); @@ -5754,6 +5922,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ what-bin@1.0.0", "", @@ -5780,6 +5949,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 1 install across 2 packages (no changes)", ]); @@ -5817,6 +5987,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 1 install across 2 packages (no changes)", ]); @@ -5852,11 +6023,12 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { var err = await new Response(stderr).text(); var out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ lifecycle-postinstall@1.0.0", "", // @ts-ignore - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(err).toContain("Saved lockfile"); expect(err).not.toContain("not found"); @@ -5878,10 +6050,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { err = await new Response(stderr).text(); out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ lifecycle-postinstall@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(err).not.toContain("Saved lockfile"); expect(err).not.toContain("not found"); @@ -5938,11 +6111,12 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ another-init-cwd@1.0.0", "+ lifecycle-init-cwd@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -5982,7 +6156,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); const out = await new Response(stdout).text(); - expect(out).toBeEmpty(); + expect(out).toEqual(expect.stringContaining("bun install v1.")); }); test("failing root lifecycle script should print output correctly", async () => { @@ -6010,7 +6184,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(await exited).toBe(1); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(await Bun.readableStreamToText(stdout)).toBeEmpty(); + expect(await Bun.readableStreamToText(stdout)).toEqual(expect.stringContaining("bun install v1.")); const err = await Bun.readableStreamToText(stderr); expect(err).toContain("error: Oops!"); expect(err).toContain('error: preinstall script from "fooooooooo" exited with 1'); @@ -6047,6 +6221,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", expect.stringContaining("done"), "", @@ -6085,6 +6260,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("hello"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ lifecycle-failing-postinstall@1.0.0", "", @@ -6124,10 +6300,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ binding-gyp-scripts@1.5.0", "", - expect.stringContaining("2 packages installed"), + "2 packages installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -6161,11 +6338,12 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ binding-gyp-scripts@1.5.0", "", - expect.stringContaining("2 packages installed"), + "2 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -6230,10 +6408,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ node-gyp@1.5.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -6293,10 +6472,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ node-gyp@1.5.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -6336,10 +6516,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ node-gyp@1.5.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -6376,11 +6557,12 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ lifecycle-install-test@github:dylan-conway/lifecycle-install-test#3ba6af5", "", - expect.stringContaining("1 package installed"), + "1 package installed", "", "Blocked 6 postinstalls. Run `bun pm untrusted` for details.", "", @@ -6471,6 +6653,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uses-what-bin-slow@1.0.0", "", @@ -6544,6 +6727,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { const out = await Bun.readableStreamToText(stdout); expect(out).not.toContain("Blocked"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", ...dependenciesList.map(dep => `+ ${dep}@${dep}`), "", @@ -6577,6 +6761,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { const out = await Bun.readableStreamToText(stdout); expect(out).not.toContain("Blocked"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", ...dependenciesList.map(dep => `+ ${dep}@${dep}`).sort((a, b) => a.localeCompare(b)), "", @@ -6621,12 +6806,13 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); var out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uses-what-bin@1.0.0", "+ what-bin@1.5.0", "", - expect.stringContaining("3 packages installed"), + "3 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -6702,11 +6888,12 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uses-what-bin@1.5.0", "+ what-bin@1.0.0", "", - expect.stringContaining("3 packages installed"), + "3 packages installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -6776,10 +6963,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ electron@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(out).not.toContain("Blocked"); expect(await exists(join(packageDir, "node_modules", "electron", "preinstall.txt"))).toBeTrue(); @@ -6818,12 +7006,13 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); var out = await new Response(stdout).text(); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ electron@1.0.0", "+ uses-what-bin@1.0.0", "", - expect.stringContaining("3 packages installed"), + "3 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -6867,12 +7056,13 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); out = await Bun.readableStreamToText(stdout); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ electron@1.0.0", "+ uses-what-bin@1.0.0", "", - expect.stringContaining("3 packages installed"), + "3 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -6914,12 +7104,13 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { 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([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ electron@1.0.0", "+ uses-what-bin@1.0.0", "", - expect.stringContaining("3 packages installed"), + "3 packages installed", "", "Blocked 2 postinstalls. Run `bun pm untrusted` for details.", "", @@ -6962,11 +7153,12 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); var out = await Bun.readableStreamToText(stdout); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ electron@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -7004,6 +7196,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 1 install across 2 packages (no changes)", ]); @@ -7152,6 +7345,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("warn:"); let out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed uses-what-bin@1.0.0", "", @@ -7184,6 +7378,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("warn:"); out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 2 installs across 3 packages (no changes)", ]); @@ -7217,10 +7412,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("warn:"); const out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed no-deps@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); expect(await exists(join(packageDir, "node_modules", "no-deps"))).toBeTrue(); @@ -7256,10 +7452,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("warn:"); let out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed no-deps@2.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); expect(await exists(join(packageDir, "node_modules", "no-deps"))).toBeTrue(); @@ -7292,6 +7489,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun add v1."), "", "installed no-deps@2.0.0", "", @@ -7341,10 +7539,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("warn:"); let out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uses-what-bin@1.0.0", "", - expect.stringContaining("2 packages installed"), + "2 packages installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -7375,6 +7574,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("warn:"); out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 2 installs across 3 packages (no changes)", ]); @@ -7412,10 +7612,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("warn:"); let out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uses-what-bin@1.0.0", "", - expect.stringContaining("2 packages installed"), + "2 packages installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -7458,6 +7659,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("warn:"); out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 2 installs across 3 packages (no changes)", ]); @@ -7502,10 +7704,11 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("warn:"); let out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ electron@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -7550,6 +7753,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("warn:"); out = await Bun.readableStreamToText(stdout); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "Checked 1 install across 2 packages (no changes)", ]); @@ -7662,11 +7866,12 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); expect(err).not.toContain("warn:"); let out = await Bun.readableStreamToText(stdout); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uses-what-bin@1.5.0", "", - expect.stringContaining("2 packages installed"), + "2 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -7742,12 +7947,13 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); expect(err).not.toContain("warn:"); let out = await Bun.readableStreamToText(stdout); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "+ uses-what-bin@1.0.0", "", - expect.stringContaining("3 packages installed"), + "3 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -7829,6 +8035,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { let expected = withRm ? ["", "Checked 1 install across 2 packages (no changes)"] : ["", expect.stringContaining("1 package removed")]; + expected = [expect.stringContaining("bun install v1."), ...expected]; expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(expected); expect(await exited).toBe(0); expect(await exists(join(packageDir, "node_modules", "uses-what-bin"))).toBe(!withRm); @@ -7865,13 +8072,14 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { "", "+ uses-what-bin@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", ] - : ["", expect.stringContaining("Checked 3 installs across 4 packages (no changes)")]; - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(expected); + : ["", expect.stringContaining("Checked 3 installs across 4 packages (no changes)"), ""]; + expected = [expect.stringContaining("bun install v1."), ...expected]; + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual(expected); ({ stdout, stderr, exited } = spawn({ cmd: [bunExe(), "pm", "untrusted"], @@ -7997,7 +8205,6 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); expect(err).not.toContain("warn:"); expect(err.split(/\r?\n/)).toEqual([ - expect.stringContaining("bun install"), "No packages! Deleted empty lockfile", "", `$ ${exe} -e 'process.stderr.write("preinstall stderr 🍦\\n")'`, @@ -8008,6 +8215,7 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { ]); const out = await Bun.readableStreamToText(stdout); expect(out.split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "install stdout 🚀", "prepare stdout done ✅", "", @@ -8050,7 +8258,6 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { expect(err).not.toContain("error:"); expect(err).not.toContain("warn:"); expect(err.split(/\r?\n/)).toEqual([ - expect.stringContaining("bun install"), "Resolving dependencies", expect.stringContaining("Resolved, downloaded and extracted "), "Saved lockfile", @@ -8062,14 +8269,14 @@ for (const forceWaiterThread of isLinux ? [false, true] : [false]) { "", ]); const out = await Bun.readableStreamToText(stdout); - expect(out.split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "install stdout 🚀", "prepare stdout done ✅", "", "+ no-deps@1.0.0", "", - expect.stringContaining("1 package installed"), - "", + "1 package installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -8152,11 +8359,12 @@ describe("pm trust", async () => { expect(err).not.toContain("error:"); expect(err).not.toContain("warn:"); let out = await Bun.readableStreamToText(stdout); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect(out.replace(/\s*\[[0-9\.]+m?s\]$/m, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ uses-what-bin@1.0.0", "", - expect.stringContaining("2 packages installed"), + "2 packages installed", "", "Blocked 1 postinstall. Run `bun pm untrusted` for details.", "", @@ -8227,10 +8435,11 @@ test("it should be able to find binary in node_modules/.bin from parent director expect(err).not.toContain("error:"); const out = await new Response(stdout).text(); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ what-bin@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -8365,6 +8574,7 @@ describe("semver", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ dep-with-tags@${expected}`, "", @@ -8402,7 +8612,7 @@ describe("semver", () => { expect(await exited).toBe(1); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); - expect(out).toBeEmpty(); + expect(out).toEqual(expect.stringContaining("bun install v1.")); }); }); @@ -8590,6 +8800,7 @@ for (let i = 0; i < prereleaseTests.length; i++) { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", `+ ${depName}@${expected}`, "", @@ -8731,7 +8942,7 @@ for (let i = 0; i < prereleaseFailTests.length; i++) { const err = await new Response(stderr).text(); const out = await new Response(stdout).text(); - expect(out).toBeEmpty(); + expect(out).toEqual(expect.stringContaining("bun install v1.")); expect(err).toContain(`No version matching "${depVersion}" found for specifier "${depName}"`); expect(await exited).toBe(1); assertManifestsPopulated(join(packageDir, ".bun-cache"), registryUrl()); @@ -8769,6 +8980,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ dragon-test-1-d@1.0.0", "+ dragon-test-1-e@1.0.0", @@ -8858,6 +9070,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ dragon-test-2-a@workspace:dragon-test-2-a", "", @@ -8904,6 +9117,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ dragon-test-3-a@1.0.0", "", @@ -8969,7 +9183,11 @@ describe("yarn tests", () => { 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(["", "3 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "3 packages installed", + ]); expect(await readdirSorted(join(packageDir, "node_modules"))).toEqual(["my-workspace", "no-deps", "peer-deps"]); expect(await file(join(packageDir, "node_modules", "no-deps", "package.json")).json()).toEqual({ name: "no-deps", @@ -9038,7 +9256,11 @@ describe("yarn tests", () => { 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(["", "5 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "5 packages installed", + ]); expect(await readdirSorted(join(packageDir, "node_modules"))).toEqual([ "a", "b", @@ -9166,6 +9388,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ a@workspace:packages/a", "+ b@workspace:packages/b", @@ -9211,6 +9434,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ dragon-test-7-a@1.0.0", "+ dragon-test-7-b@2.0.0", @@ -9293,6 +9517,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ dragon-test-8-a@1.0.0", "+ dragon-test-8-b@1.0.0", @@ -9333,6 +9558,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("error:"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ first@1.0.0", "+ no-deps@1.0.0", @@ -9410,6 +9636,7 @@ describe("yarn tests", () => { expect(err).not.toContain("error:"); expect(err).not.toContain("not found"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ a@workspace:packages/a", "+ b@workspace:packages/b", @@ -9471,7 +9698,11 @@ describe("yarn tests", () => { expect(err).toContain("Saved lockfile"); expect(err).not.toContain("error:"); expect(err).not.toContain("not found"); - expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual(["", "4 packages installed"]); + expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), + "", + "4 packages installed", + ]); expect(await readdirSorted(join(packageDir, "node_modules"))).toEqual([ "fake-peer-deps", "no-deps", @@ -9519,6 +9750,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("incorrect peer dependency"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "+ peer-deps-fixed@1.0.0", @@ -9559,6 +9791,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).toContain("incorrect peer dependency"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@2.0.0", "+ peer-deps-fixed@1.0.0", @@ -9599,6 +9832,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("incorrect peer dependency"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ provides-peer-deps-1-0-0@1.0.0", "+ provides-peer-deps-2-0-0@1.0.0", @@ -9706,6 +9940,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("incorrect peer dependency"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ provides-peer-deps-1-0-0@1.0.0", "+ provides-peer-deps-1-0-0-too@1.0.0", @@ -9770,6 +10005,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("incorrect peer dependency"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ forward-peer-deps@1.0.0", "+ forward-peer-deps-too@1.0.0", @@ -9835,6 +10071,7 @@ describe("yarn tests", () => { expect(err).not.toContain("not found"); expect(err).not.toContain("incorrect peer dependency"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps@1.0.0", "+ peer-deps@1.0.0", @@ -9893,11 +10130,12 @@ describe("yarn tests", () => { expect(err).not.toContain("error:"); expect(err).not.toContain("not found"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ no-deps-scripted@1.0.0", "+ one-dep-scripted@1.5.0", "", - expect.stringContaining("4 packages installed"), + "4 packages installed", ]); expect(await exists(join(packageDir, "node_modules/one-dep-scripted/success.txt"))).toBeTrue(); expect(await exited).toBe(0); @@ -10090,7 +10328,11 @@ describe("outdated", () => { expect(err).not.toContain("error:"); expect(err).not.toContain("panic:"); const out = await Bun.readableStreamToText(stdout); - expect(out).toMatchSnapshot(); + const first = out.slice(0, out.indexOf("\n")); + expect(first).toEqual(expect.stringContaining("bun outdated ")); + expect(first).toEqual(expect.stringContaining("v1.")); + const rest = out.slice(out.indexOf("\n") + 1); + expect(rest).toMatchSnapshot(); }); } test("in workspace", async () => { @@ -10179,7 +10421,11 @@ describe("outdated", () => { const out = await Bun.readableStreamToText(stdout); expect(out).toContain("a-dep"); - expect(out).toMatchSnapshot(); + const first = out.slice(0, out.indexOf("\n")); + expect(first).toEqual(expect.stringContaining("bun outdated ")); + expect(first).toEqual(expect.stringContaining("v1.")); + const rest = out.slice(out.indexOf("\n") + 1); + expect(rest).toMatchSnapshot(); expect(await exited).toBe(0); }); @@ -10367,10 +10613,11 @@ registry = "http://localhost:${port}/" expect(err).not.toContain("panic:"); expect(err).not.toContain("not found"); expect(out.replace(/\s*\[[0-9\.]+m?s\]\s*$/, "").split(/\r?\n/)).toEqual([ + expect.stringContaining("bun install v1."), "", "+ bunx-bins@1.0.0", "", - expect.stringContaining("1 package installed"), + "1 package installed", ]); expect(await exited).toBe(0); diff --git a/test/cli/run/env.test.ts b/test/cli/run/env.test.ts index 18dd4122ffb6f5..c2f3439a2b4d47 100644 --- a/test/cli/run/env.test.ts +++ b/test/cli/run/env.test.ts @@ -104,7 +104,7 @@ describe(".env file is loaded", () => { "index.test.ts": "console.log(process.env.A,process.env.B,process.env.C,process.env.FAIL);", }); const { stdout } = bunTest(`${dir}/index.test.ts`, {}); - expect(stdout).toBe("a b c undefined"); + expect(stdout).toBe(`bun test ${Bun.version_with_sha}\n` + "a b c undefined"); }); test(".env.local ignored when bun test", () => { const dir = tempDirWithFiles("dotenv", { @@ -113,7 +113,7 @@ describe(".env file is loaded", () => { "index.test.ts": "console.log(process.env.FAILED);", }); const { stdout } = bunTest(`${dir}/index.test.ts`, {}); - expect(stdout).toBe("false"); + expect(stdout).toBe(`bun test ${Bun.version_with_sha}\n` + "false"); }); test(".env.development and .env.production ignored when bun test", () => { const dir = tempDirWithFiles("dotenv", { @@ -125,14 +125,14 @@ describe(".env file is loaded", () => { "index.test.ts": "console.log(process.env.FAILED);", }); const { stdout } = bunTest(`${dir}/index.test.ts`); - expect(stdout).toBe("false"); + expect(stdout).toBe(`bun test ${Bun.version_with_sha}\n` + "false"); }); test("NODE_ENV is automatically set to test within bun test", () => { const dir = tempDirWithFiles("dotenv", { "index.test.ts": "console.log(process.env.NODE_ENV);", }); const { stdout } = bunTest(`${dir}/index.test.ts`); - expect(stdout).toBe("test"); + expect(stdout).toBe(`bun test ${Bun.version_with_sha}\n` + "test"); }); }); describe("dotenv priority", () => { @@ -153,7 +153,7 @@ describe("dotenv priority", () => { expect(stdout).toBe("override"); const { stdout: stdout2 } = bunTest(`${dir}/index.test.ts`, { FOO: "override" }); - expect(stdout2).toBe("override"); + expect(stdout2).toBe(`bun test ${Bun.version_with_sha}\n` + "override"); }); test(".env.{NODE_ENV}.local overrides .env.local", () => { const dir = tempDirWithFiles("dotenv", { @@ -173,7 +173,7 @@ describe("dotenv priority", () => { const { stdout: stdout_prod } = bunRun(`${dir}/index.ts`, { NODE_ENV: "production" }); expect(stdout_prod).toBe(".env.production.local"); const { stdout: stdout_test } = bunTest(`${dir}/index.test.ts`, {}); - expect(stdout_test).toBe(".env.test.local"); + expect(stdout_test).toBe(`bun test ${Bun.version_with_sha}\n` + ".env.test.local"); }); test(".env.local overrides .env.{NODE_ENV}", () => { const dir = tempDirWithFiles("dotenv", { @@ -191,7 +191,7 @@ describe("dotenv priority", () => { expect(stdout_prod).toBe(".env.local"); // .env.local is "not checked when `NODE_ENV` is `test`" const { stdout: stdout_test } = bunTest(`${dir}/index.test.ts`, {}); - expect(stdout_test).toBe(".env.test"); + expect(stdout_test).toBe(`bun test ${Bun.version_with_sha}\n` + ".env.test"); }); test(".env.{NODE_ENV} overrides .env", () => { const dir = tempDirWithFiles("dotenv", { @@ -207,7 +207,7 @@ describe("dotenv priority", () => { const { stdout: stdout_prod } = bunRun(`${dir}/index.ts`, { NODE_ENV: "production" }); expect(stdout_prod).toBe(".env.production"); const { stdout: stdout_test } = bunTest(`${dir}/index.test.ts`, {}); - expect(stdout_test).toBe(".env.test"); + expect(stdout_test).toBe(`bun test ${Bun.version_with_sha}\n` + ".env.test"); }); }); @@ -643,7 +643,7 @@ console.log(process.env.NODE_ENV, process.env.YOLO);`, bunTest(path.join(tmp, "index.test.ts"), { YOLO: "boo", }).stdout, - ).toBe("test\ndevelopment woo!"); + ).toBe(`bun test ${Bun.version_with_sha}\n` + "test\ndevelopment woo!"); }); test("in bun test with explicit setting", () => { const tmp = tempDirWithFiles("env-inlining", { @@ -659,7 +659,7 @@ console.log(process.env.NODE_ENV, process.env.YOLO);`, YOLO: "boo", NODE_ENV: "production", }).stdout, - ).toBe("production\ndevelopment woo!"); + ).toBe(`bun test ${Bun.version_with_sha}\n` + "production\ndevelopment woo!"); }); test("in bun test with dynamic access", () => { const tmp = tempDirWithFiles("env-inlining", { @@ -670,7 +670,9 @@ test("my test", () => { console.log(dynamic().NODE_ENV); });`, }); - expect(bunTest(path.join(tmp, "index.test.ts"), {}).stdout).toBe("test\nproduction"); + expect(bunTest(path.join(tmp, "index.test.ts"), {}).stdout).toBe( + `bun test ${Bun.version_with_sha}\n` + "test\nproduction", + ); }); test("in bun test with dynamic access + explicit set", () => { const tmp = tempDirWithFiles("env-inlining", { @@ -682,7 +684,7 @@ test("my test", () => { });`, }); expect(bunTest(path.join(tmp, "index.test.ts"), { NODE_ENV: "development" }).stdout).toBe( - "development\nproduction", + `bun test ${Bun.version_with_sha}\n` + "development\nproduction", ); }); }); diff --git a/test/js/bun/resolve/import-custom-condition.test.ts b/test/js/bun/resolve/import-custom-condition.test.ts index fa753b5a0b54ab..ac366209fed54f 100644 --- a/test/js/bun/resolve/import-custom-condition.test.ts +++ b/test/js/bun/resolve/import-custom-condition.test.ts @@ -109,7 +109,7 @@ it("custom condition 'import' in package.json resolves in bun test", async () => }); expect(exitCode).toBe(0); - expect(stdout.toString("utf8")).toBe("1\n"); + expect(stdout.toString("utf8")).toBe(`bun test ${Bun.version_with_sha}\n1\n`); }); it("custom condition 'import' in package.json resolves in bun test with browser condition", async () => { @@ -120,7 +120,7 @@ it("custom condition 'import' in package.json resolves in bun test with browser }); expect(exitCode).toBe(0); - expect(stdout.toString("utf8")).toBe("2\n"); + expect(stdout.toString("utf8")).toBe(`bun test ${Bun.version_with_sha}\n2\n`); }); it("custom condition 'require' in package.json resolves", async () => { diff --git a/test/js/bun/shell/bunshell-default.test.ts b/test/js/bun/shell/bunshell-default.test.ts index 6c5b6b9ce9f81c..ddd78df4dba18f 100644 --- a/test/js/bun/shell/bunshell-default.test.ts +++ b/test/js/bun/shell/bunshell-default.test.ts @@ -23,6 +23,7 @@ test("default throw on command failure", async () => { await TestBuilder.command`echo ${code} > index.test.ts; ${bunExe()} test index.test.ts` .ensureTempDir() + .stdout(`bun test ${Bun.version_with_sha}\n`) .stderr(s => s.includes("1 pass")) .env(bunEnv) .run(); @@ -47,6 +48,7 @@ test("ShellError has .text()", async () => { await TestBuilder.command`echo ${code} > index.test.ts; ${bunExe()} test index.test.ts` .ensureTempDir() + .stdout(`bun test ${Bun.version_with_sha}\n`) .stderr(s => s.includes("1 pass")) .env(bunEnv) .run(); diff --git a/test/js/bun/test/test-test.test.ts b/test/js/bun/test/test-test.test.ts index a6fce244ee7f76..76868a5d03802e 100644 --- a/test/js/bun/test/test-test.test.ts +++ b/test/js/bun/test/test-test.test.ts @@ -43,7 +43,7 @@ it("shouldn't crash when async test runner callback throws", async () => { expect(err).toContain("error: ##123##"); expect(err).toContain("error: ##456##"); expect(stdout).toBeDefined(); - expect(await new Response(stdout).text()).toBe(""); + expect(await new Response(stdout).text()).toBe(`bun test ${Bun.version_with_sha}\n`); expect(await exited).toBe(1); } finally { await rm(test_dir, { force: true, recursive: true }); @@ -189,19 +189,19 @@ test("describe scope throwing doesn't block other tests from running", async () it("test enqueued before a describe scope throws is never run", () => { throw new Error("This test failed"); }); - + throw "This test passed. Ignore the error message"; - + it("test enqueued after a describe scope throws is never run", () => { throw new Error("This test failed"); }); }); - + it("a describe scope throwing doesn't cause all other tests in the file to fail", () => { console.log( String.fromCharCode(...[73, 32, 104, 97, 118, 101, 32, 98, 101, 101, 110, 32, 114, 101, 97, 99, 104, 101, 100, 33]), ); - }); + }); `; const dir = tmpdirSync(); @@ -303,7 +303,7 @@ it("should return non-zero exit code for invalid syntax", async () => { expect(err).toContain(" 1 fail"); expect(err).toContain("Ran 1 tests across 1 files"); expect(stdout).toBeDefined(); - expect(await new Response(stdout).text()).toBe(""); + expect(await new Response(stdout).text()).toBe(`bun test ${Bun.version_with_sha}\n`); expect(await exited).toBe(1); } finally { await rm(test_dir, { force: true, recursive: true }); @@ -331,7 +331,7 @@ it("invalid syntax counts towards bail", async () => { expect(err).not.toContain("DO NOT RUN ME"); expect(err).toContain("Ran 3 tests across 3 files"); expect(stdout).toBeDefined(); - expect(await new Response(stdout).text()).toBe(""); + expect(await new Response(stdout).text()).toBe(`bun test ${Bun.version_with_sha}\n`); expect(await exited).toBe(1); } finally { // await rm(test_dir, { force: true, recursive: true }); @@ -584,6 +584,7 @@ it("test --preload supports global lifecycle hooks", () => { }); expect(stdout.toString().trim()).toBe( ` +bun test ${Bun.version_with_sha} beforeAll: #1 beforeAll: #2 beforeAll: TEST-FILE @@ -661,7 +662,14 @@ describe("empty", () => { expect(err).toContain("0 fail"); expect(stdout).toBeDefined(); const out = await new Response(stdout).text(); - expect(out.split(/\r?\n/)).toEqual(["before all", "before all scoped", "after all scoped", "after all", ""]); + expect(out.split(/\r?\n/)).toEqual([ + `bun test ${Bun.version_with_sha}`, + "before all", + "before all scoped", + "after all scoped", + "after all", + "", + ]); expect(await exited).toBe(0); } finally { await rm(test_dir, { force: true, recursive: true }); diff --git a/test/js/node/stream/node-stream.test.js b/test/js/node/stream/node-stream.test.js index c96be303f79775..287aaf8f74cc4b 100644 --- a/test/js/node/stream/node-stream.test.js +++ b/test/js/node/stream/node-stream.test.js @@ -342,7 +342,7 @@ it.if(isMacOS || isGlibcVersionAtLeast("2.36.0"))("TTY streams", () => { stdio: ["ignore", "pipe", "pipe"], }); - expect(stdout.toString()).toBe(""); + expect(stdout.toString()).toEqual(expect.stringContaining("bun test v1.")); try { expect(stderr.toString()).toContain("0 fail"); } catch (error) { diff --git a/test/regression/issue/08964/08964.test.ts b/test/regression/issue/08964/08964.test.ts index e97f0685b9d71c..20e98b84567098 100644 --- a/test/regression/issue/08964/08964.test.ts +++ b/test/regression/issue/08964/08964.test.ts @@ -10,7 +10,7 @@ test("issue 8964", async () => { stdio: ["ignore", "pipe", "inherit"], }); const stdtext = stdout.toString(); - const [actual, expected] = stdout.toString().split("\n"); + const [, actual, expected] = stdout.toString().split("\n"); expect(actual.replace("EXPECTED:", "ACTUAL:")).toBe(expected); expect(exitCode).toBe(0); expect(signalCode).toBeUndefined();