mirror of
https://github.com/oven-sh/bun
synced 2026-02-17 14:22:01 +00:00
Compare commits
7 Commits
claude/add
...
claude/add
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de831ebb32 | ||
|
|
5a0fb3db13 | ||
|
|
917e4cb702 | ||
|
|
2a88d5f670 | ||
|
|
72f350143e | ||
|
|
20e17a09c3 | ||
|
|
2b64bc5b46 |
@@ -105,6 +105,9 @@ pub const TestRunner = struct {
|
||||
filter_regex: ?*RegularExpression,
|
||||
filter_buffer: MutableString,
|
||||
|
||||
// Used for --full-test-name filtering
|
||||
full_name_filters: []const string,
|
||||
|
||||
unhandled_errors_between_tests: u32 = 0,
|
||||
summary: Summary = Summary{},
|
||||
|
||||
@@ -136,7 +139,7 @@ pub const TestRunner = struct {
|
||||
}
|
||||
|
||||
pub fn hasTestFilter(this: *const TestRunner) bool {
|
||||
return this.filter_regex != null;
|
||||
return this.filter_regex != null or this.full_name_filters.len > 0;
|
||||
}
|
||||
|
||||
pub fn setTimeout(
|
||||
@@ -1230,6 +1233,28 @@ pub const DescribeScope = struct {
|
||||
}
|
||||
|
||||
pub fn runTests(this: *DescribeScope, globalObject: *JSGlobalObject) void {
|
||||
// Early optimization: skip entire describe blocks that can't contain matching tests
|
||||
if (Jest.runner.?.full_name_filters.len > 0) {
|
||||
var could_match = false;
|
||||
for (Jest.runner.?.full_name_filters) |full_name| {
|
||||
// For trailing space case, disable optimization to let regular matching handle it
|
||||
// This is simpler and more reliable than trying to predict nested hierarchies
|
||||
if (bun.strings.endsWith(full_name, " ")) {
|
||||
could_match = true;
|
||||
break;
|
||||
}
|
||||
// Regular case: if any full test name could start with this describe block's label
|
||||
if (bun.strings.startsWith(full_name, this.label)) {
|
||||
could_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!could_match) {
|
||||
// Skip this entire describe block - no tests in it could possibly match
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 1. Initialize the test block
|
||||
globalObject.clearTerminationException();
|
||||
|
||||
@@ -2002,6 +2027,37 @@ inline fn createScope(
|
||||
is_skip = true;
|
||||
tag_to_use = .skipped_because_label;
|
||||
}
|
||||
} else if (runner.full_name_filters.len > 0) {
|
||||
var buffer: bun.MutableString = runner.filter_buffer;
|
||||
buffer.reset();
|
||||
appendParentLabel(&buffer, parent) catch @panic("Bun ran out of memory while filtering tests");
|
||||
buffer.append(label) catch unreachable;
|
||||
const full_test_name = buffer.slice();
|
||||
|
||||
// Check if the test name matches any of the provided filters
|
||||
var matches = false;
|
||||
var expected_name_buffer: [1024]u8 = undefined;
|
||||
for (runner.full_name_filters) |full_name| {
|
||||
// Handle trailing space case: "auth " means "all tests starting with 'auth '"
|
||||
if (bun.strings.endsWith(full_name, " ")) {
|
||||
const expected_prefix = std.fmt.bufPrint(&expected_name_buffer, " {s}", .{full_name}) catch continue;
|
||||
if (bun.strings.startsWith(full_test_name, expected_prefix)) {
|
||||
matches = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Regular exact match case
|
||||
const expected_name = std.fmt.bufPrint(&expected_name_buffer, " {s}", .{full_name}) catch continue;
|
||||
if (bun.strings.eql(full_test_name, expected_name)) {
|
||||
matches = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!matches) {
|
||||
is_skip = true;
|
||||
tag_to_use = .skipped_because_label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2377,6 +2433,37 @@ fn eachBind(globalThis: *JSGlobalObject, callframe: *CallFrame) bun.JSError!JSVa
|
||||
if (is_skip) {
|
||||
tag_to_use = .skipped_because_label;
|
||||
}
|
||||
} else if (Jest.runner.?.full_name_filters.len > 0) {
|
||||
var buffer: bun.MutableString = Jest.runner.?.filter_buffer;
|
||||
buffer.reset();
|
||||
appendParentLabel(&buffer, parent) catch @panic("Bun ran out of memory while filtering tests");
|
||||
buffer.append(formattedLabel) catch unreachable;
|
||||
const full_test_name = buffer.slice();
|
||||
|
||||
// Check if the test name matches any of the provided filters
|
||||
var matches = false;
|
||||
var expected_name_buffer: [1024]u8 = undefined;
|
||||
for (Jest.runner.?.full_name_filters) |full_name| {
|
||||
// Handle trailing space case: "auth " means "all tests starting with 'auth '"
|
||||
if (bun.strings.endsWith(full_name, " ")) {
|
||||
const expected_prefix = std.fmt.bufPrint(&expected_name_buffer, " {s}", .{full_name}) catch continue;
|
||||
if (bun.strings.startsWith(full_test_name, expected_prefix)) {
|
||||
matches = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Regular exact match case
|
||||
const expected_name = std.fmt.bufPrint(&expected_name_buffer, " {s}", .{full_name}) catch continue;
|
||||
if (bun.strings.eql(full_test_name, expected_name)) {
|
||||
matches = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
is_skip = !matches;
|
||||
if (is_skip) {
|
||||
tag_to_use = .skipped_because_label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -327,6 +327,7 @@ pub const Command = struct {
|
||||
coverage: TestCommand.CodeCoverageOptions = .{},
|
||||
test_filter_pattern: ?[]const u8 = null,
|
||||
test_filter_regex: ?*RegularExpression = null,
|
||||
test_full_name_filter: []const string = &.{},
|
||||
|
||||
file_reporter: ?TestCommand.FileReporter = null,
|
||||
reporter_outfile: ?[]const u8 = null,
|
||||
|
||||
@@ -196,6 +196,7 @@ pub const test_only_params = [_]ParamType{
|
||||
clap.parseParam("--coverage-dir <STR> Directory for coverage files. Defaults to 'coverage'.") catch unreachable,
|
||||
clap.parseParam("--bail <NUMBER>? Exit the test suite after <NUMBER> failures. If you do not specify a number, it defaults to 1.") catch unreachable,
|
||||
clap.parseParam("-t, --test-name-pattern <STR> Run only tests with a name that matches the given regex.") catch unreachable,
|
||||
clap.parseParam("--full-test-name <STR>... Run only tests matching any of the exact full test names (space separated, no regex).") catch unreachable,
|
||||
clap.parseParam("--reporter <STR> Specify the test reporter. Currently --reporter=junit is the only supported format.") catch unreachable,
|
||||
clap.parseParam("--reporter-outfile <STR> The output file used for the format from --reporter.") catch unreachable,
|
||||
};
|
||||
@@ -484,6 +485,13 @@ pub fn parse(allocator: std.mem.Allocator, ctx: Command.Context, comptime cmd: C
|
||||
};
|
||||
ctx.test_options.test_filter_regex = regex;
|
||||
}
|
||||
if (args.options("--full-test-name").len > 0) {
|
||||
if (ctx.test_options.test_filter_regex != null) {
|
||||
Output.prettyErrorln("<r><red>error<r>: --full-test-name and --test-name-pattern cannot be used together", .{});
|
||||
Global.exit(1);
|
||||
}
|
||||
ctx.test_options.test_full_name_filter = args.options("--full-test-name");
|
||||
}
|
||||
ctx.test_options.update_snapshots = args.flag("--update-snapshots");
|
||||
ctx.test_options.run_todo = args.flag("--todo");
|
||||
ctx.test_options.only = args.flag("--only");
|
||||
|
||||
@@ -1325,6 +1325,7 @@ pub const TestCommand = struct {
|
||||
.bail = ctx.test_options.bail,
|
||||
.filter_regex = ctx.test_options.test_filter_regex,
|
||||
.filter_buffer = bun.MutableString.init(ctx.allocator, 0) catch unreachable,
|
||||
.full_name_filters = ctx.test_options.test_full_name_filter,
|
||||
.snapshots = Snapshots{
|
||||
.allocator = ctx.allocator,
|
||||
.update_snapshots = ctx.test_options.update_snapshots,
|
||||
@@ -1693,13 +1694,24 @@ pub const TestCommand = struct {
|
||||
|
||||
reporter.printSummary();
|
||||
} else {
|
||||
Output.prettyError("<red>error<r><d>:<r> regex <b>{}<r> matched 0 tests. Searched {d} file{s} (skipping {d} test{s}) ", .{
|
||||
bun.fmt.quote(ctx.test_options.test_filter_pattern.?),
|
||||
summary.files,
|
||||
if (summary.files == 1) "" else "s",
|
||||
summary.skipped_because_label,
|
||||
if (summary.skipped_because_label == 1) "" else "s",
|
||||
});
|
||||
if (ctx.test_options.test_filter_pattern) |pattern| {
|
||||
Output.prettyError("<red>error<r><d>:<r> regex <b>{}<r> matched 0 tests. Searched {d} file{s} (skipping {d} test{s}) ", .{
|
||||
bun.fmt.quote(pattern),
|
||||
summary.files,
|
||||
if (summary.files == 1) "" else "s",
|
||||
summary.skipped_because_label,
|
||||
if (summary.skipped_because_label == 1) "" else "s",
|
||||
});
|
||||
} else if (ctx.test_options.test_full_name_filter.len > 0) {
|
||||
const names_text = if (ctx.test_options.test_full_name_filter.len == 1) "test name" else "test names";
|
||||
Output.prettyError("<red>error<r><d>:<r> {s} matched 0 tests. Searched {d} file{s} (skipping {d} test{s}) ", .{
|
||||
names_text,
|
||||
summary.files,
|
||||
if (summary.files == 1) "" else "s",
|
||||
summary.skipped_because_label,
|
||||
if (summary.skipped_because_label == 1) "" else "s",
|
||||
});
|
||||
}
|
||||
Output.printStartEnd(ctx.start_time, std.time.nanoTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
192
test/cli/full-test-name.test.ts
Normal file
192
test/cli/full-test-name.test.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { bunExe, tempDirWithFiles } from "harness";
|
||||
|
||||
test("--full-test-name matches single test", async () => {
|
||||
const dir = tempDirWithFiles("full-test-name", {
|
||||
"test.test.js": `
|
||||
describe("auth", () => {
|
||||
test("login test", () => {
|
||||
expect(1 + 1).toBe(2);
|
||||
});
|
||||
|
||||
test("logout test", () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
});
|
||||
|
||||
test("top level test", () => {
|
||||
expect(3 + 3).toBe(6);
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
// Test single nested test
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "test.test.js", "--full-test-name", "auth login test"],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("1 pass");
|
||||
// Note: With describe block optimization, skipped blocks don't contribute to "filtered out" count
|
||||
});
|
||||
|
||||
test("--full-test-name matches top-level test", async () => {
|
||||
const dir = tempDirWithFiles("full-test-name-top", {
|
||||
"test.test.js": `
|
||||
describe("auth", () => {
|
||||
test("login test", () => {
|
||||
expect(1 + 1).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
test("top level test", () => {
|
||||
expect(3 + 3).toBe(6);
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "test.test.js", "--full-test-name", "top level test"],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("1 pass");
|
||||
// Note: With describe block optimization, skipped blocks don't contribute to "filtered out" count
|
||||
});
|
||||
|
||||
test("--full-test-name supports multiple values", async () => {
|
||||
const dir = tempDirWithFiles("full-test-name-multiple", {
|
||||
"test.test.js": `
|
||||
describe("auth", () => {
|
||||
test("login test", () => {
|
||||
expect(1 + 1).toBe(2);
|
||||
});
|
||||
|
||||
test("logout test", () => {
|
||||
expect(2 + 2).toBe(4);
|
||||
});
|
||||
|
||||
test("register test", () => {
|
||||
expect(3 + 3).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe("user", () => {
|
||||
test("profile test", () => {
|
||||
expect(4 + 4).toBe(8);
|
||||
});
|
||||
});
|
||||
|
||||
test("top level test", () => {
|
||||
expect(5 + 5).toBe(10);
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
// Test multiple tests from different describe blocks
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [
|
||||
bunExe(),
|
||||
"test",
|
||||
"test.test.js",
|
||||
"--full-test-name",
|
||||
"auth login test",
|
||||
"--full-test-name",
|
||||
"user profile test",
|
||||
"--full-test-name",
|
||||
"top level test",
|
||||
],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("3 pass");
|
||||
// Note: With describe block optimization, skipped blocks don't contribute to "filtered out" count
|
||||
});
|
||||
|
||||
test("--full-test-name and --test-name-pattern are mutually exclusive", async () => {
|
||||
const dir = tempDirWithFiles("full-test-name-exclusive", {
|
||||
"test.test.js": `
|
||||
test("simple test", () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "test.test.js", "--test-name-pattern", "simple", "--full-test-name", "simple test"],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
expect(stderr).toContain("--full-test-name and --test-name-pattern cannot be used together");
|
||||
});
|
||||
|
||||
test("--full-test-name shows proper error for non-matching tests", async () => {
|
||||
const dir = tempDirWithFiles("full-test-name-no-match", {
|
||||
"test.test.js": `
|
||||
test("existing test", () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
// Single non-matching test
|
||||
{
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "test.test.js", "--full-test-name", "nonexistent test"],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
expect(stderr).toContain("test name matched 0 tests");
|
||||
}
|
||||
|
||||
// Multiple non-matching tests
|
||||
{
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [
|
||||
bunExe(),
|
||||
"test",
|
||||
"test.test.js",
|
||||
"--full-test-name",
|
||||
"nonexistent test 1",
|
||||
"--full-test-name",
|
||||
"nonexistent test 2",
|
||||
],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stderr, exitCode] = await Promise.all([proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
expect(stderr).toContain("test names matched 0 tests");
|
||||
}
|
||||
});
|
||||
215
test/cli/trailing-space-test-names.test.ts
Normal file
215
test/cli/trailing-space-test-names.test.ts
Normal file
@@ -0,0 +1,215 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { bunExe, tempDirWithFiles } from "harness";
|
||||
|
||||
test("--full-test-name with trailing space runs all tests in describe block", async () => {
|
||||
const dir = tempDirWithFiles("trailing-space", {
|
||||
"test.test.js": `
|
||||
describe("auth", () => {
|
||||
test("login test", () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
|
||||
test("logout test", () => {
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
|
||||
describe("nested", () => {
|
||||
test("deep test", () => {
|
||||
expect(3).toBe(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("user", () => {
|
||||
test("profile test", () => {
|
||||
expect(4).toBe(4);
|
||||
});
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
// Test "auth " (with trailing space) runs all tests under auth hierarchy
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "test.test.js", "--full-test-name", "auth "],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("3 pass"); // All 3 tests in auth hierarchy should run
|
||||
expect(output).toContain("1 filtered out"); // The user profile test should be filtered out
|
||||
});
|
||||
|
||||
test("--full-test-name with trailing space for nested describe block", async () => {
|
||||
const dir = tempDirWithFiles("trailing-space-nested", {
|
||||
"test.test.js": `
|
||||
describe("auth", () => {
|
||||
test("login test", () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
|
||||
describe("integration", () => {
|
||||
test("full flow test", () => {
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
|
||||
test("api test", () => {
|
||||
expect(3).toBe(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("user", () => {
|
||||
test("profile test", () => {
|
||||
expect(4).toBe(4);
|
||||
});
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
// Test "auth integration " runs only tests in that specific nested block
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "test.test.js", "--full-test-name", "auth integration "],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("2 pass"); // Only 2 tests in auth integration should run
|
||||
});
|
||||
|
||||
test("--full-test-name with multiple trailing space filters", async () => {
|
||||
const dir = tempDirWithFiles("trailing-space-multiple", {
|
||||
"test.test.js": `
|
||||
describe("auth", () => {
|
||||
test("login test", () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
|
||||
describe("nested", () => {
|
||||
test("deep test", () => {
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("user", () => {
|
||||
test("profile test", () => {
|
||||
expect(3).toBe(3);
|
||||
});
|
||||
|
||||
test("settings test", () => {
|
||||
expect(4).toBe(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe("admin", () => {
|
||||
test("dashboard test", () => {
|
||||
expect(5).toBe(5);
|
||||
});
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
// Test multiple trailing space filters
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "test.test.js", "--full-test-name", "auth ", "--full-test-name", "user "],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("4 pass"); // auth (2) + user (2) = 4 tests should run
|
||||
});
|
||||
|
||||
test("--full-test-name handles test names with actual trailing spaces", async () => {
|
||||
const dir = tempDirWithFiles("trailing-space-in-name", {
|
||||
"test.test.js": `
|
||||
describe("auth", () => {
|
||||
test("login test", () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
|
||||
test("test with trailing space ", () => {
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
// Test exact match for a test name that actually ends with a space
|
||||
await using proc = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "test.test.js", "--full-test-name", "auth test with trailing space "],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
const output = stdout + stderr;
|
||||
expect(output).toContain("1 pass"); // Only the specific test should run
|
||||
});
|
||||
|
||||
test("--full-test-name trailing space vs exact test name disambiguation", async () => {
|
||||
const dir = tempDirWithFiles("trailing-space-disambiguation", {
|
||||
"test.test.js": `
|
||||
describe("auth", () => {
|
||||
test("login test", () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
|
||||
test("logout test", () => {
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("auth integration", () => {
|
||||
test("api test", () => {
|
||||
expect(3).toBe(3);
|
||||
});
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
// Test that "auth " (describe block) and "auth integration api test" (specific test) work correctly
|
||||
await using proc1 = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "test.test.js", "--full-test-name", "auth "],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout1, stderr1, exitCode1] = await Promise.all([proc1.stdout.text(), proc1.stderr.text(), proc1.exited]);
|
||||
|
||||
expect(exitCode1).toBe(0);
|
||||
const output1 = stdout1 + stderr1;
|
||||
expect(output1).toContain("3 pass"); // All tests that start with "auth " (includes auth integration)
|
||||
|
||||
// Test specific test in auth integration
|
||||
await using proc2 = Bun.spawn({
|
||||
cmd: [bunExe(), "test", "test.test.js", "--full-test-name", "auth integration api test"],
|
||||
cwd: dir,
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const [stdout2, stderr2, exitCode2] = await Promise.all([proc2.stdout.text(), proc2.stderr.text(), proc2.exited]);
|
||||
|
||||
expect(exitCode2).toBe(0);
|
||||
const output2 = stdout2 + stderr2;
|
||||
expect(output2).toContain("1 pass"); // Only the specific test
|
||||
});
|
||||
Reference in New Issue
Block a user