ActionTextの投稿機能をRspec（system spec）でテストする

ActionTextでテキストエディタを実装しましたが、
なかなかそのテストの仕方までは探しても見つからなかったので備忘録です。

参考：
＊ [【Rails6】Action TextでRSpecのエラーが出たときにすること]('https://qiita.com/tegnike/items/122c078c7cd1087ce7c3')
＊ [ドキュメント]('https://www.rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions#attach_file-instance_method')
＊ [Everyday Rails]('https://leanpub.com/everydayrailsrspec-jp')

#前提
`Local`（地元民）がかく`Article`（記事）の作成機能をActionTextを使って作成。
`articlesテーブル`には`title`属性があり、
ActionTextを使って`content(本文)`（画像付きもOK）を作成できるようにしている。

ちなみに今回の内容とは関係ないですが、
記事にはタグ（`Tag`モデルで管理）をつけられるようにしてます.

| Left align | バージョン |
|:-----------|:------------|
|OS|macOS Big Sur 11.3|
|Ruby       | 3.0.0        |
|Rails     | 6.1.3.1     |
|Rspec      | 3.10       |

#各関連ファイル

#####モデル
```app/models/article.rb
class Article < ApplicationRecord
  has_rich_text :content
  belongs_to :local
  has_one :tag, dependent: :destroy
  accepts_nested_attributes_for :tag, allow_destroy: true
  default_scope -> { order(created_at: :desc)}
  validates :title, presence: true, length: { maximum: 255 }
  validate :content_required

  private
  def content_required
    errors.add(:content, "を入力してください") unless content.body.present?
  end
end
```

#####コントローラー
```app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  skip_before_action :authenticate_user!, if: :local_signed_in?
  skip_before_action :authenticate_local!, if: :user_signed_in?, only: [:index, :show]
  before_action :correct_local, only: [:edit, :update, :destroy]
  def index
    @articles = Article.all
  end

  def show
    @article = Article.find_by(id: params[:id])
  end

  def new
    @article = Article.new
    @article.build_tag
    tags
  end

  def create
    @article = current_local.articles.build(article_params)
    if @article.save
      flash[:success] = "投稿が完了しました"
      redirect_to @article
    else
      render 'new'
    end
  end

  def edit
　　　未
  end

  def update
　　　未
  end

  def destroy
　　　未
  end



  private

  def article_params
    params.require(:article).permit(:title, :content, tag_attributes:[:hoge ...略])
  end

  def correct_local
    @article = Article.find_by(id: [params[:id]])
    @local = Local.find_by(id: @article.local_id)
    redirect_to(top_url) unless @local == current_local
  end

  def tags
    @tags = { hoge: "hoge" ...略 }
  end
end
```

#####ビュー
```app/views/articles/new.html.erb
<h1>Articles#new</h1>
<p>Find me in app/views/articles/new.html.erb</p>

<%= form_with(model: @article, local: true) do |form| %>
  <div class="field">
    <%= form.label :title, 'タイトル' %>
    <%= form.text_field :title %>
    </div>
  <div class="field">
    <%= form.label :content, '本文' %>
    <%= form.rich_text_area :content %>
  </div>
  <p>タグ付け</p>
  <div style="display: flex; flex-wrap: wrap;">
    <%= form.fields_for :tag do |tag_form| %>
      <% @tags.each do |key, jp| %>
        <div class="field" style="padding: 5px;">
          <%= tag_form.label key, jp %>
          <%= tag_form.check_box key, {}, true, false %>
        </div>
      <% end %>
    <% end %>
  </div>
  <div class="actions">
    <%= form.submit "投稿" %>
  </div>
<% end %>
```

```app/views/articles/shoe.erb
<h1><%= @article.title %></h1>
<section>
  <%= @article.content %>
</section>
```

#本題（テスト部分）

##ハマったことその① 本文（content)のテストが通らない
```spec/system/articles_spec.rb
RSpec.describe 'Profiles', js: true, type: :system do
  let(:local) { FactoryBot.create(:local) }
  let(:article) { FactoryBot.build(:article) }
  before do
    local.confirm
    @number_of_articles = Article.count
    @number_of_tags = Tag.count
  end
  describe 'creating new article' do
    it 'success to create an article' do
      sign_in local
      visit new_article_path
      fill_in 'タイトル', with: article.title
      fill_in '本文', with: article.content 　#←←←　ここ
 以下略

```

```
Failure/Error: fill_in '本文', with: article.content

 Capybara::ElementNotFound:
　　Unable to find field '本文' that is not disabled
```
しばらく本文の2文字を書き間違えてないか見返したりしてたのですがそんなこともなく。。

正解は下記記事にありました！！　ありがとうございました。
＊ [【Rails6】Action TextでRSpecのエラーが出たときにすること]('https://qiita.com/tegnike/items/122c078c7cd1087ce7c3')

###解決策

ざっくり概要をまとめると、
原因としては本文の部分はActionTextを使って入力フォームを作っていて、
そこの箇所は`fill_in`の対象であるテキストエリアではないため、
カピバラさんが見つけられなかったよ、と仰っている。

そこで、`action_text_helper.rb`を作成し、
その中でリッチテキストエディターを見つけてそこに書き込んでねー、という`fill_in_rich_text_area`メソッドを作成。
※詳細は上記参考記事をご確認くださいませ。

すると以下で通るようになります。

```spec/system/articles_spec.rb
RSpec.describe 'Profiles', js: true, type: :system do
  let(:local) { FactoryBot.create(:local) }
  let(:article) { FactoryBot.build(:article) }
  before do
    local.confirm
    @number_of_articles = Article.count
    @number_of_tags = Tag.count
  end
  describe 'creating new article' do
    it 'success to create an article' do
      sign_in local
      visit new_article_path
      fill_in 'タイトル', with: article.title
      fill_in_rich_text_area '本文', with: article.content 　#←←←　ここ
```

##ハマったことその② 画像添付のテストの書き方がわからない・・・
低レベルだなと思った方はスルーしてください。。

恥ずかしながらファイルのアップロードのテストについて、こう書く↓知識しかなく・・

```
attach_file "Attachment", "#{Rails.root}/spec/files/attachment.jpg"
```

ActionTextを使うとファイルアップロードのボタンはクリップマーク。。。
さてどうしよう。

###解決策

で、[ドキュメント]('https://www.rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions#attach_file-instance_method')を確認したところ
> \# will attach file to whatever file input is triggered by the block
> page.attach_file('/path/to/file.png') do
>    page.find('#upload_button').click
> end

これで行けそう。

ということで、デベロッパーツールで使えそうなCSSを探し・・

```spec/system/articles_spec.rb
RSpec.describe 'Profiles', js: true, type: :system do
  let(:local) { FactoryBot.create(:local) }
  let(:article) { FactoryBot.build(:article) }
  before do
    local.confirm
    @number_of_articles = Article.count
    @number_of_tags = Tag.count
  end
  describe 'creating new article' do
    it 'success to create an article' do
      sign_in local
      visit new_article_path
      fill_in 'タイトル', with: article.title
      fill_in_rich_text_area '本文', with: article.content
      page.attach_file("#{Rails.root}/spec/files/attachment.jpeg") do #←←←ここから
        page.find('.trix-button--icon-attach').click
      end                                                             #←←←ここまで
      check 'tag'
      check 'another_tag'
      click_button '投稿'
      expect(Article.count).to eq @number_of_articles +1
      expect(Tag.count).to eq @number_of_tags +1
      expect(page).to have_current_path article_path(Article.last)
      expect(page).to have_content article.title
      expect(page).to have_content 'this is my article!'
      expect(page).to have_content "attachment.jpeg"
    end
  end
end
```

これで無事通りました！

#まとめ
とにかく困ったらドキュメント読め、と思いました。
しかしもっと良き書き方がありましたらご教示いただけますと幸いです！