with_request_urlテストヘルパーにprotocolパラメータを追加
ViewComponentのwith_request_urlテストヘルパーにprotocol:パラメータが追加され、HTTPSプロトコルを使用するコンポーネントのテストが容易になります。これにより、環境変数を直接操作することなく、宣言的にプロトコルを指定できるようになります。
背景
Railsの*_urlヘルパー(products_urlなど)をコンポーネント内で使用する場合、デフォルトではHTTPプロトコルでURLが生成されます。HTTPSプロトコルでのURL生成をテストするには、vc_test_controller.request.env['HTTPS'] = 'on'のようにRackの環境変数を直接設定する必要がありました。#2446がこの課題を提起し、#2550がより宣言的なテストインターフェースを提供しています。
with_request_urlヘルパーは既にhost:とmethod:パラメータをサポートしていましたが、プロトコルの指定には対応していませんでした。プロトコルは多くのアプリケーションで重要な関心事であり、APIエンドポイントや外部サービスとの連携では明示的なHTTPS URLの生成が求められます。
技術的な変更
lib/view_component/test_helpers.rbのwith_request_urlメソッドにprotocol:キーワード引数が追加されました。
変更前:
def with_request_url(full_path, host: nil, method: nil)
old_request_host = vc_test_request.host
old_request_method = vc_test_request.request_method
# ...
vc_test_request.host = host if host
vc_test_request.request_method = method if method
# ...
ensure
vc_test_request.host = old_request_host
vc_test_request.request_method = old_request_method
# ...
end
変更後:
def with_request_url(full_path, host: nil, method: nil, protocol: nil)
old_request_host = vc_test_request.host
old_request_method = vc_test_request.request_method
old_request_scheme = vc_test_request.scheme
# ...
vc_test_request.host = host if host
vc_test_request.request_method = method if method
vc_test_request.set_header(Rack::RACK_URL_SCHEME, protocol.to_s) if protocol
# ...
ensure
vc_test_request.host = old_request_host
vc_test_request.request_method = old_request_method
vc_test_request.set_header(Rack::RACK_URL_SCHEME, old_request_scheme)
# ...
end
プロトコルの設定にはRack::RACK_URL_SCHEMEヘッダーが使用されています。このヘッダーはRackの標準的なプロトコル指定方法であり、request.schemeとrequest.ssl?の両方に影響します。protocol:には:httpまたは:httpsのシンボルを渡すことができ、to_sで文字列に変換されてからヘッダーに設定されます。
状態管理も既存パターンに従って実装されており、old_request_schemeで元のスキームを保存し、ensureブロックで確実に復元しています。protocol:がnilの場合は何も設定されないため、既存のテストコードとの後方互換性が保たれています。
テストの拡充
実装の検証のため、3つの観点でテストケースが追加されました。
プロトコル設定の検証:
test/sandbox/test/test_helper_test.rbに、HTTPとHTTPSの両プロトコルが正しく設定されることを確認するテストが追加されています。ProtocolComponentはrequest.schemeとrequest.ssl?の値を出力するテスト用コンポーネントです。
def test_with_request_url_specifying_https_protocol
with_request_url "/products", protocol: :https do
render_inline(ProtocolComponent.new)
end
assert_selector(".protocol", text: "Protocol: https, SSL: true")
end
状態復元の検証:
with_request_urlブロックの実行後、元のプロトコル設定が確実に復元されることを確認するテストも追加されています。これは複数のテストケースが連続実行される際の状態の分離を保証します。
URL生成の検証:
test/sandbox/test/rendering_test.rbでは、protocol:パラメータが実際のURL生成に反映されることを確認するテストが追加されました。UrlForComponentはRailsのURLヘルパーを使用してURLを生成するコンポーネントです。
def test_with_request_url_with_https_protocol
with_request_url "/", protocol: :https do
render_inline UrlForComponent.new(only_path: false)
assert_text "https://test.host/?key=value"
end
with_request_url "/products", protocol: :https, host: "secure.example.com" do
render_inline UrlForComponent.new(only_path: false)
assert_text "https://secure.example.com/products?key=value"
end
end
設計判断
シンボルによるプロトコル指定が採用されました。protocol:には:httpや:httpsのシンボルを渡すインターフェースになっており、これはRailsのルーティング設定などで広く使われているパターンです。PR説明文では「Follows existing patterns for host: and method: parameters. The protocol parameter accepts symbols (:http or :https) for a cleaner API.」と述べられています。
既存の状態管理パターンの踏襲も重要な判断です。host:やmethod:パラメータと同じく、protocol:も「保存→設定→復元」のパターンで実装されています。ensureブロックでの復元により、テスト実行中に例外が発生した場合でも状態の汚染を防ぎます。
まとめ
本PRは、ViewComponentのテストヘルパーにプロトコル指定機能を追加した変更です。環境変数の直接操作から宣言的なパラメータ指定へと移行することで、HTTPSを使用するコンポーネントのテストコードがより読みやすく保守しやすくなります。既存のhost:やmethod:パラメータと同じパターンを踏襲することで、APIの一貫性も保たれています。