diff --git a/types/jasmine/index.d.ts b/types/jasmine/index.d.ts index 3bd5c689bd..d09823d54f 100644 --- a/types/jasmine/index.d.ts +++ b/types/jasmine/index.d.ts @@ -14,6 +14,7 @@ // Stephen Farrar // Alex Povar // Dominik Ehrenberg +// Chives // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.8 // For ddescribe / iit use : https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/karma-jasmine/karma-jasmine.d.ts @@ -140,7 +141,7 @@ declare function expect(): jasmine.NothingMatcher; * @checkReturnValue see https://tsetse.info/check-return-value * @param actual - Actual computed value to test expectations against. */ -declare function expectAsync(actual: PromiseLike): jasmine.AsyncMatchers; +declare function expectAsync(actual: T|PromiseLike): jasmine.AsyncMatchers; /** * Explicitly mark a spec as failed. @@ -278,7 +279,7 @@ declare namespace jasmine { function addCustomEqualityTester(equalityTester: CustomEqualityTester): void; function addMatchers(matchers: CustomMatcherFactories): void; - function addAsyncMatchers(matchers: CustomMatcherFactories): void; + function addAsyncMatchers(matchers: CustomAsyncMatcherFactories): void; function stringMatching(str: string | RegExp): AsymmetricMatcher; @@ -346,10 +347,23 @@ declare namespace jasmine { negativeCompare?(actual: any, ...expected: any[]): CustomMatcherResult; } + interface CustomAsyncMatcher { + compare(actual: T, expected: T, ...args: any[]): Promise; + compare(actual: any, ...expected: any[]): Promise; + negativeCompare?(actual: T, expected: T, ...args: any[]): Promise; + negativeCompare?(actual: any, ...expected: any[]): Promise; + } + type CustomMatcherFactory = (util: MatchersUtil, customEqualityTesters: ReadonlyArray) => CustomMatcher; + type CustomAsyncMatcherFactory = (util: MatchersUtil, customEqualityTesters: ReadonlyArray) => CustomAsyncMatcher; + interface CustomMatcherFactories { - [index: string]: CustomMatcherFactory; + [name: string]: CustomMatcherFactory; + } + + interface CustomAsyncMatcherFactories { + [name: string]: CustomAsyncMatcherFactory; } interface CustomMatcherResult { diff --git a/types/jasmine/jasmine-tests.ts b/types/jasmine/jasmine-tests.ts index 6f89df2861..227f462f46 100644 --- a/types/jasmine/jasmine-tests.ts +++ b/types/jasmine/jasmine-tests.ts @@ -1357,6 +1357,10 @@ declare namespace jasmine { toBeGoofy(expected?: Expected): boolean; toBeWithinRange(expected?: Expected, floor?: number, ceiling?: number): boolean; } + + interface AsyncMatchers { + toBeEight(): Promise; + } } describe("Custom matcher: 'toBeGoofy'", () => { @@ -1405,6 +1409,51 @@ describe("Custom matcher: 'toBeGoofy'", () => { }); }); +describe("Custom async matcher: 'toBeEight'", () => { + beforeEach(() => { + jasmine.addAsyncMatchers({ + toBeEight: () => { + return { + // tslint:disable-next-line:no-any + compare: async (input: any) => { + return { + pass: input === 8, + message: `${JSON.stringify(input)} is not 8`, + }; + }, + }; + }, + }); + + // $ExpectError + jasmine.addAsyncMatchers({ + toBeBadlyTyped: () => { + return { + compare: () => { + return { + pass: true, + message: 'I am not an async function / not returning promise!', + }; + }, + }; + }, + }); + }); + + it("works in positive case", async () => { + await expectAsync(8).toBeEight(); + }); + + it("works in negative case", async () => { + await expectAsync("seven").not.toBeEight(); + }); + + it("fails correctly", async () => { + // This compiles, but the test fails at runtime (as {} isn't 8). + await expectAsync({}).toBeEight(); + }); +}); + describe('better typed spys', () => { describe('a typed spy', () => { const spy = jasmine.createSpy('spy', (num: number, str: string) => { diff --git a/types/jasmine/ts3.1/index.d.ts b/types/jasmine/ts3.1/index.d.ts index bf828a5875..a3451979bd 100644 --- a/types/jasmine/ts3.1/index.d.ts +++ b/types/jasmine/ts3.1/index.d.ts @@ -13,6 +13,7 @@ // Stephen Farrar // Alex Povar // Dominik Ehrenberg +// Chives // For ddescribe / iit use : https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/karma-jasmine/karma-jasmine.d.ts /** @@ -137,7 +138,7 @@ declare function expect(): jasmine.NothingMatcher; * @checkReturnValue see https://tsetse.info/check-return-value * @param actual - Actual computed value to test expectations against. */ -declare function expectAsync(actual: Promise): jasmine.AsyncMatchers; +declare function expectAsync(actual: T|Promise): jasmine.AsyncMatchers; /** * Explicitly mark a spec as failed. @@ -281,7 +282,7 @@ declare namespace jasmine { function addCustomEqualityTester(equalityTester: CustomEqualityTester): void; function addMatchers(matchers: CustomMatcherFactories): void; - function addAsyncMatchers(matchers: CustomMatcherFactories): void; + function addAsyncMatchers(matchers: CustomAsyncMatcherFactories): void; function stringMatching(str: string | RegExp): AsymmetricMatcher; @@ -349,10 +350,23 @@ declare namespace jasmine { negativeCompare?(actual: any, ...expected: any[]): CustomMatcherResult; } + interface CustomAsyncMatcher { + compare(actual: T, expected: T, ...args: any[]): Promise; + compare(actual: any, ...expected: any[]): Promise; + negativeCompare?(actual: T, expected: T, ...args: any[]): Promise; + negativeCompare?(actual: any, ...expected: any[]): Promise; + } + type CustomMatcherFactory = (util: MatchersUtil, customEqualityTesters: ReadonlyArray) => CustomMatcher; + type CustomAsyncMatcherFactory = (util: MatchersUtil, customEqualityTesters: ReadonlyArray) => CustomAsyncMatcher; + interface CustomMatcherFactories { - [index: string]: CustomMatcherFactory; + [name: string]: CustomMatcherFactory; + } + + interface CustomAsyncMatcherFactories { + [name: string]: CustomAsyncMatcherFactory; } interface CustomMatcherResult { diff --git a/types/jasmine/ts3.1/jasmine-tests.ts b/types/jasmine/ts3.1/jasmine-tests.ts index 791f8b268b..27e25c1d06 100644 --- a/types/jasmine/ts3.1/jasmine-tests.ts +++ b/types/jasmine/ts3.1/jasmine-tests.ts @@ -1326,6 +1326,10 @@ declare namespace jasmine { toBeGoofy(expected?: Expected): boolean; toBeWithinRange(expected?: Expected, floor?: number, ceiling?: number): boolean; } + + interface AsyncMatchers { + toBeEight(): Promise; + } } describe("Custom matcher: 'toBeGoofy'", () => { @@ -1374,6 +1378,51 @@ describe("Custom matcher: 'toBeGoofy'", () => { }); }); +describe("Custom async matcher: 'toBeEight'", () => { + beforeEach(() => { + jasmine.addAsyncMatchers({ + toBeEight: () => { + return { + // tslint:disable-next-line:no-any + compare: async (input: any) => { + return { + pass: input === 8, + message: `${JSON.stringify(input)} is not 8`, + }; + }, + }; + }, + }); + + jasmine.addAsyncMatchers({ + // $ExpectError + toBeBadlyTyped: () => { + return { + compare: () => { + return { + pass: true, + message: 'I am not an async function / not returning promise!', + }; + }, + }; + }, + }); + }); + + it("works in positive case", async () => { + await expectAsync(8).toBeEight(); + }); + + it("works in negative case", async () => { + await expectAsync("seven").not.toBeEight(); + }); + + it("fails correctly", async () => { + // This compiles, but the test fails at runtime (as {} isn't 8). + await expectAsync({}).toBeEight(); + }); +}); + describe('better typed spys', () => { describe('a typed spy', () => { const spy = jasmine.createSpy('spy', (num: number, str: string) => {