Skip to content

Commit d18813b

Browse files
committed
Have snapshot use await only on promises
1 parent 5e829e9 commit d18813b

6 files changed

Lines changed: 98 additions & 69 deletions

File tree

jest.d.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,19 @@ declare namespace jest {
1212
* @see https://github.com/jestjs/jest/blob/73dbef5d2d3195a1e55fb254c54cce70d3036252/packages/jest-snapshot/src/types.ts#L37
1313
*/
1414

15+
// TODO dprevost: how can we make both Wdio snapshot and Jest snapshot work together?
1516
/**
1617
* snapshot matcher
1718
* @param label optional snapshot label
1819
*/
19-
toMatchSnapshot(label?: string): Promise<R>;
20-
21-
// TODO - this is not working as expected, need to investigate
22-
/**
23-
* snapshot matcher
24-
* @param label optional snapshot label
25-
*/
26-
// toMatchSnapshot: T extends WdioElementLike ? (label: string) => Promise<R> : (hint?: string) => R;
20+
toMatchSnapshot(label?: string): T extends WdioPromiseLike ? Promise<R> : R;
2721

2822
/**
2923
* inline snapshot matcher
3024
* @param snapshot snapshot string (autogenerated if not specified)
3125
* @param label optional snapshot label
3226
*/
33-
toMatchInlineSnapshot(snapshot?: string, label?: string): Promise<R>
27+
toMatchInlineSnapshot(snapshot?: string, label?: string): T extends WdioPromiseLike ? Promise<R> : R;
3428
}
3529

3630
type MatcherAndInverse<R, T> = Matchers<R, T> & AndNot<Matchers<R, T>>

test-types/jest/types-jest.test.ts

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -126,18 +126,18 @@ describe('type assertions', async () => {
126126
describe('toMatchSnapshot', () => {
127127

128128
it('should be supported correctly', async () => {
129-
expectPromiseVoid = expect(element).toMatchSnapshot()
130-
expectPromiseVoid = expect(element).toMatchSnapshot('test label')
131-
expectPromiseVoid = expect(element).not.toMatchSnapshot('test label')
129+
expectVoid = expect(element).toMatchSnapshot()
130+
expectVoid = expect(element).toMatchSnapshot('test label')
131+
expectVoid = expect(element).not.toMatchSnapshot('test label')
132132

133133
expectPromiseVoid = expect(chainableElement).toMatchSnapshot()
134134
expectPromiseVoid = expect(chainableElement).toMatchSnapshot('test label')
135135
expectPromiseVoid = expect(chainableElement).not.toMatchSnapshot('test label')
136136

137137
//@ts-expect-error
138-
expectVoid = expect(element).toMatchSnapshot()
138+
expectPromiseVoid = expect(element).toMatchSnapshot()
139139
//@ts-expect-error
140-
expectVoid = expect(element).not.toMatchSnapshot()
140+
expectPromiseVoid = expect(element).not.toMatchSnapshot()
141141
//@ts-expect-error
142142
expectVoid = expect(chainableElement).toMatchSnapshot()
143143
//@ts-expect-error
@@ -154,16 +154,16 @@ describe('type assertions', async () => {
154154
describe('toMatchInlineSnapshot', () => {
155155

156156
it('should be correctly supported', async () => {
157-
expectPromiseVoid = expect(element).toMatchInlineSnapshot()
158-
expectPromiseVoid = expect(element).toMatchInlineSnapshot('test snapshot')
159-
expectPromiseVoid = expect(element).toMatchInlineSnapshot('test snapshot', 'test label')
157+
expectVoid = expect(element).toMatchInlineSnapshot()
158+
expectVoid = expect(element).toMatchInlineSnapshot('test snapshot')
159+
expectVoid = expect(element).toMatchInlineSnapshot('test snapshot', 'test label')
160160

161161
expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot()
162162
expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot')
163163
expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label')
164164

165165
//@ts-expect-error
166-
expectVoid = expect(element).toMatchInlineSnapshot()
166+
expectPromiseVoid = expect(element).toMatchInlineSnapshot()
167167
//@ts-expect-error
168168
expectVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label')
169169
})
@@ -499,37 +499,69 @@ describe('type assertions', async () => {
499499
})
500500

501501
describe('@types/jest only - original Matchers', () => {
502-
const propertyMatchers: Partial<{}> = {}
503-
const snapshotName: string = 'test-snapshot'
504-
describe('toMatchSnapshot', () => {
502+
describe('toMatchSnapshot & toMatchInlineSnapshot', () => {
503+
const snapshotName: string = 'test-snapshot'
504+
505+
it('should work with string', async () => {
506+
const jsonString: string = '{}'
507+
const propertyMatchers = 'test'
508+
expectVoid = expect(jsonString).toMatchSnapshot(propertyMatchers)
509+
expectVoid = expect(jsonString).toMatchSnapshot(propertyMatchers, snapshotName)
510+
expectVoid = expect(jsonString).toMatchInlineSnapshot(propertyMatchers)
511+
expectVoid = expect(jsonString).toMatchInlineSnapshot(propertyMatchers, snapshotName)
512+
513+
expectVoid = expect(jsonString).not.toMatchSnapshot(propertyMatchers)
514+
expectVoid = expect(jsonString).not.toMatchSnapshot(propertyMatchers, snapshotName)
515+
expectVoid = expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers)
516+
expectVoid = expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers, snapshotName)
517+
518+
// @ts-expect-error
519+
expectPromiseVoid = expect(jsonString).toMatchSnapshot(propertyMatchers)
520+
// @ts-expect-error
521+
expectPromiseVoid = expect(jsonString).toMatchSnapshot(propertyMatchers, snapshotName)
522+
// @ts-expect-error
523+
expectPromiseVoid = expect(jsonString).toMatchInlineSnapshot(propertyMatchers)
524+
// @ts-expect-error
525+
expectPromiseVoid = expect(jsonString).toMatchInlineSnapshot(propertyMatchers, snapshotName)
526+
// @ts-expect-error
527+
expectPromiseVoid = expect(jsonString).not.toMatchSnapshot(propertyMatchers)
528+
// @ts-expect-error
529+
expectPromiseVoid = expect(jsonString).not.toMatchSnapshot(propertyMatchers, snapshotName)
530+
// @ts-expect-error
531+
expectPromiseVoid = expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers)
532+
// @ts-expect-error
533+
expectPromiseVoid = expect(jsonString).not.toMatchInlineSnapshot(propertyMatchers, snapshotName)
534+
})
505535

506-
it('should have original jest Matcher still works', async () => {
507-
expectVoid = expect(element).toMatchSnapshot(propertyMatchers)
508-
expectVoid = expect(element).toMatchSnapshot(propertyMatchers, snapshotName)
509-
expectVoid = expect(element).toMatchInlineSnapshot(propertyMatchers)
510-
expectVoid = expect(element).toMatchInlineSnapshot(propertyMatchers, snapshotName)
536+
it('should with object', async () => {
537+
const treeObject = { 1: 'test', 2: 'test2' }
538+
const propertyMatchers = { 1: 'test' }
539+
expectVoid = expect(treeObject).toMatchSnapshot(propertyMatchers)
540+
expectVoid = expect(treeObject).toMatchSnapshot(propertyMatchers, snapshotName)
541+
expectVoid = expect(treeObject).toMatchInlineSnapshot(propertyMatchers)
542+
expectVoid = expect(treeObject).toMatchInlineSnapshot(propertyMatchers, snapshotName)
511543

512-
expectVoid = expect(element).not.toMatchSnapshot(propertyMatchers)
513-
expectVoid = expect(element).not.toMatchSnapshot(propertyMatchers, snapshotName)
514-
expectVoid = expect(element).not.toMatchInlineSnapshot(propertyMatchers)
515-
expectVoid = expect(element).not.toMatchInlineSnapshot(propertyMatchers, snapshotName)
544+
expectVoid = expect(treeObject).not.toMatchSnapshot(propertyMatchers)
545+
expectVoid = expect(treeObject).not.toMatchSnapshot(propertyMatchers, snapshotName)
546+
expectVoid = expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers)
547+
expectVoid = expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers, snapshotName)
516548

517549
// @ts-expect-error
518-
expectPromiseVoid = expect(element).toMatchSnapshot(propertyMatchers)
550+
expectPromiseVoid = expect(treeObject).toMatchSnapshot(propertyMatchers)
519551
// @ts-expect-error
520-
expectPromiseVoid = expect(element).toMatchSnapshot(propertyMatchers, snapshotName)
552+
expectPromiseVoid = expect(treeObject).toMatchSnapshot(propertyMatchers, snapshotName)
521553
// @ts-expect-error
522-
expectPromiseVoid = expect(element).toMatchInlineSnapshot(propertyMatchers)
554+
expectPromiseVoid = expect(treeObject).toMatchInlineSnapshot(propertyMatchers)
523555
// @ts-expect-error
524-
expectPromiseVoid = expect(element).toMatchInlineSnapshot(propertyMatchers, snapshotName)
556+
expectPromiseVoid = expect(treeObject).toMatchInlineSnapshot(propertyMatchers, snapshotName)
525557
// @ts-expect-error
526-
expectPromiseVoid = expect(element).not.toMatchSnapshot(propertyMatchers)
558+
expectPromiseVoid = expect(treeObject).not.toMatchSnapshot(propertyMatchers)
527559
// @ts-expect-error
528-
expectPromiseVoid = expect(element).not.toMatchSnapshot(propertyMatchers, snapshotName)
560+
expectPromiseVoid = expect(treeObject).not.toMatchSnapshot(propertyMatchers, snapshotName)
529561
// @ts-expect-error
530-
expectPromiseVoid = expect(element).not.toMatchInlineSnapshot(propertyMatchers)
562+
expectPromiseVoid = expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers)
531563
// @ts-expect-error
532-
expectPromiseVoid = expect(element).not.toMatchInlineSnapshot(propertyMatchers, snapshotName)
564+
expectPromiseVoid = expect(treeObject).not.toMatchInlineSnapshot(propertyMatchers, snapshotName)
533565
})
534566
})
535567
})

test-types/mocha/types-mocha.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,18 +167,18 @@ describe('type assertions', () => {
167167
describe('toMatchSnapshot', () => {
168168

169169
it('should be supported correctly', async () => {
170-
expectPromiseVoid = expect(element).toMatchSnapshot()
171-
expectPromiseVoid = expect(element).toMatchSnapshot('test label')
172-
expectPromiseVoid = expect(element).not.toMatchSnapshot('test label')
170+
expectVoid = expect(element).toMatchSnapshot()
171+
expectVoid = expect(element).toMatchSnapshot('test label')
172+
expectVoid = expect(element).not.toMatchSnapshot('test label')
173173

174174
expectPromiseVoid = expect(chainableElement).toMatchSnapshot()
175175
expectPromiseVoid = expect(chainableElement).toMatchSnapshot('test label')
176176
expectPromiseVoid = expect(chainableElement).not.toMatchSnapshot('test label')
177177

178178
//@ts-expect-error
179-
expectVoid = expect(element).toMatchSnapshot()
179+
expectPromiseVoid = expect(element).toMatchSnapshot()
180180
//@ts-expect-error
181-
expectVoid = expect(element).not.toMatchSnapshot()
181+
expectPromiseVoid = expect(element).not.toMatchSnapshot()
182182
//@ts-expect-error
183183
expectVoid = expect(chainableElement).toMatchSnapshot()
184184
//@ts-expect-error
@@ -195,16 +195,16 @@ describe('type assertions', () => {
195195
describe('toMatchInlineSnapshot', () => {
196196

197197
it('should be correctly supported', async () => {
198-
expectPromiseVoid = expect(element).toMatchInlineSnapshot()
199-
expectPromiseVoid = expect(element).toMatchInlineSnapshot('test snapshot')
200-
expectPromiseVoid = expect(element).toMatchInlineSnapshot('test snapshot', 'test label')
198+
expectVoid = expect(element).toMatchInlineSnapshot()
199+
expectVoid = expect(element).toMatchInlineSnapshot('test snapshot')
200+
expectVoid = expect(element).toMatchInlineSnapshot('test snapshot', 'test label')
201201

202202
expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot()
203203
expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot')
204204
expectPromiseVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label')
205205

206206
//@ts-expect-error
207-
expectVoid = expect(element).toMatchInlineSnapshot()
207+
expectPromiseVoid = expect(element).toMatchInlineSnapshot()
208208
//@ts-expect-error
209209
expectVoid = expect(chainableElement).toMatchInlineSnapshot('test snapshot', 'test label')
210210
})

types/expect-webdriverio.d.ts

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,21 @@ type Test = import('@wdio/types').Frameworks.Test
44
type TestResult = import('@wdio/types').Frameworks.TestResult
55
type PickleStep = import('@wdio/types').Frameworks.PickleStep
66
type Scenario = import('@wdio/types').Frameworks.Scenario
7+
78
type SnapshotResult = import('@vitest/snapshot').SnapshotResult
89
type SnapshotUpdateState = import('@vitest/snapshot').SnapshotUpdateState
9-
type ExpectLibAsymmetricMatchers = import('expect').AsymmetricMatchers
10+
1011
type ChainablePromiseElement = import('webdriverio').ChainablePromiseElement
1112
type ChainablePromiseArray = import('webdriverio').ChainablePromiseArray
13+
14+
type ExpectLibAsymmetricMatchers = import('expect').AsymmetricMatchers
1215
type ExpectLibAsymmetricMatcher<T> = import('expect').AsymmetricMatcher<T>
1316

17+
type WdioPromiseLike<T = unknown> = PromiseLike<T> | ChainablePromiseElement | ChainablePromiseArray
18+
type ElementPromise = Promise<WebdriverIO.Element>
19+
type ElementArrayPromise = Promise<WebdriverIO.ElementArray>
20+
type WdioOnlyPromiseLike = ElementPromise | ElementArrayPromise | ChainablePromiseElement | ChainablePromiseArray
21+
1422
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T
1523

1624
interface WdioBrowserMatchers<R, T = unknown>{
@@ -55,10 +63,9 @@ interface WdioMockMatchers<R, T = unknown> {
5563
* Once we have all types working, we could check to bring those back into the `ExpectWebdriverIO` namespace.
5664
*/
5765

58-
// TODO dprevost have browser matchers and element matchers separated
59-
// TODO extending extends Record<string, any> remove ts error on unimplemented matchers
60-
6166
// TODO dprevost - check if custom matchers (https://webdriver.io/docs/custommatchers/) will still work aka webdriverio/expect-webdriverio#1408
67+
68+
// TODO dprevost - can we be better and return void for Element/ElementArray but Promise<void> for ElementPromise/ElementArrayPromise?
6269
type ElementOrArrayLike = ElementLike | ElementArrayLike
6370
type ElementLike = WebdriverIO.Element | ChainablePromiseElement
6471
type ElementArrayLike = WebdriverIO.ElementArray | ChainablePromiseArray
@@ -213,7 +220,7 @@ interface WdioCustomMatchers<R, T = unknown> {
213220
* `WebdriverIO.Element` -> `getProperty` value
214221
*/
215222
toHaveId: T extends ElementOrArrayLike ? (
216-
id: string | RegExp | ExpectWebdriverIO.PartialMatche<string>,
223+
id: string | RegExp | ExpectWebdriverIO.PartialMatcher<string>,
217224
options?: ExpectWebdriverIO.StringOptions
218225
) => Promise<R> : never
219226

@@ -338,25 +345,14 @@ interface WdioOverloadedMatchers<R> {
338345

339346
interface WdioMatchers<R, T = unknown> extends WdioOverloadedMatchers<R, T>, WdioBrowserMatchers<R, T>, WdioCustomMatchers<R, T>, WdioMockMatchers<R, T> {}
340347

341-
type WdioAsymmetricMatchers = ExpectLibAsymmetricMatchers
342-
343-
/**
344-
* Implementation of the asymmetric matcher. Equivalent as he PartialMatcher but with sample used by implementations.
345-
* // TODO dprevost - might be needed in the namespace for custom matchers implementation?
346-
*/
347-
type WdioAsymmetricMatcher<T> = ExpectWebdriverIO.PartialMatcher<T> & {
348-
// Overwrite protected properties of expect.AsymmetricMatcher to access them
349-
sample: T;
350-
}
351-
352348
/**
353349
* expect function declaration, containing two generics:
354350
* - T: the type of the actual value, e.g. any type, not just WebdriverIO.Browser or WebdriverIO.Element
355351
* - R: the type of the return value, e.g. Promise<void> or void
356352
*/
357353
// TODO dprevost should we extends Expect from expect lib or just AsyncMatchers?
358354
// TODO dprevost ExpectLibAsymmetricMatchers add arrayOf and closeTo previously not there! and not was there previously but is no more?
359-
interface WdioCustomExpect extends WdioAsymmetricMatchers {
355+
interface WdioCustomExpect extends ExpectLibAsymmetricMatchers {
360356
/**
361357
* Creates a soft assertion wrapper around standard expect
362358
* Soft assertions record failures but don't throw errors immediately
@@ -380,6 +376,15 @@ interface WdioCustomExpect extends WdioAsymmetricMatchers {
380376
clearSoftFailures(testId?: string): void
381377
}
382378

379+
/**
380+
* Implementation of the asymmetric matcher. Equivalent as the PartialMatcher but with sample used by implementations.
381+
* For the runtime but not the typing.
382+
*/
383+
type WdioAsymmetricMatcher<T> = ExpectWebdriverIO.PartialMatcher<T> & {
384+
// Overwrite protected properties of expect.AsymmetricMatcher to access them
385+
sample: T;
386+
}
387+
383388
declare namespace ExpectWebdriverIO {
384389
function setOptions(options: DefaultOptions): void
385390
// eslint-disable-next-line @typescript-eslint/no-explicit-any

types/jasmine-soft-extend.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
/// <reference types="./expect-webdriverio.d.ts"/>
22

3-
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T
4-
53
declare global {
64

75
// TODO dprevost might need to override the Array too (and more?)

types/standalone.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ type ExpectBaseExpect = import('expect').BaseExpect
66
type ExpectMatchers<R, T> = import('expect').Matchers<R, T>
77
type ExpectLibExpect = import('expect').Expect
88

9-
// Not exportable from 'expect'
9+
// To remove when exportable from 'expect'. See https://github.com/jestjs/jest/pull/15704 (already merged)
1010
type Inverse<M> = {
1111
/**
1212
* Inverse next matcher. If you know how to test something, `.not` lets you test its opposite.
@@ -21,14 +21,14 @@ declare namespace ExpectWebdriverIO {
2121
* snapshot matcher
2222
* @param label optional snapshot label
2323
*/
24-
toMatchSnapshot(label?: string): Promise<R>
24+
toMatchSnapshot(label?: string): T extends WdioPromiseLike ? Promise<R> : R;
2525

2626
/**
2727
* inline snapshot matcher
2828
* @param snapshot snapshot string (autogenerated if not specified)
2929
* @param label optional snapshot label
3030
*/
31-
toMatchInlineSnapshot(snapshot?: string, label?: string): Promise<R>
31+
toMatchInlineSnapshot(snapshot?: string, label?: string): T extends WdioPromiseLike ? Promise<R> : R;
3232
}
3333

3434
type MatchersAndInverse<R, T> = ExpectWebdriverIO.Matchers<R, T> & Inverse<ExpectWebdriverIO.Matchers<R, T>>

0 commit comments

Comments
 (0)