[RUBY] [3rd] RSpec beginners wrote SystemSpec as a beginner (final edition)

Introduction

This is the previous article [[2nd] RSpec beginner wrote SystemSpec as a beginner (swamp edition)](https://qiita.com/komaitaira/items/b9efc86cde48fb5ca8ef "[2nd] RSpec beginner However, it is a continuation of "I tried to write SystemSpec as a beginner (swamp edition)"), and it is the final edition of SystemSpec (system spec).

If you want to know about ModelSpec, please see here. ..

Also, the other day, a study session for beginners (RSpec Beginners !!) was held with the kindness of RSpec male Junichi Ito @jnchito. I also participated in "RSpec Beginners !!"), so I think that you can deepen your understanding by watching this video, so please have a look if you like.

What to do in this article

Not covered in this article

Premise

Testing articles_spec.rb

① Use FactoryBot and prepare article data in advance.

Prepare pre-data using the familiar Factory Bot. It was created at the time of Part 1, but it will also be used when writing system specifications, so it is listed below for reference. For more information on FactoryBot, please refer to the model specs article.

①spec/factories/articles.rb


FactoryBot.define do
  #Use FactoryBot and prepare article data in advance
  FactoryBot.define do
  factory :article do
    title { "Test title" }
    body { "Test body" }
    is_active { true }
    company
    genre
  end
end

② Specific code description

Now let's write the test code. Running $ rails g rspec: system articles will create articles_spec.rb in the spec / system folder. The test code (actual movement on the browser, etc.) will be written in this file. Below is a completed example.

②spec/system/articles_spec.rb


require 'rails_helper'

RSpec.describe "Articles", type: :system do
  describe 'Article testing' do
    let(:company){FactoryBot.create(:company)}
    let(:genre){FactoryBot.create(:genre)}
    let!(:article){FactoryBot.create(:article, company: company, genre: genre)}
    before do
      visit new_company_session_path
      fill_in 'mail address', with: company.email
      fill_in 'password', with: company.password
      click_button 'Login'
    end
    describe 'Sidebar test' do
      context 'Check the display' do
        it 'Article search is displayed' do
          expect(page).to have_content "Article search"
          expect(current_path).to eq corporate_articles_path
        end
        it 'Article registration is displayed' do
          expect(page).to have_content "Article registration"
          expect(current_path).to eq corporate_articles_path
        end
      end
    end

    describe 'Post test' do
      context 'Transition to new article posting page' do
        it 'Transition' do
          click_on 'Register an article'
          expect(page).to have_content "Post new article"
          expect(current_path).to eq new_corporate_article_path
        end
      end
      context 'Check the display' do
        before do
          visit new_corporate_article_path
        end
        it 'Article top image form is displayed' do
          expect(page).to have_field 'article[image]'
        end
        it 'The genre select box is displayed' do
          expect(page).to have_select 'Genre'
        end
        it 'The listing status select box is displayed' do
          expect(page).to have_select 'Posting status'
        end
        it 'Article title form is displayed' do
          expect(page).to have_field 'Article title'
        end
        it 'Article content form is displayed' do
          expect(page).to have_field 'Article content'
        end
        it 'Article posting button is displayed' do
          expect(page).to have_button 'Post an article'
        end
      end
      context 'Posting an article' do
        before do
          visit new_corporate_article_path
        end
        it 'Successful posting' do
          select "Test genre", from: 'Genre'
          select "Now posted", from: 'Posting status'
          fill_in 'Article title', with: "RSpec is difficult"
          fill_in 'Article content', with: "It ’s difficult, but I ’m happy if the test suite goes through and everything turns green."
          click_button "Post an article"
          expect(page).to have_content "I posted a new article."
        end
        it 'Posting fails' do
          fill_in 'Article title', with: ""
          click_button "Post an article"
          expect(page).to have_content "The article was not saved due to the error."
        end
      end
    end
  
    describe 'Editing test' do
      context 'Confirmation of transition to each screen' do
        it 'You can transition to the article details screen' do
          click_on article.title
          expect(page).to have_content "Article details"
          expect(current_path).to eq corporate_article_path(article)
        end
        it 'You can transition to the article edit screen' do
          visit corporate_article_path(article) #Transition to the article details screen
          click_on "To edit"
          expect(page).to have_content "Article information editing"
          expect(current_path).to eq edit_corporate_article_path(article)
        end
      end
      context 'Confirmation of display and editing' do
        before do
          visit edit_corporate_article_path(article)
        end
        it 'Article top image form is displayed' do
          expect(page).to have_field 'article[image]'
        end
        it 'The genre select box is displayed' do
          expect(page).to have_select('Genre', selected: 'テストGenre')
        end
        it 'The listing status select box is displayed' do
          expect(page).to have_select('Posting status', selected: 'Now posted')
        end
        it 'Article title form is displayed' do
          expect(page).to have_field 'Article title', with: article.title
        end
        it 'Article content form is displayed' do
          expect(page).to have_field 'Article content', with: article.body
        end
        it 'Article edit button is displayed' do
          expect(page).to have_button 'Save your changes'
        end
        it 'Successful editing' do
          select "Posting suspended"
          fill_in 'Article title', with: "I will stop posting until I can write RSpec smoothly"
          click_button 'Save your changes'
          expect(page).to have_content 'The update of the article information is completed.'
          expect(page).to have_content '[Current publication status: Posting suspended]'
          expect(current_path).to eq corporate_article_path(article)
        end
        it 'Editing fails' do
          fill_in 'Article title', with: ""
          click_button 'Save your changes'
          expect(page).to have_content "The article was not saved due to the error."
        end
      end
    end
  end
end


As I explained in the model specs, posting the article ⑴ There is a company, ⑵ There is a genre of articles, ⑶ Articles can be posted It has become a flow. Therefore, you can understand that a company exists and it is necessary to select a genre in advance to post an article. Note that the difference from the last time is that the data created by FactoryBot is saved using let, not an instance variable.


Now let's talk about testing article posts. See the completed code example for a display test. Perhaps you who have read up to this 3rd time will understand without explaining. Please note that there are several types only for have_ ◯◯. See the code example below.

②spec/system/articles_spec.rb


      context 'Posting an article' do
        before do
          visit new_corporate_article_path
        end
        it 'Successful posting' do
          select "Test genre", from: 'Genre' # セレクトボックスからGenreを選択
          select "Now posted", from: 'Posting status' # セレクトボックスからPosting status(Now posted or 掲載停止中)choose
          fill_in 'Article title', with: "RSpec is difficult" #enter title
          fill_in 'Article content', with: "It ’s difficult, but I ’m happy if the test suite goes through and everything turns green." # Article contentを入力
          click_button "Post an article" # Post an articleボタンを押下
          expect(page).to have_content "I posted a new article." 
        end
        it 'Posting fails' do
          fill_in 'Article title', with: ""
          click_button "Post an article"
          expect(page).to have_content "The article was not saved due to the error."
        end
      end

In the above code example, the page where the post form is displayed is first transitioned to in the before block. Next, post form 1. Select genre, 2. Select publication status, 3. Enter title, 4. Enter article content and press the post button.

** Stumble point: hugging: "Select select box" ** In the selection of the select box above, it is described as select" test genre ", from:'genre'. Perhaps it's not a stumbling block if you do it normally, but I've had a lot of trouble here as well, so I'll share it. The cause of the stumbling was that the ** label tag was not written correctly **, and I could not select the select box well. Here's how to write my wrong label tag.

Ruby:corporate/articles/new.html.erb


<%= f.label :Genre%><br>
<%= f.collection_select :genre_id, Genre.all, :id, :genre_name, include_blank: "--Please select--" %>

The description of <% = f.label: Genre%> is incorrect. It is displayed without any problem on the browser, but when I check it with the verification tool For some reason, the for attribute is a mixture of English and Japanese (for = "article_genre"), such as <label for =" article_genre "> genre </ label>. I can't seem to make a good choice.
Here is how to write the correct label tag.

Ruby:corporate/articles/new.html.erb


<%= f.label :genre_id, "Genre" %><br>
<%= f.collection_select :genre_id, Genre.all, :id, :genre_name, include_blank: "--Please select--" %>

** Added on October 2, 2020 ** Regarding how to write the label tag above, it seems better to put the translated version in a YAML file and display it in the view instead of writing it solidly in the view in the form of "genre". I will describe it in this way once, but I will fix it later.

The display when viewed with the verification tool is as <label for =" article_genre_id "> genre </ label>.

Rather than describing the test, it may be a plain part because the view was written incorrectly in the first place, but when I received advice in the comments of the second article, I finally understood the cause.

There may not be many people who have a hard time with this, but for the time being, this article [HTML] Why should you add the for attribute to the label tag? Thorough explanation of how to use! Explains the label tag in detail.

Probably, if ** for attribute contains a proper value (genre_id in this case), it will be linked programmatically to the input element **. I learned a lot. If for some reason the test doesn't pass like me, you may want to check it with Chrome's verification tool!

The test that fails the rest of the posts and the test of editing the article are basically the same as before, so please write it with reference to the completed code!

Testing rooms_spec.rb

① Specific code description

The test is finally over! This DM / notification test ends the core function test. let's do our best! By the way, FactoryBot is not used in this test. Below is an example of the completed code.

①spec/system/rooms_spec.rb


require 'rails_helper'

RSpec.describe "Rooms", type: :system do
  let(:user){FactoryBot.create(:user)}
  let!(:company){FactoryBot.create(:company)}

  describe 'DM test' do
    before do
      visit new_user_session_path
      fill_in 'mail address', with: user.email
      fill_in 'password', with: user.password
      click_button 'Login'
      expect(page).to have_content 'You are now logged.'
    end

    context 'Check the display' do
      it 'You can transition to the expert list' do
        click_on 'Expert'
        expect(current_path).to eq companies_path
      end
      it 'A button to move to the company details screen and start DM is displayed' do
        visit companies_path
        click_on 'Test Co., Ltd.'
        expect(current_path).to eq company_path(company)
        expect(page).to have_content 'Test Co., Ltd.'
        expect(page).to have_button 'Start DM'
      end
    end

    context 'Individual side: Sending a message' do
      before do
        visit company_path(company) #Move to company details screen
        click_on 'Start DM'
      end
      it 'You can enter the chat room and the submission form will be displayed' do
        expect expect(page).to have_field 'Please enter a message'
      end
      it 'Can send messages' do
        fill_in 'Please enter a message', with: 'Test message'
        click_button 'Send'
        expect(page).to have_content 'Test message'
      end
      it 'After sending a message, the sending history is added to the DM list screen' do
        fill_in 'Please enter a message', with: 'Test message'
        click_button 'Send'
        expect(page).to have_content 'Test message' #Messages in chat rooms
        visit rooms_path
        expect(page).to have_content 'Test message' #DM list screen message
        expect(page).to have_link 'View message'
      end
    end

    context 'Corporate side: Receive-send message(reply)' do
      before do
        #Send a message on the individual side
        visit company_path(company)
        click_on 'Start DM'
        fill_in 'Please enter a message', with: 'Test message'
        click_button 'Send'
        logout(user)
        #Corporate login
        visit new_company_session_path
        fill_in 'mail address', with: company.email
        fill_in 'password', with: company.password
        click_button 'Login'
        expect(page).to have_content 'You are now logged.'
      end

      it 'The number of notifications is displayed in the header' do
        expect(page).to have_content '1 Notification'
      end
      it 'You can move to the notification list screen from the link, and you can check the receipt of messages from individual users.' do
        click_on 'notification'
        expect(page).to have_content 'notification'
        expect(page).to have_content 'There is a message from Test Taro'
      end
      it 'You can enter the chat room from the link and see the message you received' do
        click_on 'notification'
        click_on 'message'
        expect expect(page).to have_content 'Test message'
      end
      it 'Can send messages' do
        click_on 'notification'
        click_on 'message'
        fill_in 'Please enter a message', with: 'Reply to test message'
        click_button 'Send'
        expect(page).to have_content 'Reply to test message'
      end
    end
  end
end

In the DM / notification test, I would like to explain separately for the individual side and the corporate side. First is the ** individual test **. See the code example below.

[Individual side] DM / notification test

①spec/system/rooms_spec.rb


    context 'Individual side: Sending a message' do
      before do
        visit company_path(company) #Move to company details screen
        click_on 'Start DM'
      end
      it 'You can enter the chat room and the submission form will be displayed' do
        expect expect(page).to have_field 'Please enter a message'
      end
      it 'Can send messages' do
        fill_in 'Please enter a message', with: 'Test message'
        click_button 'Send'
        expect(page).to have_content 'Test message'
      end
      it 'After sending a message, the sending history is added to the DM list screen' do
        fill_in 'Please enter a message', with: 'Test message'
        click_button 'Send'
        expect(page).to have_content 'Test message' #Messages in chat rooms
        visit rooms_path
        expect(page).to have_content 'Test message' #DM list screen message
        expect(page).to have_link 'View message'
      end
    end

I think there are some particularly difficult points.

** In the test'Can send message'**

  1. fill_in'Enter message', with:'Test message' ⇨ Enter the string test message in the text box
  2. click_button'Send'⇨ Press the send button
  3. ʻexpect (page) .to have_content'test message'`⇨ Confirm that the message was sent by expecting the string test message on the same page

It has become a flow. チャットルーム内メッセージ

** In the test "After sending a message, the transmission history is added to the DM list screen" **

  1. ** 1st ** ʻexpect (page) .to have_content'test message'`⇨ Check the sent message in the chat room
  2. visit rooms_path ⇨ Move to DM list screen
  3. ** 2nd ** ʻexpect (page) .to have_content'Test message'`⇨ Confirm that the latest message is displayed on the DM list screen

It has become a flow. DM一覧画面メッセージ

The above is the DM test on the individual side. Next, I would like to explain the test on the corporate side. See the code example below.

[Corporate side] DM / notification test

①spec/system/rooms_spec.rb


    context 'Corporate side: Receive-send message(reply)' do
      before do
        #Send a message on the individual side
        visit company_path(company)
        click_on 'Start DM'
        fill_in 'Please enter a message', with: 'Test message'
        click_button 'Send'
        logout(user)
        #Corporate login
        visit new_company_session_path
        fill_in 'mail address', with: company.email
        fill_in 'password', with: company.password
        click_button 'Login'
        expect(page).to have_content 'You are now logged.'
      end

      it 'The number of notifications is displayed in the header' do
        expect(page).to have_content '1 Notification'
      end
      it 'You can move to the notification list screen from the link, and you can check the receipt of messages from individual users.' do
        click_on 'notification'
        expect(page).to have_content 'notification'
        expect(page).to have_content 'There is a message from Test Taro'
      end
      it 'You can enter the chat room from the link and see the message you received' do
        click_on 'notification'
        click_on 'message'
        expect expect(page).to have_content 'Test message'
      end
      it 'Can send messages' do
        click_on 'notification'
        click_on 'message'
        fill_in 'Please enter a message', with: 'Reply to test message'
        click_button 'Send'
        expect(page).to have_content 'Reply to test message'
      end
    end

This is not particularly difficult either. First, in the before block, describe up to the point where the individual side sent a message and then the corporation logged in. **'The number of notifications is displayed in the header' ** In the test ʻExpect (page) .to have_content '1 Notifications'` ⇨ When you log in, check that the header shows the number of notifications according to the number of messages and a link to the notification list.

DM一覧画面メッセージ

**'You can move to the notification list screen from the link and confirm the reception of messages from individual users' ** In the test ʻExpect (page) .to have_content'There is a message from Test Taro'` ⇨ When you move to the notification list screen, you can check who the message is from.

DM一覧画面メッセージ

All you have to do is enter the chat room, check if a message is coming, and see if you can send (reply) a message from here as well.

DM一覧画面メッセージ

This is the DM / notification test.

At the end

This time, we have summarized the testing of article posting, editing, DM, and notification by system specifications. This completes the system specs that I wrote in two parts! I wrote it as a review of myself, but I thought again that there are still improvements. I would like to make small corrections so that beginners who see this do not say "What is this, I don't understand!".

At first I had a lot of trouble with things I didn't understand, but the other day's study session for beginners RSpec Beginners !! I've been able to write tests myself more than when I participated in, and if I'm asked something, I'll be able to tell people a little.

We would like to thank Mr. Ito (@jnchito) for providing such an opportunity and all the people who invited us.

Also, although it's childish, I hope this article will be of some help to RSpec beginners. Thank you for watching until the end!

Reference article

[Introduction to RSpec that can be used, Part 4 "Any browser operation is free! Reverse Capybara Dictionary"](https://qiita.com/jnchito/items/607f956263c38a5fec24 "Introduction to RSpec that can be used, Part 4" Any browser operation is free ! Reverse Capybara Dictionary "") [HTML] Why should you add the for attribute to the label tag? Thorough explanation of how to use!

Recommended Posts

[3rd] RSpec beginners wrote SystemSpec as a beginner (final edition)
[2nd] RSpec beginners wrote SystemSpec as a beginner (swamp edition)
[1st] RSpec beginners tried to write ModelSpec as a beginner