Permalink
Browse files

Add Rspec for testing

  • Loading branch information...
1 parent a618020 commit 5b54028bfbae0b6e4c139386983d4dd7da0999d6 @reyesyang committed Dec 18, 2013
View
2 .rspec
@@ -0,0 +1,2 @@
+--color
+--format documentation
View
3 Gemfile
@@ -39,6 +39,7 @@ gem 'will_paginate', '>=3.0.pre'
gem 'wmd-rails'
gem 'redcarpet'
gem "haml"
+gem 'rails-i18n', '~>4.0.0'
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.1.0'
@@ -57,4 +58,6 @@ group :development, :test do
gem 'quiet_assets'
gem 'factory_girl_rails'
gem 'pry-rails'
+
+ gem 'rspec-rails'
end
View
17 Gemfile.lock
@@ -43,6 +43,7 @@ GEM
execjs
coffee-script-source (1.6.3)
commonjs (0.2.7)
+ diff-lcs (1.2.5)
erubis (2.7.0)
execjs (2.0.1)
factory_girl (4.2.0)
@@ -102,6 +103,9 @@ GEM
bundler (>= 1.3.0, < 2.0)
railties (= 4.0.0)
sprockets-rails (~> 2.0.0)
+ rails-i18n (4.0.0)
+ i18n (~> 0.6)
+ rails (~> 4.0.0)
railties (4.0.0)
actionpack (= 4.0.0)
activesupport (= 4.0.0)
@@ -110,6 +114,17 @@ GEM
rake (10.1.0)
redcarpet (3.0.0)
ref (1.0.5)
+ rspec-core (2.14.7)
+ rspec-expectations (2.14.4)
+ diff-lcs (>= 1.1.3, < 2.0)
+ rspec-mocks (2.14.4)
+ rspec-rails (2.14.0)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ railties (>= 3.0)
+ rspec-core (~> 2.14.0)
+ rspec-expectations (~> 2.14.0)
+ rspec-mocks (~> 2.14.0)
rvm-capistrano (1.5.0)
capistrano (>= 2.15.4)
sass (3.2.10)
@@ -168,7 +183,9 @@ DEPENDENCIES
pry-rails
quiet_assets
rails (~> 4.0.0)
+ rails-i18n (~> 4.0.0)
redcarpet
+ rspec-rails
rvm-capistrano
sass-rails (~> 4.0.0)
therubyracer
View
2 app/controllers/articles_controller.rb
@@ -77,6 +77,6 @@ def load_article_with_tags
end
def article_params
- params.require(:article).permit(:title, :content, :tags_string)
+ params.require(:article).permit(:title, :content, :tag_list)
end
end
View
65 app/models/article.rb
@@ -1,66 +1,29 @@
# -*- encoding : utf-8 -*-
class Article < ActiveRecord::Base
- before_save :update_articles_count_on_tags_bf_save
- before_destroy :update_articles_count_on_tags_bf_destroy
-
- has_and_belongs_to_many :tags
+ has_many :taggings
+ has_many :tags, through: :taggings
validates :title, :content, :presence => true
+ validates :title, uniqueness: true
+ validates :content, length: { minimum: 20 }
self.per_page = 10
- @@original_tags = nil
- def tags_string=(value)
- @@original_tags = self.tags.clone
+ def tag_list=(value)
+ tags = value.split(',').map{ |tag| tag.strip.downcase }.reject{ |t| t.blank? }
- self.tags = value.split(';').map do |name|
- Tag.find_or_create_by_name(name.strip)
- end
+ self.tags = if tags.include?('draft')
+ [Tag.find_or_create_by(name: 'draft')]
+ else
+ tags.map{ |tag| Tag.find_or_create_by(name: tag) }
+ end
end
- def tags_string
- self.tags.map(&:name).join('; ')
+ def tag_list
+ self.tags.map(&:name).join(', ')
end
def draft?
- tags.any?{|tag| tag.name == 'draft'}
- end
-
- private
- def update_articles_count_on_tags_bf_save
- added_tags = []
- removed_tags = []
-
- if id
- added_tags = self.tags - @@original_tags
- removed_tags = @@original_tags - self.tags
- else
- added_tags = self.tags
- end
-
- increment_articles_count_on_tags(added_tags) if added_tags
- decrement_articles_count_on_tags(removed_tags) if removed_tags
- end
-
- def update_articles_count_on_tags_bf_destroy
- decrement_articles_count_on_tags(self.tags)
- end
-
- def increment_articles_count_on_tags(tags)
- tags.each do |tag|
- tag.update_attribute(:articles_count, tag.articles_count + 1)
- end
- end
-
- def decrement_articles_count_on_tags(tags)
- tags.each do |tag|
- articles_count = tag.articles.count - 1;
-
- if articles_count > 0
- tag.update_attribute(:articles_count, articles_count)
- else
- tag.destroy
- end
- end
+ tags.where(name: 'draft').any?
end
end
View
3 app/models/tag.rb
@@ -1,6 +1,7 @@
# -*- encoding : utf-8 -*-
class Tag < ActiveRecord::Base
- has_and_belongs_to_many :articles
+ has_many :taggings
+ has_many :articles, through: :taggings
scope :ordered, -> { order('name') }
View
5 app/models/tagging.rb
@@ -0,0 +1,5 @@
+# encoding: UTF-8
+class Tagging < ActiveRecord::Base
+ belongs_to :article
+ belongs_to :tag, counter_cache: :articles_count
+end
View
2 app/views/articles/_form.html.haml
@@ -5,7 +5,7 @@
= form_for @article do |f|
#edit-area
.field= f.text_field :title
- .field= f.text_field :tags_string
+ .field= f.text_field :tag_list
.field
#wmd-button-bar
= f.text_area :content, :id => 'wmd', cols: 80, rows: 13
View
2 config/application.rb
@@ -48,7 +48,7 @@ class Application < Rails::Application
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
- config.i18n.default_locale = :zh_CN
+ config.i18n.default_locale = :"zh-CN"
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = "utf-8"
View
5 db/migrate/20131218154845_rename_articles_tags_to_taggings.rb
@@ -0,0 +1,5 @@
+class RenameArticlesTagsToTaggings < ActiveRecord::Migration
+ def change
+ rename_table :articles_tags, :taggings
+ end
+end
View
22 db/migrate/20131218155347_add_timestamps_to_taggings.rb
@@ -0,0 +1,22 @@
+class AddTimestampsToTaggings < ActiveRecord::Migration
+ def change
+ add_column :taggings, :id, :primary_key, first: true
+ add_timestamps :taggings
+
+ reversible do |dir|
+ dir.up do
+ Tagging.find_each do |tagging|
+ article = tagging.article
+ tagging.created_at = article.created_at
+ tagging.updated_at = article.updated_at
+ tagging.save
+ end
+
+ Tag.find_each do |tag|
+ tag.articles_count = tag.articles.count
+ tag.save
+ end
+ end
+ end
+ end
+end
View
60 db/schema.rb
@@ -9,68 +9,70 @@
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
-# It's strongly recommended to check this file into your version control system.
+# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20121017120144) do
+ActiveRecord::Schema.define(version: 20131218155347) do
- create_table "acknowledges", :force => true do |t|
+ create_table "acknowledges", force: true do |t|
t.text "description"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
t.string "name"
t.string "website"
t.string "image_url"
end
- create_table "articles", :force => true do |t|
+ create_table "articles", force: true do |t|
t.string "title"
t.text "content"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
end
- create_table "articles_tags", :id => false, :force => true do |t|
- t.integer "article_id"
- t.integer "tag_id"
- end
-
- create_table "authorizations", :force => true do |t|
+ create_table "authorizations", force: true do |t|
t.string "provider"
t.string "uid"
t.integer "user_id"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
end
- create_table "comments", :force => true do |t|
+ create_table "comments", force: true do |t|
t.string "visitor_name"
t.text "content"
t.integer "article_id"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
t.string "visitor_email"
t.string "visitor_website"
end
- create_table "evolutions", :force => true do |t|
+ create_table "evolutions", force: true do |t|
t.text "change"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
t.string "version"
end
- create_table "tags", :force => true do |t|
+ create_table "taggings", force: true do |t|
+ t.integer "article_id"
+ t.integer "tag_id"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ create_table "tags", force: true do |t|
t.string "name"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
- t.integer "articles_count", :default => 0
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.integer "articles_count", default: 0
end
- create_table "users", :force => true do |t|
+ create_table "users", force: true do |t|
t.string "name"
t.string "auth_token"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
t.string "email"
t.string "image_url"
end
View
9 spec/factories/articles.rb
@@ -0,0 +1,9 @@
+# Read about factories at https://github.com/thoughtbot/factory_girl
+
+FactoryGirl.define do
+ factory :article do
+ sequence(:title) { |n| "artile title #{n}" }
+ content { 'a' * 20 }
+ tag_list 'tag1,tag2'
+ end
+end
View
139 spec/models/article_spec.rb
@@ -0,0 +1,139 @@
+require 'spec_helper'
+
+describe Article do
+ before(:each) do
+ @article = create :article
+ end
+
+ context 'validation' do
+ it 'is valide' do
+ expect(@article).to be_valid
+ end
+
+ it 'is invalid when title is empty' do
+ @article.title = ''
+ expect(@article).to be_invalid
+ end
+
+ it 'is invalid when content is empty' do
+ @article.content = ''
+ expect(@article).to be_invalid
+ end
+
+ it 'is invalid when title have been used' do
+ article = build :article, title: @article.title
+ expect(article).to be_invalid
+ end
+
+ it 'is invalid when content length less than 20' do
+ @article.content = 'a' * 19
+ expect(@article).to be_invalid
+ end
+ end
+
+ describe '#tag_list' do
+ context "assign to default value 'tag1,tag2'" do
+ it 'created two tags' do
+ expect(Tag.count).to eq 2
+ tags = Tag.pluck :name
+ expect(tags).to include 'tag1'
+ expect(tags).to include 'tag2'
+ end
+
+ it "tag1's articles_count should be 1" do
+ tag1 = Tag.find_by_name 'tag1'
+ expect(tag1.articles_count).to eq 1
+ end
+
+ it "tag2's articles_count should be 1" do
+ tag2 = Tag.find_by_name 'tag2'
+ expect(tag2.articles_count).to eq 1
+ end
+ end
+
+ context "change value to 'tag1'" do
+ before(:each) do
+ @article.tag_list = "tag1"
+ @article.save
+ end
+
+ it "tags' count is 2" do
+ expect(Tag.count).to eq 2
+ end
+
+ it "tag1's articles_count is 1" do
+ tag1 = Tag.find_by_name "tag1"
+ expect(tag1.articles_count).to eq 1
+ end
+
+ it "tag2's articles_count is 0" do
+ tag2 = Tag.find_by_name "tag2"
+ expect(tag2.articles_count).to be 0
+ end
+ end
+
+ context "change value to 'tag2,tag3'" do
+ before(:each) do
+ @article.tag_list = "tag2,tag3"
+ @article.save
+ end
+
+ it "tag's count is 3" do
+ expect(Tag.count).to eq 3
+ end
+
+ it "tag1's articles_count is 0 " do
+ tag1 = Tag.find_by_name "tag1"
+ expect(tag1.articles_count).to eq 0
+ end
+
+ it "tag2's articles_count is 1" do
+ tag2 = Tag.find_by_name "tag2"
+ expect(tag2.articles_count).to eq 1
+ end
+
+ it "tag3's articles_count is 1" do
+ tag3 = Tag.find_by_name "tag3"
+ expect(tag3.articles_count).to eq 1
+ end
+ end
+ end
+
+ describe '#draft?' do
+ it "return false when tags exclude 'draft'" do
+ expect(@article).not_to be_draft
+ end
+
+ context "change tag_list value to 'tag1,draft'" do
+ before(:each) do
+ @article.tag_list = "tag1,draft"
+ @article.save
+ end
+
+ it "Tag's count is 3" do
+ expect(Tag.count).to eq 3
+ end
+
+ it "tag1's articles_count is 0" do
+ tag1 = Tag.find_by_name "tag1"
+ expect(tag1.articles_count).to eq 0
+ end
+
+ it "tag2's articles_count is 0" do
+ tag2 = Tag.find_by_name "tag2"
+ expect(tag2.articles_count).to eq 0
+ end
+
+ it "draft's articles_count is 1" do
+ draft = Tag.find_by_name "draft"
+ expect(draft.articles_count).to eq 1
+ end
+
+ it "return true when tags include 'draft'" do
+ expect(@article).to be_draft
+ end
+ end
+
+
+ end
+end
View
13 spec/models/user_spec.rb
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe User do
+ it 'is not admin when email is not eqaul to admin_email' do
+ user = User.new "non_admin@gmail.com"
+ expect(user).not_to be_admin
+ end
+
+ it 'is admin when email is eqaul to admin_email' do
+ user = User.new APP_CONFIG[:admin_email]
+ expect(user).to be_admin
+ end
+end
View
48 spec/spec_helper.rb
@@ -0,0 +1,48 @@
+# This file is copied to spec/ when you run 'rails generate rspec:install'
+ENV["RAILS_ENV"] ||= 'test'
+require File.expand_path("../../config/environment", __FILE__)
+require 'rspec/rails'
+require 'rspec/autorun'
+
+# Requires supporting ruby files with custom matchers and macros, etc,
+# in spec/support/ and its subdirectories.
+Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
+
+# Checks for pending migrations before tests are run.
+# If you are not using ActiveRecord, you can remove this line.
+ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
+
+RSpec.configure do |config|
+ # ## Mock Framework
+ #
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
+ #
+ # config.mock_with :mocha
+ # config.mock_with :flexmock
+ # config.mock_with :rr
+
+ config.include FactoryGirl::Syntax::Methods
+
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
+
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
+ # examples within a transaction, remove the following line or assign false
+ # instead of true.
+ config.use_transactional_fixtures = true
+
+ # If true, the base class of anonymous controllers will be inferred
+ # automatically. This will be the default behavior in future versions of
+ # rspec-rails.
+ config.infer_base_class_for_anonymous_controllers = false
+
+ # Run specs in random order to surface order dependencies. If you find an
+ # order dependency and want to debug it, you can fix the order by providing
+ # the seed, which is printed after each run.
+ # --seed 1234
+ config.order = "random"
+
+ config.expect_with :rspec do |c|
+ c.syntax = :expect
+ end
+end
View
9 test/factories/authorizations.rb
@@ -1,9 +0,0 @@
-# Read about factories at https://github.com/thoughtbot/factory_girl
-
-FactoryGirl.define do
- factory :authorization do
- provider "MyString"
- uid "MyString"
- user_id 1
- end
-end
View
10 test/factories/users.rb
@@ -1,10 +0,0 @@
-# -*- encoding : utf-8 -*-
-# Read about factories at http://github.com/thoughtbot/factory_girl
-
-FactoryGirl.define do
- factory :user do
- sequence(:name) {|n| "name#{n}"}
- password 'password'
- password_confirmation 'password'
- end
-end
View
55 test/functional/articles_controller_test.rb
@@ -1,55 +0,0 @@
-# -*- encoding : utf-8 -*-
-require 'test_helper'
-
-class ArticlesControllerTest < ActionController::TestCase
- setup do
- @article = articles(:rubyonrails1)
- @update = {
- :title => 'update title',
- :summary => 'update summary test',
- :content => 'upate content test'
- }
- end
-
- test "should get index" do
- get :index
- assert_response :success
- assert_not_nil assigns(:articles)
- end
-
- test "should get new" do
- get :new
- assert_response :success
- end
-
- test "should create article" do
- assert_difference('Article.count') do
- post :create, :article => @update
- end
-
- assert_redirected_to article_path(assigns(:article))
- end
-
- test "should show article" do
- get :show, :id => @article.to_param
- assert_response :success
- end
-
- test "should get edit" do
- get :edit, :id => @article.to_param
- assert_response :success
- end
-
- test "should update article" do
- put :update, :id => @article.to_param, :article => @update
- assert_redirected_to article_path(assigns(:article))
- end
-
- test "should destroy article" do
- assert_difference('Article.count', -1) do
- delete :destroy, :id => @article.to_param
- end
-
- assert_redirected_to articles_path
- end
-end
View
7 test/functional/sessions_controller_test.rb
@@ -1,7 +0,0 @@
-require 'test_helper'
-
-class SessionsControllerTest < ActionController::TestCase
- # test "the truth" do
- # assert true
- # end
-end
View
9 test/functional/tags_controller_test.rb
@@ -1,9 +0,0 @@
-require 'test_helper'
-
-class TagsControllerTest < ActionController::TestCase
- test "should get show" do
- get :show
- assert_response :success
- end
-
-end
View
58 test/functional/users_controller_test.rb
@@ -1,58 +0,0 @@
-# -*- encoding : utf-8 -*-
-require 'test_helper'
-
-class UsersControllerTest < ActionController::TestCase
- setup do
- @admin = Factory :user
- end
-
- test "should get index" do
- login @admin
- get :index
- assert_response :success
- assert_not_nil assigns(:users)
- end
-
- test "should get new" do
- login @admin
- get :new
- assert_response :success
- end
-
- test "should create user" do
- login @admin
- assert_difference('User.count') do
- post :create, :user => Factory.attributes_for(:user)
- end
-
- assert_redirected_to users_path
- end
-
- test "should show user" do
- login @admin
- get :show, :id => @admin.to_param
- assert_response :success
- end
-
- test "should get edit" do
- login @admin
- get :edit, :id => @admin.to_param
- assert_response :success
- end
-
- test "should update user" do
- login @admin
- put :update, :id => @admin.to_param, :user => Factory.attributes_for(:user)
- assert_redirected_to users_path
- end
-
- test "should destroy user" do
- login @admin
- user = Factory :user
- assert_difference('User.count', -1) do
- delete :destroy, :id => user.to_param
- end
-
- assert_redirected_to users_path
- end
-end
View
10 test/performance/browsing_test.rb
@@ -1,10 +0,0 @@
-# -*- encoding : utf-8 -*-
-require 'test_helper'
-require 'rails/performance_test_help'
-
-# Profiling results for each test method are written to tmp/performance.
-class BrowsingTest < ActionDispatch::PerformanceTest
- def test_homepage
- get '/'
- end
-end
View
22 test/test_helper.rb
@@ -1,22 +0,0 @@
-# -*- encoding : utf-8 -*-
-ENV["RAILS_ENV"] = "test"
-require File.expand_path('../../config/environment', __FILE__)
-require 'rails/test_help'
-
-class ActiveSupport::TestCase
- # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
- #
- # Note: You'll currently still have to declare fixtures explicitly in integration tests
- # -- they do not yet inherit this setting
- # fixtures :all
-
- # Add more helper methods to be used by all tests here...
-
- def login(user)
- session[:user_id] = user.id
- end
-
- def logout
- reset_session
- end
-end
View
12 test/unit/article_test.rb
@@ -1,12 +0,0 @@
-# -*- encoding : utf-8 -*-
-require 'test_helper'
-
-class ArticleTest < ActiveSupport::TestCase
- test "article attributes must not be empty" do
- article = Article.new
- assert article.invalid?
- assert article.errors[:title].any?
- assert article.errors[:summary].any?
- assert article.errors[:content].any?
- end
-end
View
7 test/unit/authorization_test.rb
@@ -1,7 +0,0 @@
-require 'test_helper'
-
-class AuthorizationTest < ActiveSupport::TestCase
- # test "the truth" do
- # assert true
- # end
-end
View
4 test/unit/helpers/sessions_helper_test.rb
@@ -1,4 +0,0 @@
-require 'test_helper'
-
-class SessionsHelperTest < ActionView::TestCase
-end
View
9 test/unit/tag_test.rb
@@ -1,9 +0,0 @@
-# -*- encoding : utf-8 -*-
-require 'test_helper'
-
-class TagTest < ActiveSupport::TestCase
- # Replace this with your real tests.
- test "the truth" do
- assert true
- end
-end
View
12 test/unit/user_test.rb
@@ -1,12 +0,0 @@
-# -*- encoding : utf-8 -*-
-require 'test_helper'
-
-class UserTest < ActiveSupport::TestCase
- test "validation" do
- assert Factory.build(:user, :name => '').invalid?
- assert Factory.build(:user, :password => '', :password_confirmation => '').invalid?
- assert Factory.build(:user, :password => 'password', :password_confirmation => nil).invalid?
- assert Factory.build(:user, :password => 'password', :password_confirmation => 'notmatch').invalid?
- assert Factory.build(:user).valid?
- end
-end

0 comments on commit 5b54028

Please sign in to comment.