import { stringify } from "yaml"; export interface TapWriter { version(): void; plan(n: number): void; fail(e: any): void; ok(msg: string): void; skip(msg: string): void; bailOut(msg: string): void; comment(msg: string): void; yaml(data: any): void; end(): void; } enum TapState { Init, VersionWritten, Ready, ReadyWithoutPlan, End } export abstract class AbstractTapWriter implements TapWriter { private _state = TapState.Init; private _version = 13; private _testIndex = 1; private _moveVersion() { switch (this._state) { case TapState.Init: this._state = TapState.VersionWritten; break; default: throw new Error("Invalid operation"); } } private _movePlan() { switch (this._state) { case TapState.Init: case TapState.VersionWritten: this._state = TapState.Ready; break; case TapState.ReadyWithoutPlan: this._state = TapState.End; break; default: throw new Error("Invalid operation"); } } private _moveTestResult() { switch (this._state) { case TapState.Init: case TapState.VersionWritten: this._state = TapState.ReadyWithoutPlan; break; case TapState.Ready: case TapState.ReadyWithoutPlan: break; default: throw new Error("Invalid operation"); } } private _moveEnd() { switch (this._state) { case TapState.End: throw new Error("Invalid operation"); default: this._state = TapState.End; } } private _moveDiag() { switch (this._state) { case TapState.Init: case TapState.VersionWritten: this._state = TapState.ReadyWithoutPlan; break; case TapState.Ready: case TapState.ReadyWithoutPlan: break; default: throw new Error("Invalid operation"); } } version() { this._moveVersion(); this._writeLine(`TAP version ${this._version}`); } plan(n: number) { this._movePlan(); this._writeLine(`1..${n}`); } fail(e: any) { this._moveTestResult(); this._writeText(`not ok ${this._testIndex} ${e}`); this._testIndex++; } ok(msg: string) { this._moveTestResult(); this._writeText(`ok ${this._testIndex} ${msg}`); this._testIndex++; } skip(msg: string) { this._moveTestResult(); this._writeText(`ok ${this._testIndex} # SKIPPED: ${msg}`); this._testIndex++; } bailOut(msg: string) { this._moveEnd(); this._writeText(`Bail out! ${msg}`); } comment(msg: string) { this._moveDiag(); this._writeText(`# ${msg}`); } yaml(data: any) { this._moveDiag(); this._writeLine(" ---"); stringify(data).split("\r\n?").forEach(line => this._writeLine(" " + line)); this._writeLine(" ..."); } end() { this._moveEnd(); } private _writeText(text: string) { text.split("\r\n?").forEach((line, i) => this._writeLine(i ? "# " + line : line)); } abstract _writeLine(text: string): void; }