aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/test/jest.zig
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-03-19 14:08:20 -0700
committerGravatar GitHub <noreply@github.com> 2023-03-19 14:08:20 -0700
commit5a23d176208bb38483b65b9420b18c8597fabfef (patch)
treef163dc03fdc75b7827ee7f51e17355a9cc82329f /src/bun.js/test/jest.zig
parent8f02ef829474cbd5453ffcb6485d40f93424ad26 (diff)
downloadbun-5a23d176208bb38483b65b9420b18c8597fabfef.tar.gz
bun-5a23d176208bb38483b65b9420b18c8597fabfef.tar.zst
bun-5a23d176208bb38483b65b9420b18c8597fabfef.zip
Several bug fixes (#2427)
* Fix test * Fix segfault when unexpected type is passed in `expect().toThrow` * Fix issues with request constructor * Don't bother cloning headers when its empty * woops * more tests * fix incorrect test * Make the fetch error messages better * Update response.zig * Fix test that failed on macOS * Fix test * Remove extra hash table lookups * Support running dummy registry directly cc @alexlamsl * Update test * Update test * fixup * Workaround crash in test runner * Fixup test * Fixup test * Update os.test.js --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/bun.js/test/jest.zig')
-rw-r--r--src/bun.js/test/jest.zig178
1 files changed, 59 insertions, 119 deletions
diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig
index 883a3a48d..85bdb459e 100644
--- a/src/bun.js/test/jest.zig
+++ b/src/bun.js/test/jest.zig
@@ -2163,18 +2163,11 @@ pub const Expect = struct {
if (expected_value.isEmpty()) {
const signature_no_args = comptime getSignature("toThrow", "", true);
- if (result.isError()) {
- const name = result.getIfPropertyExistsImpl(globalObject, "name", 4);
- const message = result.getIfPropertyExistsImpl(globalObject, "message", 7);
+ if (result.toError()) |err| {
+ const name = err.get(globalObject, "name") orelse JSValue.undefined;
+ const message = err.get(globalObject, "message") orelse JSValue.undefined;
const fmt = signature_no_args ++ "\n\nError name: <red>{any}<r>\nError message: <red>{any}<r>\n";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{
- name.toFmt(globalObject, &formatter),
- message.toFmt(globalObject, &formatter),
- });
- return .zero;
- }
- globalObject.throw(Output.prettyFmt(fmt, false), .{
+ globalObject.throwPretty(fmt, .{
name.toFmt(globalObject, &formatter),
message.toFmt(globalObject, &formatter),
});
@@ -2183,41 +2176,25 @@ pub const Expect = struct {
// non error thrown
const fmt = signature_no_args ++ "\n\nThrown value: <red>{any}<r>\n";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{result.toFmt(globalObject, &formatter)});
- return .zero;
- }
- globalObject.throw(Output.prettyFmt(fmt, false), .{result.toFmt(globalObject, &formatter)});
+ globalObject.throwPretty(fmt, .{result.toFmt(globalObject, &formatter)});
return .zero;
}
if (expected_value.isString()) {
const received_message = result.getIfPropertyExistsImpl(globalObject, "message", 7);
+ // TODO: remove this allocation
// partial match
{
- var expected_string = ZigString.Empty;
- var received_string = ZigString.Empty;
- expected_value.toZigString(&expected_string, globalObject);
- received_message.toZigString(&received_string, globalObject);
- const expected_slice = expected_string.toSlice(default_allocator);
- const received_slice = received_string.toSlice(default_allocator);
- defer {
- expected_slice.deinit();
- received_slice.deinit();
- }
+ const expected_slice = expected_value.toSliceOrNull(globalObject) orelse return .zero;
+ defer expected_slice.deinit();
+ const received_slice = received_message.toSliceOrNull(globalObject) orelse return .zero;
+ defer received_slice.deinit();
if (!strings.contains(received_slice.slice(), expected_slice.slice())) return thisValue;
}
const fmt = signature ++ "\n\nExpected substring: not <green>{any}<r>\nReceived message: <red>{any}<r>\n";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{
- expected_value.toFmt(globalObject, &formatter),
- received_message.toFmt(globalObject, &formatter),
- });
- return .zero;
- }
- globalObject.throw(Output.prettyFmt(fmt, false), .{
+ globalObject.throwPretty(fmt, .{
expected_value.toFmt(globalObject, &formatter),
received_message.toFmt(globalObject, &formatter),
});
@@ -2227,20 +2204,14 @@ pub const Expect = struct {
if (expected_value.isRegExp()) {
const received_message = result.getIfPropertyExistsImpl(globalObject, "message", 7);
+ // TODO: REMOVE THIS GETTER! Expose a binding to call .test on the RegExp object directly.
if (expected_value.get(globalObject, "test")) |test_fn| {
const matches = test_fn.callWithThis(globalObject, expected_value, &.{received_message});
if (!matches.toBooleanSlow(globalObject)) return thisValue;
}
const fmt = signature ++ "\n\nExpected pattern: not <green>{any}<r>\nReceived message: <red>{any}<r>\n";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{
- expected_value.toFmt(globalObject, &formatter),
- received_message.toFmt(globalObject, &formatter),
- });
- return .zero;
- }
- globalObject.throw(Output.prettyFmt(fmt, false), .{
+ globalObject.throwPretty(fmt, .{
expected_value.toFmt(globalObject, &formatter),
received_message.toFmt(globalObject, &formatter),
});
@@ -2253,11 +2224,7 @@ pub const Expect = struct {
if (!expected_message.isSameValue(received_message, globalObject)) return thisValue;
const fmt = signature ++ "\n\nExpected message: not <green>{any}<r>\n";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{expected_message.toFmt(globalObject, &formatter)});
- return .zero;
- }
- globalObject.throw(Output.prettyFmt(fmt, false), .{expected_message.toFmt(globalObject, &formatter)});
+ globalObject.throwPretty(fmt, .{expected_message.toFmt(globalObject, &formatter)});
return .zero;
}
@@ -2279,22 +2246,26 @@ pub const Expect = struct {
if (did_throw) {
if (expected_value.isEmpty()) return thisValue;
- const result: JSValue = result_.?;
- const _received_message = result.get(globalObject, "message");
+ const result: JSValue = if (result_.?.toError()) |r|
+ r
+ else
+ result_.?;
+
+ const _received_message: ?JSValue = if (result.isObject())
+ result.get(globalObject, "message")
+ else if (result.toStringOrNull(globalObject)) |js_str|
+ JSC.JSValue.fromCell(js_str)
+ else
+ null;
if (expected_value.isString()) {
if (_received_message) |received_message| {
+ // TODO: remove this allocation
// partial match
- var expected_string = ZigString.Empty;
- var received_string = ZigString.Empty;
- expected_value.toZigString(&expected_string, globalObject);
- received_message.toZigString(&received_string, globalObject);
- const expected_slice = expected_string.toSlice(default_allocator);
- const received_slice = received_string.toSlice(default_allocator);
- defer {
- expected_slice.deinit();
- received_slice.deinit();
- }
+ const expected_slice = expected_value.toSliceOrNull(globalObject) orelse return .zero;
+ defer expected_slice.deinit();
+ const received_slice = received_message.toSlice(globalObject, globalObject.allocator());
+ defer received_slice.deinit();
if (strings.contains(received_slice.slice(), expected_slice.slice())) return thisValue;
}
@@ -2305,29 +2276,21 @@ pub const Expect = struct {
const expected_value_fmt = expected_value.toFmt(globalObject, &formatter);
const received_message_fmt = received_message.toFmt(globalObject, &formatter);
const fmt = signature ++ "\n\n" ++ "Expected substring: <green>{any}<r>\nReceived message: <red>{any}<r>\n";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{ expected_value_fmt, received_message_fmt });
- return .zero;
- }
-
- globalObject.throw(Output.prettyFmt(fmt, false), .{ expected_value_fmt, received_message_fmt });
+ globalObject.throwPretty(fmt, .{ expected_value_fmt, received_message_fmt });
return .zero;
}
const expected_fmt = expected_value.toFmt(globalObject, &formatter);
const received_fmt = result.toFmt(globalObject, &formatter);
const fmt = signature ++ "\n\n" ++ "Expected substring: <green>{any}<r>\nReceived value: <red>{any}<r>";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{ expected_fmt, received_fmt });
- return .zero;
- }
+ globalObject.throwPretty(fmt, .{ expected_fmt, received_fmt });
- globalObject.throw(Output.prettyFmt(fmt, false), .{ expected_fmt, received_fmt });
return .zero;
}
if (expected_value.isRegExp()) {
if (_received_message) |received_message| {
+ // TODO: REMOVE THIS GETTER! Expose a binding to call .test on the RegExp object directly.
if (expected_value.get(globalObject, "test")) |test_fn| {
const matches = test_fn.callWithThis(globalObject, expected_value, &.{received_message});
if (matches.toBooleanSlow(globalObject)) return thisValue;
@@ -2341,27 +2304,21 @@ pub const Expect = struct {
const expected_value_fmt = expected_value.toFmt(globalObject, &formatter);
const received_message_fmt = received_message.toFmt(globalObject, &formatter);
const fmt = signature ++ "\n\n" ++ "Expected pattern: <green>{any}<r>\nReceived message: <red>{any}<r>\n";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{ expected_value_fmt, received_message_fmt });
- return .zero;
- }
+ globalObject.throwPretty(fmt, .{ expected_value_fmt, received_message_fmt });
- globalObject.throw(Output.prettyFmt(fmt, false), .{ expected_value_fmt, received_message_fmt });
return .zero;
}
const expected_fmt = expected_value.toFmt(globalObject, &formatter);
const received_fmt = result.toFmt(globalObject, &formatter);
const fmt = signature ++ "\n\n" ++ "Expected pattern: <green>{any}<r>\nReceived value: <red>{any}<r>";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{ expected_fmt, received_fmt });
- return .zero;
- }
-
- globalObject.throw(Output.prettyFmt(fmt, false), .{ expected_fmt, received_fmt });
+ globalObject.throwPretty(fmt, .{ expected_fmt, received_fmt });
return .zero;
}
+ // If it's not an object, we are going to crash here.
+ std.debug.assert(expected_value.isObject());
+
if (expected_value.get(globalObject, "message")) |expected_message| {
if (_received_message) |received_message| {
if (received_message.isSameValue(expected_message, globalObject)) return thisValue;
@@ -2374,24 +2331,14 @@ pub const Expect = struct {
const expected_fmt = expected_message.toFmt(globalObject, &formatter);
const received_fmt = received_message.toFmt(globalObject, &formatter);
const fmt = signature ++ "\n\nExpected message: <green>{any}<r>\nReceived message: <red>{any}<r>\n";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{ expected_fmt, received_fmt });
- return .zero;
- }
-
- globalObject.throw(Output.prettyFmt(fmt, false), .{ expected_fmt, received_fmt });
+ globalObject.throwPretty(fmt, .{ expected_fmt, received_fmt });
return .zero;
}
const expected_fmt = expected_message.toFmt(globalObject, &formatter);
const received_fmt = result.toFmt(globalObject, &formatter);
const fmt = signature ++ "\n\nExpected message: <green>{any}<r>\nReceived value: <red>{any}<r>\n";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{ expected_fmt, received_fmt });
- return .zero;
- }
-
- globalObject.throw(Output.prettyFmt(fmt, false), .{ expected_fmt, received_fmt });
+ globalObject.throwPretty(fmt, .{ expected_fmt, received_fmt });
return .zero;
}
@@ -2408,16 +2355,8 @@ pub const Expect = struct {
if (_received_message) |received_message| {
const message_fmt = fmt ++ "Received message: <red>{any}<r>\n";
const received_message_fmt = received_message.toFmt(globalObject, &formatter);
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(message_fmt, true), .{
- expected_class,
- received_class,
- received_message_fmt,
- });
- return .zero;
- }
- globalObject.throw(Output.prettyFmt(message_fmt, false), .{
+ globalObject.throwPretty(message_fmt, .{
expected_class,
received_class,
received_message_fmt,
@@ -2427,16 +2366,8 @@ pub const Expect = struct {
const received_fmt = result.toFmt(globalObject, &formatter);
const value_fmt = fmt ++ "Received value: <red>{any}<r>\n";
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(value_fmt, true), .{
- expected_class,
- received_class,
- received_fmt,
- });
- return .zero;
- }
- globalObject.throw(Output.prettyFmt(value_fmt, false), .{
+ globalObject.throwPretty(value_fmt, .{
expected_class,
received_class,
received_fmt,
@@ -2824,7 +2755,7 @@ pub const Expect = struct {
}
unreachable;
};
-
+
if (not) pass = !pass;
if (pass) return thisValue;
@@ -3503,7 +3434,7 @@ pub const DescribeScope = struct {
.test_id = i,
.describe = this,
.globalThis = ctx,
- .source = source,
+ .source_file_path = source.path.text,
.value = JSC.Strong.create(this_object, ctx),
};
runner.ref.ref(ctx.bunVM());
@@ -3608,7 +3539,7 @@ pub const TestRunnerTask = struct {
test_id: TestRunner.Test.ID,
describe: *DescribeScope,
globalThis: *JSC.JSGlobalObject,
- source: logger.Source,
+ source_file_path: string = "",
value: JSC.Strong = .{},
needs_before_each: bool = true,
ref: JSC.Ref = JSC.Ref.init(),
@@ -3677,7 +3608,7 @@ pub const TestRunnerTask = struct {
const beforeEach = this.describe.runCallback(globalThis, .beforeEach);
if (!beforeEach.isEmpty()) {
- Jest.runner.?.reportFailure(test_id, this.source.path.text, label, 0, this.describe);
+ Jest.runner.?.reportFailure(test_id, this.source_file_path, label, 0, this.describe);
globalThis.bunVM().runErrorHandler(beforeEach, null);
return false;
}
@@ -3754,9 +3685,9 @@ pub const TestRunnerTask = struct {
fn processTestResult(this: *TestRunnerTask, globalThis: *JSC.JSGlobalObject, result: Result, test_: TestScope, test_id: u32, describe: *DescribeScope) void {
switch (result) {
- .pass => |count| Jest.runner.?.reportPass(test_id, this.source.path.text, test_.label, count, describe),
- .fail => |count| Jest.runner.?.reportFailure(test_id, this.source.path.text, test_.label, count, describe),
- .skip => Jest.runner.?.reportSkip(test_id, this.source.path.text, test_.label, describe),
+ .pass => |count| Jest.runner.?.reportPass(test_id, this.source_file_path, test_.label, count, describe),
+ .fail => |count| Jest.runner.?.reportFailure(test_id, this.source_file_path, test_.label, count, describe),
+ .skip => Jest.runner.?.reportSkip(test_id, this.source_file_path, test_.label, describe),
.pending => @panic("Unexpected pending test"),
}
describe.onTestComplete(globalThis, test_id, result == .skip);
@@ -3773,7 +3704,16 @@ pub const TestRunnerTask = struct {
this.value.deinit();
this.ref.unref(vm);
- default_allocator.destroy(this);
+
+ // there is a double free here involving async before/after callbacks
+ //
+ // Fortunately:
+ //
+ // - TestRunnerTask doesn't use much memory.
+ // - we don't have watch mode yet.
+ //
+ // TODO: fix this bug
+ // default_allocator.destroy(this);
}
};