Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matchers types #47

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@typestrong/ts-mockito",
"version": "2.6.7",
"version": "2.6.10",
"description": "Mocking library for TypeScript",
"main": "lib/ts-mockito.js",
"typings": "lib/ts-mockito",
Expand Down
4 changes: 2 additions & 2 deletions src/matcher/type/AnyFunctionMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as _ from "lodash";
import {Matcher} from "./Matcher";

export class AnyFunctionMatcher extends Matcher {
export class AnyFunctionMatcher<T extends Function> extends Matcher<T> {
constructor() {
super();
}

public match(value: any): boolean {
public match(value: T): boolean {
return _.isFunction(value);
}

Expand Down
4 changes: 2 additions & 2 deletions src/matcher/type/AnyNumberMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as _ from "lodash";
import {Matcher} from "./Matcher";

export class AnyNumberMatcher extends Matcher {
export class AnyNumberMatcher extends Matcher<number> {
constructor() {
super();
}

public match(value: any): boolean {
public match(value: number): boolean {
return _.isNumber(value);
}

Expand Down
4 changes: 2 additions & 2 deletions src/matcher/type/AnyOfClassMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {Matcher} from "./Matcher";

export class AnyOfClassMatcher<T> extends Matcher {
export class AnyOfClassMatcher<T> extends Matcher<T> {
constructor(private expectedClass: new (...args: any[]) => T) {
super();
if (expectedClass === null) {
throw new Error("The expected class cannot be null.");
}
}

public match(value: any): boolean {
public match(value: T): boolean {
return value instanceof this.expectedClass;
}

Expand Down
4 changes: 2 additions & 2 deletions src/matcher/type/AnyStringMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as _ from "lodash";
import {Matcher} from "./Matcher";

export class AnyStringMatcher extends Matcher {
export class AnyStringMatcher extends Matcher<string> {
constructor() {
super();
}

public match(value: any): boolean {
public match(value: string): boolean {
return _.isString(value);
}

Expand Down
4 changes: 2 additions & 2 deletions src/matcher/type/BetweenMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Matcher} from "./Matcher";

export class BetweenMatcher extends Matcher {
export class BetweenMatcher extends Matcher<number> {
constructor(private min: number, private max: number) {
super();

Expand All @@ -9,7 +9,7 @@ export class BetweenMatcher extends Matcher {
}
}

public match(value: any): boolean {
public match(value: number): boolean {
return value >= this.min && value <= this.max;
}

Expand Down
6 changes: 3 additions & 3 deletions src/matcher/type/DeepEqualMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as _ from "lodash";
import {Matcher} from "./Matcher";
import * as safeJsonStringify from "safe-json-stringify";
export class DeepEqualMatcher<T> extends Matcher {
export class DeepEqualMatcher<T> extends Matcher<T> {
constructor(private expectedValue: T) {
super();
}

public match(value: any): boolean {
public match(value: T): boolean {
return _.isEqualWith(this.expectedValue, value,
(expected: any, actual: any): boolean => {
(expected: any, actual: any) => {
if (expected instanceof Matcher) {
return expected.match(actual);
}
Expand Down
4 changes: 2 additions & 2 deletions src/matcher/type/Matcher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export class Matcher {
public match(value: any): boolean {
export class Matcher<T = unknown> {
public match(value: T): boolean {
return false;
}

Expand Down
8 changes: 4 additions & 4 deletions src/matcher/type/MatchingStringMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {Matcher} from "./Matcher";

export class MatchingStringMatcher extends Matcher {
constructor(private expectedValue: any) {
export class MatchingStringMatcher extends Matcher<string> {
constructor(private expectedValue: RegExp | string) {
super();
}

public match(value: any): boolean {
return value.match(this.expectedValue);
public match(value: string): boolean {
return Boolean(value.match(this.expectedValue));
}

public toString(): string {
Expand Down
4 changes: 2 additions & 2 deletions src/matcher/type/ObjectContainingMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as _ from "lodash";
import {Matcher} from "./Matcher";

export class ObjectContainingMatcher extends Matcher {
export class ObjectContainingMatcher<T extends Object> extends Matcher<T> {
constructor(private expectedValue: any) {
super();
}

public match(value: Object): boolean {
public match(value: T): boolean {
return _.isMatch(value, this.expectedValue);
}

Expand Down
4 changes: 2 additions & 2 deletions src/matcher/type/StrictEqualMatcher.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {Matcher} from "./Matcher";

export class StrictEqualMatcher extends Matcher {
export class StrictEqualMatcher<T> extends Matcher<T> {
constructor(private expectedValue: any) {
super();
}

public match(value: any): boolean {
public match(value: T): boolean {
return this.expectedValue === value;
}

Expand Down
87 changes: 44 additions & 43 deletions src/ts-mockito.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,43 +27,44 @@ import {MethodStubVerificator} from "./MethodStubVerificator";
import {MethodToStub} from "./MethodToStub";
import {Mocker} from "./Mock";
import {Spy} from "./Spy";
import {Mocked, MockedProp} from "./utils/types";

export function spy<T>(instanceToSpy: T): T {
export function spy<T>(instanceToSpy: T): Mocked<T> {
return new Spy(instanceToSpy).getMock();
}

export function mock<T>(clazz: (new(...args: any[]) => T) | (Function & { prototype: T }) ): T;
export function mock<T>(clazz?: any): T;
export function mock<T>(clazz?: any): T {
export function mock<T>(clazz: (new(...args: any[]) => T) | (Function & { prototype: T }) ): Mocked<T>;
export function mock<T>(clazz?: any): Mocked<T>;
export function mock<T>(clazz?: any): Mocked<T> {
return new Mocker(clazz).getMock();
}

export function verify<T>(method: T): MethodStubVerificator<T> {
export function verify<T>(method: MockedProp<T>): MethodStubVerificator<T> {
return new MethodStubVerificator(method as any);
}

export function when<T>(method: Promise<T>): MethodStubSetter<Promise<T>, T, Error>;
export function when<T>(method: T): MethodStubSetter<T>;
export function when<T>(method: Promise<MockedProp<T>>): MethodStubSetter<Promise<T>, T, Error>;
export function when<T>(method: MockedProp<T>): MethodStubSetter<T>;
export function when<T>(method: any): any {
return new MethodStubSetter(method);
}

export function instance<T>(mockedValue: T): T {
export function instance<T>(mockedValue: Mocked<T>): T {
const tsmockitoInstance = (mockedValue as any).__tsmockitoInstance as T;
return tsmockitoInstance;
}

export function capture<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(method: (a: T0, b: T1, c: T2, d: T3, e: T4, f: T5, g: T6, h: T7, i: T8, j: T9) => any): ArgCaptor10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>;
export function capture<T0, T1, T2, T3, T4, T5, T6, T7, T8>(method: (a: T0, b: T1, c: T2, d: T3, e: T4, f: T5, g: T6, h: T7, i: T8) => any): ArgCaptor9<T0, T1, T2, T3, T4, T5, T6, T7, T8>;
export function capture<T0, T1, T2, T3, T4, T5, T6, T7>(method: (a: T0, b: T1, c: T2, d: T3, e: T4, f: T5, g: T6, h: T7) => any): ArgCaptor8<T0, T1, T2, T3, T4, T5, T6, T7>;
export function capture<T0, T1, T2, T3, T4, T5, T6>(method: (a: T0, b: T1, c: T2, d: T3, e: T4, f: T5, g: T6) => any): ArgCaptor7<T0, T1, T2, T3, T4, T5, T6>;
export function capture<T0, T1, T2, T3, T4, T5>(method: (a: T0, b: T1, c: T2, d: T3, e: T4, f: T5) => any): ArgCaptor6<T0, T1, T2, T3, T4, T5>;
export function capture<T0, T1, T2, T3, T4>(method: (a: T0, b: T1, c: T2, d: T3, e: T4) => any): ArgCaptor5<T0, T1, T2, T3, T4>;
export function capture<T0, T1, T2, T3>(method: (a: T0, b: T1, c: T2, d: T3) => any): ArgCaptor4<T0, T1, T2, T3>;
export function capture<T0, T1, T2>(method: (a: T0, b: T1, c: T2) => any): ArgCaptor3<T0, T1, T2>;
export function capture<T0, T1>(method: (a: T0, b: T1) => any): ArgCaptor2<T0, T1>;
export function capture<T0>(method: (a: T0) => any): ArgCaptor1<T0>;
export function capture(method: (...args: any[]) => any): ArgCaptor {
export function capture<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(method: MockedProp<(a: T0, b: T1, c: T2, d: T3, e: T4, f: T5, g: T6, h: T7, i: T8, j: T9) => any>): ArgCaptor10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>;
export function capture<T0, T1, T2, T3, T4, T5, T6, T7, T8>(method: MockedProp<(a: T0, b: T1, c: T2, d: T3, e: T4, f: T5, g: T6, h: T7, i: T8) => any>): ArgCaptor9<T0, T1, T2, T3, T4, T5, T6, T7, T8>;
export function capture<T0, T1, T2, T3, T4, T5, T6, T7>(method: MockedProp<(a: T0, b: T1, c: T2, d: T3, e: T4, f: T5, g: T6, h: T7) => any>): ArgCaptor8<T0, T1, T2, T3, T4, T5, T6, T7>;
export function capture<T0, T1, T2, T3, T4, T5, T6>(method: MockedProp<(a: T0, b: T1, c: T2, d: T3, e: T4, f: T5, g: T6) => any>): ArgCaptor7<T0, T1, T2, T3, T4, T5, T6>;
export function capture<T0, T1, T2, T3, T4, T5>(method: MockedProp<(a: T0, b: T1, c: T2, d: T3, e: T4, f: T5) => any>): ArgCaptor6<T0, T1, T2, T3, T4, T5>;
export function capture<T0, T1, T2, T3, T4>(method: MockedProp<(a: T0, b: T1, c: T2, d: T3, e: T4) => any>): ArgCaptor5<T0, T1, T2, T3, T4>;
export function capture<T0, T1, T2, T3>(method: MockedProp<(a: T0, b: T1, c: T2, d: T3) => any>): ArgCaptor4<T0, T1, T2, T3>;
export function capture<T0, T1, T2>(method: MockedProp<(a: T0, b: T1, c: T2) => any>): ArgCaptor3<T0, T1, T2>;
export function capture<T0, T1>(method: MockedProp<(a: T0, b: T1) => any>): ArgCaptor2<T0, T1>;
export function capture<T0>(method: MockedProp<(a: T0) => any>): ArgCaptor1<T0>;
export function capture(method: MockedProp<(...args: any[]) => any>): ArgCaptor {
const methodStub: MethodToStub = method();
if (methodStub instanceof MethodToStub) {
const actions = methodStub.mocker.getActionsByName(methodStub.name);
Expand All @@ -73,56 +74,56 @@ export function capture(method: (...args: any[]) => any): ArgCaptor {
}
}

export function reset<T>(...mockedValues: T[]): void {
export function reset<T>(...mockedValues: Mocked<T>[]): void {
mockedValues.forEach(mockedValue => (mockedValue as any).__tsmockitoMocker.reset());
}

export function resetCalls<T>(...mockedValues: T[]): void {
export function resetCalls<T>(...mockedValues: Mocked<T>[]): void {
mockedValues.forEach(mockedValue => (mockedValue as any).__tsmockitoMocker.resetCalls());
}

export function anyOfClass<T>(expectedClass: new (...args: any[]) => T): any {
return new AnyOfClassMatcher(expectedClass) as any;
export function anyOfClass<T>(expectedClass: new (...args: any[]) => T) {
return new AnyOfClassMatcher<T>(expectedClass);
}

export function anyFunction(): any {
return new AnyFunctionMatcher() as any;
export function anyFunction() {
return new AnyFunctionMatcher();
}

export function anyNumber(): any {
return new AnyNumberMatcher() as any;
export function anyNumber() {
return new AnyNumberMatcher();
}

export function anyString(): any {
return new AnyStringMatcher() as any;
export function anyString() {
return new AnyStringMatcher();
}

export function anything(): any {
return new AnythingMatcher() as any;
export function anything() {
return new AnythingMatcher();
}

export function between(min: number, max: number): any {
return new BetweenMatcher(min, max) as any;
export function between(min: number, max: number) {
return new BetweenMatcher(min, max) ;
}

export function deepEqual<T>(expectedValue: T): T {
return new DeepEqualMatcher<T>(expectedValue) as any;
export function deepEqual<T>(expectedValue: T) {
return new DeepEqualMatcher<T>(expectedValue);
}

export function notNull(): any {
return new NotNullMatcher() as any;
export function notNull() {
return new NotNullMatcher();
}

export function strictEqual(expectedValue: any): any {
return new StrictEqualMatcher(expectedValue) as any;
export function strictEqual<T>(expectedValue: T) {
return new StrictEqualMatcher<T>(expectedValue);
}

export function match(expectedValue: RegExp | string): any {
return new MatchingStringMatcher(expectedValue) as any;
export function match(expectedValue: RegExp | string) {
return new MatchingStringMatcher(expectedValue);
}

export function objectContaining<T extends Object>(expectedValue: T): any {
return new ObjectContainingMatcher(expectedValue) as any;
export function objectContaining<T extends Object>(expectedValue: T) {
return new ObjectContainingMatcher<T>(expectedValue);
}

// Export default object with all members (ember-browserify doesn't support named exports).
Expand Down
15 changes: 14 additions & 1 deletion src/utils/types.ts
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
export type TODO = any;
import {Matcher} from "../matcher/type/Matcher";

type MockedArgs<T extends Array<unknown>> = {
[I in keyof T]: Matcher<T[I]> | T[I]
};

export type MockedProp<T> =
T extends (...args:infer Args) => infer R ?
(...args:MockedArgs<Args>) => R :
T;

export type Mocked<T> = {
[prop in keyof T]: MockedProp<T[prop]>
};
3 changes: 2 additions & 1 deletion test/capturing.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {capture, instance, mock} from "../src/ts-mockito";
import {Foo} from "./utils/Foo";
import {Mocked} from "../src/utils/types";

describe("capturing method arguments", () => {
let mockedFoo: Foo;
let mockedFoo: Mocked<Foo>;
let foo: Foo;

beforeEach(() => {
Expand Down
3 changes: 2 additions & 1 deletion test/mocking.getter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {instance, mock, when} from "../src/ts-mockito";
import {Bar} from "./utils/Bar";
import {Mocked} from "../src/utils/types";

describe("mocking", () => {
let mockedFoo: FooWithGetterAndSetter;
let mockedFoo: Mocked<FooWithGetterAndSetter>;
let foo: FooWithGetterAndSetter;

describe("mocking object with getters and setters", () => {
Expand Down
3 changes: 2 additions & 1 deletion test/recording.multiple.behaviors.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {instance, mock, when} from "../src/ts-mockito";
import {Foo} from "./utils/Foo";
import {Mocked} from "../src/utils/types";

describe("recording multiple behaviors", () => {
let mockedFoo: Foo;
let mockedFoo: Mocked<Foo>;
let foo: Foo;

beforeEach(() => {
Expand Down
3 changes: 2 additions & 1 deletion test/reseting.calls.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Mocker } from "../src/Mock";
import { anything, instance, mock, resetCalls, verify } from "../src/ts-mockito";
import {Foo} from "./utils/Foo";
import {Mocked} from "../src/utils/types";

describe("resetting mocked object", () => {
let mockedFoo: Foo;
let mockedFoo: Mocked<Foo>;
let foo: Foo;

beforeEach(() => {
Expand Down
3 changes: 2 additions & 1 deletion test/reseting.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Mocker } from "../src/Mock";
import {anything, instance, mock, reset, verify, when} from "../src/ts-mockito";
import {Foo} from "./utils/Foo";
import {Mocked} from "../src/utils/types";

describe("resetting mocked object", () => {
let mockedFoo: Foo;
let mockedFoo: Mocked<Foo>;
let foo: Foo;

beforeEach(() => {
Expand Down
Loading