mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
support expect().toThrow(/pattern/) (#2314)
- fix time-zone-dependent test failure
This commit is contained in:
2
packages/bun-types/bun-test.d.ts
vendored
2
packages/bun-types/bun-test.d.ts
vendored
@@ -76,7 +76,7 @@ declare module "bun:test" {
|
||||
toBeGreaterThanOrEqual(value: number | bigint): void;
|
||||
toBeLessThan(value: number | bigint): void;
|
||||
toBeLessThanOrEqual(value: number | bigint): void;
|
||||
toThrow(error?: string | Error | ErrorConstructor): void;
|
||||
toThrow(error?: string | Error | ErrorConstructor | RegExp): void;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1768,7 +1768,7 @@ pub const Expect = struct {
|
||||
if (expected_value.isString()) {
|
||||
const received_message = result.getIfPropertyExistsImpl(globalObject, "message", 7);
|
||||
|
||||
// partial match (regex not supported)
|
||||
// partial match
|
||||
{
|
||||
var expected_string = ZigString.Empty;
|
||||
var received_string = ZigString.Empty;
|
||||
@@ -1798,6 +1798,29 @@ pub const Expect = struct {
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (expected_value.isRegExp()) {
|
||||
const received_message = result.getIfPropertyExistsImpl(globalObject, "message", 7);
|
||||
|
||||
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), .{
|
||||
expected_value.toFmt(globalObject, &formatter),
|
||||
received_message.toFmt(globalObject, &formatter),
|
||||
});
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (expected_value.get(globalObject, "message")) |expected_message| {
|
||||
const received_message = result.getIfPropertyExistsImpl(globalObject, "message", 7);
|
||||
// no partial match for this case
|
||||
@@ -1835,7 +1858,7 @@ pub const Expect = struct {
|
||||
|
||||
if (expected_value.isString()) {
|
||||
if (_received_message) |received_message| {
|
||||
// partial match (regex not supported)
|
||||
// partial match
|
||||
var expected_string = ZigString.Empty;
|
||||
var received_string = ZigString.Empty;
|
||||
expected_value.toZigString(&expected_string, globalObject);
|
||||
@@ -1877,6 +1900,42 @@ pub const Expect = struct {
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (expected_value.isRegExp()) {
|
||||
if (_received_message) |received_message| {
|
||||
if (expected_value.get(globalObject, "test")) |test_fn| {
|
||||
const matches = test_fn.callWithThis(globalObject, expected_value, &.{received_message});
|
||||
if (matches.toBooleanSlow(globalObject)) return thisValue;
|
||||
}
|
||||
}
|
||||
|
||||
// error: message from received error does not match expected pattern
|
||||
var formatter = JSC.ZigConsoleClient.Formatter{ .globalThis = globalObject, .quote_strings = true };
|
||||
|
||||
if (_received_message) |received_message| {
|
||||
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.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 });
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (expected_value.get(globalObject, "message")) |expected_message| {
|
||||
if (_received_message) |received_message| {
|
||||
if (received_message.isSameValue(expected_message, globalObject)) return thisValue;
|
||||
@@ -1985,6 +2044,18 @@ pub const Expect = struct {
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (expected_value.isRegExp()) {
|
||||
const expected_fmt = "\n\nExpected pattern: <green>{any}<r>\n\n" ++ received_line;
|
||||
const fmt = signature ++ expected_fmt;
|
||||
if (Output.enable_ansi_colors) {
|
||||
globalObject.throw(Output.prettyFmt(fmt, true), .{expected_value.toFmt(globalObject, &formatter)});
|
||||
return .zero;
|
||||
}
|
||||
|
||||
globalObject.throw(Output.prettyFmt(fmt, false), .{expected_value.toFmt(globalObject, &formatter)});
|
||||
return .zero;
|
||||
}
|
||||
|
||||
if (expected_value.get(globalObject, "message")) |expected_message| {
|
||||
const expected_fmt = "\n\nExpected message: <green>{any}<r>\n\n" ++ received_line;
|
||||
const fmt = signature ++ expected_fmt;
|
||||
@@ -2275,7 +2346,7 @@ pub const TestScope = struct {
|
||||
task,
|
||||
);
|
||||
task.done_callback_state = .pending;
|
||||
initial_value = JSValue.fromRef(callback.?).call(vm.global, &.{callback_func});
|
||||
initial_value = JSValue.fromRef(callback).call(vm.global, &.{callback_func});
|
||||
} else {
|
||||
initial_value = js.JSObjectCallAsFunctionReturnValue(vm.global, callback, null, 0, null);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ false
|
||||
null
|
||||
undefined
|
||||
Symbol(Symbol Description)
|
||||
2022-02-27T05:11:48.999Z
|
||||
2000-06-27T02:24:34.304Z
|
||||
[ 123, 456, 789 ]
|
||||
{
|
||||
name: "foo"
|
||||
|
||||
@@ -8,7 +8,7 @@ console.log(false);
|
||||
console.log(null);
|
||||
console.log(undefined);
|
||||
console.log(Symbol("Symbol Description"));
|
||||
console.log(new Date(2021, 12, 30, 666, 777, 888, 999));
|
||||
console.log(new Date(Math.pow(2, 34) * 56));
|
||||
console.log([123, 456, 789]);
|
||||
console.log({ name: "foo" });
|
||||
console.log({ a: 123, b: 456, c: 789 });
|
||||
|
||||
@@ -3,35 +3,6 @@
|
||||
import { expect, it } from "bun:test";
|
||||
const crypto = require("crypto");
|
||||
|
||||
const assert = {
|
||||
strictEqual: (a, b) => {
|
||||
expect(a).toEqual(b);
|
||||
},
|
||||
deepStrictEqual: (a, b) => {
|
||||
expect(a).toEqual(b);
|
||||
},
|
||||
throws: (fn, err) => {
|
||||
try {
|
||||
fn();
|
||||
throw "Fail";
|
||||
} catch (e) {
|
||||
if (err.name) {
|
||||
expect(e?.name).toEqual(err.name);
|
||||
}
|
||||
|
||||
// if (err.message) {
|
||||
// expect(err.message.test(e?.message)).toBeTruthy();
|
||||
// }
|
||||
if (err.code) {
|
||||
expect(e?.code).toEqual(err.code);
|
||||
}
|
||||
|
||||
expect(e).not.toEqual("Fail");
|
||||
return;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const good = [
|
||||
// Zero-length key is legal, functions as a parameter validation check.
|
||||
{
|
||||
@@ -157,8 +128,24 @@ const badargs = [
|
||||
args: ["", "", null],
|
||||
expected: { code: "ERR_INVALID_ARG_TYPE" /*message: /"keylen"/ */ },
|
||||
},
|
||||
{
|
||||
args: ["", "", 42, null],
|
||||
expected: { code: "ERR_INVALID_ARG_TYPE" },
|
||||
},
|
||||
// TODO: throw on these
|
||||
// {
|
||||
// args: ["", "", 42, {}],
|
||||
// expected: { code: "ERR_INVALID_ARG_TYPE" },
|
||||
// },
|
||||
// {
|
||||
// args: ["", "", 42, {}, {}],
|
||||
// expected: { code: "ERR_INVALID_ARG_TYPE" },
|
||||
// },
|
||||
// {
|
||||
// args: ["", "", 42, {}, null],
|
||||
// expected: { code: "ERR_INVALID_ARG_TYPE" },
|
||||
// },
|
||||
// {
|
||||
// args: ["", "", 0.42],
|
||||
// expected: { code: "ERR_OUT_OF_RANGE" /*message: /"keylen"/ */ },
|
||||
// },
|
||||
@@ -170,41 +157,37 @@ const badargs = [
|
||||
// args: ["", "", 2147485780],
|
||||
// expected: { code: "ERR_OUT_OF_RANGE" /*message: /"keylen"/ */ },
|
||||
// },
|
||||
// {
|
||||
// args: ["", "", 0, { maxmem: 2 ** 53 }],
|
||||
// expected: { code: "ERR_OUT_OF_RANGE" /*message: /"keylen"/ */ },
|
||||
// },
|
||||
];
|
||||
|
||||
it("scrypt good", () => {
|
||||
for (const options of good) {
|
||||
const { pass, salt, keylen, expected } = options;
|
||||
const actual = crypto.scryptSync(pass, salt, keylen, options);
|
||||
assert.strictEqual(actual.toString("hex"), expected);
|
||||
expect(actual.toString("hex")).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
it("scrypt bad", () => {
|
||||
for (const options of bad) {
|
||||
const expected = {
|
||||
message: /Invalid scrypt param/,
|
||||
};
|
||||
assert.throws(() => crypto.scryptSync("pass", "salt", 1, options), expected);
|
||||
expect(() => crypto.scryptSync("pass", "salt", 1, options)).toThrow(/Invalid scrypt param/);
|
||||
}
|
||||
});
|
||||
|
||||
it("scrypt toobig", () => {
|
||||
for (const options of toobig) {
|
||||
const expected = {
|
||||
message: /Invalid scrypt param/,
|
||||
};
|
||||
assert.throws(() => crypto.scryptSync("pass", "salt", 1, options), expected);
|
||||
expect(() => crypto.scryptSync("pass", "salt", 1, options)).toThrow(/Invalid scrypt param/);
|
||||
}
|
||||
});
|
||||
|
||||
it("scrypt defaults eql", () => {
|
||||
{
|
||||
const defaults = { N: 16384, p: 1, r: 8 };
|
||||
const expected = crypto.scryptSync("pass", "salt", 1, defaults);
|
||||
const actual = crypto.scryptSync("pass", "salt", 1);
|
||||
assert.deepStrictEqual(actual.toString("hex"), expected.toString("hex"));
|
||||
}
|
||||
const defaults = { N: 16384, p: 1, r: 8 };
|
||||
const expected = crypto.scryptSync("pass", "salt", 1, defaults);
|
||||
const actual = crypto.scryptSync("pass", "salt", 1);
|
||||
expect(actual.toString("hex")).toBe(expected.toString("hex"));
|
||||
});
|
||||
|
||||
// TODO: DEFAULT_ENCODING is read-only
|
||||
@@ -217,27 +200,23 @@ it("scrypt defaults eql", () => {
|
||||
// const testEncoding = "latin1";
|
||||
// crypto.DEFAULT_ENCODING = testEncoding;
|
||||
// const actual = crypto.scryptSync("pass", "salt", 1);
|
||||
// assert.deepStrictEqual(actual, expected.toString(testEncoding));
|
||||
// expect(actual).toBe(expected.toString(testEncoding));
|
||||
|
||||
// crypto.DEFAULT_ENCODING = defaultEncoding;
|
||||
// }
|
||||
// });
|
||||
|
||||
it("scrypt badargs", () => {
|
||||
{
|
||||
for (const { args, expected } of badargs) {
|
||||
assert.throws(() => crypto.scryptSync(...args), expected);
|
||||
for (const { args, expected } of badargs) {
|
||||
try {
|
||||
crypto.scryptSync(...args);
|
||||
expect(() => {}).toThrow();
|
||||
} catch (e) {
|
||||
if (!("code" in e)) throw e;
|
||||
expect(e.code).toBe(expected.code);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const expected = { code: "ERR_INVALID_ARG_TYPE" };
|
||||
assert.throws(() => crypto.scryptSync("", "", 42, null), expected);
|
||||
// assert.throws(() => crypto.scryptSync("", "", 42, {}, null), expected);
|
||||
// assert.throws(() => crypto.scryptSync("", "", 42, {}), expected);
|
||||
// assert.throws(() => crypto.scryptSync("", "", 42, {}, {}), expected);
|
||||
}
|
||||
|
||||
// {
|
||||
// // Values for maxmem that do not fit in 32 bits but that are still safe
|
||||
// // integers should be allowed.
|
||||
@@ -247,13 +226,7 @@ it("scrypt badargs", () => {
|
||||
// 4,
|
||||
// { maxmem: 2 ** 52 },
|
||||
// common.mustSucceed((actual) => {
|
||||
// assert.strictEqual(actual.toString("hex"), "d72c87d0");
|
||||
// expect(actual.toString("hex")).toBe("d72c87d0");
|
||||
// }),
|
||||
// );
|
||||
|
||||
// // Values that exceed Number.isSafeInteger should not be allowed.
|
||||
// assert.throws(() => crypto.scryptSync("", "", 0, { maxmem: 2 ** 53 }), {
|
||||
// code: "ERR_OUT_OF_RANGE",
|
||||
// });
|
||||
// }
|
||||
});
|
||||
|
||||
@@ -156,11 +156,20 @@ test("toThrow", () => {
|
||||
throw err;
|
||||
}).toThrow(err);
|
||||
|
||||
var err = new Error("good");
|
||||
expect(() => {
|
||||
throw err;
|
||||
throw new Error("good");
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
throw new Error("foo");
|
||||
}).toThrow(/oo/);
|
||||
|
||||
expect(() =>
|
||||
expect(() => {
|
||||
throw new Error("bar");
|
||||
}).toThrow(/baz/),
|
||||
).toThrow("/baz/");
|
||||
|
||||
expect(() => {
|
||||
return true;
|
||||
}).not.toThrow();
|
||||
|
||||
Reference in New Issue
Block a user