Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/bun.js/ConsoleObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ fn messageWithTypeAndLevel_(
var writer = buffered_writer.writer();
const Writer = @TypeOf(writer);

if (bun.jsc.Jest.Jest.runner) |runner| {
runner.bun_test_root.onBeforePrint();
}

var print_length = len;
// Get console depth from CLI options or bunfig, fallback to default
const cli_context = CLI.get();
Expand Down
2 changes: 0 additions & 2 deletions src/bun.js/test/Execution.zig
Original file line number Diff line number Diff line change
Expand Up @@ -593,8 +593,6 @@ pub fn handleUncaughtException(this: *Execution, user_data: bun_test.BunTest.Ref
groupLog.begin(@src());
defer groupLog.end();

if (bun.jsc.Jest.Jest.runner) |runner| runner.current_file.printIfNeeded();

const sequence, const group = this.getCurrentAndValidExecutionSequence(user_data) orelse return .show_unhandled_error_between_tests;
_ = group;

Expand Down
30 changes: 24 additions & 6 deletions src/bun.js/test/bun_test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,25 @@ pub const BunTestRoot = struct {
first: bool,
last: bool,
};

pub fn onBeforePrint(this: *BunTestRoot) void {
if (this.active_file.get()) |active_file| {
if (active_file.reporter) |reporter| {
if (reporter.last_printed_dot and reporter.reporters.dots) {
bun.Output.prettyError("<r>\n", .{});
bun.Output.flush();
reporter.last_printed_dot = false;
}
if (bun.jsc.Jest.Jest.runner) |runner| {
runner.current_file.printIfNeeded();
}
}
}
}
};

pub const BunTest = struct {
buntest: *BunTestRoot,
bun_test_root: *BunTestRoot,
in_run_loop: bool,
allocation_scope: bun.AllocationScope,
gpa: std.mem.Allocator,
Expand Down Expand Up @@ -207,7 +222,7 @@ pub const BunTest = struct {
this.arena = this.arena_allocator.allocator();

this.* = .{
.buntest = bunTest,
.bun_test_root = bunTest,
.in_run_loop = false,
.allocation_scope = this.allocation_scope,
.gpa = this.gpa,
Expand Down Expand Up @@ -571,10 +586,10 @@ pub const BunTest = struct {
});
defer order.deinit();

const beforeall_order: Order.AllOrderResult = if (this.first_last.first) try order.generateAllOrder(this.buntest.hook_scope.beforeAll.items) else .empty;
const beforeall_order: Order.AllOrderResult = if (this.first_last.first) try order.generateAllOrder(this.bun_test_root.hook_scope.beforeAll.items) else .empty;
try order.generateOrderDescribe(this.collection.root_scope);
beforeall_order.setFailureSkipTo(&order);
const afterall_order: Order.AllOrderResult = if (this.first_last.last) try order.generateAllOrder(this.buntest.hook_scope.afterAll.items) else .empty;
const afterall_order: Order.AllOrderResult = if (this.first_last.last) try order.generateAllOrder(this.bun_test_root.hook_scope.afterAll.items) else .empty;
afterall_order.setFailureSkipTo(&order);

try this.execution.loadFromOrder(&order);
Expand Down Expand Up @@ -705,6 +720,7 @@ pub const BunTest = struct {
if (handle_status == .hide_error) return; // do not print error, it was already consumed
if (exception == null) return; // the exception should not be visible (eg m_terminationException)

this.bun_test_root.onBeforePrint();
if (handle_status == .show_unhandled_error_between_tests or handle_status == .show_unhandled_error_in_describe) {
this.reporter.?.jest.unhandled_errors_between_tests += 1;
bun.Output.prettyErrorln(
Expand All @@ -715,12 +731,14 @@ pub const BunTest = struct {
, .{});
bun.Output.flush();
}

globalThis.bunVM().runErrorHandler(exception.?, null);
bun.Output.flush();

if (handle_status == .show_unhandled_error_between_tests or handle_status == .show_unhandled_error_in_describe) {
bun.Output.prettyError("<r><d>-------------------------------<r>\n\n", .{});
bun.Output.flush();
}

bun.Output.flush();
}
};

Expand Down
26 changes: 20 additions & 6 deletions src/bun.js/test/jest.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ const CurrentFile = struct {
} = .{},
has_printed_filename: bool = false,

pub fn set(this: *CurrentFile, title: string, prefix: string, repeat_count: u32, repeat_index: u32) void {
if (Output.isAIAgent()) {
pub fn set(
this: *CurrentFile,
title: string,
prefix: string,
repeat_count: u32,
repeat_index: u32,
reporter: *CommandLineReporter,
) void {
if (Output.isAIAgent() or reporter.reporters.dots) {
this.freeAndClear();
this.title = bun.handleOom(bun.default_allocator.dupe(u8, title));
this.prefix = bun.handleOom(bun.default_allocator.dupe(u8, prefix));
Expand All @@ -28,14 +35,19 @@ const CurrentFile = struct {
}

fn print(title: string, prefix: string, repeat_count: u32, repeat_index: u32) void {
const enable_buffering = Output.enableBufferingScope();
defer enable_buffering.deinit();

Output.prettyError("<r>\n", .{});

if (repeat_count > 0) {
if (repeat_count > 1) {
Output.prettyErrorln("<r>\n{s}{s}: <d>(run #{d})<r>\n", .{ prefix, title, repeat_index + 1 });
Output.prettyErrorln("{s}{s}: <d>(run #{d})<r>\n", .{ prefix, title, repeat_index + 1 });
} else {
Output.prettyErrorln("<r>\n{s}{s}:\n", .{ prefix, title });
Output.prettyErrorln("{s}{s}:\n", .{ prefix, title });
}
} else {
Output.prettyErrorln("<r>\n{s}{s}:\n", .{ prefix, title });
Output.prettyErrorln("{s}{s}:\n", .{ prefix, title });
}

Output.flush();
Expand All @@ -44,6 +56,7 @@ const CurrentFile = struct {
pub fn printIfNeeded(this: *CurrentFile) void {
if (this.has_printed_filename) return;
this.has_printed_filename = true;

print(this.title, this.prefix, this.repeat_info.count, this.repeat_info.index);
}
};
Expand Down Expand Up @@ -456,7 +469,7 @@ pub fn formatLabel(globalThis: *JSGlobalObject, label: string, function_args: []

pub fn captureTestLineNumber(callframe: *jsc.CallFrame, globalThis: *JSGlobalObject) u32 {
if (Jest.runner) |runner| {
if (runner.test_options.file_reporter == .junit) {
if (runner.test_options.reporters.junit) {
return bun.cpp.Bun__CallFrame__getLineNumber(callframe, globalThis);
}
}
Expand All @@ -475,6 +488,7 @@ const string = []const u8;
pub const bun_test = @import("./bun_test.zig");

const std = @import("std");
const CommandLineReporter = @import("../../cli/test_command.zig").CommandLineReporter;
const Snapshots = @import("./snapshot.zig").Snapshots;

const expect = @import("./expect.zig");
Expand Down
6 changes: 5 additions & 1 deletion src/bunfig.zig
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,14 @@ pub const Bunfig = struct {
if (expr.get("junit")) |junit_expr| {
try this.expectString(junit_expr);
if (junit_expr.data.e_string.len() > 0) {
this.ctx.test_options.file_reporter = .junit;
this.ctx.test_options.reporters.junit = true;
this.ctx.test_options.reporter_outfile = try junit_expr.data.e_string.string(allocator);
}
}
if (expr.get("dots") orelse expr.get("dot")) |dots_expr| {
try this.expect(dots_expr, .e_boolean);
this.ctx.test_options.reporters.dots = dots_expr.data.e_boolean.value;
}
}

if (test_.get("coverageReporter")) |expr| brk: {
Expand Down
5 changes: 4 additions & 1 deletion src/cli.zig
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,10 @@ pub const Command = struct {
test_filter_regex: ?*RegularExpression = null,
max_concurrency: u32 = 20,

file_reporter: ?TestCommand.FileReporter = null,
reporters: struct {
dots: bool = false,
junit: bool = false,
} = .{},
reporter_outfile: ?[]const u8 = null,
};

Expand Down
14 changes: 11 additions & 3 deletions src/cli/Arguments.zig
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,9 @@ 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("--reporter <STR> Test output reporter format. Available: 'junit' (requires --reporter-outfile). Default: console output.") catch unreachable,
clap.parseParam("--reporter <STR> Test output reporter format. Available: 'junit' (requires --reporter-outfile), 'dots'. Default: console output.") catch unreachable,
clap.parseParam("--reporter-outfile <STR> Output file path for the reporter format (required with --reporter).") catch unreachable,
clap.parseParam("--dots Enable dots reporter. Shorthand for --reporter=dots.") catch unreachable,
clap.parseParam("--max-concurrency <NUMBER> Maximum number of concurrent tests to execute at once. Default is 20.") catch unreachable,
};
pub const test_params = test_only_params ++ runtime_params_ ++ transpiler_params_ ++ base_params_;
Expand Down Expand Up @@ -455,13 +456,20 @@ pub fn parse(allocator: std.mem.Allocator, ctx: Command.Context, comptime cmd: C
Output.errGeneric("--reporter=junit requires --reporter-outfile [file] to specify where to save the XML report", .{});
Global.crash();
}
ctx.test_options.file_reporter = .junit;
ctx.test_options.reporters.junit = true;
} else if (strings.eqlComptime(reporter, "dots") or strings.eqlComptime(reporter, "dot")) {
ctx.test_options.reporters.dots = true;
} else {
Output.errGeneric("unsupported reporter format '{s}'. Available options: 'junit' (for XML test results)", .{reporter});
Output.errGeneric("unsupported reporter format '{s}'. Available options: 'junit' (for XML test results), 'dots'", .{reporter});
Global.crash();
}
}

// Handle --dots flag as shorthand for --reporter=dots
if (args.flag("--dots")) {
ctx.test_options.reporters.dots = true;
}

if (args.option("--coverage-dir")) |dir| {
ctx.test_options.coverage.reports_directory = dir;
}
Expand Down
Loading