Rails アプリケーションのエンドツーエンドの Capybara 仕様でエラーが発生しました。
私の見解の関連部分は次のとおりです。
#show.html.erb
...
<%= button_to 'Cancel',
cancel_subscription_path,
class: 'button button--danger',
data: {
turbo_confirm: 'Are you sure you want to cancel?',
turbo_method: 'post'
}
%>
<div id="cancel_message"></div>
...
# cancel_subscription_spec.rb
require 'rails_helper'
RSpec.describe 'CancelSubscriptions', js: true do
it 'cancels an active subscription' do
email = sign_up_and_subscribe
visit subscription_path
accept_confirm do
click_button 'Cancel'
end
subscription = User.find_by(email:).current_subscription
expect(subscription.cancelled?).to be(true)
end
end
Sign_up_and_subscribe は、アプリケーションにサインアップし、Stripe フォームに記入してサブスクリプションを作成する単純なヘルパー メソッドです。これは他のテストでも機能し、Stripe ダッシュボードでサブスクリプションが作成されたことも確認できます。これは問題ではありません。
仕様が visit subscription_path に到達し、キャンセル ボタンをクリックしようとすると、次のエラーが表示されます。
Selenium::WebDriver::Error::UnexpectedAlertOpenError:
unexpected alert open: {Alert text : }
(Session info: chrome-headless-shell=123.0.6312.87)
accept_confirm メソッドの使用法を誤っているのではないかと思いましたが、ドキュメントで見つけたところによると、これは正しい使用法です。
私が奇妙に思ったのは、仕様の accept_confirm とビューの Turbo_confirm をコメントアウトしても、実際にはエラー メッセージが変わらないことです。 Capybara はテスト実行の間にページをキャッシュしていますか?
この時点で仕様を通過させるために動作を変更することを検討します。ユーザー エクスペリエンスに小さな変更が生じる場合でも、十分にテストされたユーザー フローを使用することを好みますが、それすらできず、問題は残ります。同じ。
役立つ場合に備えて、rails_helper.rb の関連部分は次のとおりです。
Capybara.register_driver :chrome do |app|
Capybara::Selenium::Driver.new app, browser: :chrome,
options: Selenium::WebDriver::Chrome::Options.new(args: %w[headless disable-gpu])
end
Capybara.javascript_driver = :chrome
役立つ可能性がある場合は残りを投稿することもできますが、私が見る限り、ほとんど無関係です。
コントローラーでのキャンセルアクションは次のようになります。
def cancel
@subscription = current_user.current_subscription
SubscriptionCanceller.new(subscription_id: @subscription.provider_id).call
rescue SubscriptionCancellationError => _e
render :cancellation_error
end
ここでは、cancel_error と cancel 自体の Turbo_stream ビューがあります。手動でテストすると、どちらもブラウザーで機能します。
影響を受ける場合に備えて、cancel.turbo_stream.erb を次に示します。
<%= turbo_stream.replace 'cancel_message' do %>
<div>We are cancelling your subscription.</div>
<% end %>
さらに詳細やコードが必要な場合は、お知らせください。投稿させていただきます。
問題はわかりました。問題の仕様の問題ではありませんでしたが、動作は予期していませんでした。
テスト対象のページが依存する基礎となるデータが存在しませんでした。これは、他の仕様で同じ Stripe フォーム入力機能をテストしましたが、それらのテストで行われたアサーションにより、アプリケーションがそれらが true になるまで待機するようになったためです。ただし、このテストでは、Stripe API からの結果が保存される前にページが visit subscription_path でリダイレクトされたため、エラーが発生しました。
テストで発生したエラーは、開いているはずのないダイアログ ボックスが開いていると信じ込ませたので、私をイライラさせました。一方、実際の問題は、開いているはずのダイアログ ボックスが開いていないことでした。サブスクリプション ページが空で表示されていたため、キャンセル ボタンがページに表示されませんでした。
テストは次のようになります。
RSpec.describe 'CancelSubscriptions', js: true do
it 'cancels an active subscription' do
email = sign_up_and_subscribe
expect(page).to have_current_path('/subscription/success', ignore_query: true) # making sure the Stripe return_url was hit and so the data is saved in my DB
click_on 'dropdown-toggle'
click_on 'Subscription'
expect(page).to have_content 'Your subscription'
accept_confirm do
click_button 'Cancel'
end
expect(page).to have_content 'We are cancelling your subscription.'
subscription = User.find_by(email:).current_subscription
expect(subscription.cancelled?).to be(true)
end
end
要点: Capybara/Selenium で確認またはプロンプトダイアログボックスを受け入れるかどうかをアサーションする前に、ページが期待どおりにレンダリングされていることを確認してください。そうしないと、予期しないエラーが発生する可能性があります。