Skip to content
145 changes: 105 additions & 40 deletions types/jasmine/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@
// Moshe Kolodny <https://github.com/kolodny>
// Stephen Farrar <https://github.com/stephenfarrar>
// Mochamad Arfin <https://github.com/ndunks>
// Alex Povar <https://github.com/zvirja>
// 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

type ImplementationCallback = (() => PromiseLike<any>) | (() => void) | ((done: DoneFn) => void);
/**
* @deprecated Use {@link jasmine.ImplementationCallback} instead.
*/
type ImplementationCallback = jasmine.ImplementationCallback;

/**
* Create a group of specs (often called a suite).
Expand Down Expand Up @@ -48,23 +52,23 @@ declare function xdescribe(description: string, specDefinitions: () => void): vo
* @param assertion Function that contains the code of your test. If not provided the test will be pending.
* @param timeout Custom timeout for an async spec.
*/
declare function it(expectation: string, assertion?: ImplementationCallback, timeout?: number): void;
declare function it(expectation: string, assertion?: jasmine.ImplementationCallback, timeout?: number): void;

/**
* A focused `it`. If suites or specs are focused, only those that are focused will be executed.
* @param expectation Textual description of what this spec is checking
* @param assertion Function that contains the code of your test. If not provided the test will be pending.
* @param timeout Custom timeout for an async spec.
*/
declare function fit(expectation: string, assertion?: ImplementationCallback, timeout?: number): void;
declare function fit(expectation: string, assertion?: jasmine.ImplementationCallback, timeout?: number): void;

/**
* A temporarily disabled `it`. The spec will report as pending and will not be executed.
* @param expectation Textual description of what this spec is checking
* @param assertion Function that contains the code of your test. If not provided the test will be pending.
* @param timeout Custom timeout for an async spec.
*/
declare function xit(expectation: string, assertion?: ImplementationCallback, timeout?: number): void;
declare function xit(expectation: string, assertion?: jasmine.ImplementationCallback, timeout?: number): void;

/**
* Mark a spec as pending, expectation results will be ignored.
Expand All @@ -78,30 +82,30 @@ declare function pending(reason?: string): void;
* @param action Function that contains the code to setup your specs.
* @param timeout Custom timeout for an async beforeEach.
*/
declare function beforeEach(action: ImplementationCallback, timeout?: number): void;
declare function beforeEach(action: jasmine.ImplementationCallback, timeout?: number): void;

/**
* Run some shared teardown after each of the specs in the describe in which it is called.
* @param action Function that contains the code to teardown your specs.
* @param timeout Custom timeout for an async afterEach.
*/
declare function afterEach(action: ImplementationCallback, timeout?: number): void;
declare function afterEach(action: jasmine.ImplementationCallback, timeout?: number): void;

/**
* Run some shared setup once before all of the specs in the describe are run.
* Note: Be careful, sharing the setup from a beforeAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail.
* @param action Function that contains the code to setup your specs.
* @param timeout Custom timeout for an async beforeAll.
*/
declare function beforeAll(action: ImplementationCallback, timeout?: number): void;
declare function beforeAll(action: jasmine.ImplementationCallback, timeout?: number): void;

/**
* Run some shared teardown once before all of the specs in the describe are run.
* Note: Be careful, sharing the teardown from a afterAll makes it easy to accidentally leak state between your specs so that they erroneously pass or fail.
* @param action Function that contains the code to teardown your specs.
* @param timeout Custom timeout for an async afterAll
*/
declare function afterAll(action: ImplementationCallback, timeout?: number): void;
declare function afterAll(action: jasmine.ImplementationCallback, timeout?: number): void;

/**
* Create an expectation for a spec.
Expand Down Expand Up @@ -174,55 +178,69 @@ declare function spyOnProperty<T>(object: T, property: keyof T, accessType?: 'ge
* Installs spies on all writable and configurable properties of an object.
* @param object The object upon which to install the `Spy`s.
*/
declare function spyOnAllFunctions(object: object): jasmine.Spy;
declare function spyOnAllFunctions<T>(object: T): jasmine.SpyObj<T>;

declare function runs(asyncMethod: Function): void;
declare function waitsFor(latchMethod: () => boolean, failureMessage?: string, timeout?: number): void;
declare function waits(timeout?: number): void;

declare namespace jasmine {
type ExpectedRecursive<T> = T | ObjectContaining<T> | AsymmetricMatcher | {
type Func = (...args: any[]) => any;

// Use trick with prototype to allow abstract classes.
// More info: https://stackoverflow.com/a/38642922/2009373
type Constructor = Function & { prototype: any };

type ImplementationCallback = (() => PromiseLike<any>) | ((done: DoneFn) => void);

type ExpectedRecursive<T> = T | ObjectContaining<T> | AsymmetricMatcher<any> | {
[K in keyof T]: ExpectedRecursive<T[K]> | Any;
};
type Expected<T> = T | ObjectContaining<T> | AsymmetricMatcher | Any | Spy | {
type Expected<T> = T | ObjectContaining<T> | AsymmetricMatcher<any> | Any | Spy | {
[K in keyof T]: ExpectedRecursive<T[K]>;
};
type SpyObjMethodNames<T = undefined> =
T extends undefined ?
(ReadonlyArray<string> | {[methodName: string]: any}) :
(ReadonlyArray<keyof T> | {[P in keyof T]?: ReturnType<T[P] extends (...args: any[]) => any ? T[P] : any>});
(ReadonlyArray<string> | { [methodName: string]: any }) :
(ReadonlyArray<keyof T> | { [P in keyof T]?: T[P] extends Func ? ReturnType<T[P]> : any });

function clock(): Clock;

var matchersUtil: MatchersUtil;

function any(aclass: any): Any;
/**
* That will succeed if the actual value being compared is an instance of the specified class/constructor.
*/
function any(aclass: Constructor | Symbol): AsymmetricMatcher<any>;

function anything(): Any;
/**
* That will succeed if the actual value being compared is not `null` and not `undefined`.
*/
function anything(): AsymmetricMatcher<any>;

/**
* That will succeed if the actual value being compared is `true` or anything truthy.
* @since 3.1.0
*/
function truthy(): Truthy;
function truthy(): AsymmetricMatcher<any>;

/**
* That will succeed if the actual value being compared is `null`, `undefined`, `0`, `false` or anything falsey.
* @since 3.1.0
*/
function falsy(): Falsy;
function falsy(): AsymmetricMatcher<any>;

/**
* That will succeed if the actual value being compared is empty.
* @since 3.1.0
*/
function empty(): Empty;
function empty(): AsymmetricMatcher<any>;

/**
* That will succeed if the actual value being compared is not empty.
* @since 3.1.0
*/
function notEmpty(): NotEmpty;
function notEmpty(): AsymmetricMatcher<any>;

function arrayContaining<T>(sample: ArrayLike<T>): ArrayContaining<T>;
function arrayWithExactContents<T>(sample: ArrayLike<T>): ArrayContaining<T>;
Expand All @@ -233,7 +251,7 @@ declare namespace jasmine {
function createSpyObj<T>(baseName: string, methodNames: SpyObjMethodNames<T>): SpyObj<T>;

function createSpyObj(methodNames: SpyObjMethodNames): any;
function createSpyObj<T>(methodNames: SpyObjMethodNames): SpyObj<T>;
function createSpyObj<T>(methodNames: SpyObjMethodNames<T>): SpyObj<T>;

function pp(value: any): string;

Expand All @@ -243,39 +261,34 @@ declare namespace jasmine {

function addMatchers(matchers: CustomMatcherFactories): void;

function stringMatching(str: string | RegExp): Any;
function stringMatching(str: string | RegExp): AsymmetricMatcher<string>;

function formatErrorMsg(domain: string, usage: string): (msg: string) => string;

interface Any {
interface Any extends AsymmetricMatcher<any> {
(...params: any[]): any; // jasmine.Any can also be a function
new (expectedClass: any): any;

jasmineMatches(other: any): boolean;
jasmineToString(): string;
}

interface AsymmetricMatcher<T extends string = string> {
asymmetricMatch(other: any): boolean;
jasmineToString?(): T;
}

interface Truthy extends AsymmetricMatcher<'<jasmine.truthy>'> { }
interface Falsy extends AsymmetricMatcher<'<jasmine.falsy>'> { }
interface Empty extends AsymmetricMatcher<'<jasmine.empty>'> { }
interface NotEmpty extends AsymmetricMatcher<'<jasmine.notEmpty>'> { }
interface AsymmetricMatcher<TValue> {
asymmetricMatch(other: TValue, customTesters: ReadonlyArray<CustomEqualityTester>): boolean;
jasmineToString?(): string;
}

// taken from TypeScript lib.core.es6.d.ts, applicable to CustomMatchers.contains()
interface ArrayLike<T> {
length: number;
[n: number]: T;
}

interface ArrayContaining<T> extends AsymmetricMatcher {
interface ArrayContaining<T> extends AsymmetricMatcher<any> {
new?(sample: ArrayLike<T>): ArrayLike<T>;
}

interface ObjectContaining<T> {
interface ObjectContaining<T> extends AsymmetricMatcher<any> {
new?(sample: {[K in keyof T]?: any}): {[K in keyof T]?: any};

jasmineMatches(other: any, mismatchKeys: any[], mismatchValues: any[]): boolean;
Expand Down Expand Up @@ -492,19 +505,33 @@ declare namespace jasmine {
message(): any;

/**
* Expect the actual value to be `===` to the expected value.
*
* @param expected the actual value to be === to the expected value.
* @param expected - The expected value to compare against.
* @param expectationFailOutput
* @example
* expect(thing).toBe(realThing);
*/
toBe(expected: Expected<T>, expectationFailOutput?: any): boolean;

/**
*
* @param expected the actual value to be equal to the expected, using deep equality comparison.
* Expect the actual value to be equal to the expected, using deep equality comparison.
* @param expected - Expected value.
* @param expectationFailOutput
* @example
* expect(bigObject).toEqual({ "foo": ['bar', 'baz'] });
*/
toEqual(expected: Expected<T>, expectationFailOutput?: any): boolean;

/**
* Expect the actual value to match a regular expression.
* @param expected - Value to look for in the string.
* @example
* expect("my string").toMatch(/string$/);
* expect("other string").toMatch("her");
*/
toMatch(expected: string | RegExp, expectationFailOutput?: any): boolean;

toBeDefined(expectationFailOutput?: any): boolean;
toBeUndefined(expectationFailOutput?: any): boolean;
toBeNull(expectationFailOutput?: any): boolean;
Expand All @@ -527,23 +554,61 @@ declare namespace jasmine {
toThrowMatching(predicate: (thrown: any) => boolean): boolean;
toBeNegativeInfinity(expectationFailOutput?: any): boolean;
toBePositiveInfinity(expectationFailOutput?: any): boolean;
toHaveClass(expected: any, expectationFailOutput?: any): boolean;

/**
* Expect the actual value to be a DOM element that has the expected class.
* @since 3.0.0
* @param expected - The class name to test for.
* @example
* var el = document.createElement('div');
* el.className = 'foo bar baz';
* expect(el).toHaveClass('bar');
*/
toHaveClass(expected: string, expectationFailOutput?: any): boolean;

/**
* Add some context for an expect.
* @param message - Additional context to show when the matcher fails
*/
withContext(message: string): Matchers<T>;

/**
* Invert the matcher following this expect.
*/
not: Matchers<T>;

Any: Any;
}

interface ArrayLikeMatchers<T> extends Matchers<ArrayLike<T>> {
/**
* Expect the actual value to be `===` to the expected value.
*
* @param expected - The expected value to compare against.
* @param expectationFailOutput
* @example
* expect(thing).toBe(realThing);
*/
toBe(expected: Expected<ArrayLike<T>> | ArrayContaining<T>, expectationFailOutput?: any): boolean;

/**
* Expect the actual value to be equal to the expected, using deep equality comparison.
* @param expected - Expected value.
* @param expectationFailOutput
* @example
* expect(bigObject).toEqual({ "foo": ['bar', 'baz'] });
*/
toEqual(expected: Expected<ArrayLike<T>> | ArrayContaining<T>, expectationFailOutput?: any): boolean;

toContain(expected: Expected<T>, expectationFailOutput?: any): boolean;

/**
* Add some context for an expect.
* @param message - Additional context to show when the matcher fails.
*/
withContext(message: string): ArrayLikeMatchers<T>;

/**
* Invert the matcher following this expect.
*/
not: ArrayLikeMatchers<T>;
}

Expand Down Expand Up @@ -745,7 +810,7 @@ declare namespace jasmine {
}

type SpyObj<T> = T & {
[k in keyof T]: T[k] extends Function ? T[k] & Spy : T[k];
[K in keyof T]: T[K] extends Function ? T[K] & Spy : T[K];
};

interface SpyAnd {
Expand Down
Loading