aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js
diff options
context:
space:
mode:
authorGravatar zhiyuan <32867472+zhiyuang@users.noreply.github.com> 2023-03-17 18:49:41 +0800
committerGravatar GitHub <noreply@github.com> 2023-03-17 03:49:41 -0700
commitc5f2b4264993739440f73d166280c9ec74e27c1c (patch)
treeae7acff72ecadb190bf84714b34fa1ad8dabedf9 /src/bun.js
parent37293cb26a8239d4f387218a1fdadc522787835f (diff)
downloadbun-c5f2b4264993739440f73d166280c9ec74e27c1c.tar.gz
bun-c5f2b4264993739440f73d166280c9ec74e27c1c.tar.zst
bun-c5f2b4264993739440f73d166280c9ec74e27c1c.zip
Feat(test): add toMatch (#2404)
Diffstat (limited to 'src/bun.js')
-rw-r--r--src/bun.js/bindings/bindings.cpp25
-rw-r--r--src/bun.js/bindings/bindings.zig10
-rw-r--r--src/bun.js/bindings/headers-cpp.h2
-rw-r--r--src/bun.js/bindings/headers.h4
-rw-r--r--src/bun.js/bindings/headers.zig2
-rw-r--r--src/bun.js/test/jest.zig77
6 files changed, 112 insertions, 8 deletions
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp
index f273bca46..3b0137c28 100644
--- a/src/bun.js/bindings/bindings.cpp
+++ b/src/bun.js/bindings/bindings.cpp
@@ -2845,6 +2845,31 @@ JSC__JSString* JSC__JSValue__toStringOrNull(JSC__JSValue JSValue0, JSC__JSGlobal
return value.toStringOrNull(arg1);
}
+bool JSC__JSValue__toMatch(JSC__JSValue regexValue, JSC__JSGlobalObject* global, JSC__JSValue value) {
+ JSC::JSValue regex = JSC::JSValue::decode(regexValue);
+ JSC::JSValue str = JSC::JSValue::decode(value);
+ if (regex.asCell()->type() != RegExpObjectType || !str.isString()) {
+ return false;
+ }
+ JSC::RegExpObject* regexObject = jsDynamicCast<JSC::RegExpObject*>(regex);
+
+ return !!regexObject->match(global, JSC::asString(str));
+}
+
+bool JSC__JSValue__stringIncludes(JSC__JSValue value, JSC__JSGlobalObject* globalObject, JSC__JSValue other)
+{
+ VM& vm = globalObject->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ WTF::String stringToSearchIn = JSC::JSValue::decode(value).toWTFString(globalObject);
+ RETURN_IF_EXCEPTION(scope, false);
+
+ WTF::String searchString = JSC::JSValue::decode(other).toWTFString(globalObject);
+ RETURN_IF_EXCEPTION(scope, false);
+
+ return stringToSearchIn.find(searchString, 0) != WTF::notFound;
+}
+
static void populateStackFrameMetadata(JSC::VM& vm, const JSC::StackFrame* stackFrame, ZigStackFrame* frame)
{
frame->source_url = Zig::toZigString(stackFrame->sourceURL(vm));
diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig
index 3059ba09f..1ac1fc5ca 100644
--- a/src/bun.js/bindings/bindings.zig
+++ b/src/bun.js/bindings/bindings.zig
@@ -3651,6 +3651,10 @@ pub const JSValue = enum(JSValueReprInt) {
return cppFn("toZigString", .{ this, out, global });
}
+ pub fn toMatch(this: JSValue, global: *JSGlobalObject, other: JSValue) bool {
+ return cppFn("toMatch", .{ this, global, other });
+ }
+
pub fn asArrayBuffer_(this: JSValue, global: *JSGlobalObject, out: *ArrayBuffer) bool {
return cppFn("asArrayBuffer_", .{ this, global, out });
}
@@ -3983,6 +3987,10 @@ pub const JSValue = enum(JSValueReprInt) {
});
}
+ pub fn stringIncludes(this: JSValue, globalObject: *JSGlobalObject, other: JSValue) bool {
+ return cppFn("stringIncludes", .{ this, globalObject, other });
+ }
+
pub inline fn asRef(this: JSValue) C_API.JSValueRef {
return @intToPtr(C_API.JSValueRef, @bitCast(usize, @enumToInt(this)));
}
@@ -4121,8 +4129,10 @@ pub const JSValue = enum(JSValueReprInt) {
"toWTFString",
"toZigException",
"toZigString",
+ "toMatch",
"isConstructor",
"isInstanceOf",
+ "stringIncludes",
};
};
diff --git a/src/bun.js/bindings/headers-cpp.h b/src/bun.js/bindings/headers-cpp.h
index 243ae3706..49391bb42 100644
--- a/src/bun.js/bindings/headers-cpp.h
+++ b/src/bun.js/bindings/headers-cpp.h
@@ -1,4 +1,4 @@
-//-- AUTOGENERATED FILE -- 1678855956
+//-- AUTOGENERATED FILE -- 1679048516
// clang-format off
#pragma once
diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h
index 35050c4e8..e631721f7 100644
--- a/src/bun.js/bindings/headers.h
+++ b/src/bun.js/bindings/headers.h
@@ -1,5 +1,5 @@
// clang-format off
-//-- AUTOGENERATED FILE -- 1678855956
+//-- AUTOGENERATED FILE -- 1679048516
#pragma once
#include <stddef.h>
@@ -353,6 +353,7 @@ CPP_DECL void JSC__JSValue__put(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1
CPP_DECL void JSC__JSValue__putIndex(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, uint32_t arg2, JSC__JSValue JSValue3);
CPP_DECL void JSC__JSValue__putRecord(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2, ZigString* arg3, size_t arg4);
CPP_DECL bool JSC__JSValue__strictDeepEquals(JSC__JSValue JSValue0, JSC__JSValue JSValue1, JSC__JSGlobalObject* arg2);
+CPP_DECL bool JSC__JSValue__stringIncludes(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2);
CPP_DECL JSC__JSValue JSC__JSValue__symbolFor(JSC__JSGlobalObject* arg0, ZigString* arg1);
CPP_DECL bool JSC__JSValue__symbolKeyFor(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, ZigString* arg2);
CPP_DECL bool JSC__JSValue__toBoolean(JSC__JSValue JSValue0);
@@ -360,6 +361,7 @@ CPP_DECL bool JSC__JSValue__toBooleanSlow(JSC__JSValue JSValue0, JSC__JSGlobalOb
CPP_DECL JSC__JSValue JSC__JSValue__toError_(JSC__JSValue JSValue0);
CPP_DECL int32_t JSC__JSValue__toInt32(JSC__JSValue JSValue0);
CPP_DECL int64_t JSC__JSValue__toInt64(JSC__JSValue JSValue0);
+CPP_DECL bool JSC__JSValue__toMatch(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2);
CPP_DECL JSC__JSObject* JSC__JSValue__toObject(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL JSC__JSString* JSC__JSValue__toString(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
CPP_DECL JSC__JSString* JSC__JSValue__toStringOrNull(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1);
diff --git a/src/bun.js/bindings/headers.zig b/src/bun.js/bindings/headers.zig
index 1e3530d22..eff9a1b81 100644
--- a/src/bun.js/bindings/headers.zig
+++ b/src/bun.js/bindings/headers.zig
@@ -266,6 +266,7 @@ pub extern fn JSC__JSValue__put(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobal
pub extern fn JSC__JSValue__putIndex(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, arg2: u32, JSValue3: JSC__JSValue) void;
pub extern fn JSC__JSValue__putRecord(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, arg2: [*c]ZigString, arg3: [*c]ZigString, arg4: usize) void;
pub extern fn JSC__JSValue__strictDeepEquals(JSValue0: JSC__JSValue, JSValue1: JSC__JSValue, arg2: *bindings.JSGlobalObject) bool;
+pub extern fn JSC__JSValue__stringIncludes(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, JSValue2: JSC__JSValue) bool;
pub extern fn JSC__JSValue__symbolFor(arg0: *bindings.JSGlobalObject, arg1: [*c]ZigString) JSC__JSValue;
pub extern fn JSC__JSValue__symbolKeyFor(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, arg2: [*c]ZigString) bool;
pub extern fn JSC__JSValue__toBoolean(JSValue0: JSC__JSValue) bool;
@@ -273,6 +274,7 @@ pub extern fn JSC__JSValue__toBooleanSlow(JSValue0: JSC__JSValue, arg1: *binding
pub extern fn JSC__JSValue__toError_(JSValue0: JSC__JSValue) JSC__JSValue;
pub extern fn JSC__JSValue__toInt32(JSValue0: JSC__JSValue) i32;
pub extern fn JSC__JSValue__toInt64(JSValue0: JSC__JSValue) i64;
+pub extern fn JSC__JSValue__toMatch(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, JSValue2: JSC__JSValue) bool;
pub extern fn JSC__JSValue__toObject(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject) [*c]bindings.JSObject;
pub extern fn JSC__JSValue__toString(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject) [*c]bindings.JSString;
pub extern fn JSC__JSValue__toStringOrNull(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject) [*c]bindings.JSString;
diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig
index 33e7d8269..883a3a48d 100644
--- a/src/bun.js/test/jest.zig
+++ b/src/bun.js/test/jest.zig
@@ -2759,7 +2759,7 @@ pub const Expect = struct {
if (not) {
const expected_line = "Expected constructor: not <green>{any}<r>\n";
const received_line = "Received value: <red>{any}<r>\n";
- const fmt = comptime getSignature("toBeInstanceOf", "", true) ++ "\n\n" ++ expected_line ++ received_line;
+ const fmt = comptime getSignature("toBeInstanceOf", "<green>expected<r>", true) ++ "\n\n" ++ expected_line ++ received_line;
if (Output.enable_ansi_colors) {
globalObject.throw(Output.prettyFmt(fmt, true), .{ expected_fmt, value_fmt });
return .zero;
@@ -2771,13 +2771,79 @@ pub const Expect = struct {
const expected_line = "Expected constructor: <green>{any}<r>\n";
const received_line = "Received value: <red>{any}<r>\n";
- const fmt = comptime getSignature("toBeInstanceOf", "", false) ++ "\n\n" ++ expected_line ++ received_line;
- if (Output.enable_ansi_colors) {
- globalObject.throw(Output.prettyFmt(fmt, true), .{ expected_fmt, value_fmt });
+ const fmt = comptime getSignature("toBeInstanceOf", "<green>expected<r>", false) ++ "\n\n" ++ expected_line ++ received_line;
+ globalObject.throwPretty(fmt, .{ expected_fmt, value_fmt });
+ return .zero;
+ }
+
+ pub fn toMatch(this: *Expect, globalObject: *JSC.JSGlobalObject, callFrame: *JSC.CallFrame) callconv(.C) JSValue {
+ defer this.postMatch(globalObject);
+
+ const thisValue = callFrame.this();
+ const _arguments = callFrame.arguments(1);
+ const arguments: []const JSValue = _arguments.ptr[0.._arguments.len];
+
+ if (arguments.len < 1) {
+ globalObject.throwInvalidArguments("toMatch() requires 1 argument", .{});
return .zero;
}
- globalObject.throw(Output.prettyFmt(fmt, false), .{ expected_fmt, value_fmt });
+ if (this.scope.tests.items.len <= this.test_id) {
+ globalObject.throw("toMatch() must be called in a test", .{});
+ return .zero;
+ }
+
+ active_test_expectation_counter.actual += 1;
+
+ var formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject, .quote_strings = true };
+
+ const expected_value = arguments[0];
+ if (!expected_value.isString() and !expected_value.isRegExp()) {
+ globalObject.throw("Expected value must be a string or regular expression: {any}", .{expected_value.toFmt(globalObject, &formatter)});
+ return .zero;
+ }
+ expected_value.ensureStillAlive();
+
+ const value = Expect.capturedValueGetCached(thisValue) orelse {
+ globalObject.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{});
+ return .zero;
+ };
+ value.ensureStillAlive();
+
+ if (!value.isString()) {
+ globalObject.throw("Received value must be a string: {any}", .{value.toFmt(globalObject, &formatter)});
+ return .zero;
+ }
+
+ const not = this.op.contains(.not);
+ var pass: bool = brk: {
+ if (expected_value.isString()) {
+ break :brk value.stringIncludes(globalObject, expected_value);
+ } else if (expected_value.isRegExp()) {
+ break :brk expected_value.toMatch(globalObject, value);
+ }
+ unreachable;
+ };
+
+ if (not) pass = !pass;
+ if (pass) return thisValue;
+
+ // handle failure
+ const expected_fmt = expected_value.toFmt(globalObject, &formatter);
+ const value_fmt = value.toFmt(globalObject, &formatter);
+
+ if (not) {
+ const expected_line = "Expected substring or pattern: not <green>{any}<r>\n";
+ const received_line = "Received: <red>{any}<r>\n";
+ const fmt = comptime getSignature("toMatch", "<green>expected<r>", true) ++ "\n\n" ++ expected_line ++ received_line;
+ globalObject.throwPretty(fmt, .{ expected_fmt, value_fmt });
+ return .zero;
+ }
+
+ const expected_line = "Expected substring or pattern: <green>{any}<r>\n";
+ const received_line = "Received: <red>{any}<r>\n";
+ const fmt = comptime getSignature("toMatch", "<green>expected<r>", false) ++ "\n\n" ++ expected_line ++ received_line;
+ globalObject.throwPretty(fmt, .{ expected_fmt, value_fmt });
return .zero;
}
@@ -2791,7 +2857,6 @@ pub const Expect = struct {
pub const toHaveNthReturnedWith = notImplementedJSCFn;
pub const toBeCloseTo = notImplementedJSCFn;
pub const toContainEqual = notImplementedJSCFn;
- pub const toMatch = notImplementedJSCFn;
pub const toMatchObject = notImplementedJSCFn;
pub const toMatchInlineSnapshot = notImplementedJSCFn;
pub const toThrowErrorMatchingSnapshot = notImplementedJSCFn;