Skip to content

Instantly share code, notes, and snippets.

@alistairtweed
Last active April 6, 2023 22:43
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save alistairtweed/c40b0584235881b4aa6208bb12db9209 to your computer and use it in GitHub Desktop.
Save alistairtweed/c40b0584235881b4aa6208bb12db9209 to your computer and use it in GitHub Desktop.
Testing Rails with RSpec, Factory Bot, Faker and Shoulda Matchers
--require spec_helper
# frozen_string_literal: true
# spec/views/posts/edit.html.erb_spec.rb
require 'rails_helper'
RSpec.describe 'posts/edit.html.erb', type: :view do
it 'renders ...' do
# render
# assert_select
# expect(rendered).to match()
skip '...'
end
end
# frozen_string_literal: true
# spec/support/factory_bot.rb
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
group :development, :test do
gem 'factory_bot_rails'
gem 'faker'
gem 'rspec-rails'
gem 'shoulda-matchers'
end
# frozen_string_literal: true
# spec/views/posts/index.html.erb_spec.rb
require 'rails_helper'
RSpec.describe 'posts/index.html.erb', type: :view do
before do
assign :posts, create_list(:post, 3)
end
it 'renders a list of posts' do
# render
# assert_select
skip '...'
end
end
# frozen_string_literal: true
# spec/views/posts/new.html.erb_spec.rb
require 'rails_helper'
RSpec.describe 'posts/new.html.erb', type: :view do
it 'renders ...' do
# render
# assert_select
# expect(rendered).to match()
skip '...'
end
end
# frozen_string_literal: true
# spec/models/post_spec.rb
require 'rails_helper'
RSpec.describe Post, type: :model do
end
# frozen_string_literal: true
# spec/factories/posts.rb
FactoryBot.define do
factory :post do
title { Faker::Lorem.sentence }
body { Faker::Lorem.paragraphs.join("\n\n") }
trait :invalid do
title { nil }
end
end
end
# frozen_string_literal: true
# spec/routing/posts_routing_spec.rb
RSpec.describe PostsController, type: :routing do
describe 'routing' do
# index
it 'routes GET /posts to posts#index' do
expect(get: '/posts').to route_to 'posts#index'
end
# show
it 'routes GET /posts/1 to posts#show' do
expect(get: '/posts/1').to route_to 'posts#show', id: '1'
end
# new
it 'routes GET /posts/new to posts#new' do
expect(get: '/posts/new').to route_to 'posts#new'
end
# edit
it 'routes GET /posts/1/edit to posts#edit' do
expect(get: '/posts/1/edit').to route_to 'posts#edit', id: '1'
end
# create
it 'routes POST /posts to posts#create' do
expect(post: '/posts').to route_to 'posts#create'
end
# update
it 'routes PATCH /posts/1 to posts#update' do
expect(patch: '/posts/1').to route_to 'posts#update', id: '1'
end
it 'routes PUT /posts/1 to posts#update' do
expect(put: '/posts/1').to route_to 'posts#update', id: '1'
end
# destroy
it 'routes DELETE /posts/1 to posts#destroy' do
expect(delete: '/posts/1').to route_to 'posts#destroy', id: '1'
end
end
end
# frozen_string_literal: true
# spec/requests/posts_spec.rb
RSpec.describe '/posts', type: :request do
# index
describe 'GET posts_url' do
it 'renders a successful response' do
get posts_url
expect(response).to be_successful
end
end
# show
describe 'GET post_url' do
it 'renders a successful response' do
post = create :post
get post_url post
expect(response).to be_successful
end
end
# new
describe 'GET new_post_url' do
it 'renders a successful response' do
get new_post_url
expect(response).to be_successful
end
end
# edit
describe 'GET /posts/:id/edit' do
it 'renders a successful response' do
post = create :post
get edit_post_url post
expect(response).to be_successful
end
end
# create
describe 'POST posts_url' do
context 'when post params are valid' do
let(:valid_post_params) { attributes_for :post }
it 'creates a new post' do
expect {
post posts_url, params: { post: valid_post_params }
}.to change(Post, :count).by 1
end
it 'redirects to the post url' do
post posts_url, params: { post: valid_post_params }
expect(response).to redirect_to post_url(Post.last)
end
end
context 'when post params are invalid' do
let(:invalid_post_params) { attributes_for :post, :invalid }
it 'does not create a new post' do
expect {
post posts_url, params: { post: invalid_post_params }
}.to change(Post, :count).by 0
end
it 'renders a successful response' do
post posts_url, params: { post: invalid_post_params }
expect(response).to be_successful
end
end
end
# update
describe 'PATCH post_url' do
context 'when post params are valid' do
let(:valid_post_params) { attributes_for :post }
it 'updates the post' do
post = create :post
patch post_url(post), params: { post: valid_post_params }
post.reload
skip '...'
end
it 'redirects to the post url' do
post = create :post
patch post_url(post), params: { post: valid_post_params }
post.reload
expect(response).to redirect_to post_url(post)
end
end
context 'when post params are invalid' do
let(:invalid_post_params) { attributes_for :post, :invalid }
it 'does not update the post' do
skip '...'
end
it 'renders a successful response' do
post = create :post
patch post_url(post), params: { post: invalid_post_params }
expect(response).to be_successful
end
end
end
# destroy
describe 'DELETE post_url' do
it 'destroys the post' do
post = create :post
expect {
delete post_url post
}.to change(Post, :count).by -1
end
it 'redirects to the posts url' do
post = create :post
delete post_url post
expect(response).to redirect_to posts_url
end
end
end
# frozen_string_literal: true
# spec/rails_helper.rb
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'
Dir[Rails.root.join('spec/support/**/*.rb')].sort.each { |f| require f }
begin
ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
puts e.to_s.strip
exit 1
end
RSpec.configure do |config|
config.filter_rails_from_backtrace!
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.infer_spec_type_from_file_location!
config.use_transactional_fixtures = true
end
# frozen_string_literal: true
# spec/support/shoulda_matchers.rb
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
# frozen_string_literal: true
# spec/views/posts/show.html.erb_spec.rb
require 'rails_helper'
RSpec.describe 'posts/show.html.erb', type: :view do
before do
assign :post, create(:post)
end
it 'renders ...' do
# render
# assert_select
# expect(rendered).to match()
skip '...'
end
end
# frozen_string_literal: true
# spec/spec_helper.rb
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment