mirror of
https://github.com/gosticks/DefinitelyTyped.git
synced 2026-07-01 15:50:13 +00:00
[jasmine] Improve various library types (#38412)
* Move Func helper to jasmine namespace * Move ImplementationCallback to jasmine namespace * Align tests between different versions * Fix typings for spyOnAllFunctcions * Improve typing for function matchers * Refactor AsymmetricMatcher to handle all cases * Enhance basic expectation docs and typing Improve toBe(), toEqual(), toMatch(), toHaveClass() documentation to avoid confusion around them. * Enhance any() and anything() * Add missing typing for non-named spy object * Specify that jasminewd2 depends on jasmine v2 The jasminewd2 library supports jasmine 2 only, therefore point typings to the correct reference. * Add NonTypedSpyObj for complex scenarios * Improve tool for spy names extraction * Remove undefined Any property from matchers
This commit is contained in:
committed by
Michael Crane
parent
7564c78a0a
commit
7456aa4eec
145
types/jasmine/index.d.ts
vendored
145
types/jasmine/index.d.ts
vendored
@@ -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).
|
||||
@@ -48,7 +52,7 @@ 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.
|
||||
@@ -56,7 +60,7 @@ declare function it(expectation: string, assertion?: ImplementationCallback, tim
|
||||
* @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.
|
||||
@@ -64,7 +68,7 @@ declare function fit(expectation: string, assertion?: ImplementationCallback, ti
|
||||
* @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.
|
||||
@@ -78,14 +82,14 @@ 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.
|
||||
@@ -93,7 +97,7 @@ declare function afterEach(action: ImplementationCallback, timeout?: number): vo
|
||||
* @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.
|
||||
@@ -101,7 +105,7 @@ declare function beforeAll(action: ImplementationCallback, timeout?: number): vo
|
||||
* @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.
|
||||
@@ -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>;
|
||||
@@ -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;
|
||||
|
||||
@@ -243,11 +261,11 @@ 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;
|
||||
|
||||
@@ -255,15 +273,10 @@ declare namespace jasmine {
|
||||
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> {
|
||||
@@ -271,11 +284,11 @@ declare namespace jasmine {
|
||||
[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;
|
||||
@@ -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;
|
||||
@@ -527,7 +554,17 @@ 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.
|
||||
@@ -535,15 +572,43 @@ declare namespace jasmine {
|
||||
*/
|
||||
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>;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -15,23 +15,29 @@ describe("A suite is just a function", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("The 'toBe' matcher compares with ===", () => {
|
||||
it("and has a positive case", () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
it("and can have a negative case", () => {
|
||||
expect(false).not.toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Included matchers:", () => {
|
||||
it("The 'toBe' matcher compares with ===", () => {
|
||||
const a = 12;
|
||||
const b = a;
|
||||
describe('toBe', () => {
|
||||
it("and has a positive case", () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
expect(a).toBe(b);
|
||||
expect(a).not.toBe(24);
|
||||
it("and can have a negative case", () => {
|
||||
expect(false).not.toBe(true);
|
||||
});
|
||||
|
||||
it("the 'toBe' matcher compares with ===", () => {
|
||||
const a = 12;
|
||||
const b = a;
|
||||
|
||||
expect(a).toBe(b);
|
||||
expect(a).not.toBe(24);
|
||||
});
|
||||
|
||||
it('should allow to accept any union type', () => {
|
||||
const value: number | string = null as any;
|
||||
|
||||
expect(value).toBe(12);
|
||||
});
|
||||
});
|
||||
|
||||
describe("The 'toEqual' matcher", () => {
|
||||
@@ -176,8 +182,10 @@ describe("Included matchers:", () => {
|
||||
it("async matchers", async () => {
|
||||
const badness = new Error("badness");
|
||||
await expectAsync(Promise.resolve()).toBeResolved();
|
||||
await expectAsync(Promise.resolve()).toBeResolved("good job");
|
||||
await expectAsync(Promise.resolve(true)).toBeResolvedTo(true);
|
||||
await expectAsync(Promise.reject(badness)).toBeRejected();
|
||||
await expectAsync(Promise.reject(badness)).toBeRejected("bad mojo");
|
||||
await expectAsync(Promise.reject(badness)).toBeRejectedWith(badness);
|
||||
await expectAsync(Promise.resolve()).withContext("additional info").toBeResolved();
|
||||
});
|
||||
@@ -209,7 +217,9 @@ describe("toBePositiveInfinity", () => {
|
||||
});
|
||||
|
||||
describe("toHaveClass", () => {
|
||||
expect("").toHaveClass(Array);
|
||||
const element: HTMLElement = null!;
|
||||
expect(element).toHaveClass("some-class");
|
||||
expect(element).toHaveClass(Element); // $ExpectError
|
||||
});
|
||||
|
||||
describe("A spec", () => {
|
||||
@@ -396,22 +406,19 @@ describe("A spy, when configured to call through", () => {
|
||||
});
|
||||
|
||||
describe("A spy, when configured to fake a return value", () => {
|
||||
var foo: any, bar: any, fetchedBar: any;
|
||||
|
||||
beforeEach(() => {
|
||||
foo = {
|
||||
setBar: (value: any) => {
|
||||
bar = value;
|
||||
},
|
||||
getBar: () => {
|
||||
return bar;
|
||||
}
|
||||
};
|
||||
var bar: number;
|
||||
const foo = {
|
||||
setBar: (value: number) => {
|
||||
bar = value;
|
||||
},
|
||||
getBar: () => {
|
||||
return bar;
|
||||
}
|
||||
};
|
||||
|
||||
it("verifies return value type", () => {
|
||||
spyOn(foo, "getBar").and.returnValue(745);
|
||||
|
||||
foo.setBar(123);
|
||||
fetchedBar = foo.getBar();
|
||||
spyOn(foo, "getBar").and.returnValue("42"); // Is an error with TS 3.1+ typings.
|
||||
});
|
||||
|
||||
it("tracks that the spy was called", () => {
|
||||
@@ -423,6 +430,8 @@ describe("A spy, when configured to fake a return value", () => {
|
||||
});
|
||||
|
||||
it("when called returns the requested value", () => {
|
||||
const fetchedBar = foo.getBar();
|
||||
|
||||
expect(fetchedBar).toEqual(745);
|
||||
});
|
||||
});
|
||||
@@ -720,6 +729,29 @@ describe("A spy, when created manually", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("Spy for generic method", () => {
|
||||
interface Test {
|
||||
method<T>(): Array<Box<T>>;
|
||||
}
|
||||
|
||||
interface Box<T> {
|
||||
value: T;
|
||||
}
|
||||
|
||||
it("should allow to configure generic method", () => {
|
||||
const spy = jasmine.createSpyObj<Test>('test', ['method']);
|
||||
|
||||
spy.method.and.returnValue([{ value: 1 }, { value: 2 }]);
|
||||
});
|
||||
|
||||
it("should allow to configure generic method with non-named spy", () => {
|
||||
const spy = jasmine.createSpyObj<Test>(['method']);
|
||||
jasmine.createSpyObj<Test>(['methodUnknown']); // $ExpectError
|
||||
|
||||
spy.method.and.returnValue([{ value: 1 }, { value: 2 }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Multiple spies, when created manually", () => {
|
||||
class Tape {
|
||||
private rewindTo: number;
|
||||
@@ -770,6 +802,12 @@ describe("Multiple spies, when created manually", () => {
|
||||
|
||||
it("tracks all the arguments of its calls", () => {
|
||||
expect(tape.rewind).toHaveBeenCalledWith(0);
|
||||
expect(tape.rewind).toHaveBeenCalledWith('42'); // Is an error with TS 3.1+ typings.
|
||||
expect(tape.rewind).toHaveBeenCalledWith(jasmine.anything());
|
||||
expect(tape.rewind).toHaveBeenCalledWith(jasmine.falsy());
|
||||
expect(tape.rewind).not.toHaveBeenCalledWith(1);
|
||||
expect(tape.rewind).not.toHaveBeenCalledWith('42'); // Is an error with TS 3.1+ typings.
|
||||
expect(tape.rewind).not.toHaveBeenCalledWith(jasmine.truthy());
|
||||
});
|
||||
|
||||
it("read isPlaying property", () => {
|
||||
@@ -784,13 +822,19 @@ describe("multiple spies, when created with spyOnAllFunctions", () => {
|
||||
y: (a: number) => a,
|
||||
};
|
||||
|
||||
spyOnAllFunctions(obj);
|
||||
const spy = spyOnAllFunctions(obj);
|
||||
|
||||
spy.x.and.returnValue(42);
|
||||
spy.y.and.returnValue(24);
|
||||
spy.z; // $ExpectError
|
||||
|
||||
obj.x(0);
|
||||
obj.y(1);
|
||||
|
||||
expect(obj.x).toHaveBeenCalled();
|
||||
expect(obj.y).toHaveBeenCalledWith(1);
|
||||
expect(spy.y).toHaveBeenCalledWith(1);
|
||||
expect(spy.y).toHaveBeenCalledWith("one"); // Is an error with TS 3.1+ typings.
|
||||
});
|
||||
});
|
||||
|
||||
@@ -804,6 +848,9 @@ describe("jasmine.any", () => {
|
||||
it("matches any value", () => {
|
||||
expect({}).toEqual(jasmine.any(Object));
|
||||
expect(12).toEqual(jasmine.any(Number));
|
||||
expect(42).toEqual(jasmine.any(42)); // $ExpectError
|
||||
expect({}).toEqual(jasmine.any({})); // $ExpectError
|
||||
expect(() => null).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("matches any function", () => {
|
||||
@@ -817,7 +864,7 @@ describe("jasmine.any", () => {
|
||||
fn2: (param1: number) => param1,
|
||||
};
|
||||
|
||||
const expected: Test = {
|
||||
const expected = {
|
||||
fn1: jasmine.any(Function),
|
||||
fn2: jasmine.any(Function),
|
||||
};
|
||||
@@ -825,6 +872,29 @@ describe("jasmine.any", () => {
|
||||
expect(a).toEqual(expected);
|
||||
});
|
||||
|
||||
it("matches custom types", () => {
|
||||
class Test { }
|
||||
|
||||
const obj = new Test();
|
||||
|
||||
expect(obj).toEqual(jasmine.any(Test));
|
||||
});
|
||||
|
||||
it("matches base abstract class", () => {
|
||||
abstract class TestClassBase { }
|
||||
class TestClass extends TestClassBase { }
|
||||
const obj = new TestClass();
|
||||
|
||||
expect(obj).toEqual(jasmine.any(TestClass));
|
||||
expect(obj).toEqual(jasmine.any(TestClassBase));
|
||||
});
|
||||
|
||||
it("matches symbols", () => {
|
||||
const sym = Symbol('test symbol');
|
||||
|
||||
expect(sym).toEqual(jasmine.any(sym));
|
||||
});
|
||||
|
||||
describe("when used with a spy", () => {
|
||||
it("is useful for comparing arguments", () => {
|
||||
const foo = jasmine.createSpy('foo');
|
||||
@@ -834,6 +904,15 @@ describe("jasmine.any", () => {
|
||||
|
||||
expect(foo).toHaveBeenCalledWith(jasmine.any(Number), jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("is useful for comparing arguments for typed spy", () => {
|
||||
const foo = jasmine.createSpy('foo');
|
||||
foo(12, () => {
|
||||
return true;
|
||||
});
|
||||
|
||||
expect(foo).toHaveBeenCalledWith(jasmine.any(Number), jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -949,6 +1028,15 @@ describe("jasmine.arrayContaining", () => {
|
||||
expect(foo).not.toBe(jasmine.arrayContaining([6]));
|
||||
});
|
||||
|
||||
it("matches read-only array", () => {
|
||||
const bar: ReadonlyArray<number> = [1, 2, 3, 4];
|
||||
|
||||
expect(bar).toEqual(jasmine.arrayContaining([3, 1]));
|
||||
expect(bar).not.toEqual(jasmine.arrayContaining([6]));
|
||||
|
||||
expect(bar).toBe(jasmine.arrayContaining([3, 1]));
|
||||
});
|
||||
|
||||
describe("when used with a spy", () => {
|
||||
it("is useful when comparing arguments", () => {
|
||||
const callback = jasmine.createSpy('callback');
|
||||
@@ -1206,6 +1294,75 @@ describe("Custom matcher: 'toBeGoofy'", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('better typed spys', () => {
|
||||
describe('a typed spy', () => {
|
||||
const spy = jasmine.createSpy('spy', (num: number, str: string) => {
|
||||
return `${num} and ${str}`;
|
||||
});
|
||||
it('has a typed returnValue', () => {
|
||||
// $ExpectType (val: any) => Spy
|
||||
spy.and.returnValue;
|
||||
});
|
||||
it('has a typed calls property', () => {
|
||||
spy.calls.first().args; // $ExpectType any[]
|
||||
spy.calls.first().returnValue; // $ExpectType any
|
||||
});
|
||||
it('has a typed callFake', () => {
|
||||
// $ExpectType (fn: Function) => Spy
|
||||
spy.and.callFake;
|
||||
});
|
||||
});
|
||||
describe('spyOn', () => {
|
||||
it('only works on methods', () => {
|
||||
const foo = {
|
||||
method() {
|
||||
return 'baz';
|
||||
},
|
||||
value: 'value',
|
||||
};
|
||||
const spy = spyOn(foo, 'method');
|
||||
const spy2 = spyOn(foo, 'value'); // Is an error with TS 3.1+ typings.
|
||||
|
||||
// $ExpectType any
|
||||
spy.calls.first().returnValue;
|
||||
});
|
||||
it('works on constructors', () => {
|
||||
class MyClass {
|
||||
constructor(readonly foo: string) {}
|
||||
}
|
||||
const namespace = { MyClass };
|
||||
const spy = spyOn(namespace, 'MyClass');
|
||||
spy.and.returnValue({foo: 'test'});
|
||||
spy.and.returnValue({}); // Is an error with TS 3.1+ typings.
|
||||
spy.and.returnValue({foo: 123}); // Is an error with TS 3.1+ typings.
|
||||
});
|
||||
it('can allows overriding the generic', () => {
|
||||
class Base {
|
||||
service() {}
|
||||
}
|
||||
class Super extends Base {
|
||||
service2() {}
|
||||
}
|
||||
spyOn<Base>(new Super(), 'service');
|
||||
spyOn<Base>(new Super(), 'service2'); // $ExpectError
|
||||
});
|
||||
});
|
||||
describe('createSpyObj', () => {
|
||||
it('returns the correct spy types', () => {
|
||||
const foo = {
|
||||
method() {
|
||||
return 'baz';
|
||||
},
|
||||
value: 'value',
|
||||
};
|
||||
const spyObj = jasmine.createSpyObj<typeof foo>('foo', ['method']);
|
||||
|
||||
// $ExpectType (val: any) => Spy
|
||||
spyObj.method.and.returnValue;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// test based on http://jasmine.github.io/2.5/custom_reporter.html
|
||||
var myReporter: jasmine.CustomReporter = {
|
||||
jasmineStarted: (suiteInfo: jasmine.SuiteInfo) => {
|
||||
@@ -1318,46 +1475,73 @@ describe("createSpyObj", function() {
|
||||
});
|
||||
|
||||
describe('Static Matcher Test', function() {
|
||||
it('Falsy', () => {
|
||||
expect({ value: null }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: jasmine.falsy(),
|
||||
})
|
||||
);
|
||||
});
|
||||
it('Truthy', () => {
|
||||
expect({ value: null }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: jasmine.truthy(),
|
||||
})
|
||||
);
|
||||
});
|
||||
it('Empty', () => {
|
||||
expect({ value: null }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: jasmine.empty(),
|
||||
})
|
||||
);
|
||||
});
|
||||
it('NotEmpty', () => {
|
||||
expect({ value: null }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: jasmine.notEmpty(),
|
||||
})
|
||||
);
|
||||
});
|
||||
it('Partial should OK', () => {
|
||||
expect({ value: null, label: 'abcd' }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: jasmine.anything(),
|
||||
})
|
||||
);
|
||||
expect({ value: null }).toEqual(
|
||||
it('Falsy', () => {
|
||||
expect({ value: null }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: 'any value should ok',
|
||||
value: jasmine.falsy(),
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
it('Truthy', () => {
|
||||
expect({ value: null }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: jasmine.truthy(),
|
||||
})
|
||||
);
|
||||
});
|
||||
it('Empty', () => {
|
||||
expect({ value: null }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: jasmine.empty(),
|
||||
})
|
||||
);
|
||||
});
|
||||
it('NotEmpty', () => {
|
||||
expect({ value: null }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: jasmine.notEmpty(),
|
||||
})
|
||||
);
|
||||
});
|
||||
it('Partial should OK', () => {
|
||||
expect({ value: null, label: 'abcd' }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: jasmine.anything(),
|
||||
})
|
||||
);
|
||||
expect({ value: null }).toEqual(
|
||||
jasmine.objectContaining({
|
||||
value: 'any value should ok',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("User scenarios", () => {
|
||||
describe("https://github.com/DefinitelyTyped/DefinitelyTyped/issues/34080", () => {
|
||||
interface Test {
|
||||
f(): string;
|
||||
f(x: any): number;
|
||||
}
|
||||
|
||||
it("has a way to opt out of inferred function types", () => {
|
||||
const spyObject: jasmine.SpyObj<Test> = jasmine.createSpyObj<Test>("spyObject", ["f"]);
|
||||
spyObject.f.and.returnValue("a string - working");
|
||||
|
||||
const spy2 = jasmine.createSpyObj<Test>(['f']);
|
||||
spy2.f.and.returnValue("can return string" as any);
|
||||
});
|
||||
|
||||
it("should be possible to opt out for spyOn", () => {
|
||||
const obj: Test = null!;
|
||||
|
||||
const spy1: jasmine.Spy = spyOn(obj, "f");
|
||||
spy1.and.returnValue("can return string");
|
||||
|
||||
const spy2 = spyOn(obj, "f");
|
||||
spy2.and.returnValue("can return string" as any);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
(() => {
|
||||
|
||||
222
types/jasmine/ts3.1/index.d.ts
vendored
222
types/jasmine/ts3.1/index.d.ts
vendored
@@ -12,10 +12,13 @@
|
||||
// Moshe Kolodny <https://github.com/kolodny>
|
||||
// Stephen Farrar <https://github.com/stephenfarrar>
|
||||
// Mochamad Arfin <https://github.com/ndunks>
|
||||
// Alex Povar <https://github.com/zvirja>
|
||||
// For ddescribe / iit use : https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/karma-jasmine/karma-jasmine.d.ts
|
||||
|
||||
type ImplementationCallback = (() => Promise<any>) | ((done: DoneFn) => void);
|
||||
type InferableFunction = (...args: any[]) => any;
|
||||
/**
|
||||
* @deprecated Use {@link jasmine.ImplementationCallback} instead.
|
||||
*/
|
||||
type ImplementationCallback = jasmine.ImplementationCallback;
|
||||
|
||||
/**
|
||||
* Create a group of specs (often called a suite).
|
||||
@@ -45,7 +48,7 @@ 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.
|
||||
@@ -53,7 +56,7 @@ declare function it(expectation: string, assertion?: ImplementationCallback, tim
|
||||
* @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.
|
||||
@@ -61,7 +64,7 @@ declare function fit(expectation: string, assertion?: ImplementationCallback, ti
|
||||
* @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.
|
||||
@@ -75,14 +78,14 @@ 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.
|
||||
@@ -90,7 +93,7 @@ declare function afterEach(action: ImplementationCallback, timeout?: number): vo
|
||||
* @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.
|
||||
@@ -98,14 +101,14 @@ declare function beforeAll(action: ImplementationCallback, timeout?: number): vo
|
||||
* @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.
|
||||
* @checkReturnValue see https://tsetse.info/check-return-value
|
||||
* @param spy
|
||||
*/
|
||||
declare function expect(spy: Function): jasmine.Matchers<any>;
|
||||
declare function expect<T extends jasmine.Func>(spy: T | jasmine.Spy<T>): jasmine.FunctionMatchers<T>;
|
||||
|
||||
/**
|
||||
* Create an expectation for a spec.
|
||||
@@ -160,9 +163,9 @@ interface DoneFn extends Function {
|
||||
declare function spyOn<T, K extends keyof T = keyof T>(
|
||||
object: T, method: T[K] extends Function ? K : never,
|
||||
): jasmine.Spy<
|
||||
T[K] extends InferableFunction ? T[K] :
|
||||
T[K] extends {new (...args: infer A): infer V} ? (...args: A) => V :
|
||||
T[K] extends Function ? InferableFunction : never
|
||||
T[K] extends jasmine.Func ? T[K] :
|
||||
T[K] extends { new (...args: infer A): infer V } ? (...args: A) => V :
|
||||
never
|
||||
>;
|
||||
|
||||
/**
|
||||
@@ -177,72 +180,80 @@ 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 InferableFunction ? T[P] : any>});
|
||||
|
||||
type AnyMethods<T> = {
|
||||
[K in {
|
||||
[K in keyof T]: T[K] extends Function ? K : never
|
||||
}[keyof T]]: InferableFunction
|
||||
};
|
||||
(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>;
|
||||
function objectContaining<T>(sample: Partial<T>): ObjectContaining<T>;
|
||||
function createSpy<Fun extends InferableFunction>(name?: string, originalFn?: Fun): Spy<Fun>;
|
||||
function createSpy<Fn extends Func>(name?: string, originalFn?: Fn): Spy<Fn>;
|
||||
|
||||
function createSpyObj(baseName: string, methodNames: SpyObjMethodNames): any;
|
||||
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;
|
||||
|
||||
@@ -252,11 +263,11 @@ 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;
|
||||
|
||||
@@ -264,27 +275,22 @@ declare namespace jasmine {
|
||||
jasmineToString(): string;
|
||||
}
|
||||
|
||||
interface AsymmetricMatcher<T extends string = string> {
|
||||
asymmetricMatch(other: any): boolean;
|
||||
jasmineToString?(): T;
|
||||
interface AsymmetricMatcher<TValue> {
|
||||
asymmetricMatch(other: TValue, customTesters: ReadonlyArray<CustomEqualityTester>): boolean;
|
||||
jasmineToString?(): string;
|
||||
}
|
||||
|
||||
interface Truthy extends AsymmetricMatcher<'<jasmine.truthy>'> { }
|
||||
interface Falsy extends AsymmetricMatcher<'<jasmine.falsy>'> { }
|
||||
interface Empty extends AsymmetricMatcher<'<jasmine.empty>'> { }
|
||||
interface NotEmpty extends AsymmetricMatcher<'<jasmine.notEmpty>'> { }
|
||||
|
||||
// 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;
|
||||
@@ -501,19 +507,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;
|
||||
@@ -521,7 +541,7 @@ declare namespace jasmine {
|
||||
toBeTruthy(expectationFailOutput?: any): boolean;
|
||||
toBeFalsy(expectationFailOutput?: any): boolean;
|
||||
toHaveBeenCalled(): boolean;
|
||||
toHaveBeenCalledBefore(expected: Spy): boolean;
|
||||
toHaveBeenCalledBefore(expected: Func): boolean;
|
||||
toHaveBeenCalledWith(...params: any[]): boolean;
|
||||
toHaveBeenCalledTimes(expected: number): boolean;
|
||||
toContain(expected: any, expectationFailOutput?: any): boolean;
|
||||
@@ -536,7 +556,17 @@ 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.
|
||||
@@ -544,18 +574,66 @@ declare namespace jasmine {
|
||||
*/
|
||||
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>;
|
||||
}
|
||||
|
||||
type MatchableArgs<Fn> = Fn extends (...args: infer P) => any ? { [K in keyof P]: P[K] | AsymmetricMatcher<any> } : never;
|
||||
|
||||
interface FunctionMatchers<Fn extends Func> extends Matchers<any> {
|
||||
toHaveBeenCalled(): boolean;
|
||||
toHaveBeenCalledBefore(expected: Func): boolean;
|
||||
toHaveBeenCalledTimes(expected: number): boolean;
|
||||
toHaveBeenCalledWith(...params: MatchableArgs<Fn>): boolean;
|
||||
|
||||
/**
|
||||
* Add some context for an expect.
|
||||
* @param message - Additional context to show when the matcher fails.
|
||||
*/
|
||||
withContext(message: string): FunctionMatchers<Fn>;
|
||||
|
||||
/**
|
||||
* Invert the matcher following this expect.
|
||||
*/
|
||||
not: FunctionMatchers<Fn>;
|
||||
}
|
||||
|
||||
interface NothingMatcher {
|
||||
nothing(): void;
|
||||
}
|
||||
@@ -745,61 +823,67 @@ declare namespace jasmine {
|
||||
execute(): void;
|
||||
}
|
||||
|
||||
interface Spy<Fn extends InferableFunction = InferableFunction> {
|
||||
(...params: any[]): any;
|
||||
interface Spy<Fn extends Func = Func> {
|
||||
(...params: Parameters<Fn>): ReturnType<Fn>;
|
||||
|
||||
and: SpyAnd<Fn>;
|
||||
calls: Calls<Fn>;
|
||||
withArgs(...args: any[]): Spy<Fn>;
|
||||
withArgs(...args: Parameters<Fn>): Spy<Fn>;
|
||||
}
|
||||
|
||||
type SpyObj<T> = T & {
|
||||
[k in keyof T]: T[k] extends InferableFunction ? T[k] & Spy<T[k]> : T[k];
|
||||
[K in keyof T]: T[K] extends Func ? T[K] & Spy<T[K]> : T[K];
|
||||
};
|
||||
|
||||
interface SpyAnd<Fun extends InferableFunction> {
|
||||
/**
|
||||
* It's like SpyObj, but doesn't verify argument/return types for functions.
|
||||
* Useful if TS cannot correctly infer type for complex objects.
|
||||
*/
|
||||
type NonTypedSpyObj<T> = SpyObj<{ [K in keyof T]: T[K] extends Func ? Func : T[K] }>;
|
||||
|
||||
interface SpyAnd<Fn extends Func> {
|
||||
identity: string;
|
||||
|
||||
/** By chaining the spy with and.callThrough, the spy will still track all calls to it but in addition it will delegate to the actual implementation. */
|
||||
callThrough(): Spy<Fun>;
|
||||
callThrough(): Spy<Fn>;
|
||||
/** By chaining the spy with and.returnValue, all calls to the function will return a specific value. */
|
||||
returnValue(val: ReturnType<Fun>): Spy<Fun>;
|
||||
returnValue(val: ReturnType<Fn>): Spy<Fn>;
|
||||
/** By chaining the spy with and.returnValues, all calls to the function will return specific values in order until it reaches the end of the return values list. */
|
||||
returnValues(...values: Array<ReturnType<Fun>>): Spy<Fun>;
|
||||
returnValues(...values: Array<ReturnType<Fn>>): Spy<Fn>;
|
||||
/** By chaining the spy with and.callFake, all calls to the spy will delegate to the supplied function. */
|
||||
callFake(fn: Fun): Spy<Fun>;
|
||||
callFake(fn: Fn): Spy<Fn>;
|
||||
/** By chaining the spy with and.throwError, all calls to the spy will throw the specified value. */
|
||||
throwError(msg: string): Spy;
|
||||
/** When a calling strategy is used for a spy, the original stubbing behavior can be returned at any time with and.stub. */
|
||||
stub(): Spy;
|
||||
}
|
||||
|
||||
interface Calls<Fun extends InferableFunction> {
|
||||
interface Calls<Fn extends Func> {
|
||||
/** By chaining the spy with calls.any(), will return false if the spy has not been called at all, and then true once at least one call happens. */
|
||||
any(): boolean;
|
||||
/** By chaining the spy with calls.count(), will return the number of times the spy was called */
|
||||
count(): number;
|
||||
/** By chaining the spy with calls.argsFor(), will return the arguments passed to call number index */
|
||||
argsFor(index: number): Parameters<Fun>;
|
||||
argsFor(index: number): Parameters<Fn>;
|
||||
/** By chaining the spy with calls.allArgs(), will return the arguments to all calls */
|
||||
allArgs(): Array<Parameters<Fun>>;
|
||||
allArgs(): ReadonlyArray<Parameters<Fn>>;
|
||||
/** By chaining the spy with calls.all(), will return the context (the this) and arguments passed all calls */
|
||||
all(): Array<CallInfo<Fun>>;
|
||||
all(): ReadonlyArray<CallInfo<Fn>>;
|
||||
/** By chaining the spy with calls.mostRecent(), will return the context (the this) and arguments for the most recent call */
|
||||
mostRecent(): CallInfo<Fun>;
|
||||
mostRecent(): CallInfo<Fn>;
|
||||
/** By chaining the spy with calls.first(), will return the context (the this) and arguments for the first call */
|
||||
first(): CallInfo<Fun>;
|
||||
first(): CallInfo<Fn>;
|
||||
/** By chaining the spy with calls.reset(), will clears all tracking for a spy */
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
interface CallInfo<Fun extends InferableFunction> {
|
||||
interface CallInfo<Fn extends Func> {
|
||||
/** The context (the this) for the call */
|
||||
object: any;
|
||||
/** All arguments passed to the call */
|
||||
args: Parameters<Fun>;
|
||||
args: Parameters<Fn>;
|
||||
/** The return value of the call */
|
||||
returnValue: ReturnType<Fun>;
|
||||
returnValue: ReturnType<Fn>;
|
||||
}
|
||||
|
||||
interface Util {
|
||||
|
||||
@@ -15,23 +15,29 @@ describe("A suite is just a function", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("The 'toBe' matcher compares with ===", () => {
|
||||
it("and has a positive case", () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
it("and can have a negative case", () => {
|
||||
expect(false).not.toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Included matchers:", () => {
|
||||
it("The 'toBe' matcher compares with ===", () => {
|
||||
const a = 12;
|
||||
const b = a;
|
||||
describe('toBe', () => {
|
||||
it("and has a positive case", () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
expect(a).toBe(b);
|
||||
expect(a).not.toBe(24);
|
||||
it("and can have a negative case", () => {
|
||||
expect(false).not.toBe(true);
|
||||
});
|
||||
|
||||
it("the 'toBe' matcher compares with ===", () => {
|
||||
const a = 12;
|
||||
const b = a;
|
||||
|
||||
expect(a).toBe(b);
|
||||
expect(a).not.toBe(24);
|
||||
});
|
||||
|
||||
it('should allow to accept any union type', () => {
|
||||
const value: number | string = null as any;
|
||||
|
||||
expect(value).toBe(12);
|
||||
});
|
||||
});
|
||||
|
||||
describe("The 'toEqual' matcher", () => {
|
||||
@@ -211,7 +217,9 @@ describe("toBePositiveInfinity", () => {
|
||||
});
|
||||
|
||||
describe("toHaveClass", () => {
|
||||
expect("").toHaveClass(Array);
|
||||
const element: HTMLElement = null!;
|
||||
expect(element).toHaveClass("some-class");
|
||||
expect(element).toHaveClass(Element); // $ExpectError
|
||||
});
|
||||
|
||||
describe("A spec", () => {
|
||||
@@ -398,22 +406,19 @@ describe("A spy, when configured to call through", () => {
|
||||
});
|
||||
|
||||
describe("A spy, when configured to fake a return value", () => {
|
||||
var foo: any, bar: any, fetchedBar: any;
|
||||
|
||||
beforeEach(() => {
|
||||
foo = {
|
||||
setBar: (value: any) => {
|
||||
bar = value;
|
||||
},
|
||||
getBar: () => {
|
||||
return bar;
|
||||
}
|
||||
};
|
||||
var bar: number;
|
||||
const foo = {
|
||||
setBar: (value: number) => {
|
||||
bar = value;
|
||||
},
|
||||
getBar: () => {
|
||||
return bar;
|
||||
}
|
||||
};
|
||||
|
||||
it("verifies return value type", () => {
|
||||
spyOn(foo, "getBar").and.returnValue(745);
|
||||
|
||||
foo.setBar(123);
|
||||
fetchedBar = foo.getBar();
|
||||
spyOn(foo, "getBar").and.returnValue("42"); // $ExpectError
|
||||
});
|
||||
|
||||
it("tracks that the spy was called", () => {
|
||||
@@ -425,6 +430,8 @@ describe("A spy, when configured to fake a return value", () => {
|
||||
});
|
||||
|
||||
it("when called returns the requested value", () => {
|
||||
const fetchedBar = foo.getBar();
|
||||
|
||||
expect(fetchedBar).toEqual(745);
|
||||
});
|
||||
});
|
||||
@@ -722,6 +729,29 @@ describe("A spy, when created manually", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("Spy for generic method", () => {
|
||||
interface Test {
|
||||
method<T>(): Array<Box<T>>;
|
||||
}
|
||||
|
||||
interface Box<T> {
|
||||
value: T;
|
||||
}
|
||||
|
||||
it("should allow to configure generic method", () => {
|
||||
const spy = jasmine.createSpyObj<Test>('test', ['method']);
|
||||
|
||||
spy.method.and.returnValue([{ value: 1 }, { value: 2 }]);
|
||||
});
|
||||
|
||||
it("should allow to configure generic method with non-named spy", () => {
|
||||
const spy = jasmine.createSpyObj<Test>(['method']);
|
||||
jasmine.createSpyObj<Test>(['methodUnknown']); // $ExpectError
|
||||
|
||||
spy.method.and.returnValue([{ value: 1 }, { value: 2 }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Multiple spies, when created manually", () => {
|
||||
class Tape {
|
||||
private rewindTo: number;
|
||||
@@ -772,6 +802,12 @@ describe("Multiple spies, when created manually", () => {
|
||||
|
||||
it("tracks all the arguments of its calls", () => {
|
||||
expect(tape.rewind).toHaveBeenCalledWith(0);
|
||||
expect(tape.rewind).toHaveBeenCalledWith('42'); // $ExpectError
|
||||
expect(tape.rewind).toHaveBeenCalledWith(jasmine.anything());
|
||||
expect(tape.rewind).toHaveBeenCalledWith(jasmine.falsy());
|
||||
expect(tape.rewind).not.toHaveBeenCalledWith(1);
|
||||
expect(tape.rewind).not.toHaveBeenCalledWith('42'); // $ExpectError
|
||||
expect(tape.rewind).not.toHaveBeenCalledWith(jasmine.truthy());
|
||||
});
|
||||
|
||||
it("read isPlaying property", () => {
|
||||
@@ -786,13 +822,19 @@ describe("multiple spies, when created with spyOnAllFunctions", () => {
|
||||
y: (a: number) => a,
|
||||
};
|
||||
|
||||
spyOnAllFunctions(obj);
|
||||
const spy = spyOnAllFunctions(obj);
|
||||
|
||||
spy.x.and.returnValue(42);
|
||||
spy.y.and.returnValue(24);
|
||||
spy.z; // $ExpectError
|
||||
|
||||
obj.x(0);
|
||||
obj.y(1);
|
||||
|
||||
expect(obj.x).toHaveBeenCalled();
|
||||
expect(obj.y).toHaveBeenCalledWith(1);
|
||||
expect(spy.y).toHaveBeenCalledWith(1);
|
||||
expect(spy.y).toHaveBeenCalledWith("one"); // $ExpectError
|
||||
});
|
||||
});
|
||||
|
||||
@@ -806,6 +848,9 @@ describe("jasmine.any", () => {
|
||||
it("matches any value", () => {
|
||||
expect({}).toEqual(jasmine.any(Object));
|
||||
expect(12).toEqual(jasmine.any(Number));
|
||||
expect(42).toEqual(jasmine.any(42)); // $ExpectError
|
||||
expect({}).toEqual(jasmine.any({})); // $ExpectError
|
||||
expect(() => null).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("matches any function", () => {
|
||||
@@ -819,7 +864,7 @@ describe("jasmine.any", () => {
|
||||
fn2: (param1: number) => param1,
|
||||
};
|
||||
|
||||
const expected: Test = {
|
||||
const expected = {
|
||||
fn1: jasmine.any(Function),
|
||||
fn2: jasmine.any(Function),
|
||||
};
|
||||
@@ -827,6 +872,29 @@ describe("jasmine.any", () => {
|
||||
expect(a).toEqual(expected);
|
||||
});
|
||||
|
||||
it("matches custom types", () => {
|
||||
class Test { }
|
||||
|
||||
const obj = new Test();
|
||||
|
||||
expect(obj).toEqual(jasmine.any(Test));
|
||||
});
|
||||
|
||||
it("matches base abstract class", () => {
|
||||
abstract class TestClassBase { }
|
||||
class TestClass extends TestClassBase { }
|
||||
const obj = new TestClass();
|
||||
|
||||
expect(obj).toEqual(jasmine.any(TestClass));
|
||||
expect(obj).toEqual(jasmine.any(TestClassBase));
|
||||
});
|
||||
|
||||
it("matches symbols", () => {
|
||||
const sym = Symbol('test symbol');
|
||||
|
||||
expect(sym).toEqual(jasmine.any(sym));
|
||||
});
|
||||
|
||||
describe("when used with a spy", () => {
|
||||
it("is useful for comparing arguments", () => {
|
||||
const foo = jasmine.createSpy('foo');
|
||||
@@ -836,6 +904,15 @@ describe("jasmine.any", () => {
|
||||
|
||||
expect(foo).toHaveBeenCalledWith(jasmine.any(Number), jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("is useful for comparing arguments for typed spy", () => {
|
||||
const foo = jasmine.createSpy<(num: number, fn: () => boolean) => void>('foo');
|
||||
foo(12, () => {
|
||||
return true;
|
||||
});
|
||||
|
||||
expect(foo).toHaveBeenCalledWith(jasmine.any(Number), jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -920,7 +997,7 @@ describe("jasmine.objectContaining", () => {
|
||||
|
||||
describe("when used with a spy", () => {
|
||||
it("is useful for comparing arguments", () => {
|
||||
const callback = jasmine.createSpy('callback');
|
||||
const callback = jasmine.createSpy<(arg: { bar: string }) => void>('callback');
|
||||
|
||||
callback({
|
||||
bar: "baz"
|
||||
@@ -951,9 +1028,18 @@ describe("jasmine.arrayContaining", () => {
|
||||
expect(foo).not.toBe(jasmine.arrayContaining([6]));
|
||||
});
|
||||
|
||||
it("matches read-only array", () => {
|
||||
const bar: ReadonlyArray<number> = [1, 2, 3, 4];
|
||||
|
||||
expect(bar).toEqual(jasmine.arrayContaining([3, 1]));
|
||||
expect(bar).not.toEqual(jasmine.arrayContaining([6]));
|
||||
|
||||
expect(bar).toBe(jasmine.arrayContaining([3, 1]));
|
||||
});
|
||||
|
||||
describe("when used with a spy", () => {
|
||||
it("is useful when comparing arguments", () => {
|
||||
const callback = jasmine.createSpy('callback');
|
||||
const callback = jasmine.createSpy<(numbers: number[]) => void>('callback');
|
||||
|
||||
callback([1, 2, 3, 4]);
|
||||
|
||||
@@ -980,7 +1066,7 @@ describe("jasmine.arrayWithExactContents", () => {
|
||||
|
||||
describe("when used with a spy", () => {
|
||||
it("is useful when comparing arguments", () => {
|
||||
const callback = jasmine.createSpy('callback');
|
||||
const callback = jasmine.createSpy<(arg: number[]) => void>('callback');
|
||||
|
||||
callback([1, 2, 3, 4]);
|
||||
|
||||
@@ -1274,16 +1360,6 @@ describe('better typed spys', () => {
|
||||
// $ExpectType (val: string) => Spy<() => string>
|
||||
spyObj.method.and.returnValue;
|
||||
});
|
||||
|
||||
it('has a way to opt out of inferred function types', () => {
|
||||
interface I {
|
||||
f(): string;
|
||||
f(x: any): number;
|
||||
}
|
||||
|
||||
const spyObject = jasmine.createSpyObj<jasmine.AnyMethods<I>>("spyObject", ["f"]);
|
||||
spyObject.f.and.returnValue("a string - working");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1439,7 +1515,34 @@ describe('Static Matcher Test', function() {
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("User scenarios", () => {
|
||||
describe("https://github.com/DefinitelyTyped/DefinitelyTyped/issues/34080", () => {
|
||||
interface Test {
|
||||
f(): string;
|
||||
f(x: any): number;
|
||||
}
|
||||
|
||||
it("has a way to opt out of inferred function types", () => {
|
||||
const spyObject: jasmine.NonTypedSpyObj<Test> = jasmine.createSpyObj<Test>("spyObject", ["f"]);
|
||||
spyObject.f.and.returnValue("a string - working");
|
||||
|
||||
const spy2 = jasmine.createSpyObj<Test>(['f']);
|
||||
spy2.f.and.returnValue("can return string" as any);
|
||||
});
|
||||
|
||||
it("should be possible to opt out for spyOn", () => {
|
||||
const obj: Test = null!;
|
||||
|
||||
const spy1: jasmine.Spy = spyOn(obj, "f");
|
||||
spy1.and.returnValue("can return string");
|
||||
|
||||
const spy2 = spyOn(obj, "f");
|
||||
spy2.and.returnValue("can return string" as any);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
(() => {
|
||||
// from boot.js
|
||||
|
||||
2
types/jasminewd2/index.d.ts
vendored
2
types/jasminewd2/index.d.ts
vendored
@@ -5,7 +5,7 @@
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.8
|
||||
|
||||
/// <reference types="jasmine" />
|
||||
/// <reference types="jasmine/v2" />
|
||||
|
||||
declare function it(expectation: string, assertion?: (done: DoneFn) => Promise<void>, timeout?: number): void;
|
||||
declare function fit(expectation: string, assertion?: (done: DoneFn) => Promise<void>, timeout?: number): void;
|
||||
|
||||
@@ -18,5 +18,5 @@ type Top = typeof top;
|
||||
declare function expectMatcherProxyTop(x: (arg: Top) => boolean): void;
|
||||
|
||||
expectMatcherProxyTop(when.captor());
|
||||
when.captor(jasmine.any(Number)); // $ExpectType MatcherProxy<Any>
|
||||
when.captor(jasmine.any(Number)); // $ExpectType MatcherProxy<AsymmetricMatcher<any>>
|
||||
when.noConflict(); // $ExpectType void
|
||||
|
||||
Reference in New Issue
Block a user