diff options
Diffstat (limited to 'src/bun.js')
-rw-r--r-- | src/bun.js/test/jest.zig | 73 |
1 files changed, 69 insertions, 4 deletions
diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 9f96fc1ce..f84106085 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -469,6 +469,7 @@ pub const TestRunner = struct { onTestPass: OnTestUpdate, onTestFail: OnTestUpdate, onTestSkip: OnTestUpdate, + onTestTodo: OnTestUpdate, }; pub fn reportPass(this: *TestRunner, test_id: Test.ID, file: string, label: string, expectations: u32, elapsed_ns: u64, parent: ?*DescribeScope) void { @@ -485,6 +486,11 @@ pub const TestRunner = struct { this.callback.onTestSkip(this.callback, test_id, file, label, 0, 0, parent); } + pub fn reportTodo(this: *TestRunner, test_id: Test.ID, file: string, label: string, parent: ?*DescribeScope) void { + this.tests.items(.status)[test_id] = .todo; + this.callback.onTestTodo(this.callback, test_id, file, label, 0, 0, parent); + } + pub fn addTestCount(this: *TestRunner, count: u32) u32 { this.tests.ensureUnusedCapacity(this.allocator, count) catch unreachable; const start = @truncate(Test.ID, this.tests.len); @@ -532,6 +538,7 @@ pub const TestRunner = struct { pass, fail, skip, + todo, }; }; }; @@ -3159,6 +3166,7 @@ pub const TestScope = struct { ran: bool = false, task: ?*TestRunnerTask = null, skipped: bool = false, + is_todo: bool = false, snapshot_count: usize = 0, timeout_millis: u32 = default_timeout, @@ -3169,6 +3177,7 @@ pub const TestScope = struct { .call = call, .only = only, .skip = skip, + .todo = todo, }, .{}, ); @@ -3214,6 +3223,17 @@ pub const TestScope = struct { return prepare(this, ctx, arguments, exception, .call); } + pub fn todo( + _: void, + ctx: js.JSContextRef, + this: js.JSObjectRef, + _: js.JSObjectRef, + arguments: []const js.JSValueRef, + exception: js.ExceptionRef, + ) js.JSObjectRef { + return prepare(this, ctx, arguments, exception, .todo); + } + fn prepare( this: js.JSObjectRef, ctx: js.JSContextRef, @@ -3240,16 +3260,36 @@ pub const TestScope = struct { label = (label_value.toSlice(ctx, allocator).cloneIfNeeded(allocator) catch unreachable).slice(); } + if (tag == .todo and label_value == .zero) { + JSError(getAllocator(ctx), "test.todo() requires a description", .{}, ctx, exception); + return this; + } + const function = function_value; if (function.isEmptyOrUndefinedOrNull() or !function.isCell() or !function.isCallable(ctx.vm())) { - JSError(getAllocator(ctx), "test() expects a function", .{}, ctx, exception); - return this; + // a callback is not required for .todo + if (tag != .todo) { + JSError(getAllocator(ctx), "test() expects a function", .{}, ctx, exception); + return this; + } } if (tag == .only) { Jest.runner.?.setOnly(); } + if (tag == .todo) { + DescribeScope.active.todo_counter += 1; + DescribeScope.active.tests.append(getAllocator(ctx), TestScope{ + .label = label, + .parent = DescribeScope.active, + .is_todo = true, + .callback = if (function == .zero) null else function.asObjectRef(), + }) catch unreachable; + + return this; + } + if (tag == .skip or (tag != .only and Jest.runner.?.only)) { DescribeScope.active.skipped_counter += 1; DescribeScope.active.tests.append(getAllocator(ctx), TestScope{ @@ -3369,10 +3409,15 @@ pub const TestScope = struct { if (initial_value.isAnyError()) { if (!Jest.runner.?.did_pending_test_fail) { - Jest.runner.?.did_pending_test_fail = true; + // test failed unless it's a todo + Jest.runner.?.did_pending_test_fail = !this.is_todo; vm.runErrorHandler(initial_value, null); } + if (this.is_todo) { + return .{ .todo = {} }; + } + return .{ .fail = active_test_expectation_counter.actual }; } @@ -3391,10 +3436,15 @@ pub const TestScope = struct { switch (promise.status(vm.global.vm())) { .Rejected => { if (!Jest.runner.?.did_pending_test_fail) { - Jest.runner.?.did_pending_test_fail = true; + // test failed unless it's a todo + Jest.runner.?.did_pending_test_fail = !this.is_todo; vm.runErrorHandler(promise.result(vm.global.vm()), null); } + if (this.is_todo) { + return .{ .todo = {} }; + } + return .{ .fail = active_test_expectation_counter.actual }; }, .Pending => { @@ -3427,6 +3477,11 @@ pub const TestScope = struct { return .{ .fail = active_test_expectation_counter.actual }; } + if (this.is_todo) { + Output.prettyErrorln(" <d>^<r> <red>this test is marked as todo but passes.<r> <d>Remove `.todo` or check that test is correct.<r>", .{}); + return .{ .fail = active_test_expectation_counter.actual }; + } + return .{ .pass = active_test_expectation_counter.actual }; } @@ -3465,6 +3520,7 @@ pub const DescribeScope = struct { done: bool = false, skipped: bool = false, skipped_counter: u32 = 0, + todo_counter: u32 = 0, pub fn isAllSkipped(this: *const DescribeScope) bool { return this.skipped or @as(usize, this.skipped_counter) >= this.tests.items.len; @@ -3940,6 +3996,13 @@ pub const TestRunnerTask = struct { var test_: TestScope = this.describe.tests.items[test_id]; describe.current_test_id = test_id; var globalThis = this.globalThis; + + if (!describe.skipped and test_.is_todo and test_.callback == null) { + this.processTestResult(globalThis, .{ .todo = {} }, test_, test_id, describe); + this.deinit(); + return false; + } + if (test_.skipped or describe.skipped) { this.processTestResult(globalThis, .{ .skip = {} }, test_, test_id, describe); this.deinit(); @@ -4067,6 +4130,7 @@ pub const TestRunnerTask = struct { describe, ), .skip => Jest.runner.?.reportSkip(test_id, this.source_file_path, test_.label, describe), + .todo => Jest.runner.?.reportTodo(test_id, this.source_file_path, test_.label, describe), .pending => @panic("Unexpected pending test"), } describe.onTestComplete(globalThis, test_id, result == .skip); @@ -4101,4 +4165,5 @@ pub const Result = union(TestRunner.Test.Status) { pass: u32, // assertion count pending: void, skip: void, + todo: void, }; |