honkit-testerでHonkitプラグインのテストを書く

honkit-testerとは

vowstar/honkit-testerは、Honkitのフォーク元であるGitBookのプラグインをテストするためのツールです。
このテストツールでは、テスト対象のプラグインをアタッチして一時的なブック(ドキュメントページ)を生成し、プラグインが正しく動作するかを確認できます。
honkit-testerはコンテンツの生成までを担当するため、出力された内容を検証するには別途テストフレームワークが必要です。
honkit-testerのREADMEでは、Jasmineを使ったサンプルが挙げられています。

このページでは、Vitestを例に、honkit-testerでHonkitプラグインのテストを書く方法を説明します。

動作確認したバージョン

  • Node.js v22.14.0
  • honkit-tester: v2.0.0
  • Vitest: v3.1.4

honkit-testerの使い方

基本編

honkit-testerを使うためには、開発しているプラグインのプロジェクトにツールをインストールします。
後述しますが、honkit-testerの作り上、ツールをnpmでインストールする必要があります。

npm install --save-dev honkit-tester
npm install --save-dev vitest # 好きなテストフレームワーク

次に、テスト用のファイル(index.test.js)を作成します。 honkit-testerは、testerオブジェクトを提供しており、tester.builder()を使ってインスタンスを、create()メソッドでブックを生成します。
create()メソッドはPromiseを返すので、awaitで待機します。

index.test.js
import tester from "honkit-tester";
import { expect, it } from "vitest";

it("First page should be generated", async () => {
  const result = await tester
    .builder()
    .withContent("First page content") // README.mdの内容(「Introduction」というページタイトルになる)
    .create();
  const { content } = result.get("index.html");
  expect(content).toEqual(`<p>First page content</p>`); // index.htmlの内容を検証
});

npx vitestコマンドで、テストを実行します。

npx vitest

プラグインのテスト編

開発したHonkitプラグインをテストする場合、withLocalPlugin()メソッドを使ってプラグインがあるディレクトリを指定し、withBookJson()メソッドで生成したbook.jsonにプラグインを指定します。
例では、ページ一覧をexample.jsonに出力する「honkit-plugin-example-json」というプラグインがあると仮定して、テストを書いています。

index.test.js
import tester from "honkit-tester";
import { expect, it } from "vitest";
import path from "node:path";

const exampleJsonContent = `[
  {
    "title": "Introduction",
    "content": "First page content",
    "url": "https://example.com/index.html"
  },
  {
    "title": "Second",
    "content": "Second page content",
    "url": "https://example.com/second.html"
  },
  {
    "title": "Advanced Topics",
    "content": "Third page content",
    "url": "https://example.com/advanced-topics.html"
  }
]`;


it("All pages should be exported to example.json", async () => {
  const result = await tester
    .builder()
    .withContent("First page content") // README.mdの内容(「Introduction」というページタイトルになる)
    .withPage("Second", "Second page content") // second.mdの内容
    .withLocalPlugin(path.join(__dirname, "."))
    .withBookJson({ // book.jsonの内容
      title: "Test Book",
      plugins: ["example-json"],
      pluginsConfig: { // プラグインが必要とする設定
        "example-json": {
          url: "https://example.com",
        },
      },
    })
    .create();
  const { content } = result.get("example.json");
  expect(content).toEqual(exampleJsonContent); // example.jsonの内容を検証

注意点:honkit-testerはnpmでインストールする

honkit-testerは、npmでインストールする必要があります。 honkit-testerは、テストの実行時にHonkitがなければHonkitをインストールし、あれば「node_modules」以下のHonkitを使います。 この際、Honkitのブックを作るための一時的なディレクトリへ、Honkitをコピーしようとしますが、honkit-testerはnpmを前提に作られているため、コピー先のパスが存在せず、エラーが発生します。

pnpmで実行したときのエラーの例

$ npx vitest

> honkit-plugin-example-json@0.0.1 test /Users/chick-p/works/honkit-plugin-example-json
> vitest


DEV  v3.1.4 /Users/chick-p/works/honkit-plugin-example-json

stdout | index.test.js > All pages should be exported to example.json
warn:    TypeError: (0 , mkdirp_1.default) is not a function
    at /private/var/folders/x0/h4cktbwd4jb6g064vh5y9cs40000gn/T/honkit-tester202551-72120-1wv87bh.zwna/node_modules/honkit/lib/utils/fs.js:166:60
    at _fulfilled (/Users/chick-p/works/honkit-plugin-example-json/node_modules/.pnpm/q@1.5.1/node_modules/q/q.js:854:54)
    at /Users/chick-p/works/honkit-plugin-example-json/node_modules/.pnpm/q@1.5.1/node_modules/q/q.js:883:30
    at Promise.promise.promiseDispatch (/Users/chick-p/works/honkit-plugin-example-json/node_modules/.pnpm/q@1.5.1/node_modules/q/q.js:816:13)
    at /Users/chick-p/works/honkit-plugin-example-json/node_modules/.pnpm/q@1.5.1/node_modules/q/q.js:624:44
    at runSingle (/Users/chick-p/works/honkit-plugin-example-json/node_modules/.pnpm/q@1.5.1/node_modules/q/q.js:137:13)
    at flush (/Users/chick-p/works/honkit-plugin-example-json/node_modules/.pnpm/q@1.5.1/node_modules/q/q.js:125:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:85:11)