Skip to content

fix(json-csv): デバウンス中のダウンロードを抑止 (#184) - #187

Merged
fumtas1k merged 3 commits into
developfrom
fix/issue-184-jsoncsv-debounce-download
May 1, 2026
Merged

fix(json-csv): デバウンス中のダウンロードを抑止 (#184)#187
fumtas1k merged 3 commits into
developfrom
fix/issue-184-jsoncsv-debounce-download

Conversation

@fumtas1k

@fumtas1k fumtas1k commented May 1, 2026

Copy link
Copy Markdown
Owner

概要

JsonCsv.tsxuseCodec 戻り値から isPending を取得し、CSV ダウンロードボタン(DownloadButton)の disabled prop に渡すことで、デバウンス中(タイピング直後)に古い変換結果をダウンロードしてしまうバグを修正する。

PR #181 (#149) で ConfigConverter.tsx に入れた修正の横展開。

変更内容

  • src/components/tools/JsonCsv.tsx: useCodec から isPending を取得し DownloadButtondisabled={isPending} を設定
  • tests/e2e/json-csv.spec.ts: タイピング直後にダウンロードボタンが disabled になり、デバウンス完了後に有効化されることを検証する E2E ケースを 1 件追加

テスト

  • npm run test 全件 pass(406 件)
  • npm run test:e2e -- tests/e2e/json-csv.spec.ts 全件 pass(9 件)

Closes #184

🤖 Generated with Claude Code

useCodec から isPending を取得し DownloadButton の disabled prop に渡すことで、
デバウンス中(タイピング直後)のダウンロードを防止する。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@fumtas1k fumtas1k self-assigned this May 1, 2026

fumtas1k commented May 1, 2026

Copy link
Copy Markdown
Owner Author

レビュー結果

PR #181 (#149) で ConfigConverter.tsx に入れた isPending 連動の修正を JsonCsv.tsx に横展開する、目的が明確で差分も最小限の良い修正です。useCodec フックの既存 API(isPending)を素直に再利用しており、JSDoc 上の意図(「内容と拡張子の不整合を防ぐ」)通りの実装になっています。

良い点

  • 既存の共通コンポーネント (DownloadButton) と既存フック (useCodec) を素直に再利用しており、新規 API の追加なし。
  • E2E テスト (tests/e2e/json-csv.spec.ts:67-85) が「初期入力 → enabled」「再入力直後 → disabled」「デバウンス完了後 → enabled」という 3 状態を明示的に検証できており、回帰検知に有効。
  • ConfigConverter.tsx:175-185 と同じパターン(disabled={isPending}DownloadButton に渡す)に揃っており、コードベース全体の一貫性が保たれている。
  • 規約準拠(Tailwind カラークラスなし、htmlFor/className、aria 削除なし、Conventional Commits 日本語、--base develop)も問題なし。

修正提案 / 指摘

  • [推奨] src/components/tools/JsonCsv.tsx:46-53ConfigConverter.tsx:174-186 では output ? <DownloadButton ... /> : undefinedoutput 有無で条件レンダリングしていますが、本 PR ではボタンを常時表示する既存挙動が維持されています。結果として output が空文字列のときも有効化されたボタンが表示され、handleDownloadCsv 内の if (!output) return; で握りつぶされる UX になります(本 PR の責務外なので修正必須ではありませんが、disabled={isPending || !output} とすれば「空状態で押下しても何も起きない」UX を回避でき、ConfigConverter 側との一貫性も上がります)。少なくとも別 issue 化を検討してください。
  • [任意] tests/e2e/json-csv.spec.ts:80-81await inputField.fill('[{"id":2}]'); await expect(downloadBtn).toBeDisabled(); の流れは、Playwright の fill 完了 → React の input イベント → setInput → useEffect スケジュール → setIsPending(true) の順に依存します。toBeDisabled() のデフォルトタイムアウト(5s)の中で十分余裕がありますが、同テストファイル内の他ケースに合わせて { timeout: 1000 } 程度を明示すると、CI でスタックした際に切り分けやすくなります。
  • [任意] tests/e2e/json-csv.spec.ts:84 — 「デバウンス完了(300ms)後に再び有効化される」のコメント中の 300msuseCodecdebounceMs 既定値に依存しており、将来既定値を変更したときに乖離する恐れがあります。useCodec の既定 debounce 値(src/hooks/useCodec.ts:29)に合わせて変動する旨を一言添えるか、コメントから具体値を外す方が保守性が上がります。

質問

  • ConfigConverter 側と同じ症状が他の useCodec 利用箇所にも残っていないか確認済みでしょうか? JsonCsv 以外で useCodec を使っているのは ConfigConverter のみで、その両方に isPending 連動が入ったという理解で合っていますか? もし他にあれば、本 PR か後続 issue で追跡したいところです。

総じて、変更範囲・テスト粒度・規約準拠は良好で、上記は主に UX 一貫性と将来的な保守性に関する軽微な指摘です。


Generated by Claude Code

fumtas1k commented May 1, 2026

Copy link
Copy Markdown
Owner Author

レビュー指摘の訂正・撤回

先ほどのレビューコメントで「[任意] E2E テストの toBeDisabled() にタイムアウト明示で CI 切り分け改善」と提案しましたが、これは Playwright のベストプラクティスに反するため 撤回 します。

撤回理由

  • toBeDisabled() などの web-first assertion はデフォルトで auto-retry(expect.timeout 既定 5 秒)が組み込まれており、個別タイムアウトを足さないのが推奨。
  • 個別アサーションへのタイムアウト追加は anti-pattern とされ、本当に必要なら playwright.config.tsexpect.timeout でグローバルに調整するのが筋。
  • CI でフレーク切り分けをするなら Trace Viewer--trace on / retain-on-failure)や --reporter=list,html を使うのが正攻法で、タイムアウトを伸ばすのは根本原因を覆い隠す。

該当指摘は無視してください。他の指摘(disabled={isPending || !output} 提案、テストコメントの 300ms 暗黙依存、useCodec 横展開確認)はそのままでお願いします。失礼しました。


Generated by Claude Code

- DownloadButton の disabled 条件を `isPending` から `isPending || \!output` に変更し、
  出力が空の状態でボタンが押せてしまう UX 不整合を解消(ConfigConverter 側と統一)
- E2E テストコメントの「300ms」具体値を「useCodec の既定値」に抽象化し、
  debounceMs 変更時にコメントが乖離するリスクを排除

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 1, 2026

Copy link
Copy Markdown

Deploying devtools with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8dd06fb
Status: ✅  Deploy successful!
Preview URL: https://f14acc6f.devtools-d9w.pages.dev
Branch Preview URL: https://fix-issue-184-jsoncsv-deboun.devtools-d9w.pages.dev

View logs

@fumtas1k

fumtas1k commented May 1, 2026

Copy link
Copy Markdown
Owner Author

レビューありがとうございます。指摘内容を確認し、以下の対応を行いました。

採用した修正(2 件)

[推奨] disabled={isPending || !output} への変更
src/components/tools/JsonCsv.tsxDownloadButtondisabled 条件を isPending || !output に変更しました。出力が空の状態でボタンが有効化される UX 不整合が解消され、ConfigConverter.tsx 側と挙動が統一されています。

[任意] E2E コメントの 300ms 具体値を除去
tests/e2e/json-csv.spec.ts:84 のコメントを「デバウンス完了(300ms)後」から「デバウンス完了(useCodec の既定値)後」に変更しました。debounceMs の既定値変更時にコメントが乖離するリスクを排除しています。

上記 2 件をまとめて 1 コミットにしました: 83af89e

撤回された指摘(1 件)の確認

toBeDisabled() へのタイムアウト明示の提案は撤回いただいたことを確認しました。Playwright の auto-retry に委ねる現状の実装を維持します。

横展開確認(質問への回答)

useCodec を使用するツールは JsonCsv.tsxConfigConverter.tsxJsonXml.tsxBase64Codec.tsx の 4 ファイルですが、JsonXml.tsxBase64Codec.tsx にはダウンロードボタン自体が存在しないため対象外です。isPending 連動のダウンロード抑止が必要なのは ConfigConverter(PR #181)と JsonCsv(本 PR #187)の 2 箇所で、これにより useCodec 利用のダウンロード機能は完全に網羅されました。

Generated by Claude Code

@fumtas1k fumtas1k left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

概要

JsonCsv.tsxuseCodec 戻り値から isPending を取得し、DownloadButtondisabledisPending || !output を渡すことで、デバウンス中に古い変換結果がダウンロードされる不整合を防ぐ修正です。PR #181(ConfigConverter)の横展開で、対応する E2E テストも 1 件追加されています。

良い点

  • 責務分離が綺麗: useCodec に既に isPending が用意されており、UI 側は disabled に渡すだけで済んでいる。フック設計の意図に沿った最小差分の修正。
  • !output も併せて disabled 条件に入れている: isPending のみでなく出力が空の場合も無効化しているため、初期表示や無効入力時の誤操作も防げており、ConfigConverter 側 (output ? <DownloadButton .../> : undefined) と機能的に等価な状態を保てている。
  • a11y 規約遵守: DownloadButtondisabled 時に cursor: not-allowedcolors.muted 系を切り替える既存実装の上に乗っており、a11y 属性の削除や Tailwind カラークラスの混入はない。
  • 規約遵守: PR タイトル・本文は日本語、--base develop 指定済、コード内コメントも日本語で colors.* 利用が維持されている。
  • E2E テストが同時に追加: 「初期 enable → 再入力で disable → デバウンス完了で再 enable」という遷移を 1 ケースで検証しており、回帰防止として十分。

指摘事項(必須対応)

なし。修正内容・テストともに規約とプロジェクト方針に合致しています。

改善提案(任意対応)

  • [Minor] E2E テストの待機タイムアウトの根拠: toBeEnabled({ timeout: 3000 })useCodec の既定 debounceMs = 300 に対して十分な余裕がありますが、将来 debounceMs が変わった場合の意図が読みづらくなります。コメントに「既定 300ms に対する余裕」と一言添えるか、ヘルパー定数化しておくと保守性が上がります(必須ではありません)。
  • [Minor] テスト名の表現: 「タイピング直後は disabled になり〜」は実際には inputField.fill を 2 回呼んだうちの 2 回目以降の遷移を見ています。1 回目の fill 直後の disabled→enable も検証対象に含めると、より厳密にデバウンス挙動を保証できます(ただしフレーキー要因にもなり得るため、現状のままで実用上は十分です)。
  • [Minor] ダウンロードハンドラの防御: handleDownloadCsv 内で if (!output) return; のガードがありますが、ボタン側でも !output を disabled にしているので二重防御になっています。意図通りであれば問題なし。コメントとして明記しておくと将来の混乱を避けられます。
  • [Minor] 横展開対象の確認: useCodecDownloadButton の組み合わせが ConfigConverterJsonCsv 以外にもあれば、同じ不整合が残っていないか別 issue でトラッキングしておくと良さそうです。

総評

approve 推奨(PR 作者本人レビューのため event は COMMENT で投稿)。

  • 修正の意図と実装が一致し、フック側の既存 API(isPending)をそのまま活用したミニマルかつ正しい変更です。
  • E2E テストも同時に追加されており、docs/shared-agent-rules.md のテスト規約・言語規約・スタイリング規約・a11y 規約のいずれにも違反は見られません。
  • 上記改善提案はいずれも任意で、本 PR をブロックする理由にはなりません。このままマージで問題ないと判断します。

Generated by Claude Code

fumtas1k commented May 1, 2026

Copy link
Copy Markdown
Owner Author

直前のレビューで提案した「E2E テストのタイムアウトに根拠コメントを追加すべき」という指摘を訂正させてください。

Playwright 公式は web-first assertions(toBeVisible などによる自動リトライ)と、playwright.config.tstimeout / expect.timeout によるグローバル設定を基本方針として推奨しており、個別 timeout の多用は推奨されません。個別指定は debounce 待ちなど明確な理由がある場合に限定し、その場合も定数化や根拠コメントの明示が望ましい、というのが正しい方針です。

本 PR の差分自体には影響しないため、コードベース全体の方針整理として別 issue #193 に切り出しました。混乱させてしまい申し訳ありません。


Generated by Claude Code

@fumtas1k

fumtas1k commented May 1, 2026

Copy link
Copy Markdown
Owner Author

コメントありがとうございます。issue #193 (E2E の web-first assertions / 個別 timeout 抑制方針) として別途切り出していただいたので、本 PR では追加対応不要と判断します。issue #194 (worktree 環境での E2E timeout 早期検出) と併せて、今後の E2E ガイドライン整備として継続フォローしていきます。

Generated by Claude Code

- handleDownloadCsv 内の二重防御に意図を説明するコメントを追記
- E2E の toBeEnabled timeout: 3000 に debounceMs 根拠コメントを追記

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fumtas1k added a commit that referenced this pull request May 1, 2026
PR #187/#188/#189 で Reviews API を見落として正式レビューを取りこぼした事故を受け、
3.2 章「親向けレビュー取得手順」節を追加。Issue comments と Pull Request reviews の
両 API を確認するよう明示。decisions.md [057] に事故の経緯も追記。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@fumtas1k

fumtas1k commented May 1, 2026

Copy link
Copy Markdown
Owner Author

レビューありがとうございます。改善提案 4 件について対応結果をご報告します。

採用(2 件)

[Minor 採用] E2E テストのタイムアウト根拠コメント
tests/e2e/json-csv.spec.tstoBeEnabled({ timeout: 3000 }) 直前に、useCodec の既定 debounceMs(300ms)に対する余裕であることを示すコメントを 1 行追記しました。将来 debounceMs が変更された際にもコメントが乖離しないよう、具体値ではなく「既定値に対する余裕」という表現にしています。

[Minor 採用] ダウンロードハンドラの二重防御コメント
src/components/tools/JsonCsv.tsxhandleDownloadCsvif (!output) return; 直前に、ボタン側でも disabled={!output} で防御しているが念のため二重防御している旨のコメントを 1 行追記しました。コードの意図を明示することで将来の混乱を防ぎます。

不採用(2 件)

[Minor 不採用] テスト名の表現(1 回目 fill 直後の disabled→enable 検証)
ご指摘の通り、より厳密なデバウンス保証になりますが、フレーキー要因にもなり得るとご本人も言及されているため、現状のまま維持します。実用上は現行テストで十分と判断しました。

[Minor 不採用] 横展開対象の確認
issue #194 と PR #181 / #187useCodec + DownloadButton の組み合わせを持つツール群は既に網羅済みです。別途トラッキングは不要と判断しました。

最終コミット

SHA: 8dd06fb50f86d5a75b667a6df0ed1308a835f2f4

Generated by Claude Code

@fumtas1k fumtas1k left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

再レビュー概要

前回レビューの指摘・改善提案について、採用 3 件・不採用 2 件(合理的判断)・撤回 1 件(issue #193 切り出し)が明確に整理され、最終 SHA 8dd06fb にて全て期待通り反映されていることを確認しました。差分は依然として最小(+28/-2、2 ファイル)で、規約遵守・テストカバレッジともに問題ありません。修正後の状態は十分にマージ可能 と判断します(PR 作者本人レビューのため event は COMMENT)。

前回指摘の対応確認

# 指摘内容 対応状況 確認箇所
1 [推奨] disabled={isPending || !output} で空状態の UX 不整合解消・ConfigConverter との一貫性確保 ✅ 対応済 src/components/tools/JsonCsv.tsxDownloadButton props で disabled={isPending || !output} を確認
2 [Minor] E2E テストコメントから 300ms 具体値を除去(debounceMs 既定値変更時の乖離回避) ✅ 対応済 tests/e2e/json-csv.spec.ts:84 直前のコメントが「useCodec の既定 debounceMs(300ms)に対する余裕」表現に変更され、「既定値に対する余裕」という意図が明確化
3 [Minor] handleDownloadCsvif (!output) return; の二重防御をコメントで明示 ✅ 対応済 JsonCsv.tsx の同行直前に「ボタン側でも disabled={!output} で防御しているが念のため二重防御」コメントを確認
4 [Minor] テスト名で 1 回目 fill 直後の disabled→enable も検証 N/A フレーキー要因の懸念から不採用、合理的判断
5 [Minor] useCodec × DownloadButton の他箇所横展開チェック ✅ 対応済 回答コメントにて useCodec 利用 4 ファイル(JsonCsv / ConfigConverter / JsonXml / Base64Codec)を全数確認、ダウンロード機能を持つのは前 2 者のみで PR #181#187 で網羅済みと整理
6 [任意・撤回] toBeDisabled() への個別 timeout 明示 N/A Playwright のベストプラクティス(web-first assertions + グローバル expect.timeout)に反するため撤回済。issue #193 として方針整備に切り出し

新規指摘

なし。今回の修正で残課題は解消されています。

念のため最終差分を再確認しましたが、

  • 言語規約(コミット・コメント・PR 本文すべて日本語)
  • スタイリング規約(Tailwind カラークラス未使用、DownloadButtoncolors.* 経由スタイルに依存)
  • a11y 属性(aria-* / role= の不当な削除なし、disabled 切替も既存 DownloadButton の cursor/colors 切替に乗っている)
  • React/TS 規約(className / htmlFor の崩れなし)
  • E2E テストの web-first assertions 利用(toBeVisible / toBeEnabled / toBeDisabled、個別 timeout は debounce 待ちの 1 箇所のみで根拠コメント付き)
  • ベース ブランチ(develop
  • ドキュメント(本修正は単一バグ fix のため README/SPEC/decisions 更新不要)

いずれも規約に違反する箇所はありません。

総評

修正後 approve 推奨(PR 作者本人レビューのため event は COMMENT で投稿)。

  • 前回の必須指摘・採用した改善提案はすべて反映済。
  • 不採用 2 件・撤回 1 件いずれも理由が明確で、別 issue(#193 / #194)への切り出しも適切。
  • このままマージで問題なしと判断します。

Generated by Claude Code

@fumtas1k
fumtas1k merged commit bcca7c0 into develop May 1, 2026
3 checks passed
@fumtas1k
fumtas1k deleted the fix/issue-184-jsoncsv-debounce-download branch May 1, 2026 14:09
fumtas1k added a commit that referenced this pull request May 1, 2026
PR #187/#188/#189 で Reviews API を見落として正式レビューを取りこぼした事故を受け、
3.2 章「親向けレビュー取得手順」節を追加。Issue comments と Pull Request reviews の
両 API を確認するよう明示。decisions.md [057] に事故の経緯も追記。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fumtas1k added a commit that referenced this pull request May 1, 2026
* chore(rules): E2E 実行責務をサブエージェントから親に移管

worktree 並列環境でのポート競合・sandbox 制約による誤報告を防ぐため、
サブエージェントの npm run test:e2e 実行を禁止し、親(司令塔)が代行する手順を 3 章に明文化する。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(decisions): [056] E2E 実行責務移管の判断記録を追加

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(rules): レビュー反映(CLAUDE.md 整合・親向けチェックリスト追加・補足)

- [Major 1] CLAUDE.md 検証行をサブエージェント向けに更新(npm run test:e2e は親が代行)
- [Major 2] shared-agent-rules.md 3.2 直下に親向け push 前チェックリスト(表形式)を追加
- [Minor 3] 3.2 冒頭に dev server 残置時の停止依頼に関する補足を追記
- [Minor 4] push-前必須チェックリスト アンカー参照を grep 確認(該当なし、対応不要)
- [任意 5] 環境由来の失敗例に Playwright 固有メッセージ(Timed out/webServer was not ready)を追記
- [任意 6] 3.2 手順 2 に npm run test:e2e -- <spec> でも可の旨を追記
- [任意 7] decisions.md [057] に将来の見直しトリガーを追記
- [任意 8] 3.2 末尾に関連 issue #193 への参照を追記

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(rules): 親向けレビュー取得手順を追記(取りこぼし防止)

PR #187/#188/#189 で Reviews API を見落として正式レビューを取りこぼした事故を受け、
3.2 章「親向けレビュー取得手順」節を追加。Issue comments と Pull Request reviews の
両 API を確認するよう明示。decisions.md [057] に事故の経緯も追記。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

useCodec 利用ツール横展開: JsonCsv のダウンロードボタンをデバウンス中に抑止する

1 participant