eater の reporter の API

# 問題

[yosuke-furukawa/eater][] (v1.7.0) の reporter の API が分からない。

# 解決策

Document はないため Source Code を読んで確認する。

ぼくが [bouzuya/eater-b-reporter][] をつくった際の知見を記録しておく。あくまで v1.7.0 のものであり、変更に追随する予定はないので、あしからず。

# Eater の標準 Reporter を読む

標準の Reporter は次のとおり。

https://github.com/yosuke-furukawa/eater/blob/v1.7.0/lib/reporter/Reporter.js

上記 `Reporter.js` に comment をつけたものが以下。

```js
'use strict';
const colo = require('colo');

class Reporter {
  // eater の起動時に呼び出される。
  // 対象となる file の数が渡される。
  reportFileNumber(num) {
    console.log(colo.cyan(`Test File Num : ${num}`));
  }

  // file ごとに読み込み前に呼び出される。
  // 対象となる file の path が渡される。
  reportTestName(name) {
    console.log(colo.grey(`Testing... : ${name}`));
  }

  // `test()` ごとに実行前に呼び出される……はずだが、現在は呼び出されていない。
  // See: https://twitter.com/yosuke_furukawa/status/739004911707258881
  reportSubTestName(name, parent) {
    console.log(colo.cyan.bold(`Test Name : ${name} in ${parent}`));
  }

  // file を `child_process.fork()` で読み込み後に呼び出される。
  // `child_process.fork()` の戻り値の `childProcess` が渡される。
  setChildProc(child) {
    child.stdout.pipe(process.stdout);
    child.stderr.pipe(process.stderr);
  }

  // `test()` の終了(失敗)時に呼び出される。
  // `test(name, ...)` の `name` と file の path が渡される。
  // ※個人的には error がほしいところだ。
  reportSubFailure(name, parent) {
    console.log(`${colo.red.bold('  ✗ failure: ')} ${name}`);
  }

  // `test()` の終了(成功)時に呼び出される。
  // `test(name, ...)` の `name` と file の path が渡される。
  reportSubSuccess(name, parent) {
    console.log(`${colo.green.bold('  ✓ success: ')} ${name}`);
  }

  // file の終了(失敗)時に呼び出される。
  // 対象となる file の path が渡される。
  // ※個人的には error がほしいところだ。
  reportFailure(name) {
    console.log(`${colo.red('✗ failure: ')} ${name}`);
  }

  // file の終了(失敗)時に呼び出される。
  // 対象となる file の path が渡される。
  reportSuccess(name) {
    console.log(`${colo.green('✓ success: ')} ${name}`);
  }

  // eater の終了時(成功/失敗)に呼び出される。
  // error の有無と { [file]: stderr } が渡される。
  reportFinish(hasAnyError, errors) {
  }
}

// ここでは `module.exports = Reporter;` だが、
// es modules で `export default Reporter;` しても良い。
module.exports = Reporter;
```

補足しておくと、次の変更はぼくが [bouzuya/eater-b-reporter][] をつくるにあたって Pull Request して merge されたもの (自慢) 。

- `reportSubFailure` と `reportSubSuccess` の `parent` [yosuke-furukawa/eater#27](https://github.com/yosuke-furukawa/eater/pull/27)
- `export default Reporter;` [yosuke-furukawa/eater#28](https://github.com/yosuke-furukawa/eater/pull/28)

素早い merge ありがたい。

# TypeScript 版 Reporter interface

ぼくが [bouzuya/eater-b-reporter][] を使う際に定義した `reporter.ts` が次のとおり。TypeScript user ならこちらのほうが読みやすいかもしれない。

https://github.com/bouzuya/eater-b-reporter/blob/19439a50264695766a1c8fdf7f1268284c606b37/src/reporter.ts

```ts
import { ChildProcess } from 'child_process';

export type TestName = string; // TestName.js
export type SubTestName = string; // test(SubTestName, (done) => /* ... */);
export type ErrorMessage = string; // stderr output

export interface Reporter {
  reportFileNumber(num: number): void;

  reportTestName(name: TestName): void;

  setChildProc(child: ChildProcess): void;

  reportSubFailure(name: SubTestName, parent: TestName): void;

  reportSubSuccess(name: SubTestName, parent: TestName): void;

  // deprecated.
  // see: https://twitter.com/yosuke_furukawa/status/739004911707258881
  reportSubTestName(name: SubTestName, parent: TestName): void;

  reportFailure(name: TestName): void;

  reportSuccess(name: TestName): void;

  reportFinish(
    hasAnyError: boolean,
    errors: { [testName: string]: ErrorMessage; }
  ): void;
}
```

# 参考

- [bouzuya/eater-b-reporter][]

[bouzuya/eater-b-reporter]: https://github.com/bouzuya/eater-b-reporter
[yosuke-furukawa/eater]: https://github.com/yosuke-furukawa/eater