mcpField
E
e2e-testing

e2e-testing

github.com/langflow-aiテスト・品質156.1k39 回インストール6 日前に更新
リポジトリ

e2e-testing について

Langflowのフロントエンド向けに、PlaywrightのE2Eテスト作成と保守を案内するスキルです。機能テスト、失敗の調査、カバレッジ確認に取り組む開発者向けに、フィクスチャ、セレクター、ヘルパー、タグの規約を説明します。

主な機能

  1. 01Playwright E2Eテストの作成と絞り込み
  2. 02フィクスチャによるAPIとフローのエラー検出
  3. 03優先順位に沿った安定セレクターの選択
  4. 04セットアップ・画面・フロー用ヘルパーの再利用
  5. 05リリースと領域タグの付与

活用シーン

  1. 01新機能のE2Eテスト作成
  2. 02失敗したPlaywrightテストの調査
  3. 03テストタグとカバレッジの確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/langflow-ai/langflow --skill e2e-testing

インストール後、Claude Code で/e2e-testingを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
fixtures.md
helpers.md
selectors.md

詳細

Langflow E2E テスト(Playwright)

適用するケース

  • 機能やフローの E2E テストの作成をユーザーが依頼した場合
  • 失敗する E2E テストの 修正をユーザーが依頼した場合
  • E2E テストのカバレッジの レビューをユーザーが依頼した場合
  • ユーザーがコンポーネントの data-testid 属性を変更した場合(既存のテストが壊れる可能性があります)
  • ユーザーが src/frontend/tests/utils/ のテストユーティリティを変更した場合

次の場合は適用しないでください:

  • ユーザーが単体テストについて尋ねている場合(Jest には frontend-testing スキルを使用してください)
  • ユーザーがバックエンドテストについて尋ねている場合(pytest には backend-code-review スキルを使用してください)

技術スタック

ツールバージョン目的
Playwright1.59.1E2E テストランナー+ブラウザー自動化
Chromium(同梱)デフォルトのブラウザー(Firefox/Safari は無効)
カスタムフィクスチャtests/fixtures.tsAPI エラーとフロー実行の失敗を自動検出

主なコマンド

# Run all E2E tests
npx playwright test

# Run tests filtered by tag
npx playwright test --grep "@release"
npx playwright test --grep "@workspace"
npx playwright test --grep "@starter-projects"

# Run a specific test file
npx playwright test tests/core/features/run-flow.spec.ts

# Debug mode (headed browser + step through)
npx playwright test --debug

# Show HTML report after run
npx playwright show-report

# Update snapshots (if used)
npx playwright test --update-snapshots

設定

ファイル:src/frontend/playwright.config.ts

設定値理由
fullyParalleltrueテストを並列実行して高速化します
timeout5 分フローのビルドには時間がかかる場合があるため、誤ったタイムアウトを防ぎます
retries3(ローカル)、2(CI)不安定なネットワーク/レンダリングの問題を再試行で捕捉します
workers2速度とリソース使用量のバランスを取ります
actionTimeout20s個々のアクション(クリック、入力など)のタイムアウト
traceon-first-retryデバッグ用に失敗時のトレースを記録します
baseURLhttp://localhost:3000Vite 開発サーバー

WebServer:Playwright はバックエンド(7860 で uvicorn)とフロントエンド(3000 で npm start)を自動起動します。

ディレクトリ構成

src/frontend/tests/
├── fixtures.ts                     # Custom test fixture with error detection
├── globalTeardown.ts               # Cleanup (removes temp DB after tests)
├── core/
│   ├── features/                   # Main feature tests (run-flow, playground, etc.)
│   ├── integrations/               # Starter project / template tests
│   ├── regression/                 # Bug regression tests
│   └── unit/                       # Component-level Playwright tests
├── extended/
│   ├── features/                   # Extended features (MCP, auto-save, etc.)
│   ├── integrations/               # Extended integrations
│   └── regression/                 # Extended regressions
└── utils/                          # 37+ shared helper functions

ファイル名

  • .spec.ts サフィックスを付けた kebab-case:run-flow.spec.ts、playground.spec.ts、flow-lock.spec.ts
  • テンプレートのテストではスペースを使用できます:Document QA.spec.ts、Social Media Agent.spec.ts
  • 並列化用のシャーディングされたテスト:chatInputOutputUser-shard-0.spec.ts

注:E2E テストでは .spec.ts(Playwright の規約)を使用します。単体テストでは .test.tsx(Jest の規約)を使用します。混在させないでください。

テストの構成

基本的なテスト
import { expect, test } from "../../fixtures";
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";

test(
  "user should be able to run a flow successfully",
  { tag: ["@release", "@workspace"] },
  async ({ page }) => {
    await awaitBootstrapTest(page);

    // Arrange: Create a flow
    await page.getByTestId("blank-flow").click();

    // Act: Add components and run
    await page.getByTestId("sidebar-search-input").fill("Chat Output");
    // ... setup ...

    // Assert: Verify result
    await expect(page.getByTestId("build-status-success")).toBeVisible({ timeout: 30000 });
  },
);
test.describe を使用する場合
test.describe("Flow Lock Feature", () => {
  test(
    "should lock and unlock a flow",
    { tag: ["@release", "@api"] },
    async ({ page }) => {
      // ...
    },
  );

  test(
    "should prevent editing when locked",
    { tag: ["@release"] },
    async ({ page }) => {
      // ...
    },
  );
});
シリアルモードを使用する場合(順序に依存するテスト)
test.describe.configure({ mode: "serial" });

test("step 1: create flow", async ({ page }) => { /* ... */ });
test("step 2: edit flow", async ({ page }) => { /* ... */ });
test("step 3: delete flow", async ({ page }) => { /* ... */ });
イベント配信モードを使用する場合(ストリーミング/ポーリング/直接)
import { withEventDeliveryModes } from "../../utils/withEventDeliveryModes";

withEventDeliveryModes(
  "Document Q&A should work",
  { tag: ["@release", "@starter-projects"] },
  async ({ page }) => {
    // This test runs 3 times: streaming, polling, direct
    // Each mode is configured automatically via route interception
  },
);

タグシステム

すべてのテストに @release タグを付ける必要があります。リリース実行ではこのタグを検索するため、タグがない、または誤ったタグが付いた spec は、リリースのカバレッジから気付かれないまま除外されます。@release に加えて、以下のドメインタグを付けてください(テストには複数のタグを付けられます)。使用できるタグはこの6つのみです。新しいタグを作らないでください。

タグ目的使用するケース
@releaseリリース実行の対象(すべての spec で必須)すべてのテスト
@workspaceワークスペース/フローの管理フローの作成、編集、削除
@apiAPI に依存する機能バックエンドのエンドポイントを呼び出すテスト
@databaseデータベース操作永続化を伴うテスト
@componentsコンポーネントレベルのテスト個々のコンポーネントの動作
@starter-projectsテンプレート/スタータープロジェクトのテスト事前構築済みフローのテンプレート
// Right: tag your test
test("my feature test", { tag: ["@release", "@workspace"] }, async ({ page }) => { ... });

// Wrong: no tags — test can't be filtered
test("my feature test", async ({ page }) => { ... });

カスタムフィクスチャ:エラー検出

@playwright/test ではなく、必ず ../../fixtures から test と expect をインポートしてください。

// Right
import { expect, test } from "../../fixtures";

// Wrong — bypasses error detection
import { expect, test } from "@playwright/test";

理由:カスタムフィクスチャはすべての /api/ レスポンスを自動で監視し、次の場合にテストを失敗させます。

  • HTTP 400、404、422、または500エラーが発生した場合
  • フローの実行結果として、イベントストリームに error: true が返された場合
  • ストリーミングされたレスポンスに Python の例外が含まれる場合

想定されるエラー(エラー処理のテストなど)を許可するには、次のようにします。

test("should show error on invalid input", { tag: ["@release"] }, async ({ page }) => {
  page.allowFlowErrors();  // Allow flow errors for this test
  // ... test that expects errors ...
});

セレクター戦略

優先順位(上から順に推奨)
  1. getByTestId — 最も安定しており、Langflow では95%のケースで使用します
  2. getByRole — ボタン、見出し、フォーム要素に使用します
  3. getByText — 表示されるテキストコンテンツに使用します
  4. waitForSelector — CSS セレクターや動的な要素に使用します
  5. locator — 複雑なセレクター(CSS、XPath)に使用します
共通の data-testid パターン

キャンバスとナビゲーション:

  • blank-flow — 新規ブランクフローボタン
  • sidebar-search-input — コンポーネント検索
  • canvas_controls_dropdown — キャンバス操作メニュー
  • fit_view、zoom_out、zoom_in — キャンバス操作
  • react-flow-id — ReactFlow キャンバスコンテナ

コンポーネントのフィールド:

  • popover-anchor-input-{fieldname} — コンポーネントパラメータの入力フィールド
  • input-chat-playground — プレイグラウンドのチャット入力
  • div-chat-message — プレイグラウンドのチャットメッセージ

アクション:

  • add-component-button-{component} — キャンバスにコンポーネントを追加
  • button-send — チャットメッセージを送信
  • button_run_{component} — 特定のコンポーネントを実行
  • publish-button、save-flow-button — フローの操作
  • edit-fields-button — インスペクションパネルのフィールドエディタを切り替え

モーダルとパネル:

  • modal-title — モーダルの見出し
  • icon-Globe — グローバル変数
  • icon-Lock — フローロックの切り替え
  • session-selector — プレイグラウンドのセッション切り替え
重要: グローバル変数とバッジ

コンポーネントのフィールドでグローバル変数が選択されている場合(load_from_db: true + value: "OPENAI_API_KEY")、フィールドは <input> 要素の代わりにバッジをレンダリングします。つまり、getByTestId("popover-anchor-input-api_key") はその要素を見つけられません — DOM に存在しないためです。

グローバル変数が事前に選択されているテンプレート: Market Research、Price Deal Finder、Research Agent。 選択されていないテンプレート(input がレンダリングされる): Instagram Copywriter。

コアヘルパー関数

src/frontend/tests/utils/ にあります:

関数何をするかいつ使うか
awaitBootstrapTest(page)アプリが完全に読み込まれるまで待機しますすべてのテストの開始時
initialGPTsetup(page)完全なセットアップ: adjustView → updateComponents → selectModel → addKey → adjustView → unselectNodesOpenAI の設定が必要なテスト
adjustScreenView(page, opts?)ビューをフィット + ズームアウトしますキャンバスにコンポーネントを追加した後
zoomOut(page, times)N 回ズームアウトしますコンポーネントが小さすぎる場合
selectGptModel(page)すべての Language Model ノードに gpt-4o-mini を選択しますGPT に依存するテスト
addOpenAiInputKey(page)すべての openai_api_key フィールドに OPENAI_API_KEY を入力しますAPI キーが必要なテスト
enableInspectPanel(page)インスペクションパネルを ON に切り替えますedit-fields-button の前に必ず呼び出す必要があります
disableInspectPanel(page)インスペクションパネルを OFF に切り替えますインスペクション後のクリーンアップ
updateOldComponents(page)古いコンポーネントが存在する場合に「Update all」をクリックします保存されたフローを読み込んだ後
unselectNodes(page)空のキャンバス領域をクリックしてすべてのノードの選択を解除しますノード操作の後
renameFlow(page, { flowName })現在のフローの名前を変更しますフロー管理のテスト
uploadFile(page, filename)テストアセットからファイルをアップロードしますファイルアップロードのテスト
withEventDeliveryModes(...)テストを3回実行します: streaming、polling、directスタータープロジェクトのテスト
initialGPTsetup のオプション
await initialGPTsetup(page);  // All steps

await initialGPTsetup(page, {
  skipAdjustScreenView: true,
  skipUpdateOldComponents: true,
  skipSelectGptModel: true,
});
インスペクションパネルのパターン(重要)
// MUST enable inspection panel FIRST
await enableInspectPanel(page);

// Click a node to select it
await page.getByTestId("title-OpenAI").click();

// Open field editor
await page.getByTestId("edit-fields-button").click();

// Toggle field visibility
await page.getByTestId("showmodel_name").click();

// Close field editor
await page.getByTestId("edit-fields-button").click();

enableInspectPanel(page) をスキップすると、edit-fields-button は表示されません。

スキップパターン

// Skip test if env var missing
test.skip(!process?.env?.OPENAI_API_KEY, "OPENAI_API_KEY required to run this test");

// Skip test unconditionally with reason
test.skip(true, "Feature not yet implemented with new designs");

優れた E2E テストの書き方

すべきこと:
  • すべてのテストにタグを付ける: @release(該当する場合は任意のドメインタグも追加)
  • ../../fixtures からインポートする: @playwright/test からではなく
  • awaitBootstrapTest(page) で開始する — 常に
  • 安定したセレクタには getByTestId を使う
  • 明示的なタイムアウトを設定する: 非同期操作では waitForSelector と expect(...).toBeVisible() に設定
  • 完全なユーザーフローをテストする: セットアップ → アクション → 検証
  • withEventDeliveryModes を使う: フロー実行(チャット、ビルド)を伴うテストの場合
やってはいけないこと:
  • page.waitForTimeout() は、絶対に必要な場合を除いて使用しないでください — 代わりに waitForSelector または expect().toBeVisible() を使用してください
  • API キーをハードコードしないでください — process.env.OPENAI_API_KEY から読み込んでください
  • 理由なくテストをスキップしないでください — test.skip() には必ず第2引数を指定してください
  • @playwright/test からインポートしないでください — カスタムフィクスチャを使用してください
  • edit-fields-button にアクセスする前に enableInspectPanel(page) を呼び出し忘れないでください
  • グローバル変数が選択されているときに、入力フィールドが存在すると決めつけないでください(代わりにバッジが表示されます)
チャレンジテスト(ここにも適用)

E2E テストでは、敵対的なシナリオもカバーしてください。

  • 無効な入力:10K 文字の貼り付け、特殊文字(<script>alert(1)</script>)、空の送信
  • ネットワークの中断:ビルド中にユーザーの接続が切れた場合、どうなりますか?
  • 権限の境界:ユーザーは直接 URL を通じて、別のユーザーのフローにアクセスできますか?
  • 同時操作:削除のダブルクリック、チャットメッセージの連続送信
  • エラーからの回復:500 エラーから UI は適切に回復しますか?

参考資料

コメント