-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add some jest-extended
matchers to bun test
#13628
base: main
Are you sure you want to change the base?
Changes from all commits
3d5675d
9291720
e01ca07
d9f19a2
1d1dc04
d430360
d8fc3d4
16efcc8
115ae09
62c3a77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1295,6 +1295,282 @@ pub const Expect = struct { | |
return this.throw(globalObject, comptime getSignature("toContainAnyValues", "<green>expected<r>", false), fmt, .{ expected_fmt, value_fmt }); | ||
} | ||
|
||
pub fn toContainEntry( | ||
this: *Expect, | ||
globalObject: *JSGlobalObject, | ||
callFrame: *CallFrame, | ||
) JSValue { | ||
defer this.postMatch(globalObject); | ||
const thisValue = callFrame.this(); | ||
const arguments_ = callFrame.arguments(1); | ||
const arguments = arguments_.slice(); | ||
|
||
if (arguments.len < 1) { | ||
globalObject.throwInvalidArguments("toContainEntry() takes 1 argument", .{}); | ||
return .zero; | ||
} | ||
|
||
incrementExpectCallCounter(); | ||
|
||
const expected = arguments[0]; | ||
if (!expected.jsType().isArray()) { | ||
globalObject.throwInvalidArgumentType("toContainEntry", "expected", "array"); | ||
return .zero; | ||
} | ||
expected.ensureStillAlive(); | ||
const value: JSValue = this.getValue(globalObject, thisValue, "toContainEntry", "<green>expected<r>") orelse return .zero; | ||
|
||
const not = this.flags.not; | ||
var pass = false; | ||
|
||
if (!value.isUndefinedOrNull()) { | ||
const key = expected.getIndex(globalObject, 0); | ||
const key_string = key.toBunString(globalObject); | ||
defer key_string.deref(); | ||
|
||
const property_value = expected.getIndex(globalObject, 1); | ||
const accessed_property_value = value.getOwn(globalObject, key_string) orelse JSValue.undefined; | ||
nithinkjoy-tech marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the expect({}).toContainEntry([ a, 1 ]); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Applies similarly to |
||
if (globalObject.hasException()) return .zero; | ||
if (property_value.jestDeepEquals(accessed_property_value, globalObject)) pass = true; | ||
} | ||
|
||
if (not) pass = !pass; | ||
if (pass) return thisValue; | ||
|
||
// handle failure | ||
var formatter = JSC.ConsoleObject.Formatter{ .globalThis = globalObject, .quote_strings = true }; | ||
const value_fmt = value.toFmt(&formatter); | ||
const expected_fmt = expected.toFmt(&formatter); | ||
if (not) { | ||
const received_fmt = value.toFmt(&formatter); | ||
const expected_line = "Expected object to not contain entry: <green>{any}<r>\nReceived: <red>{any}<r>\n"; | ||
const fmt = "\n\n" ++ expected_line; | ||
this.throw(globalObject, comptime getSignature("toContainEntry", "<green>expected<r>", true), fmt, .{ expected_fmt, received_fmt }); | ||
return .zero; | ||
} | ||
|
||
const expected_line = "Expected object to contain entry:: <green>{any}<r>\n"; | ||
const received_line = "Received: <red>{any}<r>\n"; | ||
const fmt = "\n\n" ++ expected_line ++ received_line; | ||
this.throw(globalObject, comptime getSignature("toContainEntry", "<green>expected<r>", false), fmt, .{ expected_fmt, value_fmt }); | ||
return .zero; | ||
} | ||
|
||
pub fn toContainEntries( | ||
this: *Expect, | ||
globalObject: *JSGlobalObject, | ||
callFrame: *CallFrame, | ||
) JSValue { | ||
defer this.postMatch(globalObject); | ||
const thisValue = callFrame.this(); | ||
const arguments_ = callFrame.arguments(1); | ||
const arguments = arguments_.slice(); | ||
|
||
if (arguments.len < 1) { | ||
globalObject.throwInvalidArguments("toContainEntries() takes 1 argument", .{}); | ||
return .zero; | ||
} | ||
|
||
incrementExpectCallCounter(); | ||
|
||
const expected = arguments[0]; | ||
if (!expected.jsType().isArray()) { | ||
globalObject.throwInvalidArgumentType("toContainEntries", "expected", "array"); | ||
return .zero; | ||
} | ||
expected.ensureStillAlive(); | ||
const value: JSValue = this.getValue(globalObject, thisValue, "toContainEntries", "<green>expected<r>") orelse return .zero; | ||
|
||
const not = this.flags.not; | ||
var pass = true; | ||
|
||
if (!value.isUndefinedOrNull()) { | ||
var itr = expected.arrayIterator(globalObject); | ||
|
||
while (itr.next()) |item| { | ||
if (!item.isUndefinedOrNull()) { | ||
const key = item.getIndex(globalObject, 0); | ||
const key_string = key.toBunString(globalObject); | ||
defer key_string.deref(); | ||
|
||
const property_value = item.getIndex(globalObject, 1); | ||
if (globalObject.hasException()) return .zero; | ||
const accessed_property_value = value.getOwn(globalObject, key_string) orelse JSValue.undefined; | ||
if (globalObject.hasException()) return .zero; | ||
|
||
if (!property_value.jestDeepEquals(accessed_property_value, globalObject)) { | ||
pass = false; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if (not) pass = !pass; | ||
if (pass) return thisValue; | ||
|
||
// handle failure | ||
var formatter = JSC.ConsoleObject.Formatter{ .globalThis = globalObject, .quote_strings = true }; | ||
const value_fmt = value.toFmt(&formatter); | ||
const expected_fmt = expected.toFmt(&formatter); | ||
if (not) { | ||
const received_fmt = value.toFmt(&formatter); | ||
const expected_line = "Expected object to not contain all of the given entries: <green>{any}<r>\nReceived: <red>{any}<r>\n"; | ||
const fmt = "\n\n" ++ expected_line; | ||
this.throw(globalObject, comptime getSignature("toContainEntries", "<green>expected<r>", true), fmt, .{ expected_fmt, received_fmt }); | ||
return .zero; | ||
} | ||
|
||
const expected_line = "Expected object to contain all of the given entries: <green>{any}<r>\n"; | ||
const received_line = "Received: <red>{any}<r>\n"; | ||
const fmt = "\n\n" ++ expected_line ++ received_line; | ||
this.throw(globalObject, comptime getSignature("toContainEntries", "<green>expected<r>", false), fmt, .{ expected_fmt, value_fmt }); | ||
return .zero; | ||
} | ||
|
||
pub fn toContainAllEntries( | ||
this: *Expect, | ||
globalObject: *JSGlobalObject, | ||
callFrame: *CallFrame, | ||
) JSValue { | ||
defer this.postMatch(globalObject); | ||
const thisValue = callFrame.this(); | ||
const arguments_ = callFrame.arguments(1); | ||
const arguments = arguments_.slice(); | ||
|
||
if (arguments.len < 1) { | ||
globalObject.throwInvalidArguments("toContainAllEntries() takes 1 argument", .{}); | ||
return .zero; | ||
} | ||
|
||
incrementExpectCallCounter(); | ||
|
||
const expected = arguments[0]; | ||
if (!expected.jsType().isArray()) { | ||
globalObject.throwInvalidArgumentType("toContainAllEntries", "expected", "array"); | ||
return .zero; | ||
} | ||
expected.ensureStillAlive(); | ||
const value: JSValue = this.getValue(globalObject, thisValue, "toContainAllEntries", "<green>expected<r>") orelse return .zero; | ||
|
||
const not = this.flags.not; | ||
var pass = true; | ||
|
||
const count = expected.getLength(globalObject); | ||
if (!value.isUndefinedOrNull()) { | ||
if (value.keys(globalObject).getLength(globalObject) == count) { | ||
var itr = expected.arrayIterator(globalObject); | ||
|
||
while (itr.next()) |item| { | ||
if (!item.isUndefinedOrNull()) { | ||
const property_key = item.getIndex(globalObject, 0); | ||
const key_string = property_key.toBunString(globalObject); | ||
defer key_string.deref(); | ||
|
||
const property_value = item.getIndex(globalObject, 1); | ||
const accessed_property_value = value.getOwn(globalObject, key_string) orelse JSValue.undefined; | ||
if (globalObject.hasException()) return .zero; | ||
if (!accessed_property_value.jestDeepEquals(property_value, globalObject)) { | ||
pass = false; | ||
break; | ||
} | ||
} | ||
} | ||
} else pass = false; | ||
} | ||
|
||
if (not) pass = !pass; | ||
if (pass) return thisValue; | ||
|
||
// handle failure | ||
var formatter = JSC.ConsoleObject.Formatter{ .globalThis = globalObject, .quote_strings = true }; | ||
const value_fmt = value.toFmt(&formatter); | ||
const expected_fmt = expected.toFmt(&formatter); | ||
if (not) { | ||
const received_fmt = value.toFmt(&formatter); | ||
const expected_line = "Expected object to not only contain all of the given entries: <green>{any}<r>\nReceived: <red>{any}<r>\n"; | ||
const fmt = "\n\n" ++ expected_line; | ||
this.throw(globalObject, comptime getSignature("toContainAllEntries", "<green>expected<r>", true), fmt, .{ expected_fmt, received_fmt }); | ||
return .zero; | ||
} | ||
|
||
const expected_line = "Expected object to only contain all of the given entries: <green>{any}<r>\n"; | ||
const received_line = "Received: <red>{any}<r>\n"; | ||
const fmt = "\n\n" ++ expected_line ++ received_line; | ||
this.throw(globalObject, comptime getSignature("toContainAllEntries", "<green>expected<r>", false), fmt, .{ expected_fmt, value_fmt }); | ||
return .zero; | ||
} | ||
|
||
pub fn toContainAnyEntries( | ||
this: *Expect, | ||
globalObject: *JSGlobalObject, | ||
callFrame: *CallFrame, | ||
) JSValue { | ||
defer this.postMatch(globalObject); | ||
const thisValue = callFrame.this(); | ||
const arguments_ = callFrame.arguments(1); | ||
const arguments = arguments_.slice(); | ||
|
||
if (arguments.len < 1) { | ||
globalObject.throwInvalidArguments("toContainAnyEntries() takes 1 argument", .{}); | ||
return .zero; | ||
} | ||
|
||
incrementExpectCallCounter(); | ||
|
||
const expected = arguments[0]; | ||
if (!expected.jsType().isArray()) { | ||
globalObject.throwInvalidArgumentType("toContainAnyEntries", "expected", "array"); | ||
return .zero; | ||
} | ||
expected.ensureStillAlive(); | ||
const value: JSValue = this.getValue(globalObject, thisValue, "toContainAnyEntries", "<green>expected<r>") orelse return .zero; | ||
|
||
const not = this.flags.not; | ||
var pass = false; | ||
|
||
if (!value.isUndefinedOrNull()) { | ||
var itr = expected.arrayIterator(globalObject); | ||
|
||
while (itr.next()) |item| { | ||
if (!item.isUndefinedOrNull()) { | ||
const key = item.getIndex(globalObject, 0); | ||
const key_string = key.toBunString(globalObject); | ||
defer key_string.deref(); | ||
|
||
const property_value = item.getIndex(globalObject, 1); | ||
const accessed_property_value = value.getOwn(globalObject, key_string) orelse JSValue.undefined; | ||
if (globalObject.hasException()) return .zero; | ||
if (property_value.jestDeepEquals(accessed_property_value, globalObject)) { | ||
pass = true; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
if (not) pass = !pass; | ||
if (pass) return thisValue; | ||
|
||
// handle failure | ||
var formatter = JSC.ConsoleObject.Formatter{ .globalThis = globalObject, .quote_strings = true }; | ||
const value_fmt = value.toFmt(&formatter); | ||
const expected_fmt = expected.toFmt(&formatter); | ||
if (not) { | ||
const received_fmt = value.toFmt(&formatter); | ||
const expected_line = "Expected object to not contain any of the provided entries: <green>{any}<r>\nReceived: <red>{any}<r>\n"; | ||
const fmt = "\n\n" ++ expected_line; | ||
this.throw(globalObject, comptime getSignature("toContainAnyEntries", "<green>expected<r>", true), fmt, .{ expected_fmt, received_fmt }); | ||
return .zero; | ||
} | ||
|
||
const expected_line = "Expected object to contain any of the provided entries: <green>{any}<r>\n"; | ||
const received_line = "Received: <red>{any}<r>\n"; | ||
const fmt = "\n\n" ++ expected_line ++ received_line; | ||
this.throw(globalObject, comptime getSignature("toContainAnyEntries", "<green>expected<r>", false), fmt, .{ expected_fmt, value_fmt }); | ||
return .zero; | ||
} | ||
|
||
pub fn toContainEqual( | ||
this: *Expect, | ||
globalThis: *JSGlobalObject, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each
getIndex
call will need to check for exceptions. It's possible for the array to throw