Skip to content

Commit

Permalink
refactor!: simplify options API (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
mcous authored Dec 5, 2023
1 parent 9c88168 commit 9d1b256
Show file tree
Hide file tree
Showing 7 changed files with 696 additions and 315 deletions.
54 changes: 32 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export const calculateQuestion = async (answer: number): Promise<string> => {

## API

### `when(spy: TFunc): StubWrapper<TFunc>`
### `when(spy: TFunc, options?: WhenOptions): StubWrapper<TFunc>`

Configures a `vi.fn()` mock function to act as a vitest-when stub. Adds an implementation to the function that initially no-ops, and returns an API to configure behaviors for given arguments using [`.calledWith(...)`][called-with]

Expand All @@ -199,6 +199,16 @@ when(spy)
expect(spy()).toBe(undefined)
```

#### Options

```ts
import type { WhenOptions } from 'vitest-when'
```

| option | required | type | description |
| ------- | -------- | ------- | -------------------------------------------------- |
| `times` | no | integer | Only trigger configured behavior a number of times |

### `.calledWith(...args: TArgs): Stub<TArgs, TReturn>`

Create a stub that matches a given set of arguments which you can configure with different behaviors using methods like [`.thenReturn(...)`][then-return].
Expand Down Expand Up @@ -266,20 +276,20 @@ when(spy).calledWith('hello').thenReturn('world')
expect(spy('hello')).toEqual('world')
```

To only return a value once, use the `ONCE` option.
To only return a value once, use the `times` option.

```ts
import { ONCE, when } from 'vitest-when'
import { when } from 'vitest-when'

const spy = vi.fn()

when(spy).calledWith('hello').thenReturn('world', ONCE)
when(spy, { times: 1 }).calledWith('hello').thenReturn('world')

expect(spy('hello')).toEqual('world')
expect(spy('hello')).toEqual(undefined)
```

You may pass several values to `thenReturn` to return different values in succession. The last value will be latched, unless you pass the `ONCE` option.
You may pass several values to `thenReturn` to return different values in succession. If you do not specify `times`, the last value will be latched. Otherwise, each value will be returned the specified number of times.

```ts
const spy = vi.fn()
Expand All @@ -303,20 +313,20 @@ when(spy).calledWith('hello').thenResolve('world')
expect(await spy('hello')).toEqual('world')
```

To only resolve a value once, use the `ONCE` option.
To only resolve a value once, use the `times` option.

```ts
import { ONCE, when } from 'vitest-when'
import { when } from 'vitest-when'

const spy = vi.fn()

when(spy).calledWith('hello').thenResolve('world', ONCE)
when(spy, { times: 1 }).calledWith('hello').thenResolve('world')

expect(await spy('hello')).toEqual('world')
expect(spy('hello')).toEqual(undefined)
```

You may pass several values to `thenResolve` to resolve different values in succession. The last value will be latched, unless you pass the `ONCE` option.
You may pass several values to `thenResolve` to resolve different values in succession. If you do not specify `times`, the last value will be latched. Otherwise, each value will be resolved the specified number of times.

```ts
const spy = vi.fn()
Expand All @@ -340,20 +350,20 @@ when(spy).calledWith('hello').thenThrow(new Error('oh no'))
expect(() => spy('hello')).toThrow('oh no')
```

To only throw an error only once, use the `ONCE` option.
To only throw an error only once, use the `times` option.

```ts
import { ONCE, when } from 'vitest-when'
import { when } from 'vitest-when'

const spy = vi.fn()

when(spy).calledWith('hello').thenThrow(new Error('oh no'), ONCE)
when(spy, { times: 1 }).calledWith('hello').thenThrow(new Error('oh no'))

expect(() => spy('hello')).toThrow('oh no')
expect(spy('hello')).toEqual(undefined)
```

You may pass several values to `thenThrow` to throw different errors in succession. The last value will be latched, unless you pass the `ONCE` option.
You may pass several values to `thenThrow` to throw different errors in succession. If you do not specify `times`, the last value will be latched. Otherwise, each error will be thrown the specified number of times.

```ts
const spy = vi.fn()
Expand All @@ -379,20 +389,20 @@ when(spy).calledWith('hello').thenReject(new Error('oh no'))
await expect(spy('hello')).rejects.toThrow('oh no')
```

To only throw an error only once, use the `ONCE` option.
To only throw an error only once, use the `times` option.

```ts
import { ONCE, when } from 'vitest-when'
import { times, when } from 'vitest-when'

const spy = vi.fn()

when(spy).calledWith('hello').thenReject(new Error('oh no'), ONCE)
when(spy, { times: 1 }).calledWith('hello').thenReject(new Error('oh no'))

await expect(spy('hello')).rejects.toThrow('oh no')
expect(spy('hello')).toEqual(undefined)
```

You may pass several values to `thenReject` to throw different errors in succession. The last value will be latched, unless you pass the `ONCE` option.
You may pass several values to `thenReject` to throw different errors in succession. If you do not specify `times`, the last value will be latched. Otherwise, each rejection will be triggered the specified number of times.

```ts
const spy = vi.fn()
Expand Down Expand Up @@ -425,22 +435,22 @@ expect(spy('hello')).toEqual('world')
expect(called).toEqual(true)
```

To only run the callback once, use the `ONCE` option.
To only run the callback once, use the `times` option.

```ts
import { ONCE, when } from 'vitest-when'
import { times, when } from 'vitest-when'

const spy = vi.fn()

when(spy)
when(spy, { times: 1 })
.calledWith('hello')
.thenDo(() => 'world', ONCE)
.thenDo(() => 'world')

expect(spy('hello')).toEqual('world')
expect(spy('hello')).toEqual(undefined)
```

You may pass several callbacks to `thenDo` to trigger different side-effects in succession. The last callback will be latched, unless you pass the `ONCE` option.
You may pass several callbacks to `thenDo` to trigger different side-effects in succession. If you do not specify `times`, the last callback will be latched. Otherwise, each callback will be triggered the specified number of times.

```ts
const spy = vi.fn()
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,20 @@
"@mcous/eslint-config": "0.4.2",
"@mcous/prettier-config": "0.3.0",
"@mcous/typescript-config": "0.2.1",
"@typescript-eslint/eslint-plugin": "6.13.1",
"@typescript-eslint/parser": "6.13.1",
"@vitest/coverage-istanbul": "^1.0.0-beta.6",
"@vitest/expect": "^1.0.0-beta.6",
"@typescript-eslint/eslint-plugin": "6.13.2",
"@typescript-eslint/parser": "6.13.2",
"@vitest/coverage-istanbul": "^1.0.1",
"@vitest/expect": "^1.0.1",
"concurrently": "^8.2.2",
"eslint": "8.54.0",
"eslint-config-prettier": "9.0.0",
"eslint": "8.55.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-sonarjs": "0.23.0",
"eslint-plugin-unicorn": "49.0.0",
"prettier": "3.1.0",
"tsup": "^8.0.1",
"typescript": "5.3.2",
"vitest": "^1.0.0-beta.6"
"vitest": "^1.0.1"
},
"peerDependencies": {
"@vitest/expect": ">=0.31.0 <2.0.0",
Expand Down
Loading

0 comments on commit 9d1b256

Please sign in to comment.