82731


**嵌っていること**

* * *

  1. Navbar上のトグルスイッチを押してドロップメニューを表示
  2. メニューの中のログインのリンクを押すとログイン用フォームをモーダルで表示
  3. フォーム全部空欄で’送信’ボタンを押し、モーダル上でエラーメッセージが出ることを確認する

アプリ上では動くのですが、一連の動作をどうやってRSpecで表記すればよいのか分からず詰まっています。  
ご教授いただければ有難いです。

**環境**

* * *

主なGemfileは以下です

[code]

    ruby '2.7.4'
    
    gem 'bootstrap',                  '~> 4.6.0'
    gem 'jquery-rails'
    gem 'rails',                      '6.0.3'
    gem 'rails-i18n'
    gem 'sass-rails',                 '5.1.0'
    gem 'sprockets-rails',             '~> 3.2.2'
    gem 'turbolinks',                 '5.2.0'
    gem 'uglifier'
    gem 'webpacker',                  '~> 3.5'
    
    group :development, :test do
      gem 'factory_bot_rails'
      gem 'rspec-rails',       '~> 5.0'
      gem 'shoulda-matchers'
      gem 'sqlite3',           '1.4.2'
    end
    
    group :test do
      gem 'capybara',                 '3.28.0'
      gem 'rails-controller-testing', '1.0.4'
      gem 'selenium-webdriver',       '3.142.4'
      gem 'webdrivers',               '4.1.2'
    end
    
[/code]

spec/rails_helpの主な内容が以下です

[code]

    require 'spec_helper'
    ENV['RAILS_ENV'] ||= 'test'
    require File.expand_path('../config/environment', __dir__)
    abort("The Rails environment is running in production mode!") if Rails.env.production?
    require 'rspec/rails'
    begin
      ActiveRecord::Migration.maintain_test_schema!
    rescue ActiveRecord::PendingMigrationError => e
      puts e.to_s.strip
      exit 1
    end
    #capybara内のmethodを読み込む
    require 'capybara/rspec'
    
    RSpec.configure do |config|
    
      config.fixture_path = "#{::Rails.root}/spec/fixtures"
    
      config.use_transactional_fixtures = true
    
      config.infer_spec_type_from_file_location!
    
      config.filter_rails_from_backtrace!
    
    
      config.include FactoryBot::Syntax::Methods
      
      config.before(:each, type: :system) do
        driven_by :selenium_chrome_headless
      end
    
      config.include ApplicationHelper
      #signup_pathがundefinedと言われたので入れてみた
      config.include Rails.application.routes.url_helpers
      #強制的にCapybara::DSLを読み込む
      config.include Capybara::DSL
    end
    
    #shoulda matcherを入れる
    Shoulda::Matchers.configure do |config|
      config.integrate do |with|
        with.test_framework :rspec
        with.library :rails
      end
    end
    # トグルSWやモーダルなどで非表示になっているものをtestするため
    Capybara.ignore_hidden_elements = false
    
    # Capybaraのdriverを指定してみる(デフォルトは:rack_test)
    Capybara.default_driver = :rack_test
    # jsオプション有効時のドライバを設定(デフォルトは:selenium)
    Capybara.javascript_driver = :selenium
    
    #任意の場所でScreenshotを撮るために用意する
    def take_screenshot
      page.save_screenshot "tmp/capybara/screenshot-#{DateTime.now}.png"
    end
    
[/code]

layouts/_navbar.html.erbの抜粋は以下です

[code]

    # <div class="modal fade role="dialog" aria-hidden="true">はappeication.html.erbに記載
    
       <nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-secondary">
           <div class="container">
                <a id="logo" class="navbar-brand" href='/'>
                    <i class="fas fa-hand-holding-heart"></i>
                    ブランド
                </a>
                <button class="navbar-toggler" type="button" id="humberger"    
                        data-toggle="collapse"  
                        data-target="#navcol-1"
                        aria-controls="#navcol-1" aria-expanded="false"
                        aria-label="#navcol-1">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navcol-1">
                    <ul class="nav navbar-nav ml-auto">
                        <li>
                            <a class="text-light" href='/'>Home</a>
                        </li>
                        <li>
                            <%= link_to "ログイン", login_path, remote: true, 
                                class: "text-light", id: "modal-open" %>
                        </li>
                        <li>
                            <a class="text-light" href='/signup'>新規登録</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    
[/code]

layouts/sessions/_login_form-modal.html.erbの内容が以下です

[code]

    <!-- ログインフォーム用モーダル   -->
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">ログイン</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
        <hr style="margin-bottom: 3px">
        <div class="modal-body">
    
            <%= form_with(url: login_path, scope: :session, 
                                           class: 'js-form') do |f| %>
              <!-- ここにエラーメッセージが出る-->
              <div class="js-message-error"></div>
    
              <%= f.label :email, "メールアドレス" %>
              <%= f.email_field :email, class: 'form-control' %>
    
              <%= f.label :password, "パスワード" %>
              <%= f.password_field :password, class: 'form-control' %>
    
              <hr />
              
              <%= f.submit "送信", class: "mt2 btn btn-info form-btn float-right" %>
          
            <% end %>   
             
        </div>
      </div> 
    </div>
    
[/code]

テストを試みているファイル（spec/systems/sessions_spec.rb）は以下です

[code]

    require 'rails_helper'
    
    RSpec.describe 'Sessions', type: :system do
      before do
        visit root_path
      end
    
      it 'モーダルが表示されるか', js: true do 
          find(".navbar-toggler").click
          sleep 0.5
          take_screenshot
          page.evaluate_script('$(".fade").removeClass("fade")')
          click_link 'ログイン'
          sleep 0.5
          is_expected.to have_selector(text: "メールアドレス")
      end
        
      #一連の流れを以下のように書きましたが、うまくいかず、上記のexampleを書いて確認を試みました。
        # #モーダルを表示して無効な値を入力する
        # describe 'enter an invalid values', js: true do
        #   before do
        #   find(".navbar-toggler").click
        #   page.evaluate_script('$(".fade").removeClass("fade")')
        #   click_link 'ログイン' 
        #   fill_in 'メールアドバイス', with: ''
        #   fill_in 'パスワード', with: ''
        #   click_button '送信'
        # end
        # #エラーメッセージが出る
        # it 'gets an error message' do
        #   is_expected.to have_selector(text: "入力内容に誤りがあります")
        # end
        # #一度モーダルを閉じる
        # context 'close modal' do
        #   before do
        #     click_on 'x'
            
        #     click_on 'ログイン'
        #   end
        #   #エラーメッセージが消える
        #   it 'is message disappear' do
        #     is_expected.to_not have_selector(text: "入力内容に誤りがあります" )
        #   end
      #   end
      # end
    end
    
[/code]

エラーの内容です

[code]

    Failures:
    
      1) Sessions モーダルが表示されるか
         Failure/Error: click_link 'ログイン'
         
         Selenium::WebDriver::Error::ElementNotInteractableError:
           element not interactable
             (Session info: headless chrome=93.0.4577.82)
         
         [Screenshot]: toggleが開いておらずプルダウンが出てないスクリーンショット
    
         
         # 0   chromedriver                        0x0000000100c976d9 chromedriver + 2758361
         # 1   chromedriver                        0x000000010134a893 chromedriver + 9783443
         # 2   chromedriver                        0x0000000100a2298f chromedriver + 182671
         # 3   chromedriver                        0x0000000100a57f39 chromedriver + 401209
         # 4   chromedriver                        0x0000000100a4c358 chromedriver + 353112
         # 5   chromedriver                        0x0000000100a74022 chromedriver + 516130
         # 6   chromedriver                        0x0000000100a4c0e5 chromedriver + 352485
         # 7   chromedriver                        0x0000000100a7429e chromedriver + 516766
         # 8   chromedriver                        0x0000000100a86514 chromedriver + 591124
         # 9   chromedriver                        0x0000000100a74243 chromedriver + 516675
         # 10  chromedriver                        0x0000000100a4aa0e chromedriver + 346638
         # 11  chromedriver                        0x0000000100a4bc75 chromedriver + 351349
         # 12  chromedriver                        0x0000000100c5e1df chromedriver + 2523615
         # 13  chromedriver                        0x0000000100c709f2 chromedriver + 2599410
         # 14  chromedriver                        0x0000000100c4302b chromedriver + 2412587
         # 15  chromedriver                        0x0000000100c71e1a chromedriver + 2604570
         # 16  chromedriver                        0x0000000100c5396c chromedriver + 2480492
         # 17  chromedriver                        0x0000000100c8bd38 chromedriver + 2710840
         # 18  chromedriver                        0x0000000100c8bec1 chromedriver + 2711233
         # 19  chromedriver                        0x0000000100c9c6f8 chromedriver + 2778872
         # 20  libsystem_pthread.dylib             0x00007fff204a78fc _pthread_start + 224
         # 21  libsystem_pthread.dylib             0x00007fff204a3443 thread_start + 15
         # ./spec/systems/sessions_spec.rb:13:in `block (2 levels) in <main>'
    
    Finished in 6.9 seconds (files took 1.23 seconds to load)
    1 example, 1 failure
    
    Failed examples:
    
    rspec ./spec/systems/sessions_spec.rb:8 # Sessions モーダルが表示されるか
    
[/code]

**やってみたこと**

* * *

qiitaの記事などを参考に  
`js: true`
を入れる、`sleep`で少し待つ、`page.evaluate_script('$(".fade").removeClass("fade")')`を入れてみる  
を試みましたが、どれも効果がありませんでした。  
スクショではそもそもプルダウンが開いていないので、何か根本的に誤りがあるのかもと感じています

何かお気づきの点があればご指摘いただきたく。  
よろしくお願いします。


CC BY-SA 4.0
2021-09-22T19:08:07.743
82644
2021-09-28T07:38:46.963
48234
question
ruby-on-rails ruby rspec bootstrap4
rails6 + Bootstrap4 + RSpec トグル表示のリンクやモーダルのテストについて


よくわかりませんが、自己解決できたようです。  
理由は皆目わかりませんが、

[code]

      it 'モーダルが表示されるか', js: true do
          find(".navbar-toggler").click
          expect(page).to have_link 'ログイン', href: login_path, visible: false
          page.evaluate_script('$(".fade").removeClass("fade")')
          click_link 'ログイン'
          expect(page).to have_content('メールアドレス')
      end
    
[/code]

これでモーダルの表示は確認できました。  
`sleep`を消していますが、別にあってもなくても結果は変わらないので消しています。  
何がきっかけで通ったのかは正直全くわかりません。困惑しております。  
これを参考にして、やりたかったテストを以下のように記載しました。

[code]

        context '無効な値を入力したとき', js: true do
          before do
          find(".navbar-toggler").click
          page.evaluate_script('$(".fade").removeClass("fade")')
          click_on 'ログイン'
          fill_in 'メールアドレス', with: ''
          fill_in 'パスワード', with: ''
          click_button '送信'
          end
          
          it 'エラーメッセージが出ること' do
            expect(page).to have_content('入力内容に誤りがあります')
          end
    
        context 'モーダルを一度閉じて再度開いたとき', js: true do
          before do
            page.evaluate_script("$('#login-modal').modal('hide')")
            click_on 'ログイン'
          end
          it 'エラーメッセージが消えていること' do
            expect(page).to_not have_content('入力内容に誤りがあります')
          end
        end
      end
    
    
[/code]

これでテストが通りましたので一先ずよしとしてます。


CC BY-SA 4.0
2021-09-28T07:38:46.963
82731
2021-09-28T07:38:46.963
48234
82644
answer