Core · プラグインを開発する

テストと検証

プラグインのチェック、アプリへの登録、動作するユーザーの操作の流れは、それぞれ別の結果です。変更が影響する境界を確認します。まずプラグイン、次にアプリでの動作、公開する場合はパッケージの内容です。

エージェントを使う場合

プレーンテキスト
このプラグインに動作のテストを追加し、成功、不正な入力、アクセスの境界を扱ってください。
本番の実装と実際のプラグインの宣言を使ってください。
コンポーネント、API、アプリのチェックを区別し、プラグインのチェックとアプリのビルドを実行して、
どのユーザーの操作の流れを確認し、どれを確認していないかを報告してください。

テストの置き場所

ジェネレーターは、選んだ機能に合わせてテストと Vitest の設定を用意します。1 つのケースを直すためにすべてのテストをブラウザーの環境に移すのではなく、Node と jsdom の境界を保ってください。

ディレクトリ環境とツール対象
tests/server/Node、@nocobase/app-testing/serverAPI、サービス、Server への組み込み
tests/database/Node、同じ Server のテストの入口マイグレーション、メタデータ、実際のデータベースの操作
tests/client/jsdom、@nocobase/app-testing/clientコンポーネント、翻訳、操作、リクエストの取り決め
tests/cli/Node、@nocobase/app-testing/cli引数、出力、エラー、コマンドの動作
アプリのブラウザーのテストアプリの既存のブラウザーの設定サインイン、ナビゲーション、再読み込み、実際の API とのやり取り

@nocobase/app-testing は devDependencies に宣言します。生成された依存関係とインストールされた公開のエクスポートを確認してください。/database や /playwright の入口はありません。

本番の実装を動かす

ルートと HTTP の API は、実際の提供内容の createRouter() を呼び出して、成功、不正な入力、API のドキュメントを確認します。データベースのリソースとマイグレーション は、実際の Migrator で適用、ロールバック、再適用を行います。コマンドラインの拡張 は、bindAppCommand() と runAppCommand() でコマンドの出力を確認します。

テストの中でルート、サービス、モデルを実装し直し、その複製をテストすることは避けてください。

コンテナだけを使う Provider は、完全な狭いインターフェース { container: ServiceContainer } を受け取れます。不完全なオブジェクトをアプリ全体にキャストせずに、実際のコンテナのフィクスチャーを使えます。認証、データベース、ライフサイクルには、アプリのフィクスチャーを使い、本番のプラグインを登録します。

Client のテストの境界

renderWithApp() は実際の Client のプラグインを登録し、サービス、API のクライアント、ルーティング、多言語化を提供します。MemoryRouter を追加しないでください。ルートのツリーを動かす場合も、実際の宣言からコンポーネントをレンダリングします。ページ、ルート、メニュー を参照してください。

ネットワークの境界でレスポンスを差し替えるには answerApi() を使います。メソッドと API の相対パスの両方を照合してください。すべてのリクエストに成功を返すと、パスの綴りの誤りや想定外の呼び出しが隠れます。

次は既存のページのテストのパターンです。Page とプラグインのファクトリーは実際のモジュールに置き換えてください。

TSX
const calls: { method: string; path: string }[] = [];
await renderWithApp(<Page />, {
  plugins: [plugin()],
  locale: 'zh-CN',
  fetch: answerApi((call) => {
    calls.push({ method: call.method, path: call.path });
    if (call.method === 'GET' && call.path === 'announcements') {
      return { data: [], meta: { total: 0 } };
    }
    return new Response(null, { status: 404 });
  }),
});
expect(await screen.findByText('暂无公告。')).toBeInTheDocument();
expect(calls).toEqual([{ method: 'GET', path: 'announcements' }]);

answerApi() は、ハンドラーの例外を HTTP 500 のレスポンスに変えます。ページのエラーの UI がアサーションの失敗を飲み込まないよう、アサーションはハンドラーの外に置きます。非同期の UI は findBy... や waitFor() で待ちますが、操作は再試行される waitFor() のコールバックの外に置きます。読み込み中の状態をテストするには、固定の待ち時間ではなく、レスポンスの完了を制御します。

アクセスとクリーンアップ

匿名の呼び出し元、サインインしているが拒否される呼び出し元、許可された呼び出し元を別々にテストします。テナントやレコードの範囲がある機能では、ユーザーをまたぐケースとレコードをまたぐケースも必要です。Client のボタンを隠しても、Server での書き込みは保護されません。

フィクスチャーは、自分が所有するデータベース、一時ディレクトリ、購読、アプリのインスタンスをクリーンアップします。直接作成したリソースには finally を使います。テストを通常の開発用のデータベースに向けたり、テストを通すためにエラーのチェックを無効にしたりしないでください。

関係する範囲を実行する

notice-api の場合、アプリのルートで次を実行します。

Bash
pnpm --filter @nocobase/app-plugin-notice-api exec vitest run tests/server/routes.test.ts
pnpm --filter @nocobase/app-plugin-notice-api check
pnpm build

まず対象を絞ったテストを、次にプラグインの check と、影響を受けるアプリのチェックを実行します。マイグレーションを変更した場合、データベースの統合テストは順番に実行します。文言だけの変更では、リポジトリ全体のテストは必要ありません。

作成時に --no-install を使った場合は、先にインストールします。--passWithNoTests で成功しても、テストできたことにはなりません。実際に実行されたファイルとケースを確認してください。

引き渡しの前に

変更追加の確認
Client のページサインインしたうえでのアクセス、URL の直接入力、再読み込み、ブラウザーの履歴
Server の APIアプリのマウントの接頭辞、認証、認可、エラー、API のドキュメント
マイグレーション新規のインストール、古いデータからのアップグレード、コンパイル後のチェックサム
CLI登録されたアプリのコマンドとデプロイ環境のコマンド
公開のエクスポートや公開公開の入口からの利用。tarball に含まれる dist、リソース、スキル

実行したコマンドと結果を正確に報告し、残っている境界も含めます。たとえば、「コンポーネントとルーターのテストは成功し、アプリもビルドできたが、サインインしたブラウザーでの操作の流れはまだ実行していない」のように書きます。plugin inspect は静的な登録だけを確認するもので、動作の検証の代わりにはなりません。

NocoBase ドキュメントアシスタント

NocoBase について何を知りたいですか?

質問は個別に回答され、過去の質問や回答は参照されません。必要な背景をすべて含めてください。