Skip to content

Commit 9c8fdbb

Browse files
authored
fix: symbol key could not be enum (#14414)
1 parent a5cdc86 commit 9c8fdbb

File tree

4 files changed

+24
-11
lines changed

4 files changed

+24
-11
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Fixes
66

7+
- `[expect, @jest/expect-utils]` `ObjectContaining` support `sumbol` as key ([#14414](https://github.com/jestjs/jest/pull/14414))
78
- `[expect]` Remove `@types/node` from dependencies ([#14385](https://github.com/jestjs/jest/pull/14385))
89
- `[jest-core]` Use workers in watch mode by default to avoid crashes ([#14059](https://github.com/facebook/jest/pull/14059) & [#14085](https://github.com/facebook/jest/pull/14085)).
910
- `[jest-reporters]` Update `istanbul-lib-instrument` dependency to v6. ([#14401](https://github.com/jestjs/jest/pull/14401))

packages/expect-utils/src/utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const hasPropertyInObject = (object: object, key: string | symbol): boolean => {
4747
// the prototype chain for string keys but not for symbols. (Otherwise, it
4848
// could find values such as a Set or Map's Symbol.toStringTag, with unexpected
4949
// results.)
50-
const getObjectKeys = (object: object) => [
50+
export const getObjectKeys = (object: object): Array<string | symbol> => [
5151
...Object.keys(object),
5252
...Object.getOwnPropertySymbols(object),
5353
];

packages/expect/src/__tests__/asymmetricMatchers.test.ts

+8
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ test('ArrayNotContaining throws for non-arrays', () => {
181181
});
182182

183183
test('ObjectContaining matches', () => {
184+
const foo = Symbol('foo');
184185
[
185186
objectContaining({}).asymmetricMatch('jest'),
186187
objectContaining({foo: 'foo'}).asymmetricMatch({foo: 'foo', jest: 'jest'}),
@@ -192,12 +193,15 @@ test('ObjectContaining matches', () => {
192193
foo: Buffer.from('foo'),
193194
jest: 'jest',
194195
}),
196+
objectContaining({[foo]: 'foo'}).asymmetricMatch({[foo]: 'foo'}),
195197
].forEach(test => {
196198
jestExpect(test).toEqual(true);
197199
});
198200
});
199201

200202
test('ObjectContaining does not match', () => {
203+
const foo = Symbol('foo');
204+
const bar = Symbol('bar');
201205
[
202206
objectContaining({foo: 'foo'}).asymmetricMatch({bar: 'bar'}),
203207
objectContaining({foo: 'foo'}).asymmetricMatch({foo: 'foox'}),
@@ -206,6 +210,7 @@ test('ObjectContaining does not match', () => {
206210
answer: 42,
207211
foo: {bar: 'baz', foobar: 'qux'},
208212
}).asymmetricMatch({foo: {bar: 'baz'}}),
213+
objectContaining({[foo]: 'foo'}).asymmetricMatch({[bar]: 'bar'}),
209214
].forEach(test => {
210215
jestExpect(test).toEqual(false);
211216
});
@@ -250,9 +255,12 @@ test('ObjectContaining does not mutate the sample', () => {
250255
});
251256

252257
test('ObjectNotContaining matches', () => {
258+
const foo = Symbol('foo');
259+
const bar = Symbol('bar');
253260
[
254261
objectContaining({}).asymmetricMatch(null),
255262
objectContaining({}).asymmetricMatch(undefined),
263+
objectNotContaining({[foo]: 'foo'}).asymmetricMatch({[bar]: 'bar'}),
256264
objectNotContaining({foo: 'foo'}).asymmetricMatch({bar: 'bar'}),
257265
objectNotContaining({foo: 'foo'}).asymmetricMatch({foo: 'foox'}),
258266
objectNotContaining({foo: undefined}).asymmetricMatch({}),

packages/expect/src/asymmetricMatchers.ts

+14-10
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import {
1010
equals,
11+
getObjectKeys,
1112
isA,
1213
iterableEquality,
1314
subsetEquality,
@@ -52,7 +53,10 @@ function getPrototype(obj: object) {
5253
return obj.constructor.prototype;
5354
}
5455

55-
export function hasProperty(obj: object | null, property: string): boolean {
56+
export function hasProperty(
57+
obj: object | null,
58+
property: string | symbol,
59+
): boolean {
5660
if (!obj) {
5761
return false;
5862
}
@@ -216,8 +220,10 @@ class ArrayContaining extends AsymmetricMatcher<Array<unknown>> {
216220
}
217221
}
218222

219-
class ObjectContaining extends AsymmetricMatcher<Record<string, unknown>> {
220-
constructor(sample: Record<string, unknown>, inverse = false) {
223+
class ObjectContaining extends AsymmetricMatcher<
224+
Record<string | symbol, unknown>
225+
> {
226+
constructor(sample: Record<string | symbol, unknown>, inverse = false) {
221227
super(sample, inverse);
222228
}
223229

@@ -232,14 +238,12 @@ class ObjectContaining extends AsymmetricMatcher<Record<string, unknown>> {
232238
let result = true;
233239

234240
const matcherContext = this.getMatcherContext();
235-
for (const property in this.sample) {
241+
const objectKeys = getObjectKeys(this.sample);
242+
243+
for (const key of objectKeys) {
236244
if (
237-
!hasProperty(other, property) ||
238-
!equals(
239-
this.sample[property],
240-
other[property],
241-
matcherContext.customTesters,
242-
)
245+
!hasProperty(other, key) ||
246+
!equals(this.sample[key], other[key], matcherContext.customTesters)
243247
) {
244248
result = false;
245249
break;

0 commit comments

Comments
 (0)