types_of_tests.step

message <<-MARKDOWN
  Now, that you know what tests are, let's discuss the different types of tests!

  In your Rails app, you have models, views, and controllers. It should be no surprise that tests can be written for models, views, and controllers.

  As you learned in the previous section, tests are used to verify that your code is working as expected. So, a couple things we can test right off the bat are that a tree should have certain associations and validations. Let's start by writing some model tests also known as unit tests! This link might come in handy to remember singular vs. plural Rails conventions: https://alexander-clark.com/blog/rails-conventions-singular-or-plural/
MARKDOWN

steps do
  step do
    message "First, create a orange model. By creating the model, a spec file will also be added to the models folder of the spec folder. Type this in the terminal:"

    console_without_message "rails generate model Orange"

    message "Then, run the migration to actually create the oranges table."

    console_without_message "bundle exec rake db:migrate"
  end
  step do
    message "Then, run rspec."

    console_without_message "bundle exec rspec"

    message "You will see a report with one pending test. When you generated your Orange model, RSpec also generated a matching spec file. Copy the test below into spec/models/orange_spec.rb and run 'bundle exec rspec' on the terminal again."


    source_code :ruby, <<-RUBY
      RSpec.describe Orange, :type => :model do
        context 'ActiveRecord associations' do
          it 'Orange belongs to tree' do
            expect(Orange.reflect_on_association(:tree).macro).to be (:belongs_to)
          end
        end
      end
    RUBY

    message "Run 'bundle exec rspec'. This test fails! Let's add an associaton to our model. Add a belongs_to association to orange.rb:"

    source_code :ruby, <<-RUBY
    class Orange < ActiveRecord::Base
      belongs_to :tree
    end
    RUBY

    message "Run 'bundle exec rspec' and now you should see one passing test! That's an example of an association test. Let's modify that test to fail. Then, run 'bundle exec rspec' and see what happens. Cool! Let's revert back to the passing test."
  end

  step do

    message "Now let's write a has_many association test for the relationship between the Tree model and the Orange model! (hint: this doesn't exist yet so you'll have to create the model and migrate!)"

    message "On to controller tests! Just like the Orange model, you will create the OrangesController, which will also create spec files in the /spec/controllers folder of your app."
  end

  step do
    message "First, create the oranges controller and relevant spec files by typing this in the terminal:"

    console_without_message "rails generate controller Oranges"
  end
  step do
    message "Then, run RSpec."

    console_without_message "bundle exec rspec"

    message "You should see a report with some passing tests but those are just the model tests you wrote. So, let's add some controller tests! Copy the below test, paste it into the oranges controller spec file, create the relevant view files and then run 'bundle exec rspec' on the terminal again."

    source_code :ruby, <<-RUBY
      RSpec.describe OrangesController do
        context '#index' do
          it "renders the index view" do
            get :index
            expect(response).to render_template("index")
          end
  
          it "renders html" do
            process :index, method: :get
            expect(response.content_type).to eq "text/html"
          end
        end
      end
    RUBY

    message "You should see two failing tests. You'll need to add a route, index action, and a view. Not sure where to start? Read the errors in your failing tests for a hint. Run 'bundle exec rspec' after each change until both tests pass."

    message "Note: as you write the controller tests, you may be prompted to install a missing gem called 'rails-controller-testing' to use the assert_template method. If prompted, please add it to your Gemfile and do a bundle install!"
  end

  step do
    message "Now, write another controller test for the new action (hint: you might need to look up what a mock is)."
  end

  step do
    message <<-MARKDOWN
      Last but not least: view tests! Below is an short snippet of a possible Orange show HTML page you can create in your app:
    MARKDOWN

    source_code :erb, <<-ERB
      <br>
      Orange title: <%= @orange.name %>
      <br>
      <br>
      Orange tree id: <%= @orange.tree_id %>
      <br>
    ERB

    message <<-MARKDOWN
      So, based on the orange you create, the show page should render HTML with the orange's name and tree id. Let's verify that with a few tests.
    MARKDOWN

    message "First, create a views folder in the spec folder. Then, create an oranges folder in the views folder. Lastly, create an oranges view spec file in the oranges folder. Type these commands in the terminal:"

    console_without_message "mkdir app/spec/views"
    console_without_message "mkdir app/spec/views/oranges"
    console_without_message "cd app/spec/views/oranges"
    console_without_message "touch show.html.erb_spec.rb"
  end
  step do
    message "Then, run rspec."

    console_without_message "bundle exec rspec"

    message "You should see a report with some passing tests but those are just the model and controller tests you wrote. So, let's add some view tests!"
    message "We're going to up the ante a bit here and NOT show you an example :) Google and StackOverflow are your friends here!"
  end
end

message <<-MARKDOWN
  Once, you have written some passing view tests, take a deep breath and pat yourself on the back! Testing is hard. But, it's critical in making sure software is stable and functional.

  So, I fibbed a little bit. There are more types of tests than just MVC tests. One of these other important tests is called an integration test. As the name indicates, it tries to assess how well multiple components in an app interact and is written in Rails as a feature spec test. Typically, these tests simulate a user and a user's actions to test end-to-end functionality.

  Here's a diagram from Thoughtbot that may help with understanding how integration tests fit in:

MARKDOWN

img src: "img/rails-test-types.png", alt: "Thoughtbot's diagram of types of Rails tests"

message <<-MARKDOWN
  Capybara is a common framework used to write integration tests in Rails. It integrates nicely with RSpec such that you can use the same kind of test language to write integration tests.

  As an added bonus for this section, write an integration test :)

  Use the following link to get started: https://www.sitepoint.com/basics-capybara-improving-tests/

MARKDOWN

next_step "additional_concepts"