feat: add toContainAnyKeys (#7946)

* feat: add toContainAnyKeys

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Lucas Coratger
2024-01-06 06:21:12 +01:00
committed by GitHub
parent e8179adcbb
commit bfe8afd674
4 changed files with 93 additions and 0 deletions

View File

@@ -966,11 +966,23 @@ declare module "bun:test" {
*/
toContainKey(expected: unknown): void;
/**
* Asserts that an `object` contains at least one of the provided keys.
* Asserts that an `object` contains all the provided keys.
*
* The value must be an object
*
* @example
* expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['a']);
* expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b']);
* expect({ a: 'hello', b: 'world' }).toContainAnyKeys(['b', 'c']);
* expect({ a: 'hello', b: 'world' }).not.toContainAnyKeys(['c']);
*
* @param expected the expected value
*/
toContainAnyKeys(expected: unknown): void;
/**
* Asserts that an `object` contains all the provided keys.
* expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b']);
* expect({ a: 'foo', b: 'bar', c: 'baz' }).toContainKeys(['a', 'b', 'c']);
* expect({ a: 'foo', b: 'bar', c: 'baz' }).not.toContainKeys(['a', 'b', 'e']);

View File

@@ -852,6 +852,75 @@ pub const Expect = struct {
return .zero;
}
pub fn toContainAnyKeys(
this: *Expect,
globalObject: *JSC.JSGlobalObject,
callFrame: *JSC.CallFrame,
) callconv(.C) JSC.JSValue {
defer this.postMatch(globalObject);
const thisValue = callFrame.this();
const arguments_ = callFrame.arguments(1);
const arguments = arguments_.ptr[0..arguments_.len];
if (arguments.len < 1) {
globalObject.throwInvalidArguments("toContainAnyKeys() takes 1 argument", .{});
return .zero;
}
incrementExpectCallCounter();
const expected = arguments[0];
expected.ensureStillAlive();
const value: JSValue = this.getValue(globalObject, thisValue, "toContainAnyKeys", "<green>expected<r>") orelse return .zero;
if (!expected.jsType().isArray()) {
globalObject.throwInvalidArgumentType("toContainAnyKeys", "expected", "array");
return .zero;
}
const not = this.flags.not;
var pass = false;
const count = expected.getLength(globalObject);
var i: u32 = 0;
while (i < count) : (i += 1) {
const key = expected.getIndex(globalObject, i);
if (value.hasOwnProperty(globalObject, key.toString(globalObject).getZigString(globalObject))) {
pass = true;
break;
}
}
if (not) pass = !pass;
if (pass) return thisValue;
// handle failure
var formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject, .quote_strings = true };
const value_fmt = value.toFmt(globalObject, &formatter);
const expected_fmt = expected.toFmt(globalObject, &formatter);
if (not) {
const received_fmt = value.toFmt(globalObject, &formatter);
const expected_line = "Expected to not contain: <green>{any}<r>\n\nReceived: <red>{any}<r>\n";
const fmt = comptime getSignature("toContainAnyKeys", "<green>expected<r>", true) ++ "\n\n" ++ expected_line;
globalObject.throwPretty(fmt, .{ expected_fmt, received_fmt });
return .zero;
}
const expected_line = "Expected to contain: <green>{any}<r>\n";
const received_line = "Received: <red>{any}<r>\n";
const fmt = comptime getSignature("toContainAnyKeys", "<green>expected<r>", false) ++ "\n\n" ++ expected_line ++ received_line;
if (Output.enable_ansi_colors) {
globalObject.throw(Output.prettyFmt(fmt, true), .{ expected_fmt, value_fmt });
return .zero;
}
globalObject.throw(Output.prettyFmt(fmt, false), .{ expected_fmt, value_fmt });
return .zero;
}
pub fn toContainEqual(
this: *Expect,
globalObject: *JSC.JSGlobalObject,

View File

@@ -419,6 +419,9 @@ export default [
fn: "toContainKey",
length: 1,
},
toContainAnyKeys: {
fn: "toContainAnyKeys",
},
toContainKeys: {
fn: "toContainKeys",
length: 1,

View File

@@ -2251,6 +2251,15 @@ describe("expect()", () => {
expect(o).not.toContainKey({ a: "foo" });
});
test("toContainAnyKeys", () => {
expect({ a: "hello", b: "world" }).toContainAnyKeys(["a"]);
expect({ a: "hello", b: "world" }).toContainAnyKeys(["a", "c"]);
expect({ 1: "test", 2: "test2" }).toContainAnyKeys([1]);
expect({ a: "hello", b: "world" }).toContainAnyKeys(["b"]);
expect({ a: "hello", b: "world" }).toContainAnyKeys(["b", "c"]);
expect({ a: "hello", b: "world" }).not.toContainAnyKeys(["c"]);
});
test("toContainKeys", () => {
expect({ a: "foo", b: "bar", c: "baz" }).toContainKeys(["a", "b"]);
expect({ a: "foo", b: "bar", c: "baz" }).toContainKeys(["a", "b", "c"]);