Skip to content

Commit d07fb0c

Browse files
committed
Refactor Flowtype definition
Minor syntactical changes aside, it's now equivalent to the TypeScript definition!
1 parent e04e7d6 commit d07fb0c

File tree

9 files changed

+304
-194
lines changed

9 files changed

+304
-194
lines changed

docs/recipes/flow.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Flow
2+
3+
AVA comes bundled with a Flow definition file. This allows developers to leverage Flow for writing tests.
4+
5+
This guide assumes you've already set up Flow for your project. Note that AVA's definition as been tested with version 0.64.
6+
7+
We recommend you use AVA's built-in Babel pipeline to strip Flow type annotations and declarations. AVA automatically applies your project's Babel configuration, so everything may just work without changes. Alternatively install [`@babel/plugin-transform-flow-strip-types`](https://www.npmjs.com/package/@babel/plugin-transform-flow-strip-types) and customize AVA's configuration in the `package.json` file as follows:
8+
9+
```json
10+
{
11+
"ava": {
12+
"babel": {
13+
"testOptions": {
14+
"plugins": ["@babel/plugin-transform-flow-strip-types"]
15+
}
16+
}
17+
}
18+
}
19+
```
20+
21+
See our [Babel documentation](babel.md) for more details.
22+
23+
## Writing tests
24+
25+
Create a `test.js` file.
26+
27+
```js
28+
// @flow
29+
import test from 'ava';
30+
31+
const fn = async () => Promise.resolve('foo');
32+
33+
test(async (t) => {
34+
t.is(await fn(), 'foo');
35+
});
36+
```
37+
38+
## Typing [`t.context`](https://github.com/avajs/ava#test-context)
39+
40+
By default, the type of `t.context` will be the empty object (`{}`). 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:
41+
42+
```js
43+
// @flow
44+
import anyTest from 'ava';
45+
import type {TestInterface} from 'ava';
46+
47+
const test: TestInterface<{foo: string}> = (anyTest: any);
48+
49+
test.beforeEach(t => {
50+
t.context = {foo: 'bar'};
51+
});
52+
53+
test.beforeEach(t => {
54+
t.context.foo = 123; // error: Type '123' is not assignable to type 'string'
55+
});
56+
57+
test.serial.cb.failing('very long chains are properly typed', t => {
58+
t.context.fooo = 'a value'; // error: Property 'fooo' does not exist on type ''
59+
});
60+
61+
test('an actual test', t => {
62+
t.deepEqual(t.context.foo.map(c => c), ['b', 'a', 'r']); // error: Property 'map' does not exist on type 'string'
63+
});
64+
```
65+
66+
Note that, despite the type cast above, when executing `t.context` is an empty object unless it's assigned.
67+
68+
## Using `t.throws()` and `t.notThrows()`
69+
70+
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:
71+
72+
```ts
73+
import test from 'ava';
74+
75+
test('just throws', async t => {
76+
const expected = new Error();
77+
const err = t.throws((): void => { throw expected; });
78+
t.is(err, expected);
79+
80+
const err2 = await t.throws((): Promise<*> => Promise.reject(expected));
81+
t.is(err2, expected);
82+
});
83+
```

0 commit comments

Comments
 (0)