I've just written my first full batch of RSpec tests and wondered if anyone can comment at a glance on how they might be written easier, more readable, faster etc. There are some pending specs so excuse those. It should describe what they will test when I finish. I've given examples of models, controllers and feature specs as each spec for these groups are quite consistent. I've given just one of each:
Model
require 'spec_helper'
describe Favorite do
it "has a valid factory" do
expect(FactoryGirl.build(:favorite)).to be_valid
end
it "is invalid without a title" do
favorite = FactoryGirl.build(:favorite, :title => nil)
expect(favorite).to have(1).errors_on(:title)
end
it "is invalid without a user id" do
favorite = FactoryGirl.build(:favorite, :user_id => nil)
expect(favorite).to have(1).errors_on(:user_id)
end
it "is invalid without a yt video id" do
favorite = FactoryGirl.build(:favorite, :yt_video_id => nil)
expect(favorite).to have(1).errors_on(:yt_video_id)
end
it "is valid without a thumbnail" do
favorite = FactoryGirl.build(:favorite, :thumbnail => nil)
expect(favorite).to be_valid
end
it "is invalid if thumbnail is not a url" do
favorite = FactoryGirl.build(:favorite, :thumbnail => "not a url")
expect(favorite).to have(1).errors_on(:thumbnail)
end
end
Controller
require "spec_helper"
describe CategoriesController do
let(:user) { FactoryGirl.create(:user) }
describe "GET #index" do
context "signed in" do
before(:each) do
sign_in :user, user
end
it "renders the category/index template" do
get :index
expect(response).to render_template :index
end
end
context "not signed in" do
it "renders the devise/sign_in template"
end
end
describe "GET #new" do
context "signed in" do
before(:each) do
sign_in :user, user
end
it "assigns a new Category to @category" do
get :new
expect(assigns(:category)).to be_a_new(Category)
end
it "renders the :new template" do
get :new
expect(response).to render_template :new
end
end
context "not signed in" do
it "assigns a new Category to @category"
it "renders the :new template"
end
end
describe "GET #edit" do
context "signed in" do
before(:each) do
sign_in :user, user
@category = FactoryGirl.create(:category, :user_id => user.id)
get :edit, id: @category
end
it "assigns the requested Category to @category" do
expect(assigns(:category)).to eq @category
end
it "renders the :edit template" do
expect(response).to render_template :edit
end
end
context "not signed in" do
it "assigns the requested Category to @category"
it "renders the :edit template"
end
end
describe "POST #create" do
context "signed in" do
before(:each) do
sign_in :user, user
end
context "with valid attributes" do
it "saves the new category in the database" do
expect{
post :create, category: FactoryGirl.attributes_for(:category)
}.to change(Category, :count).by(1)
end
it "redirects to category #index"
end
context "with invalid attributes" do
it "does not save the new category in the database"
it "re-renders the :new template"
it "provides errors"
end
end
context "not signed in" do
it "blocks access (somehow)"
end
end
describe "PATCH #update" do
context "with valid attributes" do
it "updates the category in the database"
it "redirects to category #index"
end
context "with invalid attributes" do
it "does not update the category in the database"
it "re-renders the :edit template"
it "provides errors"
end
end
end
Feature
require 'spec_helper'
require 'requests_helper'
feature "console" do
let(:user) { FactoryGirl.create(:user) }
feature "authenticated session" do
before(:each) do
login(user)
end
feature "favorites" do
scenario "show favorites page when favorites is clicked" do
visit favorites_path
click_link("Favorites")
expect(current_path).to eq(favorites_path)
end
scenario "add a video to add page when clicked" do
# add song from favorites to add view
favorite = FactoryGirl.create(:favorite)
visit favorites_path
click_link(favorite.title)
expect(page).to have_content(favorite.title)
end
feature "delete" do #, :js => true do
scenario "delete a video when delete icon is clicked"
end
end
end
end
Anyway, if there is anything I'm doing that, certainly for a bigger project, would be inefficient, slow, difficult for others to understand (e.g. not conventional), please comment.