Skip to content

Commit

Permalink
fix(expect): accept array index as number in toHaveProperty (#2808)
Browse files Browse the repository at this point in the history
* test(expect): add toHaveProperty array index string

* test(expect): add toHaveProperty array index number

* fix: coerce key to string primitive in expect.toHaveProperty

* fix: accept string or number array in toHaveProperty property

* test: remove ts-expect-error from toHaveProperty test for array index number

* test: expect.toHaveProperty with object key '0'

* fix: snapshot for complex object in jest-expect.test.ts

* docs: expect.toHaveProperty deep referencing using an array containing the keyPath
  • Loading branch information
trivikr authored Feb 11, 2023
1 parent d3d6b1f commit 8705e6b
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 5 deletions.
6 changes: 5 additions & 1 deletion docs/api/expect.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,10 @@ type Awaitable<T> = T | PromiseLike<T>
expect(invoice).toHaveProperty('items[0].type', 'apples')
expect(invoice).toHaveProperty('items.0.type', 'apples') // dot notation also works

// Deep referencing using an array containing the keyPath
expect(invoice).toHaveProperty(['items', 0, 'type'], 'apples')
expect(invoice).toHaveProperty(['items', '0', 'type'], 'apples') // string notation also works

// Wrap your key in an array to avoid the key from being parsed as a deep reference
expect(invoice).toHaveProperty(['P.O'], '12345')
})
Expand Down Expand Up @@ -1270,4 +1274,4 @@ type Awaitable<T> = T | PromiseLike<T>

:::tip
If you want to know more, checkout [guide on extending matchers](/guide/extending-matchers).
:::
:::
4 changes: 2 additions & 2 deletions packages/expect/src/jest-expect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,9 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
return this.have.length(length)
})
// destructuring, because it checks `arguments` inside, and value is passing as `undefined`
def('toHaveProperty', function (...args: [property: string | string[], value?: any]) {
def('toHaveProperty', function (...args: [property: string | (string | number)[], value?: any]) {
if (Array.isArray(args[0]))
args[0] = args[0].map(key => key.replace(/([.[\]])/g, '\\$1')).join('.')
args[0] = args[0].map(key => String(key).replace(/([.[\]])/g, '\\$1')).join('.')

const actual = this._obj
const [propertyName, expected] = args
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/types/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ declare global {
toBeInstanceOf<E>(expected: E): void
toBeCalledTimes(times: number): void
toHaveLength(length: number): void
toHaveProperty<E>(property: string | string[], value?: E): void
toHaveProperty<E>(property: string | (string | number)[], value?: E): void
toBeCloseTo(number: number, numDigits?: number): void
toHaveBeenCalledTimes(times: number): void
toHaveBeenCalledOnce(): void
Expand Down
13 changes: 12 additions & 1 deletion test/core/test/jest-expect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ describe('jest-expect', () => {

const foo = {}
const complex = {
'0': 'zero',
'foo': 1,
'foo.bar[0]': 'baz',
'a-b': true,
Expand All @@ -227,12 +228,22 @@ describe('jest-expect', () => {

expect(complex).toHaveProperty('a-b')
expect(complex).toHaveProperty('a-b-1.0.0')
expect(complex).toHaveProperty('0')
expect(complex).toHaveProperty('0', 'zero')
expect(complex).toHaveProperty(['0'])
expect(complex).toHaveProperty(['0'], 'zero')
expect(complex).toHaveProperty([0])
expect(complex).toHaveProperty([0], 'zero')
expect(complex).toHaveProperty('foo')
expect(complex).toHaveProperty('foo', 1)
expect(complex).toHaveProperty('bar.foo', 'foo')
expect(complex).toHaveProperty('bar.arr[0]')
expect(complex).toHaveProperty('bar.arr[1].zoo', 'monkey')
expect(complex).toHaveProperty('bar.arr.0')
expect(complex).toHaveProperty(['bar', 'arr', '0'])
expect(complex).toHaveProperty(['bar', 'arr', '0'], 'first')
expect(complex).toHaveProperty(['bar', 'arr', 0])
expect(complex).toHaveProperty(['bar', 'arr', 0], 'first')
expect(complex).toHaveProperty('bar.arr.1.zoo', 'monkey')
expect(complex).toHaveProperty(['bar', 'arr', '1', 'zoo'], 'monkey')
expect(complex).toHaveProperty(['foo.bar[0]'], 'baz')
Expand All @@ -248,7 +259,7 @@ describe('jest-expect', () => {

expect(() => {
expect(complex).toHaveProperty('a-b', false)
}).toThrowErrorMatchingInlineSnapshot('"expected { foo: 1, \'foo.bar[0]\': \'baz\', …(3) } to have property \\"a-b\\" with value false"')
}).toThrowErrorMatchingInlineSnapshot('"expected { \'0\': \'zero\', foo: 1, …(4) } to have property \\"a-b\\" with value false"')
})

it('assertions', () => {
Expand Down

0 comments on commit 8705e6b

Please sign in to comment.