diff options
author | 2023-06-20 07:39:44 +0200 | |
---|---|---|
committer | 2023-06-19 22:39:44 -0700 | |
commit | e9e0e051569d3858cfc18b21a6aa6d1b7184f7e7 (patch) | |
tree | 3e31f68eb27b1b60c174c8970f11523d378ea43e /src/bun.js/test/jest.zig | |
parent | 7d94a49ef403750886c2e9ebfc5a7752b8ccb882 (diff) | |
download | bun-e9e0e051569d3858cfc18b21a6aa6d1b7184f7e7.tar.gz bun-e9e0e051569d3858cfc18b21a6aa6d1b7184f7e7.tar.zst bun-e9e0e051569d3858cfc18b21a6aa6d1b7184f7e7.zip |
feat(bun/test): Impl. "toBeArray", "toBeArrayOfSize" & "toBeTypeOf" (#3316)
* Implement toBeArray, toBeArrayOfSize, toBeTypeOf
* fix typos/variable names
* Add testcases for regex and dates
* little fix
* i didn't paste that...
Diffstat (limited to 'src/bun.js/test/jest.zig')
-rw-r--r-- | src/bun.js/test/jest.zig | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index 62be3fbae..ad60a9c5e 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -3006,6 +3006,94 @@ pub const Expect = struct { return .zero; } + pub fn toBeArray(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + defer this.postMatch(globalThis); + + const thisValue = callFrame.this(); + const value = Expect.capturedValueGetCached(thisValue) orelse { + globalThis.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + value.ensureStillAlive(); + + if (this.scope.tests.items.len <= this.test_id) { + globalThis.throw("toBeArray() must be called in a test", .{}); + return .zero; + } + + active_test_expectation_counter.actual += 1; + + const not = this.op.contains(.not); + const pass = value.jsType().isArray() != not; + + if (pass) return thisValue; + + var formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = globalThis, .quote_strings = true }; + const received = value.toFmt(globalThis, &formatter); + + if (not) { + const fmt = comptime getSignature("toBeArray", "", true) ++ "\n\n" ++ "Received: <red>{any}<r>\n"; + globalThis.throwPretty(fmt, .{received}); + return .zero; + } + + const fmt = comptime getSignature("toBeArray", "", false) ++ "\n\n" ++ "Received: <red>{any}<r>\n"; + globalThis.throwPretty(fmt, .{received}); + return .zero; + } + + pub fn toBeArrayOfSize(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + defer this.postMatch(globalThis); + + const thisValue = callFrame.this(); + const _arguments = callFrame.arguments(1); + const arguments = _arguments.ptr[0.._arguments.len]; + + if (arguments.len < 1) { + globalThis.throwInvalidArguments("toBeArrayOfSize() requires 1 argument", .{}); + return .zero; + } + + const value = Expect.capturedValueGetCached(thisValue) orelse { + globalThis.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + + if (this.scope.tests.items.len <= this.test_id) { + globalThis.throw("toBeArrayOfSize() must be called in a test", .{}); + return .zero; + } + + const size = arguments[0]; + size.ensureStillAlive(); + + if (!size.isAnyInt()) { + globalThis.throw("toBeArrayOfSize() requires the first argument to be a number", .{}); + return .zero; + } + + active_test_expectation_counter.actual += 1; + + const not = this.op.contains(.not); + var pass = value.jsType().isArray() and @intCast(i32, value.getLength(globalThis)) == size.toInt32(); + + if (not) pass = !pass; + if (pass) return thisValue; + + var formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = globalThis, .quote_strings = true }; + const received = value.toFmt(globalThis, &formatter); + + if (not) { + const fmt = comptime getSignature("toBeArrayOfSize", "", true) ++ "\n\n" ++ "Received: <red>{any}<r>\n"; + globalThis.throwPretty(fmt, .{received}); + return .zero; + } + + const fmt = comptime getSignature("toBeArrayOfSize", "", false) ++ "\n\n" ++ "Received: <red>{any}<r>\n"; + globalThis.throwPretty(fmt, .{received}); + return .zero; + } + pub fn toBeBoolean(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { defer this.postMatch(globalThis); @@ -3312,6 +3400,99 @@ pub const Expect = struct { return .zero; } + pub fn toBeTypeOf(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { + defer this.postMatch(globalThis); + + const thisValue = callFrame.this(); + const _arguments = callFrame.arguments(1); + const arguments = _arguments.ptr[0.._arguments.len]; + + if (arguments.len < 1) { + globalThis.throwInvalidArguments("toBeTypeOf() requires 1 argument", .{}); + return .zero; + } + + if (this.scope.tests.items.len <= this.test_id) { + globalThis.throw("toBeTypeOf() must be called in a test", .{}); + return .zero; + } + + const value = Expect.capturedValueGetCached(thisValue) orelse { + globalThis.throw("Internal consistency error: the expect(value) was garbage collected but it should not have been!", .{}); + return .zero; + }; + value.ensureStillAlive(); + + const expected = arguments[0]; + expected.ensureStillAlive(); + + const expectedAsStr = expected.toString(globalThis).toSlice(globalThis, default_allocator).slice(); + active_test_expectation_counter.actual += 1; + + if (!expected.isString()) { + globalThis.throwInvalidArguments("toBeTypeOf() requires a string argument", .{}); + return .zero; + } + + if (!std.mem.eql(u8, expectedAsStr, "function") and + !std.mem.eql(u8, expectedAsStr, "object") and + !std.mem.eql(u8, expectedAsStr, "bigint") and + !std.mem.eql(u8, expectedAsStr, "boolean") and + !std.mem.eql(u8, expectedAsStr, "number") and + !std.mem.eql(u8, expectedAsStr, "string") and + !std.mem.eql(u8, expectedAsStr, "symbol") and + !std.mem.eql(u8, expectedAsStr, "undefined")) + { + globalThis.throwInvalidArguments("toBeTypeOf() requires a valid type string argument ('function', 'object', 'bigint', 'boolean', 'number', 'string', 'symbol', 'undefined')", .{}); + return .zero; + } + + const not = this.op.contains(.not); + var pass = false; + var whatIsTheType: []const u8 = ""; + + // Checking for function/class should be done before everything else, or it will fail. + if (value.isCallable(globalThis.vm())) { + whatIsTheType = "function"; + } else if (value.isObject() or value.jsType().isArray() or value.isNull()) { + whatIsTheType = "object"; + } else if (value.isBigInt()) { + whatIsTheType = "bigint"; + } else if (value.isBoolean()) { + whatIsTheType = "boolean"; + } else if (value.isNumber()) { + whatIsTheType = "number"; + } else if (value.jsType().isString()) { + whatIsTheType = "string"; + } else if (value.isSymbol()) { + whatIsTheType = "symbol"; + } else if (value.isUndefined()) { + whatIsTheType = "undefined"; + } else { + globalThis.throw("Internal consistency error: unknown JSValue type", .{}); + return .zero; + } + + pass = std.mem.eql(u8, expectedAsStr, whatIsTheType); + + if (not) pass = !pass; + if (pass) return thisValue; + + var formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = globalThis, .quote_strings = true }; + const received = value.toFmt(globalThis, &formatter); + const expected_str = expected.toFmt(globalThis, &formatter); + + if (not) { + const fmt = comptime getSignature("toBeTypeOf", "", true) ++ "\n\n" ++ "Expected type: not <green>{any}<r>\n" ++ "Received type: <red>\"{s}\"<r>\nReceived value: <red>{any}<r>\n"; + globalThis.throwPretty(fmt, .{ expected_str, whatIsTheType, received }); + return .zero; + } + + const fmt = comptime getSignature("toBeTypeOf", "", false) ++ "\n\n" ++ "Expected type: <green>{any}<r>\n" ++ "Received type: <red>\"{s}\"<r>\nReceived value: <red>{any}<r>\n"; + globalThis.throwPretty(fmt, .{ expected_str, whatIsTheType, received }); + return .zero; + } + pub fn toBeWithin(this: *Expect, globalThis: *JSGlobalObject, callFrame: *CallFrame) callconv(.C) JSValue { defer this.postMatch(globalThis); |