Skip to content

Commit

Permalink
add new extension strategy example and write documentation for regist…
Browse files Browse the repository at this point in the history
…erMock
  • Loading branch information
Pmyl committed Dec 28, 2019
1 parent 28786c0 commit 76a54e1
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 15 deletions.
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,57 @@ mockList[0].id // id0
mockList[1].id // id1
```

#### Register mock
registerMock will register your custom mock that will be used in favour of creating a new one

./person.ts
```ts person.ts
export interface Person {
id: string;
}
```

./person-fake.ts
```ts person-fake.ts
import { Person } from './person';

export class PersonFake extends Person {
public id: string;
public name: string;

constructor() {
this.id = "Basic Id";
this.name = "Basic name";
}
}
```

./context.ts
```ts context.ts
import { registerMock } from 'ts-auto-mock';
import { Person } from './person';
import { PersonFake } from './person-fake';

registerMock<Person>(() => new PersonFake());
```

./my-test.ts
```ts my-test.ts
interface Wrapper {
person: Person;
}

const mock: Wrapper = createMock<Wrapper>();
mock.person // PersonFake
mock.person.id // "Basic Id"
mock.person.name // "Basic name"
```

When using a fake we recommend using the [extension strategy](docs/EXTENSION.md) to retrieve the fake object.
An example of usage for Promise->FakePromise can be found in [the test folder](test/registerMock/extensionStrategy/extensionStrategy.test.ts).

**Note:** You can use it only in the common file (webpack context.ts, mocha tsnode.js, etc), using `registerMock` in other files will have unexpected results.

## Type Examples
The library try to convert the type given to createMock so you dont need to create concrete mock manually.
[Open this link to see more examples](docs/DETAILS.md)
Expand Down
4 changes: 2 additions & 2 deletions src/extension/extensionHandler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Extension } from './extension';
import { isFunction } from './method/function';

type AsMockedPropertyHandler<TMockedPropertyHandler, TMock, TPropName extends keyof TMock> = (mock: TMock, propName: TPropName, prop: TMock[TPropName]) => TMockedPropertyHandler;
type AsMockedPropertyHandler<TMockedPropertyHandler, TMock, TPropName extends keyof TMock> = (prop: TMock[TPropName], mock: TMock, propName: TPropName) => TMockedPropertyHandler;

export class ExtensionHandler<TMock> {
private readonly _mock: TMock;
Expand All @@ -25,6 +25,6 @@ export class ExtensionHandler<TMock> {
return extensionOrPropertyName(this._mock);
}

return maybePropertyHandler(this._mock, extensionOrPropertyName, this._mock[extensionOrPropertyName]);
return maybePropertyHandler(this._mock[extensionOrPropertyName], this._mock, extensionOrPropertyName);
}
}
4 changes: 1 addition & 3 deletions src/register-mock.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
export declare function registerMock<T extends object, TCustomMock extends T>(
factory: (mock: any, propName: string | number | symbol, prop: T) => TCustomMock, // tslint:disable-line no-any
): void;
export declare function registerMock<T extends object>(factory: () => T): void;
2 changes: 1 addition & 1 deletion test/registerMock/context.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { registerMock } from 'ts-auto-mock';
import { FakePromise } from './fakePromise';

registerMock<Promise<unknown>, FakePromise<unknown>>(() => new FakePromise<unknown>());
registerMock<Promise<unknown>>(() => new FakePromise<unknown>());

const frameworkContext: __WebpackModuleApi.RequireContext = require.context('./', true, /\.test\.ts$/);
frameworkContext.keys().map(frameworkContext);
25 changes: 25 additions & 0 deletions test/registerMock/extensionStrategy/extensionStrategy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createMock } from 'ts-auto-mock';
import { On } from 'ts-auto-mock/extension';
import { FakePromise } from '../fakePromise';

function asFakePromise<T, TProp extends Promise<T>, TFake extends FakePromise<T>>(prop: Promise<T>): FakePromise<T> {
return prop as unknown as FakePromise<T>;
}

describe('extension strategy for fake promise', () => {
it('should retrieve the fake promise correctly', (done: Function) => {
interface WithPromise {
promise: Promise<string>;
a: number;
}

const mock: WithPromise = createMock<WithPromise>();

On(mock).get('promise', asFakePromise).resolve('custom resolution value');

mock.promise.then((value: string) => {
expect(value).toBe('custom resolution value');
done();
});
});
});
2 changes: 1 addition & 1 deletion test/registerMock/interface/interface.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('registerMock for interface', () => {
prop: APropInterface;
}

registerMock<APropInterface, APropInterface>(() => ({ internalProp: 'whaaat' }));
registerMock<APropInterface>(() => ({ internalProp: 'whaaat' }));
const mock: AParentInterface = createMock<AParentInterface>();

expect(mock.prop.internalProp).toBe('whaaat');
Expand Down
4 changes: 2 additions & 2 deletions test/registerMock/typeAlias/typeAlias.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('registerMock for type alias', () => {
prop: APropType;
}

registerMock<APropType, APropType>(() => ({ internalProp: 'whaaat' }));
registerMock<APropType>(() => ({ internalProp: 'whaaat' }));
const mock: AParentInterface = createMock<AParentInterface>();

expect(mock.prop.internalProp).toBe('whaaat');
Expand All @@ -23,7 +23,7 @@ describe('registerMock for type alias', () => {
prop: APropType;
}

registerMock<APropType, APropType>(() => ({ internalProp: 'whaaat', else: 53 }));
registerMock<APropType>(() => ({ internalProp: 'whaaat', else: 53 }));
const mock: AParentInterface = createMock<AParentInterface>();

expect(mock.prop.internalProp).toBe('whaaat');
Expand Down
2 changes: 1 addition & 1 deletion test/registerMock/typeLiteral/typeLiteral.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createMock, createMockList, registerMock } from 'ts-auto-mock';

describe('registerMock type literal', () => {
it('should never work', () => {
registerMock<{prop: string;},{prop: string;}>(() => ({prop: 'mocked one'}));
registerMock<{prop: string;}>(() => ({prop: 'mocked one'}));

const mock1: {prop: string} = createMock<{prop: string;}>();
const mock2: {prop: string}[] = createMockList<{prop: string;}>(1);
Expand Down
6 changes: 3 additions & 3 deletions test/registerMock/typeQuery/typeQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('registerMock of typeQuery', () => {
B = "B"
}

registerMock<typeof MyEnum, typeof MyEnum & { C: string; }>(() => ({A: 0, B: MyEnum.B, C: "Something"}));
registerMock<typeof MyEnum>(() => ({A: 0, B: MyEnum.B, C: "Something"}));

const mock1: typeof MyEnum = createMock<typeof MyEnum>();
const mock2: { sub: typeof MyEnum; } = createMock<{ sub: typeof MyEnum; }>();
Expand Down Expand Up @@ -37,7 +37,7 @@ describe('registerMock of typeQuery', () => {
prop: string;
}

registerMock<typeof MyClass, typeof MyClass & { C: string; }>(() => (Object.assign(class Some { prop: string; }, { C: 'something' })));
registerMock<typeof MyClass>(() => (Object.assign(class Some { prop: string; }, { C: 'something' })));

const mock1: typeof MyClass = createMock<typeof MyClass>();
const mock2: { sub: typeof MyClass; } = createMock<{ sub: typeof MyClass; }>();
Expand All @@ -63,7 +63,7 @@ describe('registerMock of typeQuery', () => {
it('should not work for variable', () => {
const a: Interface2 = { b: 23 };

registerMock<typeof a, typeof a & { C: string; }>(() => ({ b: 45, C: 'something' }));
registerMock<typeof a>(() => ({ b: 45, C: 'something' }));

const mock1: typeof a = createMock<typeof a>();
const mock2: { sub: typeof a; } = createMock<{ sub: typeof a; }>();
Expand Down
3 changes: 1 addition & 2 deletions test/transformer/register-mock.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createMock, registerMock } from 'ts-auto-mock';
import { On } from 'ts-auto-mock/extension';

describe('register-mock', () => {
it('should override standard behaviour of mock creation', () => {
Expand All @@ -11,7 +10,7 @@ describe('register-mock', () => {
prop: APropInterface;
}

registerMock<APropInterface, APropInterface>(() => ({ internalProp: 'whaaat' }));
registerMock<APropInterface>(() => ({ internalProp: 'whaaat' }));
const mock: AParentInterface = createMock<AParentInterface>();

expect(mock.prop.internalProp).toBe('whaaat');
Expand Down

0 comments on commit 76a54e1

Please sign in to comment.