Skip to content

Commit

Permalink
docs and updated types
Browse files Browse the repository at this point in the history
  • Loading branch information
lgandecki committed Jan 11, 2019
1 parent ebae1cc commit 83435fb
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 7 deletions.
9 changes: 7 additions & 2 deletions README.md
Expand Up @@ -265,7 +265,9 @@ double function and can be called in three modes:
name'`, which will appear in any error messages as well as the debug info
returned by passing the returned test double into
[td.explain()](/docs/9-debugging.md#tdexplainsometestdouble)

* **`td.func<Type>()`** - returns a test double function imitating the passed type.
Examples and more details can be found in [using with TypeScript](/docs/10-using-with-typescript.md)

#### `td.object()`

The `td.object()` function returns an object containing test double functions,
Expand All @@ -286,7 +288,10 @@ and supports three types of invocations:
The proxy will automatically intercept any call made to it and shunt in a test
double that can be used for stubbing or verification. More details can be
found in [our full docs](/docs/4-creating-test-doubles.md#objectobjectname)

* **`td.object<Interface>()`** - returns an object with methods exposed as test doubles
that are typed according to the passed interface. Examples and more details can be found in
[using with TypeScript](/docs/10-using-with-typescript.md)

#### `td.constructor()`

If your code depends on ES classes or functions intended to be called with
Expand Down
69 changes: 69 additions & 0 deletions docs/10-using-with-typescript.md
@@ -0,0 +1,69 @@
# Using with TypeScript

## Interfaces

You can create an object with methods exposed as testdoubles that are typed according to the passed interface.

Let's create a mocked object for a following interface:

```typescript
interface IUserRepository {
findByName(name: string): string;
}

const mockedRepository = td.object<IUserRepository>();
```

Now we can work with it as any other testdouble:

```typescript
td.when(mockedMyInterface.findByName("Alice")).thenReturn("Alice Alicy");

const value = mockedMyInterface.findByName("Alice");
expect(value).toEqual("Alice Alicy");
```

What's different is that we get the typesafety about our calls, so, typescript will alert as in following three situations:

```typescript
td.when(mockedMyInterface.findByName(3)).thenReturn("returnedString");
```

with
`TS2345: Argument of type '3' is not assignable to parameter of type 'string'.`

```typescript
td.when(mockedMyInterface.findByNaame("passedString")).thenReturn(
"returnedString"
);
```

`TS2551: Property 'findByNaame' does not exist on type 'IUserRepository'. Did you mean 'findByName'?`

## Function Types

Similarly to working with interfaces you can define a function type, and use that:

```typescript
type pickFirstFrom = (strings: string[]) => string;
const mockedPickFirst = td.func<pickFirstFrom>();
```

Again, typescript helps us mock properly:

```typescript
mockedPickFirst("myString");
```

`TS2345: Argument of type '"myString"' is not assignable to parameter of type 'string[]'.`

And also ensures that we don't wrongly used returned values:

```typescript
td.when(mockedPickFirst(["", ""])).thenReturn({ abc: () => {} });
const result = mockedPickFirst(["", ""]);
result.abc();
```

Gives us:
`TS2339: Property 'abc' does not exist on type 'string'.`
9 changes: 6 additions & 3 deletions docs/README.md
Expand Up @@ -61,10 +61,13 @@ section:
8. [Writing custom argument matchers](8-custom-matchers.md#custom-argument-matchers)
9. [Debugging with testdouble.js](9-debugging.md#debugging-with-testdoublejs)
1. [td.explain() API](9-debugging.md#tdexplainsometestdouble)
10. [Plugins](A-plugins.md#plugins)
10. [Using with TypeScript](10-using-with-typescript.md)
1. [Interfaces](10-using-with-typescript.md#interfaces)
2. [Function Types](10-using-with-typescript.md#function-types)
11. [Plugins](A-plugins.md#plugins)
1. [testdouble-chai](https://github.com/basecase/testdouble-chai)
2. [testdouble-jasmine](https://github.com/BrianGenisio/testdouble-jasmine)
11. [Frequently Asked Questions](B-frequently-asked-questions.md#frequently-asked-questions)
12. [Frequently Asked Questions](B-frequently-asked-questions.md#frequently-asked-questions)
1. [Why shouldn't I call both td.when and td.verify for a single interaction with a test double?](B-frequently-asked-questions.md#why-shouldnt-i-call-both-tdwhen-and-tdverify-for-a-single-interaction-with-a-test-double)
12. [Configuration](C-configuration.md#configuration)
13. [Configuration](C-configuration.md#configuration)
1. [td.config](C-configuration.md#tdconfig)
12 changes: 10 additions & 2 deletions index.d.ts
Expand Up @@ -123,8 +123,8 @@ export function constructor<T>(constructor: Constructor<T>): TestDoubleConstruct
declare function functionDouble(name?: string): TestDouble<Function>;

/**
* Create a fake function.
*
* Create a fake function. Typed when type is provided.
* @example td.func<MyType>();
* @template T
* @param {T} [name] Name of function to copy.
* @returns {TestDouble<T>}
Expand Down Expand Up @@ -167,6 +167,14 @@ export function object<T extends string>(props: T[]): DoubledObjectWithKey<T>;
* @returns {DoubledObject<T>}
*/
export function object<T>(object: string): DoubledObject<T>;

/**
* Create a fake empty object using a Proxy object that is cast as the generic of a passed interface.
*
* @export
* @template T
* @returns {DoubledObject<T>}
*/
export function object<T>(): DoubledObject<T>;

/**
Expand Down

0 comments on commit 83435fb

Please sign in to comment.