Turbo Driveのナビゲーション競合によるフォームテストの不安定さを修正

basecamp/lexxy

Turbo Driveの非同期ナビゲーションとカスタム要素の初期化タイミングの競合により、CIで断続的にタイムアウトしていたシステムテストを修正しました。アサーション実行前に適切なページ遷移と wait_for_editor の待機を挿入することで、テストの再現性が確保されます。

背景

FormTest の「edit existing records」テストは、Turbo Driveによるページ遷移が完了する前にアサーションが実行される競合状態を抱えていました。click_on "Update Post" を実行すると、Turbo Driveはショウページへの非同期ナビゲーションを開始します。しかしショウページには lexxy-editor 要素が存在しないため、その直後に実行される assert_editor_html はナビゲーション完了前に間に合えば成功し、CIのような低速な環境では lexxy-editor 要素が見つからずタイムアウトするという不安定な挙動になっていました。

CIランナーの速度によって結果が変わるこの種の競合は、ローカル環境では再現しにくく、根本原因の特定が難しいという特徴があります。

技術的な変更

修正は2種類のパターンを組み合わせて FormTest 全体の一貫性を高めています。

1つ目の修正は「edit existing records」テストへの click_on "Edit this post"wait_for_editor の追加です。click_on "Update Post" の直後にアサーションするのではなく、明示的に編集ページへ戻ってから assert_editor_html を実行するよう変更されました。これは他のフォームテストが採用していたパターンと一致します。

変更前:

click_on "Update Post"

assert_editor_html "<p>Hello</p><p>there</p>"

変更後:

click_on "Update Post"
click_on "Edit this post"
wait_for_editor

assert_editor_html "<p>Hello</p><p>there</p>"

2つ目の修正は、FormTest 内の他のテストに対して wait_for_editor の呼び出しを追加・整理することです。「create a new record」や別のテストケースにおいて、click_on "Edit this post" の直後に wait_for_editor が挿入されています。これにより、flush_lexical_updates がエディタインスタンスにアクセスする前に、カスタム要素が完全にコネクトされていることが保証されます。

変更の差分としては4行追加・1行削除と最小限ですが、テストスイート全体で wait_for_editor の呼び出し位置が統一されました。

設計判断

ナビゲーション先を変更してアサーション条件を安定させるアプローチが採用されました。

ショウページでのアサーションを諦め、エディタ要素が存在する編集ページに戻ってからアサーションすることで、「アサーション対象の要素が必ず存在する」という前提条件が整理されています。タイムアウト値の延長や sleep による待機ではなく、テストの意図(編集後の内容確認)を損なわずに競合の根本原因を取り除いた点が重要です。

また wait_for_editor を「ナビゲーション直後・アサーション直前」に統一配置することで、カスタム要素のライフサイクル(connected callback)が完了していない状態でエディタインスタンスへアクセスするという別の競合も同時に防いでいます。これにより FormTest 全体のテストパターンが一貫したものになりました。

まとめ

Turbo Driveの非同期ナビゲーションとWeb Componentsのライフサイクルが絡み合う競合を、タイムアウト調整ではなくテストフローの修正で解消した変更です。「アサーション前にエディタ要素が存在するページにいること」と「wait_for_editor でカスタム要素の初期化を待つこと」という2つの前提条件を明示化することで、CI環境での再現性が確保されました。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
85838dab

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術詳細・設計判断(各論)→まとめ(結論)という「総論→各論→結論」の構成が記事全体に適用されており、非常に分かりやすい構造です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```ruby:test/system/form_test.rb)とGitHubのPRリンク記法([PR #896](URL))が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

Turbo Drive、システムテスト、競合状態といったトピックを前提知識として扱っており、専門知識を持つエンジニアという対象読者に適合した内容です。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論→各論で構成され、各パラグラフの先頭にトピックセンテンスが置かれているため、非常に読みやすく、要点を素早く把握できます。段落の長さも適切です。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内のコードブロックは、提供されたDiff情報を正確に反映しています。「変更前」のコードもDiffから推測される内容と一致しており、変更内容が的確に示されています。「4行追加・1行削除」という記述もPR情報と一致しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「競合状態」「カスタム要素」「ライフサイクル」「connected callback」など、PR情報や関連技術分野の用語が正確かつ適切に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

Turbo Driveの非同期ナビゲーションが原因で競合が発生する仕組みや、その解決策(ページ遷移と待機処理の追加)に関する説明は、技術的に正確で論理的です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張は、PRのDescriptionやDiffの内容に裏付けられています。特に「設計判断」セクションは、PRに明記されていないものの、コードの変更意図から論理的に導かれる妥当な解説であり、ハルシネーションには該当しません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#896)、コードの変更行数(4行追加・1行削除)など、記事に含まれる数値や固有名詞はすべて正確です。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトルは、PRのタイトル「Fix flaky form system test timeout」の内容を汲み取りつつ、原因である「Turbo Driveのナビゲーション競合」を加えており、より具体的で分かりやすいものになっています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事には、PR情報に基づかないバージョン情報やリリース日程などの外部知識は含まれていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

記事内の時間表現は、過去に発生した問題とその修正という文脈を正確に反映しており、PR情報と一致しています。