Skip to content

Commit 255be17

Browse files
committed
Refactor Flowtype definition
Minor syntactical changes aside, it's now equivalent to the TypeScript definition!
1 parent 5734fbd commit 255be17

File tree

9 files changed

+307
-194
lines changed

9 files changed

+307
-194
lines changed

docs/recipes/flow.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Flow
2+
3+
Translations: [Español](https://github.com/avajs/ava-docs/blob/master/es_ES/docs/recipes/typescript.md), [Français](https://github.com/avajs/ava-docs/blob/master/fr_FR/docs/recipes/typescript.md), [Italiano](https://github.com/avajs/ava-docs/blob/master/it_IT/docs/recipes/typescript.md), [Русский](https://github.com/avajs/ava-docs/blob/master/ru_RU/docs/recipes/typescript.md), [简体中文](https://github.com/avajs/ava-docs/blob/master/zh_CN/docs/recipes/typescript.md)
4+
5+
AVA comes bundled with a Flow definition file. This allows developers to leverage Flow for writing tests.
6+
7+
This guide assumes you've already set up Flow for your project. Note that AVA's definition as been tested with version 0.64.
8+
9+
> TODO: Best practices for stripping the flow types when running the tests.
10+
11+
## Writing tests
12+
13+
Create a `test.js` file.
14+
15+
```js
16+
// @flow
17+
import test from 'ava';
18+
19+
const fn = async () => Promise.resolve('foo');
20+
21+
test(async (t) => {
22+
t.is(await fn(), 'foo');
23+
});
24+
```
25+
26+
## Typing [`t.context`](https://github.com/avajs/ava#test-context)
27+
28+
By default, the type of `t.context` will be [`any`](https://www.typescriptlang.org/docs/handbook/basic-types.html#any). AVA exposes an interface `TestInterface<Context>` which you can use to apply your own type to `t.context`. This can help you catch errors at compile-time:
29+
30+
```js
31+
// @flow
32+
import anyTest, {TestInterface} from 'ava';
33+
import type {TestInterface} from 'ava';
34+
35+
const test: TestInterface<{foo: string}> = anyTest;
36+
37+
test.beforeEach(t => {
38+
t.context = {foo: 'bar'};
39+
});
40+
41+
test.beforeEach(t => {
42+
t.context.foo = 123; // error: Type '123' is not assignable to type 'string'
43+
});
44+
45+
test.serial.cb.failing('very long chains are properly typed', t => {
46+
t.context.fooo = 'a value'; // error: Property 'fooo' does not exist on type ''
47+
});
48+
49+
test('an actual test', t => {
50+
t.deepEqual(t.context.foo.map(c => c), ['b', 'a', 'r']); // error: Property 'map' does not exist on type 'string'
51+
});
52+
```
53+
54+
Note that `t.context` is `null` unless it's assigned. You'll have to guard against this to avoid Flow errors:
55+
56+
```ts
57+
import anyTest, {TestInterface} from 'ava';
58+
59+
const test: TestInterface<{foo: string}> = anyTest;
60+
61+
test.beforeEach(t => {
62+
t.context = {foo: 'bar'};
63+
});
64+
65+
test('foo is bar', t => {
66+
t.context && t.is(t.context.foo, 'bar');
67+
});
68+
```
69+
70+
## Using `t.throws()` and `t.notThrows()`
71+
72+
The `t.throws()` and `t.noThrows()` assertions can be called with a function that returns an observable or a promise. You may have to explicitly type functions that have no return value:
73+
74+
```ts
75+
import test from 'ava';
76+
77+
test('just throws', t => {
78+
const expected = new Error();
79+
const err = t.throws((): void => { throw expected; });
80+
t.is(err, expected);
81+
});
82+
```

0 commit comments

Comments
 (0)