test

### 曖昧検索
```ruby
assert_equal 1, page.all('a', text: /Edit/i).count
```


### クリック
```ruby
find("input[value$='Create Category']").click
```
```ruby
# 最初の要素
find("a", text: /◯/i, match: :first).click
```

### チェックボックス
```ruby
Capybara.execute_script(
  "window.scrollTo(
  #{(target = find('label', text: text = '公開設定')).native.location.x},
  #{target.native.location.y-300}
  );"
  )
check text
```

### パスチェック
```ruby
assert_equal category_menu_url(@public_category, @public_menu, locale: 'ja'), current_url
```

### カウンティング
- 正規表現を使うことで`EDIT`,`Edit`,`edit`など大文字小文字を区別せずにテキストとタグで検索をかける
```ruby
assert_equal 0, page.all('a', text: /Edit/i).count
```
```ruby
assert_selector "h1.test", text: "This is Test Text!", count: 1
```

### 待機
```ruby
// 5秒間停止
sleep(5)
```

### スクロール
##### 絶対位置でスクロール（推奨）
```ruby
Capybara.execute_script(
  "window.scrollTo(
  #{(target = find('label', text: text = '公開設定')).native.location.x},
  #{target.native.location.y-100}
  );"
  )
```
##### 相対位置でスクロール（非推奨）
```ruby
Capybara.execute_script(
  "window.scrollBy(
  #{(target = find('label', text: text = '公開設定')).native.location.x},
  #{target.native.location.y-100}
  );"
  )
```

### クラスの付与/削除
```ruby
Capybara.execute_script("document.getElementById('header').classList.add('d-none')")
```

### スクリーンショット
```ruby
  def take_full_page_screenshot(path)
    width  = Capybara.page.execute_script("return Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);")
    height = Capybara.page.execute_script("return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);")

    window = Capybara.current_session.driver.browser.manage.window
    window.resize_to(width+100, height+100)

    page.save_screenshot path
  end
```


---

## Assertion with Javascript
### タイムアウトする場合の対応
```
Minitest::UnexpectedError:
Capybara::ElementNotFound:
Unable to find checkbox "公開設定" that is not disabled
```
- capybaraの操作がブラウザの操作より早く動くので意図しないエラーがよく発生する
- そんな時はTimeoutを設定してあげて処理を待ってあげよう
- タイムアウトは10秒設定しないと、Redなテストで時間ロスしてしまう

###### test/test_helper.rb
```diff
class ActiveSupport::TestCase
  parallelize(workers: :number_of_processors)
  fixtures :all
+  Capybara.default_max_wait_time = 10
end
```
```ruby
test 'タイムアウト処理' do
  Timeout.timeout(Capybara.default_max_wait_time) do
    loop until (target = find('a.footer-link', text: text = '新規カテゴリ作成')).visible?
    target.click
  end
end
```

---

## フルサイズスクリーンショット
```ruby
def take_full_page_screenshot(path)
  width  = Capybara.page.execute_script("return Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);")
  height = Capybara.page.execute_script("return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);")
  window = Capybara.current_session.driver.browser.manage.window
  window.resize_to(width+100, height+100)
  page.save_screenshot path
end
```


---

## デフォルトのシステムテスト
```ruby
class SetUp < self
  def setup
    @one = 1
  end
end
class AccessCheck < SetUp
  class ValidCase < self
    test '' do
      assert_equal 1, @one
    end
  end
  class InvalidCase < self
  end
end
class Default < SetUp
  class ValidCase < self
  end
  class InvalidCase < self
  end
end
```


## 処理を共通化してユーザーを変更
```ruby
class SetUp < self
  def setup
    @one = 1
    @public_category = categories(:public)
    @unpublic_category = categories(:unpublic)
    @public_menu = menus(:public)
    @unpublic_menu = menus(:unpublic)
  end
  def success_story
    visit edit_category_menu_path(@public_category, @public_menu, locale: 'ja')
    beforeChange = @public_menu.title
    afterChange = @public_menu.title+'changed!'
    fill_in 'タイトル', with: afterChange
    find("input[value$='Update Menu']").click
    @public_menu.reload
    assert_equal afterChange, @public_menu.title
  end
end
class Default < SetUp
  class ValidCase < self
    test 'Adminは更新できる' do
      sign_in(users(:admin).email, 'password')
      success_story
    end
    test 'Maintainは更新できる' do
      sign_in(users(:maintain).email, 'password')
      success_story
    end
  end
end
```

---

## デフォルトセッティング
### テスト用のgemを追加
###### Gemfile
```ruby
group :test do
  gem "capybara"
  gem "selenium-webdriver"
  gem "webdrivers"
  gem 'minitest-reporters', '~> 1.5'
end
```


### テストの際のブラウザ使用の有無を設定
```ruby
require "test_helper"
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :chrome, screen_size: [500, 800]
  # driven_by :selenium_chrome_headless, using: :chrome, screen_size: [500, 800]
end
```

### デフォルトのテストメソッド作成/読み込み
```
touch test/default_test_helper.rb
```
###### test/default_test_helper.rb
```ruby
def log_in(email, password)
  visit new_user_session_path
  fill_in 'メールアドレス', with: email
  fill_in 'パスワード', with: password
  Capybara.execute_script("arguments[0].click();", find("input[type='submit']"))
end
def log_out
  Capybara.execute_script("arguments[0].click();", find('button', text: 'サインアウト'))
end
def access_refused
  assert_text "Access Denied."
end
def access_permitted
  assert_no_text "Access Denied."
end
```

### 必要なファイルを読み込み
###### test/test_helper.rb
```diff
ENV["RAILS_ENV"] ||= "test"
require_relative "../config/environment"
require "rails/test_help"
require "minitest/reporters"
Minitest::Reporters.use!
+ include ApplicationHelper
+ require "default_test_helper"
class ActiveSupport::TestCase
  parallelize(workers: :number_of_processors)
  fixtures :all
end
```


## テストの作成
### システムテストの作成
```
rails g system_test user_create
```
- `user_creates_test.rb`が作成される


## テストの実行
### (test/ 以下の)すべてのテストを実行
```
rails test
```
### 特定フォルダ以下のすべてのテストを実行
```
rails test test/models
```
### 複数のフォルダ以下のすべてのテストを実行
```
rails test test/models test/jobs
```
### 特定のファイルを実行
```
rails test test/models/user_test.rb
```
### 特定のファイルの特定の行を実行
```
rails test test/models/user_test.rb:14
```