-
Notifications
You must be signed in to change notification settings - Fork 75
UnconfirmedLink.jsxを非React化 #9184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Walkthrough複数の提出物・日報ビューで一括オープン機能を統一するため、ターゲットマッピング機構を導入。React の UnconfirmedLink コンポーネントを削除し、vanilla JavaScript 実装に置き換え。ヘルパーメソッドでターゲット値に応じた日本語ラベルを提供し、パーシャルで条件付きレンダリング実装。 Changes
Sequence DiagramsequenceDiagram
participant User as ユーザー<br/>(メンター)
participant Controller as コントローラー<br/>(e.g. ProductsController)
participant Helper as ヘルパー<br/>(ProductsHelper)
participant View as ビュー<br/>(.slim)
participant JS as JavaScript<br/>(unconfirmed-links-open.js)
participant Browser as ブラウザ<br/>(新規タブ)
User->>Controller: /products へアクセス
Controller->>Controller: set_target<br/>(`@target` = 'all')
Controller->>Controller: index<br/>(クエリ実行)
Controller->>View: `@target`, `@products`<br/>をテンプレートに渡す
View->>Helper: unconfirmed_links_label(`@target`)
Helper-->>View: 日本語ラベル<br/>('全ての提出物を...')
alt `@products.present`?
View->>View: unconfirmed_links_open<br/>パーシャル render
View->>JS: DOM 生成<br/>(js-unconfirmed-link)
end
View-->>User: HTML 返す<br/>(ボタン付き)
User->>JS: ボタンクリック
JS->>JS: document.querySelectorAll<br/>('js-unconfirmed-link')
loop 各リンク
JS->>Browser: window.open(href, '_blank')
end
Note over JS: 100ms 遅延
JS->>Browser: location.reload()
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 重点確認項目:
Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
27f9f33 to
9a8b870
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
app/views/products/unchecked/index.html.slim (1)
25-26: LGTM! ただし、将来的なリファクタリングの検討を推奨条件付きレンダリングのロジックは正しく実装されています。ただし、同じ条件式が複数のビュー(index, unassigned, unchecked, self_assigned)で繰り返されています。
将来的には、ViewComponentパターンを使用して条件判定をコンポーネント内にカプセル化することを検討してください(コーディングガイドラインに沿った実装)。これにより、DRY原則に従いながら保守性が向上します。
コーディングガイドラインより: "Viewにpartialを作る場合はViewComponentを使うことを検討する。"
app/helpers/products_helper.rb (1)
6-11: 国際化(i18n)の検討を推奨ラベル文字列がハードコーディングされていますが、将来的な多言語対応を考慮すると、i18nファイルに移行することを推奨します。
例:
def unconfirmed_links_label(target) - case target - when 'all' then '全ての提出物を一括で開く' - when 'unchecked', 'unchecked_all' then '未完了の提出物を一括で開く' - when 'unchecked_no_replied' then '未返信の提出物を一括で開く' - when 'unassigned' then '未アサインの提出物を一括で開く' - when 'self_assigned', 'self_assigned_all' then '自分の担当の提出物を一括で開く' - when 'self_assigned_no_replied' then '未返信の担当提出物を一括で開く' - else '' - end + I18n.t("products.unconfirmed_links.#{target}", default: '') end対応するi18nファイル (
config/locales/ja.yml) に追加:ja: products: unconfirmed_links: all: '全ての提出物を一括で開く' unchecked: '未完了の提出物を一括で開く' unchecked_all: '未完了の提出物を一括で開く' unchecked_no_replied: '未返信の提出物を一括で開く' unassigned: '未アサインの提出物を一括で開く' self_assigned: '自分の担当の提出物を一括で開く' self_assigned_all: '自分の担当の提出物を一括で開く' self_assigned_no_replied: '未返信の担当提出物を一括で開く'
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
app/controllers/products/unassigned_controller.rb(2 hunks)app/controllers/products/unchecked_controller.rb(2 hunks)app/controllers/products_controller.rb(2 hunks)app/helpers/products_helper.rb(1 hunks)app/javascript/components/Notifications.jsx(0 hunks)app/javascript/components/Product.jsx(1 hunks)app/javascript/components/Products.jsx(0 hunks)app/javascript/components/Reports.jsx(0 hunks)app/javascript/components/UnconfirmedLink.jsx(0 hunks)app/javascript/unconfirmed-links-open.js(1 hunks)app/views/notifications/index.html.slim(1 hunks)app/views/products/index.html.slim(1 hunks)app/views/products/self_assigned/index.html.slim(1 hunks)app/views/products/unassigned/index.html.slim(1 hunks)app/views/products/unchecked/index.html.slim(1 hunks)test/models/product_test.rb(1 hunks)test/models/report_test.rb(1 hunks)test/system/product/products_view_system_test.rb(1 hunks)test/system/product/unconfirmed_links_open_test.rb(1 hunks)test/system/report/reports_view_system_test.rb(1 hunks)test/system/report/unconfirmed_links_open_test.rb(1 hunks)
💤 Files with no reviewable changes (4)
- app/javascript/components/Products.jsx
- app/javascript/components/Notifications.jsx
- app/javascript/components/UnconfirmedLink.jsx
- app/javascript/components/Reports.jsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.rb
⚙️ CodeRabbit configuration file
**/*.rb: # refactoring
- まずFat Controllerを避け、次にFat Modelを避ける。
- Serviceクラスの乱用を避ける。
- controller concernを作ろうとしたらPORO(Plain Old Ruby Object)やActiveRecordモデルでの実装で代替できないか検討する。
Rails Patterns
- ViewHelperにメソッドを実装する時にはまずDecoratorパターンを使うことを検討する。(active_decorator gemを導入しているのでそれを使う)
- 複雑なActiveRecordクエリがあり、再利用できそうな場合はQueryObjectパターンを検討する。(rails-patterns gemを導入しているのでそれのQuery機能を使う)
- Viewにpartialを作る場合はViewComponentを使うことを検討する。
- 複数のActiveRecordモデルを操作する1つの責務がある時や外部APIとやりとりする処理がある場合にはInteractorオブジェクトパターンを検討する。(interactor gemを導入しているのでそれを使う)
- 複数のInteractorを実行するような処理がある場合Organizerオブジェクトパターンを検討する。(interactor gemを導入しており、その中にOrganizerの機能があるので使う)
Files:
app/controllers/products/unchecked_controller.rbapp/helpers/products_helper.rbtest/models/report_test.rbtest/system/report/unconfirmed_links_open_test.rbtest/models/product_test.rbtest/system/report/reports_view_system_test.rbapp/controllers/products_controller.rbtest/system/product/unconfirmed_links_open_test.rbtest/system/product/products_view_system_test.rbapp/controllers/products/unassigned_controller.rb
test/**/*
⚙️ CodeRabbit configuration file
test/**/*: # Test
- TestCase名は英語で書く。
- どうしても避けられない時以外にsystem testでsleepは使わない。
Unit Test
model, helper, decorator, view_componentについてはメソッドを追加した場合は必ず対応したUnit TestのTestCaseを1つは書く。
Files:
test/models/report_test.rbtest/system/report/unconfirmed_links_open_test.rbtest/models/product_test.rbtest/system/report/reports_view_system_test.rbtest/system/product/unconfirmed_links_open_test.rbtest/system/product/products_view_system_test.rb
**/*.js
⚙️ CodeRabbit configuration file
**/*.js: - どうしても避けられない時以外に新規にVue.js, Reactのコードを追加しない。
- fetchメソッドの代わりにrequest.jsを使う。
Files:
app/javascript/unconfirmed-links-open.js
🧬 Code graph analysis (8)
app/controllers/products/unchecked_controller.rb (3)
app/controllers/products/unassigned_controller.rb (2)
before_action(3-20)set_target(17-19)app/controllers/products_controller.rb (2)
before_action(3-161)set_target(158-160)app/controllers/products/self_assigned_controller.rb (2)
before_action(3-31)target_allowlist(16-18)
test/system/report/unconfirmed_links_open_test.rb (3)
test/system/product/unconfirmed_links_open_test.rb (1)
setup(5-55)test/system/report/reports_view_system_test.rb (1)
setup(5-36)test/models/report_test.rb (1)
test(5-76)
test/models/product_test.rb (1)
app/models/product.rb (1)
self_assigned_no_replied_products(70-72)
test/system/report/reports_view_system_test.rb (2)
test/system/report/unconfirmed_links_open_test.rb (1)
setup(5-24)test/models/report_test.rb (1)
test(5-76)
app/controllers/products_controller.rb (3)
app/controllers/products/unassigned_controller.rb (2)
before_action(3-20)set_target(17-19)app/controllers/products/unchecked_controller.rb (2)
before_action(3-27)set_target(23-26)app/controllers/products/self_assigned_controller.rb (1)
before_action(3-31)
test/system/product/unconfirmed_links_open_test.rb (2)
test/system/product/products_view_system_test.rb (1)
setup(5-66)test/system/report/unconfirmed_links_open_test.rb (1)
setup(5-24)
test/system/product/products_view_system_test.rb (2)
test/system/product/unconfirmed_links_open_test.rb (1)
setup(5-55)test/models/product_test.rb (1)
test(5-288)
app/controllers/products/unassigned_controller.rb (2)
app/controllers/products/unchecked_controller.rb (2)
before_action(3-27)set_target(23-26)app/controllers/products_controller.rb (2)
before_action(3-161)set_target(158-160)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_and_test
🔇 Additional comments (19)
app/controllers/products/unassigned_controller.rb (1)
5-19: LGTM!
before_action :set_targetの追加とset_targetメソッドの実装は、他のコントローラ(UncheckedController、ProductsController)と一貫したパターンに従っています。シンプルで明確な責務分離が保たれています。test/models/report_test.rb (1)
65-75: LGTM!
uncheckedスコープのユニットテストが適切に追加されています。テスト名が英語で記載されており、コーディングガイドラインに準拠しています。app/controllers/products_controller.rb (2)
7-7: LGTM!
before_action :set_target, only: %i[index]の追加により、indexアクションのみに適用範囲を限定しています。他のコントローラとの一貫性が保たれています。
157-160: LGTM!
set_targetメソッドの実装はシンプルで明確です。@targetの初期化により、ビューでの条件分岐に必要なコンテキストを提供しています。test/system/report/reports_view_system_test.rb (1)
1-36: LGTM!システムテストの実装が適切です:
- NotificationとWatchの副作用を適切にstub
- メンターの視点からの未チェックレポート表示を検証
js-unconfirmed-linkクラスとhref属性の存在を確認- テスト名が英語でコーディングガイドラインに準拠
app/controllers/products/unchecked_controller.rb (2)
5-5: LGTM!
before_action :set_targetの追加により、targetの初期化をindexアクションから分離し、他のコントローラとの一貫性が向上しています。
23-26: LGTM!
set_targetメソッドへのリファクタリングにより、関心の分離が改善されています。ロジックは変更されておらず、許可リストによる検証も適切に維持されています。test/models/product_test.rb (4)
254-258: LGTM!
uncheckedスコープのテストが適切に実装されています。テスト名が英語で記載され、checksが空であることとスコープへの包含を検証しています。
260-275: LGTM!
self_assigned_no_replied_productsのテストが包括的です:
- メンターに担当された提出物が含まれることを検証
- コメント追加後に除外されることを検証
- 動作の両面をカバーしています
277-281: LGTM!
unassignedスコープのテストが適切です。checker_idがnilであることとスコープへの包含を検証しています。
283-287: LGTM!
self_assigned_productスコープのテストが適切に実装されています。指定されたユーザーに担当された提出物が含まれることを検証しています。app/javascript/components/Product.jsx (1)
57-57: LGTM!
js-unconfirmed-linkクラスの追加により、システムテストとバニラJSの一括オープン機能が提出物リンクを識別できるようになります。ロジックやレンダリングに影響はありません。app/views/notifications/index.html.slim (1)
48-49: LGTM!未読通知の一括オープンUI追加が適切です:
- メンター権限、未読ステータス、未読通知の存在を適切に条件判定
- ラベルが明確で分かりやすい
- 他のビュー(products系)との一貫性が保たれています
app/views/products/unassigned/index.html.slim (1)
16-17: LGTM!条件付きレンダリングのロジックが正しく、
@productsの存在確認と@targetの値チェックが適切に行われています。ヘルパーメソッドを使用したラベル生成も適切です。app/javascript/unconfirmed-links-open.js (1)
11-11: セキュリティとブラウザ互換性の改善
window.openのターゲットを'_blank'に変更したことで、標準的な新規タブ/ウィンドウでの開き方になり、noopenerパラメータによりセキュリティも向上しています。以前の'_target'は非標準だったため、この変更は適切です。app/views/products/self_assigned/index.html.slim (1)
18-19: LGTM!実装は正しく、他のビューファイルと一貫性があります。DRY原則に関する改善提案は
app/views/products/unchecked/index.html.slimのレビューコメントを参照してください。app/views/products/index.html.slim (1)
17-18: LGTM!条件付きレンダリングが正しく実装されており、staff_login?ブロック内で適切に配置されています。
test/system/product/unconfirmed_links_open_test.rb (1)
39-54: テスト構造は適切テストケース名が英語で書かれており、コーディングガイドラインに準拠しています。カバレッジも適切です(ボタンの表示/非表示の両方のケースをテスト)。
ただし、Line 45のバグ修正が必要です(別のコメントを参照)。
test/system/report/unconfirmed_links_open_test.rb (1)
11-23: LGTM!日報に対する一括開封ボタンのテストが適切に実装されています。既存の
Report.uncheckedスコープを活用した効率的なテストです。テストケース名も英語で記述されており、コーディングガイドラインに準拠しています。
d0b5e72 to
2461480
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
test/system/report/unconfirmed_links_open_test.rb (2)
37-39: 特定のレポートのみをチェック済みにする方が安全です。
Report.unchecked.find_eachは、fixtureに含まれる他の未チェックレポートもすべて対象にしてしまいます。テストの独立性を保つため、setupで作成した2つのレポートのみを明示的にチェック済みにする方が望ましいです。以下の差分を適用してください:
- Report.unchecked.find_each do |report| - report.checks.create!(user: @mentor) - end + @unchecked_report1.checks.create!(user: @mentor) + @unchecked_report2.checks.create!(user: @mentor)
49-50:waitオプションの追加を検討してください。Product側のテスト(
test/system/product/unconfirmed_links_open_test.rb)では.js-unconfirmed-linkセレクタにwait: 5オプションを使用している箇所があります。JavaScriptによる動的なレンダリングが発生する可能性がある場合、同様にwaitオプションを追加することでテストの安定性が向上します。以下のように修正できます:
- assert_selector "a.js-unconfirmed-link[href='#{report_path(@unchecked_report1)}']", count: 1 - assert_selector "a.js-unconfirmed-link[href='#{report_path(@unchecked_report2)}']", count: 1 + assert_selector "a.js-unconfirmed-link[href='#{report_path(@unchecked_report1)}']", count: 1, wait: 5 + assert_selector "a.js-unconfirmed-link[href='#{report_path(@unchecked_report2)}']", count: 1, wait: 5
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
test/helpers/products_helper_test.rb(1 hunks)test/models/product_test.rb(1 hunks)test/system/product/unconfirmed_links_open_test.rb(1 hunks)test/system/report/unconfirmed_links_open_test.rb(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- test/helpers/products_helper_test.rb
- test/models/product_test.rb
- test/system/product/unconfirmed_links_open_test.rb
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rb
⚙️ CodeRabbit configuration file
**/*.rb: # refactoring
- まずFat Controllerを避け、次にFat Modelを避ける。
- Serviceクラスの乱用を避ける。
- controller concernを作ろうとしたらPORO(Plain Old Ruby Object)やActiveRecordモデルでの実装で代替できないか検討する。
Rails Patterns
- ViewHelperにメソッドを実装する時にはまずDecoratorパターンを使うことを検討する。(active_decorator gemを導入しているのでそれを使う)
- 複雑なActiveRecordクエリがあり、再利用できそうな場合はQueryObjectパターンを検討する。(rails-patterns gemを導入しているのでそれのQuery機能を使う)
- Viewにpartialを作る場合はViewComponentを使うことを検討する。
- 複数のActiveRecordモデルを操作する1つの責務がある時や外部APIとやりとりする処理がある場合にはInteractorオブジェクトパターンを検討する。(interactor gemを導入しているのでそれを使う)
- 複数のInteractorを実行するような処理がある場合Organizerオブジェクトパターンを検討する。(interactor gemを導入しており、その中にOrganizerの機能があるので使う)
Files:
test/system/report/unconfirmed_links_open_test.rb
test/**/*
⚙️ CodeRabbit configuration file
test/**/*: # Test
- TestCase名は英語で書く。
- どうしても避けられない時以外にsystem testでsleepは使わない。
Unit Test
model, helper, decorator, view_componentについてはメソッドを追加した場合は必ず対応したUnit TestのTestCaseを1つは書く。
Files:
test/system/report/unconfirmed_links_open_test.rb
🧬 Code graph analysis (1)
test/system/report/unconfirmed_links_open_test.rb (2)
test/system/product/unconfirmed_links_open_test.rb (1)
setup(5-73)test/models/report_test.rb (1)
test(5-76)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_and_test
21ab9b6 to
c87f685
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
app/views/products/self_assigned/index.html.slim (1)
18-19: ターゲットリストの範囲が広すぎる可能性があります。この自分の担当提出物ビューで、
'all'、'unchecked_all'、'unchecked_no_replied'、'unassigned'といったターゲットが含まれていますが、これらは self_assigned ビューには関連性が低いように見えます。このビューでは
'self_assigned'、'self_assigned_all'、'self_assigned_no_replied'のみをチェックする方が適切ではないでしょうか。以下の diff を適用して、ターゲットリストを絞り込むことを検討してください:
- - if @products.present? && %w[all unchecked_all unchecked_no_replied unassigned self_assigned self_assigned_all self_assigned_no_replied].include?(@target) + - if @products.present? && %w[self_assigned self_assigned_all self_assigned_no_replied].include?(@target) = render 'application/unconfirmed_links_open', label: unconfirmed_links_label(@target)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
app/javascript/components/Notifications.jsx(1 hunks)app/views/products/index.html.slim(1 hunks)app/views/products/self_assigned/index.html.slim(1 hunks)app/views/products/unassigned/index.html.slim(1 hunks)app/views/products/unchecked/index.html.slim(1 hunks)test/helpers/products_helper_test.rb(1 hunks)test/models/product_test.rb(1 hunks)test/system/product/unconfirmed_links_open_test.rb(1 hunks)test/system/report/unconfirmed_links_open_test.rb(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- app/views/products/unassigned/index.html.slim
- app/javascript/components/Notifications.jsx
- test/models/product_test.rb
- app/views/products/unchecked/index.html.slim
- test/system/product/unconfirmed_links_open_test.rb
- app/views/products/index.html.slim
- test/system/report/unconfirmed_links_open_test.rb
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rb
⚙️ CodeRabbit configuration file
**/*.rb: # refactoring
- まずFat Controllerを避け、次にFat Modelを避ける。
- Serviceクラスの乱用を避ける。
- controller concernを作ろうとしたらPORO(Plain Old Ruby Object)やActiveRecordモデルでの実装で代替できないか検討する。
Rails Patterns
- ViewHelperにメソッドを実装する時にはまずDecoratorパターンを使うことを検討する。(active_decorator gemを導入しているのでそれを使う)
- 複雑なActiveRecordクエリがあり、再利用できそうな場合はQueryObjectパターンを検討する。(rails-patterns gemを導入しているのでそれのQuery機能を使う)
- Viewにpartialを作る場合はViewComponentを使うことを検討する。
- 複数のActiveRecordモデルを操作する1つの責務がある時や外部APIとやりとりする処理がある場合にはInteractorオブジェクトパターンを検討する。(interactor gemを導入しているのでそれを使う)
- 複数のInteractorを実行するような処理がある場合Organizerオブジェクトパターンを検討する。(interactor gemを導入しており、その中にOrganizerの機能があるので使う)
Files:
test/helpers/products_helper_test.rb
test/**/*
⚙️ CodeRabbit configuration file
test/**/*: # Test
- TestCase名は英語で書く。
- どうしても避けられない時以外にsystem testでsleepは使わない。
Unit Test
model, helper, decorator, view_componentについてはメソッドを追加した場合は必ず対応したUnit TestのTestCaseを1つは書く。
Files:
test/helpers/products_helper_test.rb
🧬 Code graph analysis (1)
test/helpers/products_helper_test.rb (1)
app/helpers/products_helper.rb (1)
unconfirmed_links_label(4-14)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_and_test
🔇 Additional comments (2)
app/views/products/self_assigned/index.html.slim (1)
13-13: 削除されたタイトル設定の影響を確認してください。この行では
@target == 'self_assigned_no_replied'の場合にページタイトルを設定していましたが、削除されています。この削除が意図的なものか、またページタイトルの表示に影響がないか確認してください。test/helpers/products_helper_test.rb (1)
1-21: テストの実装が適切です!
unconfirmed_links_labelヘルパーのすべてのケースを網羅しており、未知のターゲットと nil の処理も確認されています。コーディングガイドラインに従って、英語のテストケース名を使用し、追加されたメソッドに対する単体テストが適切に実装されています。
c87f685 to
24757b4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
app/javascript/unconfirmed-links-open.js (1)
1-15: LGTM! セキュリティ対策が適切に実装されています。
window.openに'noopener'オプションを指定することで、開かれたウィンドウからwindow.openerへのアクセスを防ぎ、セキュリティリスクを軽減しています。ただし、ポップアップブロッカーによってリンクが開けない場合のユーザーフィードバックがありません。必要に応じて、以下のような処理を追加することを検討してください:
allOpenButton.addEventListener('click', () => { + let openedCount = 0 const links = document.querySelectorAll( '.card-list-item .js-unconfirmed-link' ) links.forEach((link) => { - window.open(link.href, '_blank', 'noopener') + const opened = window.open(link.href, '_blank', 'noopener') + if (opened) openedCount++ }) + if (openedCount === 0 && links.length > 0) { + alert('ポップアップがブロックされました。ブラウザの設定を確認してください。') + } })test/models/report_test.rb (1)
65-75: LGTM! 基本的なテストケースは適切です。
uncheckedスコープの基本動作を検証するテストが正しく実装されています。テストケース名も英語で記述されており、コーディングガイドラインに準拠しています。より堅牢なテストのために、チェック済みのレポートが
uncheckedスコープに含まれないことを検証するテストケースの追加を検討してください:test 'unchecked scope does not return reports with checks' do checked_report = reports(:report1) # Assuming this has checks assert_not_empty checked_report.checks assert_not_includes Report.unchecked, checked_report endtest/system/product/unconfirmed_links_open_test.rb (1)
55-72: wait パラメータの一貫性を確認してください。Lines 58 と 64 では
wait: 5を使用していますが、Line 70 では使用していません。動的コンテンツの読み込みタイミングが異なる可能性がありますが、一貫性のために Line 70-71 にもwait: 5を追加することを検討してください。以下のように修正することを検討してください:
test 'mentor sees self_assigned products links' do visit_with_auth '/products/self_assigned', 'komagata' - assert_selector "a.js-unconfirmed-link[href$='#{@self_assigned_product.id}']", count: 1 - assert_selector "a.js-unconfirmed-link[href$='#{@unchecked_no_replied_product.id}']", count: 1 + assert_selector "a.js-unconfirmed-link[href$='#{@self_assigned_product.id}']", count: 1, wait: 5 + assert_selector "a.js-unconfirmed-link[href$='#{@unchecked_no_replied_product.id}']", count: 1, wait: 5 end
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (24)
app/controllers/products/unassigned_controller.rb(2 hunks)app/controllers/products/unchecked_controller.rb(2 hunks)app/controllers/products_controller.rb(2 hunks)app/helpers/products_helper.rb(1 hunks)app/javascript/components/Notifications.jsx(1 hunks)app/javascript/components/Product.jsx(1 hunks)app/javascript/components/Products.jsx(0 hunks)app/javascript/components/Reports.jsx(0 hunks)app/javascript/components/UnconfirmedLink.jsx(0 hunks)app/javascript/unconfirmed-links-open.js(1 hunks)app/views/notifications/index.html.slim(1 hunks)app/views/products/index.html.slim(1 hunks)app/views/products/self_assigned/index.html.slim(1 hunks)app/views/products/unassigned/index.html.slim(1 hunks)app/views/products/unchecked/index.html.slim(1 hunks)test/helpers/products_helper_test.rb(1 hunks)test/models/product_test.rb(1 hunks)test/models/report_test.rb(1 hunks)test/system/product/self_assigned_test.rb(1 hunks)test/system/product/unassigned_test.rb(1 hunks)test/system/product/unchecked_test.rb(1 hunks)test/system/product/unconfirmed_links_open_test.rb(1 hunks)test/system/products_test.rb(3 hunks)test/system/report/unconfirmed_links_open_test.rb(1 hunks)
💤 Files with no reviewable changes (3)
- app/javascript/components/Products.jsx
- app/javascript/components/UnconfirmedLink.jsx
- app/javascript/components/Reports.jsx
🚧 Files skipped from review as they are similar to previous changes (7)
- app/views/products/unassigned/index.html.slim
- app/controllers/products/unassigned_controller.rb
- app/controllers/products/unchecked_controller.rb
- app/helpers/products_helper.rb
- test/helpers/products_helper_test.rb
- test/system/report/unconfirmed_links_open_test.rb
- app/controllers/products_controller.rb
🧰 Additional context used
📓 Path-based instructions (3)
**/*.rb
⚙️ CodeRabbit configuration file
**/*.rb: # refactoring
- まずFat Controllerを避け、次にFat Modelを避ける。
- Serviceクラスの乱用を避ける。
- controller concernを作ろうとしたらPORO(Plain Old Ruby Object)やActiveRecordモデルでの実装で代替できないか検討する。
Rails Patterns
- ViewHelperにメソッドを実装する時にはまずDecoratorパターンを使うことを検討する。(active_decorator gemを導入しているのでそれを使う)
- 複雑なActiveRecordクエリがあり、再利用できそうな場合はQueryObjectパターンを検討する。(rails-patterns gemを導入しているのでそれのQuery機能を使う)
- Viewにpartialを作る場合はViewComponentを使うことを検討する。
- 複数のActiveRecordモデルを操作する1つの責務がある時や外部APIとやりとりする処理がある場合にはInteractorオブジェクトパターンを検討する。(interactor gemを導入しているのでそれを使う)
- 複数のInteractorを実行するような処理がある場合Organizerオブジェクトパターンを検討する。(interactor gemを導入しており、その中にOrganizerの機能があるので使う)
Files:
test/models/report_test.rbtest/system/product/unchecked_test.rbtest/models/product_test.rbtest/system/products_test.rbtest/system/product/unassigned_test.rbtest/system/product/self_assigned_test.rbtest/system/product/unconfirmed_links_open_test.rb
test/**/*
⚙️ CodeRabbit configuration file
test/**/*: # Test
- TestCase名は英語で書く。
- どうしても避けられない時以外にsystem testでsleepは使わない。
Unit Test
model, helper, decorator, view_componentについてはメソッドを追加した場合は必ず対応したUnit TestのTestCaseを1つは書く。
Files:
test/models/report_test.rbtest/system/product/unchecked_test.rbtest/models/product_test.rbtest/system/products_test.rbtest/system/product/unassigned_test.rbtest/system/product/self_assigned_test.rbtest/system/product/unconfirmed_links_open_test.rb
**/*.js
⚙️ CodeRabbit configuration file
**/*.js: - どうしても避けられない時以外に新規にVue.js, Reactのコードを追加しない。
- fetchメソッドの代わりにrequest.jsを使う。
Files:
app/javascript/unconfirmed-links-open.js
🧬 Code graph analysis (6)
test/system/product/unchecked_test.rb (1)
test/supports/product_helper.rb (1)
delete_most_unchecked_products!(4-10)
app/javascript/unconfirmed-links-open.js (1)
app/javascript/user-icon.js (1)
link(7-7)
test/models/product_test.rb (1)
app/models/product.rb (1)
self_assigned_no_replied_products(70-72)
test/system/products_test.rb (2)
test/system/product/self_assigned_test.rb (1)
test(5-207)test/system/product/checker_test.rb (1)
test(5-78)
test/system/product/unassigned_test.rb (2)
test/system/product/self_assigned_test.rb (1)
test(5-207)test/supports/product_helper.rb (1)
delete_most_unassigned_products!(12-18)
test/system/product/unconfirmed_links_open_test.rb (4)
test/system/report/unconfirmed_links_open_test.rb (1)
setup(5-52)test/helpers/products_helper_test.rb (1)
test(5-21)test/system/product/self_assigned_test.rb (1)
test(5-207)test/system/products_test.rb (1)
test(5-731)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_and_test
🔇 Additional comments (15)
app/javascript/components/Product.jsx (1)
57-57: LGTM! クラス追加により一括開封機能との連携が適切に実装されています。
js-unconfirmed-linkクラスの追加により、unconfirmed-links-open.jsのセレクタで正しく選択されるようになっています。既存の機能に影響を与えない適切な変更です。app/javascript/components/Notifications.jsx (1)
9-9: LGTM! React からバニラ JS への移行が適切に反映されています。
isMentorプロップの削除により、未確認リンクの一括開封機能がサーバーサイドレンダリングに移行したことが正しく反映されています。app/views/notifications/index.html.slimで条件付きレンダリングが行われるため、この変更は適切です。test/models/product_test.rb (1)
254-287: LGTM! スコープの動作を包括的にテストしています。追加された4つのテストケースは、各スコープの動作を適切に検証しています:
- unchecked scope: チェックのない提出物が正しく含まれることを確認
- self_assigned_no_replied_products: 担当メンターへの割り当て後、返信がない場合は含まれ、返信後は除外されることを確認(状態変化のテストとして特に優れています)
- unassigned scope: チェッカーが割り当てられていない提出物が含まれることを確認
- self_assigned_product scope: 特定のメンターに割り当てられた提出物が含まれることを確認
テストケース名も英語で記述されており、コーディングガイドラインに準拠しています。
app/views/products/unchecked/index.html.slim (1)
25-26: LGTM! 条件付きレンダリングが適切に実装されています。
@products.present?と@targetのホワイトリストチェックにより、適切な条件下でのみ一括開封ボタンが表示されます。unconfirmed_links_label(@target)ヘルパーの使用も一貫性があり、他のビューと整合性が取れています。app/views/notifications/index.html.slim (1)
48-49: LGTM! メンター向けの一括開封機能が適切に実装されています。3つの条件(
mentor_login?、params[:status] == 'unread'、current_user.notifications.unreads.any?)により、適切な状況でのみ一括開封ボタンが表示されます。未読通知が存在しない場合にボタンが表示されないことで、優れたユーザーエクスペリエンスを提供しています。app/views/products/index.html.slim (1)
17-18: LGTM! 一貫性のある実装です。条件付きレンダリングの実装が他の提出物ビュー(unchecked、unassigned、self_assigned)と一貫性があり、適切です。
@targetのホワイトリストチェックにより、対応するターゲットタイプの場合のみ一括開封機能が表示されます。app/views/products/self_assigned/index.html.slim (1)
18-19: LGTM!条件付きレンダリングのロジックは適切です。
@products.present?と@targetの値を確認し、該当する場合にunconfirmed_links_open部分テンプレートをレンダリングしています。test/system/product/self_assigned_test.rb (1)
28-39: LGTM!テストのリファクタリングは適切です。ウィンドウ操作を削除し、
js-unconfirmed-linkクラスを持つリンク要素の存在確認に変更しています。これは React から vanilla JS への移行に合致しています。test/system/products_test.rb (3)
285-286: LGTM!フォーム要素の読み込みを待つために
wait: 5を追加しています。動的コンテンツの読み込みを考慮した適切な変更です。
302-303: LGTM!Lines 285-286 と同様に、フォーム要素の読み込みを待つために
wait: 5を追加しています。
727-730: LGTM!一括で開くボタンの表示を確認する新しいテストが追加されています。テスト名は英語で記述されており、コーディングガイドラインに準拠しています。
test/system/product/unassigned_test.rb (1)
24-36: LGTM!テストのリファクタリングは他のテストファイルと一貫性があり、適切です。
js-unconfirmed-linkクラスを持つリンク要素の存在を確認するようになっています。test/system/product/unconfirmed_links_open_test.rb (2)
6-46: LGTM!setup ブロックは適切に構成されています。
Notification.stubとWatch.stubを使用して副作用を回避し、テストに必要な3つの提出物(未返信、未アサイン、自分が担当)を作成しています。
49-52: LGTM!一括で開くボタンの表示を確認するテストです。適切です。
test/system/product/unchecked_test.rb (1)
24-35: LGTM!テストのリファクタリングは他のテストファイル(unassigned_test.rb、self_assigned_test.rb)と一貫性があり、適切です。
js-unconfirmed-linkクラスを持つリンク要素の存在を確認するようになっています。
24757b4 to
fc40e5c
Compare
|
@tyrrell-IH さん |
|
@sharoa119 レビューやります! もし「急ぎで〜」とかがあれば先におっしゃってください、その際には優先してレビューします |
|
@sharoa119 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sharoa119 お疲れ様です!時間がかかって申し訳ございません。ようやくレビュー終わりました。
私も知識がないので自信はないですが、ReactからVanillaJSへの置き換えは上手くできているのではないかと思いました。
以下レビューしていて思ったことがあるので書いておきます。
動作確認手順について
動作確認手順をもう少し詳しく書いて欲しかったです。
決められた手順がないので、自分でコードを読んでから手順を考えないといけなかったのがちょっと大変でした💦
警告メッセージの適切な表示
Issueの注意点に「警告メッセージの適切な表示」とあり、sharoaさんのdescriptionにも
警告メッセージの表示確認済み
とありましたが、それがどの部分の動作を指すのかわかりませんでした。なので警告メッセージの動作確認はできていません。この辺をちょっと教えていただきたいです。
挙動についてのところ
descriptionの「挙動について」のところ
一括で開封した直後は「一括で開く」ボタンは画面上に残ります。
ただし「全て」タブを再選択すると非表示になります。
これは、React 版で行っていたような即時非表示の挙動を再現するには状態管理や非同期処理が必要となるため、今回の移行では対応していません。
今回の issue の趣旨(状態管理を使わず、バニラ JS でシンプルに移行する)に沿った実装です。
と書いていますが、
例えば通知機能だけでよければ
//app/javascript/unconfirmed-links-open.js
document.addEventListener('DOMContentLoaded', () => {
const allOpenButton = document.querySelector(
'#js-shortcut-unconfirmed-links-open'
)
if (allOpenButton) {
allOpenButton.addEventListener('click', () => {
const links = document.querySelectorAll(
'.card-list-item .js-unconfirmed-link'
)
links.forEach((link) => {
window.open(link.href, '_blank', 'noopener')
})
if (links.length > 0) { // ←追加
location.reload(); // ←追加
} // ←追加
})
}
})のようにreloadを挟めば一応表示は消えてくれると思います。
追記 2025/10/21 13:30
提出物を一括開いて確認処理をした後でもボタンが残ってしまう問題↓これ
については、この実装でいいか駒形さんによく確認しておいた方が良いと思います。
実装が難しいにしても、以前実現できていたことが、修正によってできなくなるというのは「バグ」と認識されても仕方ないのかなと思います。
Issueにも
未確認リンクの警告を表示する機能。現在はReactコンポーネントとして実装されているが、状態管理が不要な単純な表示コンポーネントのためバニラJSで十分対応可能。
と書いてあるので、何か検討する余地が残されているかもしれません。
(駒形さんに確認した上でこの実装なら、このままで良いと思います👍)
最後に
色々お伝えしましたが、私が間違っていること、勘違いしていることもあるかと思いますので、何か気づくことがあったら教えてください!
app/views/products/index.html.slim
Outdated
| .page-body | ||
| .container.is-md | ||
| = react_component('Products', title: title, selectedTab: 'all', isMentor: mentor_login?, isAdmin: admin_login?, currentUserId: current_user.id) | ||
| - if @products.present? && %w[all unchecked_all unchecked_no_replied unassigned self_assigned self_assigned_all self_assigned_no_replied].include?(@target) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%w[all unchecked_all unchecked_no_replied unassigned self_assigned self_assigned_all self_assigned_no_replied].include?(@target)の条件は必要でしょうか?
products_controller.rbでは
def set_target
@target = 'all'
endとなっているので基本的に@targetにはallしか入らないような気がします。
この条件自体いらないかも?と思いましたが、どんなことを想定して書いたものか教えていただきたいです🙏
app/views/products/self_assigned/index.html.slim
app/views/products/unassigned/index.html.slim
app/views/products/unchecked/index.html.slim
についても同様です。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご指摘ありがとうございます。
当初は unconfirmed_links_open(一括開くボタン)の部分テンプレートを
各サブタブ(unchecked, self_assignedなど)でも共通で使う想定があり、
どのタブで表示すべきかを共通条件で判定できるように実装していました。
ただ、 @tyrrell-IH さんのご指摘のとおり、現状は各タブが個別のビューを持ち、@targetも固定値になっているため、
この条件は現在では不要であると再確認しました。
ご教示くださりありがとうございます。該当箇所は全て修正いたします🙇♀️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご指摘ありがとうございます!コミットメッセージを編集してメンションを外しました。🙇♀️
| assert_equal '全ての提出物を一括で開く', unconfirmed_links_label('all') | ||
| assert_equal '未完了の提出物を一括で開く', unconfirmed_links_label('unchecked') | ||
| assert_equal '未完了の提出物を一括で開く', unconfirmed_links_label('unchecked_all') | ||
| assert_equal '未返信の提出物を一括で開く', unconfirmed_links_label('unchecked_no_replied') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
未返信の提出物を一括で開く(未返信の担当提出物を一括で開くも同様)という分類は以前はなかったように思いますが追加されましたでしょうか?
文言はこのままで問題ないと思いますが、細かなことでも仕様変更があったらどこかに書いといてもらえると助かります🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
元々uncheckedとself_assignedのサブタブには全てと未返信がありましたが、
どちらもボタンラベルが同じで表示されていました。
UX上、サブタブごとにラベルを適切にする方がわかりやすいと判断し、
ProductsHelper#unconfirmed_links_labelにunchecked_no_repliedと self_assigned_no_repliedを追加して対応しました。
文言は既存のパターンに沿っており、動作も既存と同様です。
ただ、最初にこの意図を説明しておくべきでした。すみません。😞
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UX上、サブタブごとにラベルを適切にする方がわかりやすいと判断し、
ProductsHelper#unconfirmed_links_labelにunchecked_no_repliedと self_assigned_no_repliedを追加して対応しました。
確かにサブタブごとの方が見やすいですね、了解です🙆
| # 自分が担当かつ未返信提出物 | ||
| @unchecked_no_replied_product = Product.create!( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
自分が担当かつ未返信提出物なら@self_assigned_no_replied_productが正しいかも?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご指摘ありがとうございます!
確かにです!修正しました!
test/system/products_test.rb
Outdated
| test 'sees the open all products button on products page' do | ||
| visit_with_auth '/products', 'komagata' | ||
| assert_selector 'button', text: '全ての提出物を一括で開く' | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test/system/product/unconfirmed_links_open_test.rbの49行目とテストが重複しているような気がします。
| test 'mentor sees bulk open button when unchecked products exist' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご指摘ありがとうございます!
自分で同じ内容のテストを追加していましたね💦全然気づいていませんでした💦
重複しているテストは削除いたしました。
| test 'mentor sees unassigned products links' do | ||
| visit_with_auth '/products/unassigned', 'komagata' | ||
|
|
||
| assert_selector "a.js-unconfirmed-link[href$='#{@unassigned_product.id}']", count: 1, wait: 5 | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test/system/product/unassigned_test.rbの24行目のテストと重複してるかもしれません。
| test 'unassigned products links are rendered correctly' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご指摘ありがとうございます。
テストの重複について、こちらで探しきれておらず申し訳ありませんでした😞
今後は既存テストの確認も含めて整理するようにします。
| test 'mentor sees self_assigned products links' do | ||
| visit_with_auth '/products/self_assigned', 'komagata' | ||
|
|
||
| assert_selector "a.js-unconfirmed-link[href$='#{@self_assigned_product.id}']", count: 1 | ||
| assert_selector "a.js-unconfirmed-link[href$='#{@unchecked_no_replied_product.id}']", count: 1 | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test/system/product/self_assigned_test.rbの28行目と重複してるかもしれません。
| test 'self-assigned products links are rendered correctly' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご指摘ありがとうございます。
こちらも上と同様、テストの重複についてこちらで探しきれておらず申し訳ありませんでした😞
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
テストを書く場所が人によってまちまちなので、気づかなくてもしょうがないですよね😅
「どこにテストを書く」みたいな指針があればいいなと思いますが、、
test/models/product_test.rb
Outdated
| test 'self_assigned_no_replied_products returns products assigned to user with no reply' do | ||
| mentor = users(:komagata) | ||
| product = Product.create!(user: users(:hajime), practice: practices(:practice2), body: '提出物', checker_id: mentor.id) | ||
|
|
||
| assert_includes Product.self_assigned_no_replied_products(mentor.id), product | ||
|
|
||
| Comment.create!( | ||
| commentable: product, | ||
| user: mentor, | ||
| description: '返信済み', | ||
| created_at: Time.current, | ||
| updated_at: Time.current | ||
| ) | ||
|
|
||
| assert_not_includes Product.self_assigned_no_replied_products(mentor.id), product | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bootcamp/test/models/product_test.rb
Line 134 in fc40e5c
| test '.self_assigned_no_replied_products' do |
同じテストがあると思います。
Comment.create!以降のコードはself_assigned_no_replied_productsの動作と関係ないので必要ないかもしれません。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご指摘ありがとうございます。
既存の .self_assigned_no_replied_productsのテストでは「返信がない提出物が含まれること」を確認していましたが、
「返信済みの提出物が除外されること」はカバーされていなかったため、
このテストではそのケースも合わせて検証しています。
つまり、スコープの正確な条件分岐のテストとして追加している形になります。
(Comment.create! 以降の処理はその確認のために追加しています)
もしテストとして冗長すぎると判断される場合は、削除していただいて構いませんので、遠慮なくお知らせください
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
「返信済みの提出物が除外されること」はカバーされていなかったため、
このテストではそのケースも合わせて検証しています。
なるほど、おっしゃる通りですね。理解しました👍
テスト内容の意図は別でもタイトルが
.self_assigned_no_replied_productsとself_assigned_no_replied_products returns products assigned to user with no reply
では同じ内容のテストに見えるので
.self_assigned_no_replied_productsに
Comment.create!(
commentable: product,
user: mentor,
description: '返信済み',
created_at: Time.current,
updated_at: Time.current
)
assert_not_includes Product.self_assigned_no_replied_products(mentor.id), product
を追記しまう。
- テスト内容自体はこのままにして、テスト名を例えば
self_assigned_no_replied_products excludes products that have already been replied toのように「返信済みのものが除外されていることを確認する」のようなニュアンスにする。
のどちらかの方が良いかなと思うのですが、どうでしょうか?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご指摘ありがとうございます。
いただいた案を検討した結果、今回はテスト内容をまとめて .self_assigned_no_replied_productsの1つのテスト内で、「未返信の提出物に含まれること」と「コメントが返されたら除外されること」の両方を確認する形にしました。
テスト名は従来のままにし、コメントで「メンターがコメントすると除外されることを確認」と追記して、意図がわかるようにしています⭐️
| Notification.stub(:create!, nil) do | ||
| Watch.stub(:create!, nil) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ここはどういった理由で書いてますか?
特に意図がある質問ではなく、純粋に「何でだろう」と思ったので質問しました🧐
Productを作成してもNotification.create! や Watch.create!は呼ばれなそうだし、呼ばれたとしてunconfirmed_links_open_testの動作にはあんまり影響しないように思いました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご質問ありがとうございます。
もともとは Product.create!時にNotificationやWatchが作成される副作用を抑えるために書いたのですが、今回のテストではボタン表示やリンク確認のみを行うため、NotificationやWatchの有無はテスト結果に影響しないことに改めて確認して気づきました。教えていただきありがとうございます🙂
そのため、このテストに関してはstubは不要であり、削除いたします。
|
@tyrrell-IH さん ①動作確認手順について ご指摘ありがとうございます! ②警告メッセージの適切な表示 Issueの『警告メッセージの適切な表示』という文言についてですが、実際の ③挙動についてのところ コメントありがとうございます! とりあえず、こちらの返信を先にさせていただきました〜。 |
|
@komagata さん #9184 (review) 提出物を一括開いた後でもボタンが残る件についての件なのですが、 UXや以前の挙動との差異について、駒形さんにご確認いただいた上で、この実装で問題ないか判断していただけると助かります。 もし「以前のように即時非表示にしたほうが良い」という判断であれば、別Issueで対応を検討することも可能です。 よろしくお願いいたします🙇♀️ |
|
@sharoa119 本PRと修正箇所が重なると思うので、どうするか相談して決めた方が良いのかなと思いました |
|
@sharoa119 |
|
@tyrrell-IH さん @smallmonkeykey さん
こちら、かしこまりました! 1点確認させてください。
とのことですが、リサさんの担当されていた issue を確認したところ、
という内容でした。 つまり今回は、Stimulus の導入はやめて、削除対象だったファイルを戻し、バニラJSでの対応に変更、という認識で合っていますか? その場合、通知機能まわりはリサさんが対応される予定という理解でよいでしょうか? とりあえず、何か変更や調整があればご連絡いただければと思います🙇♀️ |
| def set_target | ||
| @target = params[:target] | ||
| @target = 'unchecked_all' unless target_allowlist.include?(@target) | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
こちらも app/controllers/products/unassigned_controller.rb と同じようにindexしかアクションがないのであれば、indexで処理した方がわかりやすいかとおもいます。
他にも同様の指摘が当てはまる場所がないかどうか確かめてみるとよいかもです〜
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご指摘ありがとうございます。
unchecked_controller もindexのみのアクションであったため、
before_actionを使用せず index内で処理する形に修正しました。
他にも同様の指摘が当てはまる場所がないかどうか確かめてみるとよいかもです〜
かしこまりました!ご教示ありがとうございます🙇♀️
| require 'test_helper' | ||
|
|
||
| class ProductsHelperTest < ActionView::TestCase | ||
| test 'unconfirmed_links_label returns correct label for all targets' do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
helperメソッドを追加したときにしっかりテストも追加しているのいいですね!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ありがとうございます✨
- unconfirmed_links_label ヘルパーを更新して self_assigned_all / self_assigned_no_replied に対応 - self_assigned タブでボタンが正しく表示されるよう修正し、他のタブと整合性を揃えた
- window.open の挙動確認は廃止 - モデル・コントローラのテストに追加・修正
- 重複していたテストを削除 - それに伴いsetupなど修正
3ade16c to
eac76e9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
app/views/users/reports/index.html.slim (1)
19-20: ラベルの生成方法を統一することを検討してください提出物ページでは
unconfirmed_links_label(@target)ヘルパーを使用していますが、こちらでは日本語ラベルがハードコードされています。将来的に日報用のヘルパーメソッドを追加するか、既存の
ProductsHelper#unconfirmed_links_labelをApplicationHelperに移動して日報のターゲット ('unchecked_reports'など) にも対応させることで、一貫性が向上します。現時点では動作に問題はありませんが、ラベル管理の一元化を検討する価値があります。
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
app/controllers/products/self_assigned_controller.rb(1 hunks)app/controllers/products/unassigned_controller.rb(1 hunks)app/controllers/products/unchecked_controller.rb(1 hunks)app/controllers/products_controller.rb(2 hunks)app/controllers/users/reports_controller.rb(2 hunks)app/helpers/products_helper.rb(1 hunks)app/javascript/components/Notifications.jsx(1 hunks)app/javascript/components/Product.jsx(1 hunks)app/javascript/components/Products.jsx(0 hunks)app/javascript/components/Reports.jsx(0 hunks)app/javascript/components/UnconfirmedLink.jsx(0 hunks)app/javascript/unconfirmed-links-open.js(1 hunks)app/views/application/_unconfirmed_links_open.html.slim(1 hunks)app/views/products/index.html.slim(1 hunks)app/views/products/self_assigned/index.html.slim(1 hunks)app/views/products/unassigned/index.html.slim(1 hunks)app/views/products/unchecked/index.html.slim(1 hunks)app/views/users/reports/index.html.slim(2 hunks)test/helpers/products_helper_test.rb(1 hunks)test/models/product_test.rb(3 hunks)test/models/report_test.rb(1 hunks)test/system/product/self_assigned_test.rb(1 hunks)test/system/product/unassigned_test.rb(1 hunks)test/system/product/unchecked_test.rb(1 hunks)test/system/product/unconfirmed_links_open_test.rb(1 hunks)test/system/report/unconfirmed_links_open_test.rb(1 hunks)
💤 Files with no reviewable changes (3)
- app/javascript/components/Products.jsx
- app/javascript/components/Reports.jsx
- app/javascript/components/UnconfirmedLink.jsx
🚧 Files skipped from review as they are similar to previous changes (14)
- app/views/products/unchecked/index.html.slim
- app/javascript/unconfirmed-links-open.js
- test/system/product/self_assigned_test.rb
- test/helpers/products_helper_test.rb
- app/controllers/products/self_assigned_controller.rb
- app/javascript/components/Product.jsx
- test/models/product_test.rb
- app/views/products/unassigned/index.html.slim
- test/system/product/unconfirmed_links_open_test.rb
- app/controllers/products/unchecked_controller.rb
- test/system/report/unconfirmed_links_open_test.rb
- app/views/products/index.html.slim
- app/controllers/products/unassigned_controller.rb
- test/system/product/unchecked_test.rb
🧰 Additional context used
📓 Path-based instructions (7)
**/*.slim
📄 CodeRabbit inference engine (AGENTS.md)
Slim templates should be linted according to
config/slim_lint.yml
Files:
app/views/products/self_assigned/index.html.slimapp/views/users/reports/index.html.slimapp/views/application/_unconfirmed_links_open.html.slim
app/**/*.{rb,js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Rails app code should be organized in
app/directory with subdirectories:models/,controllers/,views/,jobs/,helpers/, and frontend code underjavascript/(Shakapacker)
Files:
app/controllers/products_controller.rbapp/javascript/components/Notifications.jsxapp/helpers/products_helper.rbapp/controllers/users/reports_controller.rb
**/*.rb
📄 CodeRabbit inference engine (AGENTS.md)
Ruby code should use 2-space indentation, snake_case for method names, and CamelCase for class names, enforced by RuboCop (
.rubocop.yml)
Files:
app/controllers/products_controller.rbtest/system/product/unassigned_test.rbtest/models/report_test.rbapp/helpers/products_helper.rbapp/controllers/users/reports_controller.rb
⚙️ CodeRabbit configuration file
**/*.rb: # refactoring
- まずFat Controllerを避け、次にFat Modelを避ける。
- Serviceクラスの乱用を避ける。
- controller concernを作ろうとしたらPORO(Plain Old Ruby Object)やActiveRecordモデルでの実装で代替できないか検討する。
Rails Patterns
- ViewHelperにメソッドを実装する時にはまずDecoratorパターンを使うことを検討する。(active_decorator gemを導入しているのでそれを使う)
- 複雑なActiveRecordクエリがあり、再利用できそうな場合はQueryObjectパターンを検討する。(rails-patterns gemを導入しているのでそれのQuery機能を使う)
- Viewにpartialを作る場合はViewComponentを使うことを検討する。
- 複数のActiveRecordモデルを操作する1つの責務がある時や外部APIとやりとりする処理がある場合にはInteractorオブジェクトパターンを検討する。(interactor gemを導入しているのでそれを使う)
- 複数のInteractorを実行するような処理がある場合Organizerオブジェクトパターンを検討する。(interactor gemを導入しており、その中にOrganizerの機能があるので使う)
Files:
app/controllers/products_controller.rbtest/system/product/unassigned_test.rbtest/models/report_test.rbapp/helpers/products_helper.rbapp/controllers/users/reports_controller.rb
test/**/*_test.rb
📄 CodeRabbit inference engine (AGENTS.md)
test/**/*_test.rb: Test suite should use Minitest with structure:system/,models/,controllers/, and fixtures intest/fixtures/; test files should be named*_test.rb
Use Minitest + Capybara for system tests; place unit and integration tests under matchingtest/*directories
Files:
test/system/product/unassigned_test.rbtest/models/report_test.rb
test/**
📄 CodeRabbit inference engine (AGENTS.md)
Keep tests deterministic and use fixtures stored in
test/fixtures/for test data
Files:
test/system/product/unassigned_test.rbtest/models/report_test.rb
test/**/*
⚙️ CodeRabbit configuration file
test/**/*: # Test
- TestCase名は英語で書く。
- どうしても避けられない時以外にsystem testでsleepは使わない。
Unit Test
model, helper, decorator, view_componentについてはメソッドを追加した場合は必ず対応したUnit TestのTestCaseを1つは書く。
Files:
test/system/product/unassigned_test.rbtest/models/report_test.rb
app/javascript/**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
JavaScript/TypeScript code in
app/javascript/should be linted with ESLint and formatted with Prettier viayarn lintscripts; use React 17 and Shakapacker/Webpack 5
Files:
app/javascript/components/Notifications.jsx
🧠 Learnings (17)
📓 Common learnings
Learnt from: tyrrell-IH
Repo: fjordllc/bootcamp PR: 9306
File: app/javascript/components/Bookmarks.jsx:248-265
Timestamp: 2025-11-17T00:46:30.794Z
Learning: fjordllc/bootcamp プロジェクトでは、Reactからバニラ JavaScript への移行作業が進行中である。そのため、新しいReactファイルの作成は避け、既存のReactコンポーネント内で完結する実装が推奨される。BookmarksInDashboard.jsx は issue #9045 で削除予定。
Learnt from: sjabcdefin
Repo: fjordllc/bootcamp PR: 9090
File: app/javascript/user-sns.js:2-25
Timestamp: 2025-08-25T08:00:11.369Z
Learning: app/javascript/user-sns.js において、アクセシビリティ改善(aria-label属性の追加など)は他の箇所との整合性を保つため、別途統一して対応する方針である
📚 Learning: 2025-11-19T07:55:51.504Z
Learnt from: smallmonkeykey
Repo: fjordllc/bootcamp PR: 9314
File: app/helpers/page_tabs/dashboard_helper.rb:8-12
Timestamp: 2025-11-19T07:55:51.504Z
Learning: fjordllc/bootcamp プロジェクトにおいて、分報(micro_reports)は current_user 専用の機能ではなく、他ユーザーの分報も閲覧・管理する UI で使われているため、ダッシュボードの「自分の分報」タブでは user_micro_reports_path(current_user, ...) を使用し、/users/:id/micro_reports の URL 構造を維持する。current_user 名前空間に新しいルートを追加しない方針である。
Applied to files:
app/views/users/reports/index.html.slim
📚 Learning: 2025-09-12T01:00:58.452Z
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: app/views/mentor/buzzes/edit.html.slim:1-0
Timestamp: 2025-09-12T01:00:58.452Z
Learning: app/views/mentor/buzzes/edit.html.slim では `- title` と `- set_meta_tags` の両方が正しく設定されており、タイトルは削除されていない。変更内容はメタディスクリプションの追加のみ。
Applied to files:
app/views/users/reports/index.html.slim
📚 Learning: 2025-08-28T00:34:28.541Z
Learnt from: mousu-a
Repo: fjordllc/bootcamp PR: 8566
File: app/views/application/_global_nav.slim:48-54
Timestamp: 2025-08-28T00:34:28.541Z
Learning: app/views/application/_global_nav.slim のQ&A/ペアワークバッジの環境分岐は、ペアワーク機能の本番リリース後に削除される一時的な実装である。その際、メンター・管理者のみに表示する制限仕様も撤廃される予定のため、現在の実装にはアクセス権限ガードを追加する必要がない。
Applied to files:
app/views/users/reports/index.html.slim
📚 Learning: 2025-07-23T20:31:13.856Z
Learnt from: jun-kondo
Repo: fjordllc/bootcamp PR: 8977
File: app/controllers/reports_controller.rb:63-63
Timestamp: 2025-07-23T20:31:13.856Z
Learning: fjordllc/bootcampプロジェクトの`app/controllers/reports_controller.rb`において、`create`と`update`アクションは両方とも`report.save_uniquely`を使用し、同じ`:report_save`イベントと`'report.save'`イベントを発行する。これは両方とも本質的に「レポートの保存」操作であり、作成と更新を区別する必要がないためである。
Applied to files:
app/views/users/reports/index.html.slimtest/models/report_test.rbapp/controllers/users/reports_controller.rb
📚 Learning: 2025-08-31T03:39:07.792Z
Learnt from: mousu-a
Repo: fjordllc/bootcamp PR: 8566
File: app/views/pair_works/_body.html.slim:85-85
Timestamp: 2025-08-31T03:39:07.792Z
Learning: app/views/pair_works/_body.html.slimテンプレートには2つの独立したif pair_work.solved?条件分岐があり、user変数は最初の分岐でのみ設定されるため、2番目の分岐での参照には注意が必要。
Applied to files:
app/views/users/reports/index.html.slim
📚 Learning: 2025-07-23T20:42:19.974Z
Learnt from: jun-kondo
Repo: fjordllc/bootcamp PR: 0
File: :0-0
Timestamp: 2025-07-23T20:42:19.974Z
Learning: fjordllc/bootcampプロジェクトでは、hタグ(見出し)の文言は日本語でハードコーディングする方針が確立されており、I18n対応は行わない。例:app/views/welcome/logo.html.slimでh2、h3タグが日本語でハードコーディングされている。
Applied to files:
app/views/users/reports/index.html.slim
📚 Learning: 2025-09-12T21:18:00.834Z
Learnt from: komagata
Repo: fjordllc/bootcamp PR: 9101
File: app/notifiers/discord_notifier.rb:131-135
Timestamp: 2025-09-12T21:18:00.834Z
Learning: Rails アップグレードPRにおいて、product_review_not_completed メソッドの webhook URL 設定の shared フォールバック追加も、設定システム全体の変更として別PRで対応すべきである。
Applied to files:
test/system/product/unassigned_test.rbapp/views/application/_unconfirmed_links_open.html.slimapp/helpers/products_helper.rb
📚 Learning: 2025-09-05T03:16:53.387Z
Learnt from: sharoa119
Repo: fjordllc/bootcamp PR: 9012
File: app/queries/grass_learning_time_query.rb:30-37
Timestamp: 2025-09-05T03:16:53.387Z
Learning: reports テーブルには既に (user_id, reported_on) の一意制約インデックス index_reports_on_user_id_and_reported_on が存在するため、学習時間集計クエリのパフォーマンス最適化には追加のインデックスは不要。
Applied to files:
test/models/report_test.rb
📚 Learning: 2025-09-05T03:33:31.659Z
Learnt from: sharoa119
Repo: fjordllc/bootcamp PR: 9012
File: db/migrate/20250905025850_remove_redundant_index_from_reports.rb:5-5
Timestamp: 2025-09-05T03:33:31.659Z
Learning: reports テーブルには既存の一意制約インデックス index_reports_on_user_id_and_reported_on があるため、同じカラム組み合わせ (user_id, reported_on) の非一意インデックスは冗長であり削除が適切。
Applied to files:
test/models/report_test.rb
📚 Learning: 2025-09-05T03:33:31.659Z
Learnt from: sharoa119
Repo: fjordllc/bootcamp PR: 9012
File: db/migrate/20250905025850_remove_redundant_index_from_reports.rb:5-5
Timestamp: 2025-09-05T03:33:31.659Z
Learning: reports テーブルには既存の一意制約インデックス index_reports_on_user_id_and_reported_on があるため、同じカラム組み合わせ (user_id, reported_on) の非一意インデックスは冗長であり削除が適切。一意制約インデックスは非一意インデックスと同等かそれ以上のクエリ性能を提供する。
Applied to files:
test/models/report_test.rb
📚 Learning: 2025-07-10T12:59:27.807Z
Learnt from: kitarou888
Repo: fjordllc/bootcamp PR: 8277
File: test/models/searcher_test.rb:326-331
Timestamp: 2025-07-10T12:59:27.807Z
Learning: モデルテストにおいて、1つのクラスメソッドの複数の挙動を検証する場合、機能の異なる側面を同じテストメソッドでテストすることは、包括的なテストとして適切である。特に`only_me`のような機能では、異なる検索条件(空文字と具体的な検索語)を使い分けることで、より広範囲な動作保証が可能となる。
Applied to files:
test/models/report_test.rb
📚 Learning: 2025-10-22T06:04:36.036Z
Learnt from: sjabcdefin
Repo: fjordllc/bootcamp PR: 9247
File: app/controllers/checks_controller.rb:0-0
Timestamp: 2025-10-22T06:04:36.036Z
Learning: ChecksController#createおよび#destroyでは、Checkの作成・削除とActiveSupport::Notifications.instrumentによるイベント発行(プラクティスのステータス更新)を同一トランザクション内で実行し、いずれかが失敗した場合は両方をロールバックする。これによりWebUI表示とDB状態の整合性を保証している。
Applied to files:
test/models/report_test.rb
📚 Learning: 2025-07-07T12:46:01.650Z
Learnt from: masyuko0222
Repo: fjordllc/bootcamp PR: 8277
File: test/models/searcher_test.rb:0-0
Timestamp: 2025-07-07T12:46:01.650Z
Learning: テストにおいて、`result.all? { |condition| }` でコレクションの全要素が条件を満たすことを確認できれば、その条件を満たさない要素が含まれていないことも論理的に保証されるため、追加のアサーションは冗長となる。
Applied to files:
test/models/report_test.rb
📚 Learning: 2025-08-25T08:00:11.369Z
Learnt from: sjabcdefin
Repo: fjordllc/bootcamp PR: 9090
File: app/javascript/user-sns.js:2-25
Timestamp: 2025-08-25T08:00:11.369Z
Learning: app/javascript/user-sns.js において、アクセシビリティ改善(aria-label属性の追加など)は他の箇所との整合性を保つため、別途統一して対応する方針である
Applied to files:
app/views/application/_unconfirmed_links_open.html.slim
📚 Learning: 2025-11-17T00:46:30.794Z
Learnt from: tyrrell-IH
Repo: fjordllc/bootcamp PR: 9306
File: app/javascript/components/Bookmarks.jsx:248-265
Timestamp: 2025-11-17T00:46:30.794Z
Learning: fjordllc/bootcamp プロジェクトでは、Reactからバニラ JavaScript への移行作業が進行中である。そのため、新しいReactファイルの作成は避け、既存のReactコンポーネント内で完結する実装が推奨される。BookmarksInDashboard.jsx は issue #9045 で削除予定。
Applied to files:
app/javascript/components/Notifications.jsx
📚 Learning: 2025-07-30T07:26:36.599Z
Learnt from: ryufuta
Repo: fjordllc/bootcamp PR: 8992
File: app/models/correct_answer_notifier.rb:23-23
Timestamp: 2025-07-30T07:26:36.599Z
Learning: Railsの標準的なヘルパーメソッド(例:`question_url`、`user_path`など)が通常の方法で使用されている場合、それらの動作テストは不要である。これらのメソッドはRailsフレームワーク自体でテストされており、アプリケーション固有のロジックではないため。
Applied to files:
app/helpers/products_helper.rb
🧬 Code graph analysis (3)
app/controllers/products_controller.rb (3)
app/controllers/products/unchecked_controller.rb (1)
before_action(3-25)app/controllers/products/self_assigned_controller.rb (1)
before_action(3-32)app/controllers/products/unassigned_controller.rb (1)
before_action(3-15)
test/system/product/unassigned_test.rb (2)
test/system/product/self_assigned_test.rb (1)
test(5-207)test/supports/product_helper.rb (1)
delete_most_unassigned_products!(12-18)
app/controllers/users/reports_controller.rb (1)
app/controllers/reports/unchecked_controller.rb (1)
before_action(3-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_and_test
🔇 Additional comments (8)
app/javascript/components/Notifications.jsx (1)
9-98: LGTM - コンポーネント全体の構成は適切です通知一覧の表示、ページネーション、フィルタリングのロジックが明確に分離されています。SWRキーの問題を修正すれば、このコンポーネントは正しく動作します。
test/models/report_test.rb (1)
65-75: LGTM - uncheckedスコープのテストが適切に追加されていますテストは必要な検証を行っており、checksが空であることと
Report.uncheckedに含まれることの両方を確認しています。コーディングガイドラインに従い、モデルメソッドのテストケースが適切に追加されています。app/views/products/self_assigned/index.html.slim (1)
18-19: LGTM - 他のproductsビューと一貫したパターンで実装されています
@products.present?の条件付きレンダリングとunconfirmed_links_label(@target)ヘルパーの使用は、products/index.html.slimやproducts/unassigned/index.html.slimと同じパターンに従っています。app/controllers/products_controller.rb (1)
7-7: LGTM - 他の Products 関連コントローラーと一貫したパターンです
set_targetメソッドはProducts::UnassignedControllerでの@target = 'unassigned'、Products::SelfAssignedControllerでのパラメータベースの@target設定と同じパターンに従っています。ビューでのunconfirmed_links_label(@target)呼び出しをサポートするために必要な変更です。Also applies to: 158-160
app/controllers/users/reports_controller.rb (1)
66-68: LGTM - 過去のレビューフィードバックに従った実装です
set_unchecked_countを専用メソッドとして切り出すことで、set_reportsの責務とカウント取得の責務が適切に分離されています。なお、
set_reportsメソッド(36-37行目)でも@user.reports.unchecked.not_wipを使用していますが、現時点では共通化よりも可読性を優先する形で問題ありません。app/views/application/_unconfirmed_links_open.html.slim (1)
1-5: LGTM! 実装が適切ですフォームアクション構造がクリーンで、
type="button"属性も正しく設定されています。以前のレビューコメントで指摘された点が適切に修正されており、問題ありません。app/helpers/products_helper.rb (1)
4-14: LGTM! ヘルパーメソッドの実装が適切ですターゲットに応じた日本語ラベルのマッピングが明確で、すべてのケースが適切にカバーされています。以前のレビューで指摘された単体テストも追加済みです。
test/system/product/unassigned_test.rb (1)
24-36: LGTM! テストの実装が適切ですReact コンポーネントからバニラ JavaScript への移行に合わせて、テストが適切に更新されています。ウィンドウ操作の検証から、レンダリングされたリンク要素(
js-unconfirmed-linkクラス)の存在確認に変更されており、新しい実装方針と一致しています。他の system test(
self_assigned_test.rbなど)とも一貫性のあるパターンになっています。
|
@komagata さん |
| ) | ||
| links.forEach((link) => { | ||
| window.open(link.href, '_target', 'noopener') | ||
| window.open(link.href, '_blank', 'noopener') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ここってなんで_blankに変更されてるんでしたっけ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@komagata さん
コメントありがとうございます。
自分なりに調べたところ、_targetは予約されたtargetではなく、
ウィンドウ名として扱われることがわかり、
そうなると、同じタブが再利用される可能性があるということがわかりました。
このunconfirmed-links-open.jsは複数リンクをそれぞれ新しいタブで開く意図だったため、
毎回新しいタブが開く_blank に変更しています。
よろしくお願いいたします🙇♀️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@komagata さん
ブラウザ側であらかじめ意味と挙動が定義されている
特別な target 名、という意味で使っていました。
(_blank / _self など)
これらは仕様上それぞれ挙動が固定されており、
それ以外の文字列は単なるウィンドウ名として扱われる挙動になります。
よろしくお願いいたします🙇♀️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sharoa119 なるほどです〜
| @@ -1,5 +1,5 @@ | |||
| - title "#{@user.login_name} 日報" | |||
| - set_meta_tags description: "#{@user.login_name}さんの質問一覧ページです。" | |||
| - set_meta_tags description: "#{@user.login_name}さんの日報一覧ページです。" | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
komagata
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
確認させていただきました。OKです〜🙆♂️
| ) | ||
| links.forEach((link) => { | ||
| window.open(link.href, '_target', 'noopener') | ||
| window.open(link.href, '_blank', 'noopener') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sharoa119 なるほどです〜
Issue
概要
UnconfirmedLink.jsxコンポーネントをReactからバニラJavaScriptに移行する。(非React化)実装内容
挙動について
一括で開封した直後は「一括で開く」ボタンは画面上に残ります。
ただし「全て」タブを再選択すると非表示になります。
これは、React 版で行っていたような即時非表示の挙動を再現するには状態管理や非同期処理が必要となるため、今回の移行では対応していません。
今回の issue の趣旨(状態管理を使わず、バニラ JS でシンプルに移行する)に沿った実装です。
確認事項
変更確認方法
chore/replace_vanilla_js_in_unconfirmed_link_jsxをローカルに取り込むforeman start -f Procfile.devでローカル環境を立ち上げるkomagataのアカウントでログイン。パスワードはtesttest/notifications?status=unread→ 表示されるボタン:未読の通知を一括で開く/products→ 表示されるボタン:全ての提出物を一括で開く/products/unchecked→ 表示されるボタン:未完了の提出物を一括で開く/products/unchecked?target=unchecked_no_replied→ 表示されるボタン:未返信の提出物を一括で開く/unassigned→ 表示されるボタン:未アサインの提出物を一括で開く/products/self_assigned→ 表示されるボタン:自分の担当の提出物を一括で開く/products/self_assigned?target=self_assigned_no_replied→ 表示されるボタン:未返信の担当の提出物を一括で開く各リンクが新しいタブで開けばOK。
もし1件しか開かない場合は、Chromeのポップアップブロックが原因。(発生した場合は、以下の動作確認時の注意を読んでください。)
2025-10-03.11.10.09.mov
※自分が担当の提出物において、最初は何もありませんが、
未完了のところからどれかを選んで「担当する」ボタンを押していただくと、
自分の担当タブの中に表示されるので、そちらでボタンが表示されるかなどのご確認をお願いいたします。
動作確認時の注意
表示されている「一括で開く」ボタンを押した際、先頭の1件しか開かない場合があります。
これは
Chromeのポップアップブロック機能(window.openを利用したタブの同時オープンも対象)が原因です。動作確認を行う場合は、以下いずれかでポップアップを許可してください。
Screenshot
内部変更で画面の変更がないので、スクリーンショットはありません。
テスト方針について
前提
通知: 開封すると既読処理が入るため、通常のテストで補える
日報・提出物: 開封しても未チェックのままなので、JS でリンクが正しく開かれることを保証する必要がある
テスト方針
今回の変更で使用しているバニラ JavaScript は、
「ボタンをクリックすると未確認リンクを
window.openで一括開封する」処理です。しかし、
window.openの挙動をシステムテストで直接検証するのは難しいため、以下の 3 つの観点で間接的にテストを行っています。
1. モデル単体テスト
2. システムテスト(ボタン表示)
※本テストでは、移行後のコードが元々の仕様に沿って動作することを確認しています。
3. システムテスト(リンク存在)
.js-unconfirmed-linkが期待通りレンダリングされているかを確認※従来のテストを活かしつつ、内容を「
.js-unconfirmed-linkが正しくレンダリングされていることを確認する」形式に修正しています。補足: window.open の挙動について
本テストでは、ボタンが正しく表示されクリック可能であることまでを確認しています。
ただし、ボタン押下時に新しいタブが開くかどうか(
window.openの挙動)はMinitest(Rails の System Test)では直接検証できない仕様です。この動作はフロントエンド側の
JavaScriptに依存しており、手動またはブラウザ上での確認により保証しています。👉 System Test では最低限、ユーザーがボタンを認識して操作できることを確認することが目的です。
補足: webpacker のエラーについて
テスト実行時に
packが最新でない場合、JavaScriptやCSSが正しく読み込まれずエラーになることがあります。その場合は以下を実行してください。
👉 この 3 点で、直接 JS をテストしなくても
「対象データが正しくレンダリングされ、必要な場面でボタンが表示される」ことを確認しています。
Summary by CodeRabbit
リリースノート
新機能
改善
✏️ Tip: You can customize this high-level summary in your review settings.