mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 13:51:47 +00:00
Compare commits
1 Commits
claude/red
...
claude/add
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0dca0ee6a9 |
@@ -470,6 +470,37 @@ pub const Bunfig = struct {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (test_.get("resolveExtensions")) |expr| brk: {
|
||||
// Only apply bunfig value if not already set via CLI
|
||||
if (this.ctx.test_options.resolve_extensions != null) break :brk;
|
||||
|
||||
switch (expr.data) {
|
||||
.e_string => |str| {
|
||||
const pattern = try str.string(allocator);
|
||||
const patterns = try allocator.alloc(string, 1);
|
||||
patterns[0] = pattern;
|
||||
this.ctx.test_options.resolve_extensions = patterns;
|
||||
},
|
||||
.e_array => |arr| {
|
||||
if (arr.items.len == 0) break :brk;
|
||||
|
||||
const patterns = try allocator.alloc(string, arr.items.len);
|
||||
for (arr.items.slice(), 0..) |item, i| {
|
||||
if (item.data != .e_string) {
|
||||
try this.addError(item.loc, "resolveExtensions array must contain only strings");
|
||||
return;
|
||||
}
|
||||
patterns[i] = try item.data.e_string.string(allocator);
|
||||
}
|
||||
this.ctx.test_options.resolve_extensions = patterns;
|
||||
},
|
||||
else => {
|
||||
try this.addError(expr.loc, "resolveExtensions must be a string or array of strings");
|
||||
return;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -353,6 +353,7 @@ pub const Command = struct {
|
||||
test_filter_pattern: ?[]const u8 = null,
|
||||
test_filter_regex: ?*RegularExpression = null,
|
||||
max_concurrency: u32 = 20,
|
||||
resolve_extensions: ?[]const []const u8 = null,
|
||||
|
||||
reporters: struct {
|
||||
dots: bool = false,
|
||||
|
||||
@@ -219,6 +219,7 @@ pub const test_only_params = [_]ParamType{
|
||||
clap.parseParam("--dots Enable dots reporter. Shorthand for --reporter=dots.") catch unreachable,
|
||||
clap.parseParam("--only-failures Only display test failures, hiding passing tests.") catch unreachable,
|
||||
clap.parseParam("--max-concurrency <NUMBER> Maximum number of concurrent tests to execute at once. Default is 20.") catch unreachable,
|
||||
clap.parseParam("--resolve-extensions <STR>... Test file name suffixes to match. Defaults to ['.test', '_test', '.spec', '_spec'].") catch unreachable,
|
||||
};
|
||||
pub const test_params = test_only_params ++ runtime_params_ ++ transpiler_params_ ++ base_params_;
|
||||
|
||||
@@ -566,6 +567,15 @@ pub fn parse(allocator: std.mem.Allocator, ctx: Command.Context, comptime cmd: C
|
||||
std.process.exit(1);
|
||||
};
|
||||
}
|
||||
|
||||
if (args.options("--resolve-extensions").len > 0) {
|
||||
const extensions = args.options("--resolve-extensions");
|
||||
const patterns = try allocator.alloc(string, extensions.len);
|
||||
for (extensions, 0..) |ext, i| {
|
||||
patterns[i] = ext;
|
||||
}
|
||||
ctx.test_options.resolve_extensions = patterns;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.args.absolute_working_dir = cwd;
|
||||
|
||||
@@ -14,6 +14,9 @@ scan_dir_buf: bun.PathBuffer = undefined,
|
||||
options: *BundleOptions,
|
||||
has_iterated: bool = false,
|
||||
search_count: usize = 0,
|
||||
/// Custom test name suffixes to use instead of the default ones.
|
||||
/// If null, uses the default test_name_suffixes.
|
||||
custom_test_name_suffixes: ?[]const []const u8 = null,
|
||||
|
||||
const log = bun.Output.scoped(.jest, .hidden);
|
||||
const Fifo = bun.LinearFifo(ScanEntry, .Dynamic);
|
||||
@@ -129,8 +132,16 @@ pub fn couldBeTestFile(this: *Scanner, name: []const u8, comptime needs_test_suf
|
||||
if (extname.len == 0 or !this.options.loader(extname).isJavaScriptLike()) return false;
|
||||
if (comptime !needs_test_suffix) return true;
|
||||
const name_without_extension = name[0 .. name.len - extname.len];
|
||||
inline for (test_name_suffixes) |suffix| {
|
||||
if (strings.endsWithComptime(name_without_extension, suffix)) return true;
|
||||
|
||||
// Use custom suffixes if provided, otherwise use defaults
|
||||
if (this.custom_test_name_suffixes) |custom_suffixes| {
|
||||
for (custom_suffixes) |suffix| {
|
||||
if (strings.endsWith(name_without_extension, suffix)) return true;
|
||||
}
|
||||
} else {
|
||||
inline for (test_name_suffixes) |suffix| {
|
||||
if (strings.endsWithComptime(name_without_extension, suffix)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1447,6 +1447,7 @@ pub const TestCommand = struct {
|
||||
|
||||
var scanner = bun.handleOom(Scanner.init(ctx.allocator, &vm.transpiler, ctx.positionals.len));
|
||||
defer scanner.deinit();
|
||||
scanner.custom_test_name_suffixes = ctx.test_options.resolve_extensions;
|
||||
const has_relative_path = for (ctx.positionals) |arg| {
|
||||
if (std.fs.path.isAbsolute(arg) or
|
||||
strings.startsWith(arg, "./") or
|
||||
@@ -1590,15 +1591,39 @@ pub const TestCommand = struct {
|
||||
if (ctx.positionals.len < 2) {
|
||||
if (Output.isAIAgent()) {
|
||||
// Be very clear to ai.
|
||||
Output.errGeneric("0 test files matching **{{.test,.spec,_test_,_spec_}}.{{js,ts,jsx,tsx}} in --cwd={f}", .{bun.fmt.quote(bun.fs.FileSystem.instance.top_level_dir)});
|
||||
const suffixes = ctx.test_options.resolve_extensions orelse &Scanner.test_name_suffixes;
|
||||
var buf = bun.MutableString.initEmpty(bun.default_allocator);
|
||||
defer buf.deinit();
|
||||
var writer = buf.writer();
|
||||
writer.writeAll("0 test files matching **{") catch {};
|
||||
for (suffixes, 0..) |suffix, i| {
|
||||
if (i > 0) writer.writeAll(",") catch {};
|
||||
writer.writeAll(suffix) catch {};
|
||||
}
|
||||
writer.writeAll("}.{js,ts,jsx,tsx} in --cwd=") catch {};
|
||||
Output.errGeneric("{s}{f}", .{ buf.list.items, bun.fmt.quote(bun.fs.FileSystem.instance.top_level_dir) });
|
||||
} else {
|
||||
// Be friendlier to humans.
|
||||
const suffixes = ctx.test_options.resolve_extensions orelse &Scanner.test_name_suffixes;
|
||||
var buf = bun.MutableString.initEmpty(bun.default_allocator);
|
||||
defer buf.deinit();
|
||||
var writer = buf.writer();
|
||||
for (suffixes, 0..) |suffix, i| {
|
||||
if (i > 0) {
|
||||
if (i == suffixes.len - 1) {
|
||||
writer.writeAll(" or ") catch {};
|
||||
} else {
|
||||
writer.writeAll(", ") catch {};
|
||||
}
|
||||
}
|
||||
writer.print("\"{s}\"", .{suffix}) catch {};
|
||||
}
|
||||
Output.prettyErrorln(
|
||||
\\<yellow>No tests found!<r>
|
||||
\\
|
||||
\\Tests need ".test", "_test_", ".spec" or "_spec_" in the filename <d>(ex: "MyApp.test.ts")<r>
|
||||
\\Tests need {s} in the filename <d>(ex: "MyApp{s}.ts")<r>
|
||||
\\
|
||||
, .{});
|
||||
, .{ buf.list.items, suffixes[0] });
|
||||
}
|
||||
} else {
|
||||
if (Output.isAIAgent()) {
|
||||
@@ -1624,11 +1649,26 @@ pub const TestCommand = struct {
|
||||
Output.printStartEnd(ctx.start_time, std.time.nanoTimestamp());
|
||||
}
|
||||
|
||||
const suffixes = ctx.test_options.resolve_extensions orelse &Scanner.test_name_suffixes;
|
||||
var buf = bun.MutableString.initEmpty(bun.default_allocator);
|
||||
defer buf.deinit();
|
||||
var writer = buf.writer();
|
||||
for (suffixes, 0..) |suffix, i| {
|
||||
if (i > 0) {
|
||||
if (i == suffixes.len - 1) {
|
||||
writer.writeAll(" or ") catch {};
|
||||
} else {
|
||||
writer.writeAll(", ") catch {};
|
||||
}
|
||||
}
|
||||
writer.print("\"{s}\"", .{suffix}) catch {};
|
||||
}
|
||||
|
||||
Output.prettyErrorln(
|
||||
\\
|
||||
\\
|
||||
\\<blue>note<r><d>:<r> Tests need ".test", "_test_", ".spec" or "_spec_" in the filename <d>(ex: "MyApp.test.ts")<r>
|
||||
, .{});
|
||||
\\<blue>note<r><d>:<r> Tests need {s} in the filename <d>(ex: "MyApp{s}.ts")<r>
|
||||
, .{ buf.list.items, suffixes[0] });
|
||||
|
||||
// print a helpful note
|
||||
if (has_file_like) |i| {
|
||||
|
||||
79
test/cli/test-resolve-extensions.md
Normal file
79
test/cli/test-resolve-extensions.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Test Resolve Extensions
|
||||
|
||||
The `--resolve-extensions` flag and `resolveExtensions` bunfig.toml property allow you to customize which file name patterns are recognized as test files.
|
||||
|
||||
## Default Behavior
|
||||
|
||||
By default, Bun recognizes test files with these suffixes:
|
||||
- `.test` (e.g., `myfile.test.ts`)
|
||||
- `_test` (e.g., `myfile_test.ts`)
|
||||
- `.spec` (e.g., `myfile.spec.ts`)
|
||||
- `_spec` (e.g., `myfile_spec.ts`)
|
||||
|
||||
## Usage
|
||||
|
||||
### CLI Flag
|
||||
|
||||
```bash
|
||||
# Use a single custom extension
|
||||
bun test --resolve-extensions .check
|
||||
|
||||
# Use multiple custom extensions
|
||||
bun test --resolve-extensions .check --resolve-extensions .verify
|
||||
```
|
||||
|
||||
### bunfig.toml
|
||||
|
||||
```toml
|
||||
[test]
|
||||
# Single extension
|
||||
resolveExtensions = ".check"
|
||||
|
||||
# Multiple extensions
|
||||
resolveExtensions = [".check", ".verify"]
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Custom test suffix
|
||||
|
||||
If you prefer using `.check.ts` for your test files:
|
||||
|
||||
```toml
|
||||
# bunfig.toml
|
||||
[test]
|
||||
resolveExtensions = ".check"
|
||||
```
|
||||
|
||||
Now `myfile.check.ts` will be recognized as a test file, but `myfile.test.ts` will not.
|
||||
|
||||
### Multiple custom patterns
|
||||
|
||||
You can mix different patterns:
|
||||
|
||||
```toml
|
||||
# bunfig.toml
|
||||
[test]
|
||||
resolveExtensions = [".check", ".verify", "_integration"]
|
||||
```
|
||||
|
||||
This will recognize:
|
||||
- `myfile.check.ts`
|
||||
- `myfile.verify.ts`
|
||||
- `myfile_integration.ts`
|
||||
|
||||
### Override via CLI
|
||||
|
||||
The CLI flag takes precedence over bunfig.toml:
|
||||
|
||||
```bash
|
||||
# Even if bunfig.toml has resolveExtensions = ".check"
|
||||
# This will only run .verify files
|
||||
bun test --resolve-extensions .verify
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The extensions are matched against the filename **before** the file extension (`.ts`, `.js`, etc.)
|
||||
- All standard JavaScript/TypeScript file extensions (`.ts`, `.tsx`, `.js`, `.jsx`, `.mjs`, `.cjs`) are still supported
|
||||
- When custom extensions are specified, the default patterns (`.test`, `_test`, `.spec`, `_spec`) are **replaced**, not supplemented
|
||||
379
test/cli/test-resolve-extensions.test.ts
Normal file
379
test/cli/test-resolve-extensions.test.ts
Normal file
@@ -0,0 +1,379 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
|
||||
|
||||
describe("bun test --resolve-extensions", () => {
|
||||
test("CLI flag allows custom test file suffixes", async () => {
|
||||
const dir = tempDirWithFiles("resolve-extensions-cli", {
|
||||
"mytest.check.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("check test", () => {
|
||||
console.log("RUNNING: check test");
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
`,
|
||||
"regular.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("regular test", () => {
|
||||
console.log("RUNNING: regular test");
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "--resolve-extensions", ".check"],
|
||||
env: bunEnv,
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("RUNNING: check test");
|
||||
expect(output).not.toContain("RUNNING: regular test");
|
||||
expect(output).toContain("1 pass");
|
||||
});
|
||||
|
||||
test("CLI flag supports multiple extensions", async () => {
|
||||
const dir = tempDirWithFiles("resolve-extensions-multiple", {
|
||||
"alpha.check.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("check test", () => {
|
||||
console.log("RUNNING: check");
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
`,
|
||||
"beta.verify.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("verify test", () => {
|
||||
console.log("RUNNING: verify");
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
`,
|
||||
"gamma.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("regular test", () => {
|
||||
console.log("RUNNING: regular");
|
||||
expect(3).toBe(3);
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "--resolve-extensions", ".check", "--resolve-extensions", ".verify"],
|
||||
env: bunEnv,
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("RUNNING: check");
|
||||
expect(output).toContain("RUNNING: verify");
|
||||
expect(output).not.toContain("RUNNING: regular");
|
||||
expect(output).toContain("2 pass");
|
||||
});
|
||||
|
||||
test("bunfig.toml resolveExtensions as string", async () => {
|
||||
const dir = tempDirWithFiles("resolve-extensions-bunfig-string", {
|
||||
"mytest.check.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("check test", () => {
|
||||
console.log("RUNNING: check test");
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
`,
|
||||
"regular.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("regular test", () => {
|
||||
console.log("RUNNING: regular test");
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
`,
|
||||
"bunfig.toml": `[test]\nresolveExtensions = ".check"`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test"],
|
||||
env: bunEnv,
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("RUNNING: check test");
|
||||
expect(output).not.toContain("RUNNING: regular test");
|
||||
expect(output).toContain("1 pass");
|
||||
});
|
||||
|
||||
test("bunfig.toml resolveExtensions as array", async () => {
|
||||
const dir = tempDirWithFiles("resolve-extensions-bunfig-array", {
|
||||
"alpha.check.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("check test", () => {
|
||||
console.log("RUNNING: check");
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
`,
|
||||
"beta.verify.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("verify test", () => {
|
||||
console.log("RUNNING: verify");
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
`,
|
||||
"gamma.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("regular test", () => {
|
||||
console.log("RUNNING: regular");
|
||||
expect(3).toBe(3);
|
||||
});
|
||||
`,
|
||||
"bunfig.toml": `[test]\nresolveExtensions = [".check", ".verify"]`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test"],
|
||||
env: bunEnv,
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("RUNNING: check");
|
||||
expect(output).toContain("RUNNING: verify");
|
||||
expect(output).not.toContain("RUNNING: regular");
|
||||
expect(output).toContain("2 pass");
|
||||
});
|
||||
|
||||
test("CLI flag overrides bunfig.toml", async () => {
|
||||
const dir = tempDirWithFiles("resolve-extensions-cli-override", {
|
||||
"alpha.check.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("check test", () => {
|
||||
console.log("RUNNING: check");
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
`,
|
||||
"beta.verify.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("verify test", () => {
|
||||
console.log("RUNNING: verify");
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
`,
|
||||
"bunfig.toml": `[test]\nresolveExtensions = ".check"`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "--resolve-extensions", ".verify"],
|
||||
env: bunEnv,
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).not.toContain("RUNNING: check");
|
||||
expect(output).toContain("RUNNING: verify");
|
||||
expect(output).toContain("1 pass");
|
||||
});
|
||||
|
||||
test("custom extensions work with underscore prefix", async () => {
|
||||
const dir = tempDirWithFiles("resolve-extensions-underscore", {
|
||||
"mytest_check.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("check test", () => {
|
||||
console.log("RUNNING: check");
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
`,
|
||||
"regular.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("regular test", () => {
|
||||
console.log("RUNNING: regular");
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "--resolve-extensions", "_check"],
|
||||
env: bunEnv,
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("RUNNING: check");
|
||||
expect(output).not.toContain("RUNNING: regular");
|
||||
expect(output).toContain("1 pass");
|
||||
});
|
||||
|
||||
test("no tests found shows custom extensions in error message", async () => {
|
||||
const dir = tempDirWithFiles("resolve-extensions-no-tests", {
|
||||
"regular.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("regular test", () => expect(1).toBe(1));
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "--resolve-extensions", ".custom"],
|
||||
env: bunEnv,
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("No tests found");
|
||||
expect(output).toContain(".custom");
|
||||
});
|
||||
|
||||
test("works with nested directories", async () => {
|
||||
const dir = tempDirWithFiles("resolve-extensions-nested", {
|
||||
"src/feature/alpha.check.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("nested check", () => {
|
||||
console.log("RUNNING: nested check");
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
`,
|
||||
"src/feature/beta.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("nested test", () => {
|
||||
console.log("RUNNING: nested test");
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "--resolve-extensions", ".check"],
|
||||
env: bunEnv,
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("RUNNING: nested check");
|
||||
expect(output).not.toContain("RUNNING: nested test");
|
||||
expect(output).toContain("1 pass");
|
||||
});
|
||||
|
||||
test("works with default extensions when not specified", async () => {
|
||||
const dir = tempDirWithFiles("resolve-extensions-default", {
|
||||
"alpha.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("test suffix", () => {
|
||||
console.log("RUNNING: test");
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
`,
|
||||
"beta.spec.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("spec suffix", () => {
|
||||
console.log("RUNNING: spec");
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
`,
|
||||
"gamma_test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("_test suffix", () => {
|
||||
console.log("RUNNING: _test");
|
||||
expect(3).toBe(3);
|
||||
});
|
||||
`,
|
||||
"delta_spec.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
test("_spec suffix", () => {
|
||||
console.log("RUNNING: _spec");
|
||||
expect(4).toBe(4);
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test"],
|
||||
env: bunEnv,
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
proc.exited,
|
||||
]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("RUNNING: test");
|
||||
expect(output).toContain("RUNNING: spec");
|
||||
expect(output).toContain("RUNNING: _test");
|
||||
expect(output).toContain("RUNNING: _spec");
|
||||
expect(output).toContain("4 pass");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user