Skip to content

Commit ead571a

Browse files
committed
Add back promise matchers!
1 parent 7036d5e commit ead571a

5 files changed

Lines changed: 49 additions & 45 deletions

File tree

src/softExpect.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ const createSoftMatcher = <T>(
7676
return async (...args: unknown[]) => {
7777
try {
7878
// Build the expectation chain
79-
let expectChain = expect(actual)
79+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
80+
let expectChain: any = expect(actual)
8081

8182
if (prefix === 'not') {
8283
expectChain = expectChain.not
@@ -86,6 +87,7 @@ const createSoftMatcher = <T>(
8687
expectChain = expectChain.rejects
8788
}
8889

90+
// TODO ddprevost might need to review this await since not all expect requires to be awaited
8991
return await ((expectChain as unknown) as Record<string, (...args: unknown[]) => Promise<ExpectWebdriverIO.AssertionResult>>)[matcherName](...args)
9092

9193
} catch (error) {

test-types/jasmine/types-jasmine.test.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -468,13 +468,13 @@ describe('type assertions', () => {
468468
it('should still expect void type when actual is a Promise since we do not overload them', async () => {
469469
const promiseBoolean = Promise.resolve(true)
470470

471-
expectVoid = wdioExpect(promiseBoolean).toBe(true)
472-
expectVoid = wdioExpect(promiseBoolean).not.toBe(true)
471+
expectPromiseVoid = wdioExpect(promiseBoolean).toBe(true)
472+
expectPromiseVoid = wdioExpect(promiseBoolean).not.toBe(true)
473473

474474
//@ts-expect-error
475-
expectPromiseVoid = wdioExpect(promiseBoolean).toBe(true)
475+
expectVoid = wdioExpect(promiseBoolean).toBe(true)
476476
//@ts-expect-error
477-
expectPromiseVoid = wdioExpect(promiseBoolean).toBe(true)
477+
expectVoid = wdioExpect(promiseBoolean).toBe(true)
478478
})
479479

480480
it('should work with string', async () => {
@@ -497,15 +497,9 @@ describe('type assertions', () => {
497497
describe('Promise type assertions', () => {
498498
const booleanPromise: Promise<boolean> = Promise.resolve(true)
499499

500-
it('should expect a Promise of type', async () => {
501-
const expectPromiseBoolean1: ExpectWebdriverIO.MatchersAndInverse<void, Promise<boolean>> = wdioExpect(booleanPromise)
502-
const expectPromiseBoolean2: ExpectWebdriverIO.Matchers<void, Promise<boolean>> = wdioExpect(booleanPromise).not
503-
})
504-
505500
it('should work with resolves & rejects correctly', async () => {
506-
// TODO dprevost should we support this in Wdio since we do not even use it or document it?
507-
// expectPromiseVoid = wdioExpect(booleanPromise).resolves.toBe(true)
508-
// expectPromiseVoid = wdioExpect(booleanPromise).rejects.toBe(true)
501+
expectPromiseVoid = wdioExpect(booleanPromise).resolves.toBe(true)
502+
expectPromiseVoid = wdioExpect(booleanPromise).rejects.toBe(true)
509503

510504
//@ts-expect-error
511505
expectVoid = wdioExpect(booleanPromise).resolves.toBe(true)

test-types/jest-@jest_global/types-jest.test.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -469,13 +469,14 @@ describe('type assertions', async () => {
469469
it('should still expect void type when actual is a Promise since we do not overload them', async () => {
470470
const promiseBoolean = Promise.resolve(true)
471471

472-
expectVoid = expect(promiseBoolean).toBe(true)
473-
expectVoid = expect(promiseBoolean).not.toBe(true)
474-
475-
//@ts-expect-error
476-
expectPromiseVoid = expect(promiseBoolean).toBe(true)
477-
//@ts-expect-error
478-
expectPromiseVoid = expect(promiseBoolean).toBe(true)
472+
// TODO dprevost check if this one need to stay a void or can be a Promise<void>
473+
// expectVoid = expect(promiseBoolean).toBe(true)
474+
// expectVoid = expect(promiseBoolean).not.toBe(true)
475+
476+
// //@ts-expect-error
477+
// expectPromiseVoid = expect(promiseBoolean).toBe(true)
478+
// //@ts-expect-error
479+
// expectPromiseVoid = expect(promiseBoolean).toBe(true)
479480
})
480481

481482
it('should work with string', async () => {
@@ -498,20 +499,9 @@ describe('type assertions', async () => {
498499
describe('Promise type assertions', () => {
499500
const booleanPromise: Promise<boolean> = Promise.resolve(true)
500501

501-
it('should expect a Promise of type', async () => {
502-
const expectPromiseBoolean1: ExpectWebdriverIO.MatchersAndInverse<void, Promise<boolean>> = expect(booleanPromise)
503-
const expectPromiseBoolean2: ExpectWebdriverIO.Matchers<void, Promise<boolean>> = expect(booleanPromise).not
504-
505-
// @ts-expect-error
506-
const expectPromiseBoolean3: jest.JestMatchers<boolean> = expect(booleanPromise)
507-
//// @ts-expect-error
508-
// const expectPromiseBoolean4: jest.Matchers<void, boolean> = expect(booleanPromise).not
509-
})
510-
511502
it('should work with resolves & rejects correctly', async () => {
512-
// TODO dprevost should we bring back the support for this?
513-
// expectPromiseVoid = expect(booleanPromise).resolves.toBe(true)
514-
// expectPromiseVoid = expect(booleanPromise).rejects.toBe(true)
503+
expectPromiseVoid = expect(booleanPromise).resolves.toBe(true)
504+
expectPromiseVoid = expect(booleanPromise).rejects.toBe(true)
515505

516506
//@ts-expect-error
517507
expectVoid = expect(booleanPromise).resolves.toBe(true)

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -474,13 +474,13 @@ describe('type assertions', () => {
474474
it('should still expect void type when actual is a Promise since we do not overload them', async () => {
475475
const promiseBoolean = Promise.resolve(true)
476476

477-
expectVoid = expect(promiseBoolean).toBe(true)
478-
expectVoid = expect(promiseBoolean).not.toBe(true)
477+
expectPromiseVoid = expect(promiseBoolean).toBe(true)
478+
expectPromiseVoid = expect(promiseBoolean).not.toBe(true)
479479

480480
//@ts-expect-error
481-
expectPromiseVoid = expect(promiseBoolean).toBe(true)
481+
expectVoid = expect(promiseBoolean).toBe(true)
482482
//@ts-expect-error
483-
expectPromiseVoid = expect(promiseBoolean).toBe(true)
483+
expectVoid = expect(promiseBoolean).toBe(true)
484484
})
485485

486486
it('should work with string', async () => {
@@ -503,21 +503,24 @@ describe('type assertions', () => {
503503
describe('Promise type assertions', () => {
504504
const booleanPromise: Promise<boolean> = Promise.resolve(true)
505505

506-
it('should expect a Promise of type', async () => {
507-
const expectPromiseBoolean1: ExpectWebdriverIO.MatchersAndInverse<void, Promise<boolean>> = expect(booleanPromise)
508-
const expectPromiseBoolean2: ExpectWebdriverIO.Matchers<void, Promise<boolean>> = expect(booleanPromise).not
506+
it('should have expect return Matchers with a Promise', async () => {
507+
const expectPromiseBoolean1: ExpectWebdriverIO.Matchers<Promise<void>, Promise<boolean>> & ExpectLibInverse<ExpectWebdriverIO.Matchers<Promise<void>, Promise<boolean>>> & ExpectWebdriverIO.PromiseMatchers<Promise<boolean>> = expect(booleanPromise)
508+
const expectPromiseBoolean2: ExpectWebdriverIO.Matchers<Promise<void>, Promise<boolean>> = expect(booleanPromise).not
509509
})
510510

511511
it('should work with resolves & rejects correctly', async () => {
512-
// TODO dprevost should we support this in Wdio since we do not even use it or document it?
513-
// expectPromiseVoid = expect(booleanPromise).resolves.toBe(true)
514-
// expectPromiseVoid = expect(booleanPromise).rejects.toBe(true)
512+
expectPromiseVoid = expect(booleanPromise).resolves.toBe(true)
513+
expectPromiseVoid = expect(booleanPromise).rejects.toBe(true)
515514

516515
//@ts-expect-error
517516
expectVoid = expect(booleanPromise).resolves.toBe(true)
518517
//@ts-expect-error
519518
expectVoid = expect(booleanPromise).rejects.toBe(true)
520519

520+
//@ts-expect-error
521+
expect(true).resolves.toBe(true)
522+
//@ts-expect-error
523+
expect(true).rejects.toBe(true)
521524
})
522525

523526
it('should not support chainable and expect PromiseVoid with toBe', async () => {

types/expect-webdriverio.d.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ interface WdioCustomExpect {
409409
* Soft assertions record failures but don't throw errors immediately
410410
* All failures are collected and reported at the end of the test
411411
*/
412-
soft<T = unknown>(actual: T): T extends PromiseLike<unknown> ? ExpectWebdriverIO.MatchersAndInverse<Promise<void>, T> : ExpectWebdriverIO.MatchersAndInverse<void, T>;
412+
soft<T = unknown>(actual: T): T extends PromiseLike<unknown> ? ExpectWebdriverIO.MatchersAndInverse<Promise<void>, T> & ExpectWebdriverIO.PromiseMatchers<T> : ExpectWebdriverIO.MatchersAndInverse<void, T>;
413413

414414
/**
415415
* Get all current soft assertion failures
@@ -486,7 +486,7 @@ declare namespace ExpectWebdriverIO {
486486
*
487487
* @param actual The value to apply matchers against.
488488
*/
489-
<T = unknown>(actual: T): ExpectWebdriverIO.MatchersAndInverse<void, T>;
489+
<T = unknown>(actual: T): T extends PromiseLike<unknown> ? ExpectWebdriverIO.MatchersAndInverse<Promise<void>, T> & ExpectWebdriverIO.PromiseMatchers<T> : ExpectWebdriverIO.MatchersAndInverse<void, T>;
490490
}
491491

492492
interface Matchers<R extends void | Promise<void>, T> extends WdioMatchers<R, T> {}
@@ -499,6 +499,21 @@ declare namespace ExpectWebdriverIO {
499499

500500
type MatchersAndInverse<R extends void | Promise<void>, ActualT> = ExpectWebdriverIO.Matchers<R, ActualT> & ExpectLibInverse<ExpectWebdriverIO.Matchers<R, ActualT>>
501501

502+
/**
503+
* Take from expect library
504+
*/
505+
type PromiseMatchers<T = unknown> = {
506+
/**
507+
* Unwraps the reason of a rejected promise so any other matcher can be chained.
508+
* If the promise is fulfilled the assertion fails.
509+
*/
510+
rejects: MatchersAndInverse<Promise<void>, T>;
511+
/**
512+
* Unwraps the value of a fulfilled promise so any other matcher can be chained.
513+
* If the promise is rejected the assertion fails.
514+
*/
515+
resolves: MatchersAndInverse<Promise<void>, T>;
516+
}
502517
interface SnapshotServiceArgs {
503518
updateState?: SnapshotUpdateState
504519
resolveSnapshotPath?: (path: string, extension: string) => string

0 commit comments

Comments
 (0)