mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
fix(bun:test): toContain and toContainEqual string fix (#8270)
* update toContain, toContainEqual, and tests * fix build, use cursor * `strings.indexOf` and `jsType` once
This commit is contained in:
@@ -3360,6 +3360,18 @@ pub const JSValue = enum(JSValueReprInt) {
|
||||
return this == .String;
|
||||
}
|
||||
|
||||
pub inline fn isStringObject(this: JSType) bool {
|
||||
return this == .StringObject;
|
||||
}
|
||||
|
||||
pub inline fn isDerivedStringObject(this: JSType) bool {
|
||||
return this == .DerivedStringObject;
|
||||
}
|
||||
|
||||
pub inline fn isStringObjectLike(this: JSType) bool {
|
||||
return this == .StringObject or this == .DerivedStringObject;
|
||||
}
|
||||
|
||||
pub inline fn isStringLike(this: JSType) bool {
|
||||
return switch (this) {
|
||||
.String, .StringObject, .DerivedStringObject => true,
|
||||
@@ -4183,6 +4195,27 @@ pub const JSValue = enum(JSValueReprInt) {
|
||||
return jsType(this).isStringLike();
|
||||
}
|
||||
|
||||
/// Returns true only for string literals
|
||||
/// - `" string literal"`
|
||||
pub inline fn isStringLiteral(this: JSValue) bool {
|
||||
if (!this.isCell()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return jsType(this).isString();
|
||||
}
|
||||
|
||||
/// Returns true if
|
||||
/// - `new String("123")`
|
||||
/// - `class DerivedString extends String; new DerivedString("123")`
|
||||
pub inline fn isStringObjectLike(this: JSValue) bool {
|
||||
if (!this.isCell()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return jsType(this).isStringObjectLike();
|
||||
}
|
||||
|
||||
pub fn isBigInt(this: JSValue) bool {
|
||||
return cppFn("isBigInt", .{this});
|
||||
}
|
||||
|
||||
@@ -670,13 +670,15 @@ pub const Expect = struct {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (value.isString() and expected.isString()) {
|
||||
const value_string = value.toString(globalObject).toSlice(globalObject, default_allocator).slice();
|
||||
const expected_string = expected.toString(globalObject).toSlice(globalObject, default_allocator).slice();
|
||||
} else if (value.isStringLiteral() and expected.isStringLiteral()) {
|
||||
const value_string = value.toString(globalObject).toSlice(globalObject, default_allocator);
|
||||
defer value_string.deinit();
|
||||
const expected_string = expected.toString(globalObject).toSlice(globalObject, default_allocator);
|
||||
defer expected_string.deinit();
|
||||
|
||||
if (expected_string.len == 0) { // edge case empty string is always contained
|
||||
pass = true;
|
||||
} else if (strings.contains(value_string, expected_string)) {
|
||||
} else if (strings.contains(value_string.slice(), expected_string.slice())) {
|
||||
pass = true;
|
||||
} else if (value_string.len == 0 and expected_string.len == 0) { // edge case two empty strings are true
|
||||
pass = true;
|
||||
@@ -952,7 +954,10 @@ pub const Expect = struct {
|
||||
pass: *bool,
|
||||
};
|
||||
|
||||
if (value.jsTypeLoose().isArrayLike()) {
|
||||
const value_type = value.jsType();
|
||||
const expected_type = expected.jsType();
|
||||
|
||||
if (value_type.isArrayLike()) {
|
||||
var itr = value.arrayIterator(globalObject);
|
||||
while (itr.next()) |item| {
|
||||
if (item.jestDeepEquals(expected, globalObject)) {
|
||||
@@ -960,13 +965,24 @@ pub const Expect = struct {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (value.isString() and expected.isString()) {
|
||||
const value_string = value.toString(globalObject).toSlice(globalObject, default_allocator).slice();
|
||||
const expected_string = expected.toString(globalObject).toSlice(globalObject, default_allocator).slice();
|
||||
if (strings.contains(value_string, expected_string)) {
|
||||
pass = true;
|
||||
} else if (value_string.len == 0 and expected_string.len == 0) { // edge case two empty strings are true
|
||||
pass = true;
|
||||
} else if (value_type.isStringLike() and expected_type.isStringLike()) {
|
||||
if (expected_type.isStringObjectLike() and value_type.isString()) pass = false else {
|
||||
const value_string = value.toString(globalObject).toSlice(globalObject, default_allocator);
|
||||
defer value_string.deinit();
|
||||
const expected_string = expected.toString(globalObject).toSlice(globalObject, default_allocator);
|
||||
defer expected_string.deinit();
|
||||
|
||||
// jest does not have a `typeof === "string"` check for `toContainEqual`.
|
||||
// it immediately spreads the value into an array.
|
||||
|
||||
var expected_codepoint_cursor = strings.CodepointIterator.Cursor{};
|
||||
var expected_iter = strings.CodepointIterator.init(expected_string.slice());
|
||||
_ = expected_iter.next(&expected_codepoint_cursor);
|
||||
|
||||
pass = if (expected_iter.next(&expected_codepoint_cursor))
|
||||
false
|
||||
else
|
||||
strings.indexOf(value_string.slice(), expected_string.slice()) != null;
|
||||
}
|
||||
} else if (value.isIterable(globalObject)) {
|
||||
var expected_entry = ExpectedEntry{
|
||||
|
||||
@@ -2086,9 +2086,9 @@ describe("expect()", () => {
|
||||
|
||||
test.each([
|
||||
["hello", "h"],
|
||||
["hello", ""],
|
||||
["hello", "hello"],
|
||||
[new String("hello"), "h"],
|
||||
[new String("hello"), "hello"],
|
||||
["emoji: 😃", "😃"],
|
||||
["😄", "😄"],
|
||||
["", ""],
|
||||
@@ -2118,9 +2118,10 @@ describe("expect()", () => {
|
||||
test.each([
|
||||
["hello", "a"],
|
||||
["hello", "hello?"],
|
||||
["hello", ""],
|
||||
[new String("hello"), "a"],
|
||||
[new String("hello"), "hello?"],
|
||||
[new String("hello"), "hello"],
|
||||
[new String("hello"), "llo"],
|
||||
[new String("hello"), ""],
|
||||
["emoji: 😃", "😄"],
|
||||
[[1, 2, 3], -1],
|
||||
@@ -2147,12 +2148,10 @@ describe("expect()", () => {
|
||||
|
||||
test.each([
|
||||
["hello", "h"],
|
||||
["hello", "hello"],
|
||||
[new String("hello"), "h"],
|
||||
[new String("hello"), "hello"],
|
||||
["emoji: 😃", "😃"],
|
||||
["😄", "😄"],
|
||||
["", ""],
|
||||
[new String("😄"), "😄"],
|
||||
[[1, 2, 3], 1],
|
||||
[[{ a: 1 }, { b: 2 }, { c: 3 }], { c: 3 }],
|
||||
[[{}], {}],
|
||||
@@ -2197,10 +2196,18 @@ describe("expect()", () => {
|
||||
test.each([
|
||||
["hello", "a"],
|
||||
["hello", "hello?"],
|
||||
["hello", "hello"],
|
||||
["hello", "llo"],
|
||||
["hello", ""],
|
||||
["", ""],
|
||||
[new String(""), new String("")],
|
||||
[new String("hello"), "a"],
|
||||
[new String("hello"), "hello?"],
|
||||
[new String("hello"), "hello"],
|
||||
[new String("hello"), "llo"],
|
||||
[new String("hello"), ""],
|
||||
["😄", new String("😄")],
|
||||
["1", new String("1")],
|
||||
["emoji: 😃", "😄"],
|
||||
[[1, 2, 3], -1],
|
||||
[[{ a: 1 }, { b: 2 }, { c: 3 }], { c: 1 }],
|
||||
|
||||
Reference in New Issue
Block a user