crowdblog 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/.travis.yml +8 -0
  2. data/Gemfile +5 -2
  3. data/Gemfile.lock +20 -37
  4. data/README.md +7 -0
  5. data/Rakefile +5 -2
  6. data/app/assets/javascripts/crowdblog/templates/posts/edit.jst.eco +1 -1
  7. data/app/controllers/crowdblog/application_controller.rb +1 -11
  8. data/app/controllers/crowdblog/sessions_controller.rb +1 -21
  9. data/app/models/crowdblog/post.rb +53 -44
  10. data/app/models/crowdblog/user.rb +9 -13
  11. data/app/views/layouts/crowdblog/application.html.slim +1 -0
  12. data/config/cucumber.yml +4 -3
  13. data/config/routes.rb +1 -2
  14. data/crowdblog.gemspec +6 -2
  15. data/features/posts/listing.feature +16 -0
  16. data/features/posts/manage.feature +31 -0
  17. data/features/posts/publish.feature +17 -0
  18. data/features/step_definitions/global_steps.rb +19 -0
  19. data/features/step_definitions/navigation_steps.rb +45 -0
  20. data/features/step_definitions/posts_steps.rb +113 -20
  21. data/features/support/env.rb +18 -0
  22. data/lib/crowdblog/version.rb +1 -1
  23. data/script/build +5 -1
  24. data/spec/dummy/app/models/user.rb +12 -0
  25. data/spec/dummy/config/application.rb +9 -0
  26. data/spec/dummy/config/initializers/crowdblog.rb +24 -0
  27. data/spec/dummy/config/initializers/devise.rb +3 -4
  28. data/spec/dummy/config/routes.rb +1 -0
  29. data/spec/fabricators/posts_fabricator.rb +21 -0
  30. data/spec/fabricators/users_fabricator.rb +19 -0
  31. data/spec/models/post_spec.rb +152 -56
  32. data/spec/models/user_spec.rb +57 -0
  33. metadata +116 -60
  34. data/README.rdoc +0 -3
  35. data/app/controllers/crowdblog/users/omniauth_callbacks_controller.rb +0 -21
  36. data/features/posts/manage_posts.feature +0 -46
  37. data/features/step_definitions/index_steps.rb +0 -16
  38. data/features/step_definitions/interaction_steps.rb +0 -26
  39. data/features/step_definitions/session_steps.rb +0 -15
@@ -1,35 +1,128 @@
1
- Given /^I go to the posts page$/ do
2
- visit posts_path
1
+ #*****************
2
+ # GIVEN steps
3
+ #-----------------
4
+ Given /^(a|\d+) Post.? from other User exists$/ do |number|
5
+ number = 1 if number.to_i < 1
6
+
7
+ number.times { Fabricate :post, author: Fabricate(:user) }
3
8
  end
4
9
 
5
- Given /^I fill "([^"]*)" as the post title$/ do |text|
6
- fill_in 'Title', with: text
10
+ Given /^(?:|the )Published Post exists$/ do
11
+ step 'Publisher User exists' unless @current_user
12
+ step 'Test User exists' unless @current_user
13
+
14
+ @published_post = Fabricate :post_published, author: @current_user, publisher: @publisher_user
15
+ end
16
+
17
+ Given /^(?:|the )Test Post exists$/ do
18
+ step 'Test User exists' unless @current_user
19
+
20
+ @post = Fabricate :post_test, author: @current_user
7
21
  end
8
22
 
9
- Given /^I fill "([^"]*)" as the post body$/ do |text|
10
- fill_in 'Body', with: text
23
+
24
+ #*****************
25
+ # WHEN steps
26
+ #-----------------
27
+ When /^(?:|I )delete the Test Post$/ do
28
+ post = page.find('#posts table tr', text: 'This is a Test Post')
29
+
30
+ post.click_link 'Delete'
31
+ step 'confirm the popup dialog'
11
32
  end
12
33
 
13
- Then /^the post "([^"]*)" should be authored by current user$/ do |post_title|
14
- post = Crowdblog::Post.find_by_title(post_title)
15
- post.author.should == @current_user
34
+ When /^(?:|I )Draft a published Post$/ do
35
+ post = page.find('#posts table tr', text: 'This is a Published Post')
36
+
37
+ post.click_link 'Publish' # button should be 'Draft' ?
16
38
  end
17
39
 
18
- Then /^the post "([^"]*)" should have "([^"]*)" as its permalink$/ do |post_title, permalink|
19
- post = Crowdblog::Post.find_by_title(post_title)
20
- post.permalink.should == permalink
40
+ When /^(?:|I )edit the Test Post$/ do
41
+ fill_in 'Title', with: 'I just edited this Post'
42
+ fill_in 'Body', with: 'OMG, I changed the body of this post!'
43
+ click_button 'Save'
21
44
  end
22
45
 
23
- Then /^the post titled "([^"]*)" is marked as published$/ do |post_title|
24
- @current_post = Crowdblog::Post.find_by_title(post_title)
25
- @current_post.should be_published
46
+ When /^(?:|I )Publish a drafted Post$/ do
47
+ post = page.find('#posts table tr', text: 'This is a Test Post')
48
+
49
+ post.click_link 'Publish'
26
50
  end
27
51
 
28
- Then /^current user is set as its publisher$/ do
29
- @current_post.publisher.should == @current_user
52
+ When /^(?:|I )write a Post$/ do
53
+ fill_in 'Title', with: 'A Great Post Title'
54
+ fill_in 'Body', with: 'I just wrote a loooooooong Post'
55
+ click_button 'Save'
30
56
  end
31
57
 
32
- Then /^the post titled "([^"]*)" is marked as drafted$/ do |post_title|
33
- @current_post = Crowdblog::Post.find_by_title(post_title)
34
- @current_post.should be_drafted
58
+
59
+ #*****************
60
+ # THEN steps
61
+ #-----------------
62
+ Then /^(?:|I )should not see the Test Post$/ do
63
+ posts = page.find('#posts table')
64
+
65
+ posts.should_not have_content 'This is a Test Post'
66
+ end
67
+
68
+ Then /^(?:|I )should only see my Posts$/ do
69
+ posts = page.find('#posts table')
70
+
71
+ posts.should have_content 'This is a Test Post'
72
+ posts.should_not have_content 'Random Post title'
73
+ end
74
+
75
+ Then /^(?:|I )should see my New Post$/ do
76
+ posts = page.find('#posts table')
77
+
78
+ posts.should have_content 'A Great Post Title' # Post Title
79
+ posts.should have_content 'test@crowdint.com' # Post Author
80
+
81
+ post = Crowdblog::Post.find_by_title('A Great Post Title')
82
+ post.reload.author.should == @current_user
83
+ post.permalink.should == 'a-great-post-title'
84
+ end
85
+
86
+ Then /^(?:|I )should see Posts for all Users$/ do
87
+ posts = page.find('#posts table')
88
+
89
+ posts.should have_content 'This is a Test Post'
90
+ posts.should have_content 'Random Post title'
91
+ end
92
+
93
+ Then /^(?:|I )should see the Edit Post page$/ do
94
+ page.should have_content 'Edit Post'
95
+
96
+ step 'should see the Post form'
97
+ end
98
+
99
+ Then /^(?:|I )should see the New Post page$/ do
100
+ page.should have_content 'New Post'
101
+
102
+ step 'should see the Post form'
103
+ end
104
+
105
+ Then /^(?:|I )should see the Post as Drafted$/ do
106
+ @post.reload.should be_drafted
107
+ end
108
+
109
+ Then /^(?:|I )should see the Post as Published$/ do
110
+ @post.reload.should be_published # Post is published
111
+ @post.publisher.should == @current_user # Post published by Publisher
112
+ end
113
+
114
+ Then /^(?:|I )should see the Post form$/ do
115
+ form = page.find('.container form')
116
+
117
+ form.should have_content 'Title'
118
+ form.should have_content 'Body'
119
+ form.should have_content 'Markdown syntax'
120
+ form.should have_content 'Save'
121
+ form.should have_content 'Cancel'
122
+ end
123
+
124
+ Then /^(?:|I )should see the Test Post changed$/ do
125
+ posts = page.find('#posts table')
126
+
127
+ posts.should have_content 'I just edited this Post'
35
128
  end
@@ -11,6 +11,10 @@ ENV["RAILS_ROOT"] ||= File.dirname(__FILE__) + "../../../spec/dummy"
11
11
 
12
12
  require 'cucumber/rails'
13
13
 
14
+ # Headless tests: http://bit.ly/xve9YJ
15
+ require 'capybara/webkit'
16
+ Capybara.javascript_driver = ENV['DEBUG'] ? :selenium : :webkit
17
+
14
18
  # Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In
15
19
  # order to ease the transition to Capybara we set the default here. If you'd
16
20
  # prefer to use XPath just remove this line and adjust any selectors in your
@@ -67,3 +71,17 @@ module EngineRoutesHelper
67
71
  include Crowdblog::Engine.routes.url_helpers
68
72
  end
69
73
  World(EngineRoutesHelper)
74
+
75
+ # Wait for AJAX requests when using @javascript tags: http://bit.ly/zige8p
76
+ AfterStep('@javascript') do
77
+ begin
78
+ unless page.evaluate_script('typeof(jQuery)') == 'undefined' # only when JQuery is loaded
79
+ start_time = Time.now
80
+ until page.evaluate_script('jQuery.isReady&&jQuery.active==0') or (start_time + 5.seconds) < Time.now
81
+ page.evaluate_script('jQuery.isReady&&jQuery.active==0').class.should_not eql(String)
82
+ sleep 1
83
+ end
84
+ end
85
+ rescue
86
+ end
87
+ end
@@ -1,3 +1,3 @@
1
1
  module Crowdblog
2
- VERSION = "0.0.1"
2
+ VERSION = '0.0.2'
3
3
  end
data/script/build CHANGED
@@ -16,9 +16,13 @@ which bundle || gem install bundler
16
16
  echo "-- Install Gem dependencies"
17
17
  bundle install
18
18
 
19
+ echo "-- Migrations"
20
+ # both rake db:migrates needed
21
+ bundle exec rake db:migrate
22
+ RAILS_ENV=test bundle exec rake db:migrate
23
+
19
24
  echo "-- Build project"
20
25
  export DISPLAY=:0.0
21
- RAILS_ENV=test rake db:migrate
22
26
  bundle exec rake
23
27
  EXIT_CODE=$?
24
28
 
@@ -0,0 +1,12 @@
1
+ class User < Crowdblog::User
2
+
3
+ # Include default devise modules. Others available are:
4
+ # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
5
+ devise :database_authenticatable, :token_authenticatable, :trackable
6
+
7
+ # Setup accessible (or protected) attributes for your model
8
+ attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :is_publisher
9
+
10
+ validate :email, uniqueness: true
11
+
12
+ end
@@ -60,3 +60,12 @@ module Dummy
60
60
  end
61
61
  end
62
62
 
63
+ # Require and configure Fabrication for test and dev environments (not production)
64
+ unless Rails.env.production?
65
+ require 'fabrication'
66
+ require 'faker'
67
+
68
+ Fabrication.configure do |config|
69
+ config.fabricator_dir = '../../spec/fabricators'
70
+ end
71
+ end
@@ -0,0 +1,24 @@
1
+ module Crowdblog::Devise
2
+
3
+ module Sessions
4
+ def destroy
5
+ sign_out current_user
6
+ redirect_to root_url
7
+ end
8
+ end
9
+
10
+ module Auth
11
+ def authenticate!
12
+ # sign out the user if trying to sign another user
13
+ sign_out current_user if params['auth_token'] && current_user
14
+
15
+ # if no one signed in, use the default user
16
+ unless user_signed_in?
17
+ user = Crowdblog::User.find_by_email('foo@crowdint.com') || Crowdblog::User.create!(email: 'foo@crowdint.com', is_publisher: true)
18
+ sign_in user
19
+ end
20
+
21
+ end
22
+ end
23
+
24
+ end
@@ -213,10 +213,9 @@ Devise.setup do |config|
213
213
  # Add a new OmniAuth provider. Check the wiki for more information on setting
214
214
  # up on your models and hooks.
215
215
  #config.omniauth :google_oauth2, '289799840893.apps.googleusercontent.com', '6DYqOtdhC8S5WARlkiOwS3zb'
216
- config.omniauth :google_oauth2, ENV['GOOGLE_APP_ID'], ENV['GOOGLE_SECRET_KEY'],
217
- {:client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}}}
218
-
219
- config.omniauth :google_apps, :domain => 'crowdint.com'
216
+ #config.omniauth :google_oauth2, ENV['GOOGLE_APP_ID'], ENV['GOOGLE_SECRET_KEY'],
217
+ # {:client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}}}
218
+ #config.omniauth :google_apps, :domain => 'crowdint.com'
220
219
 
221
220
 
222
221
  # ==> Warden configuration
@@ -3,4 +3,5 @@ Rails.application.routes.draw do
3
3
  mount Crowdblog::Engine => '/admin'
4
4
 
5
5
  root to: 'crowdblog/posts#index'
6
+
6
7
  end
@@ -0,0 +1,21 @@
1
+ Fabricator :post, class_name: 'Crowdblog::Post' do
2
+ title { sequence { |i| "Random Post title #{i}" } }
3
+ body { Faker::Lorem.words(rand(10) + 1) }
4
+ state 'drafted'
5
+ author(fabricator: :user)
6
+ end
7
+
8
+ Fabricator :post_test, from: :post do
9
+ title 'This is a Test Post'
10
+ body 'A great post about how Crowd Interactive ROCKS!'
11
+ author(fabricator: :user_test)
12
+ end
13
+
14
+ Fabricator :post_published, from: :post do
15
+ title 'This is a Published Post'
16
+ body 'Published Post! *yeeei*'
17
+ state 'published'
18
+ published_at { 1.minute.ago }
19
+ publisher(fabricator: :user_publisher)
20
+ permalink { |post| post.title.parameterize }
21
+ end
@@ -0,0 +1,19 @@
1
+ Fabricator :user, class_name: 'Crowdblog::User' do
2
+ email { sequence { |i| "user#{i}@crowdint.com" } }
3
+ name { Faker::Name.name }
4
+ is_publisher false
5
+ end
6
+
7
+ Fabricator :user_test, from: :user do
8
+ email 'test@crowdint.com'
9
+ name 'Test User'
10
+ is_publisher false
11
+ authentication_token 'user'
12
+ end
13
+
14
+ Fabricator :user_publisher, from: :user do
15
+ email 'publisher@crowdint.com'
16
+ name 'Publisher User'
17
+ is_publisher true
18
+ authentication_token 'publisher'
19
+ end
@@ -1,94 +1,190 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Crowdblog::Post do
4
- describe "#regenerate_permalink" do
5
- it "generates the permalink based on the post title" do
6
- subject.title = 'A big long post title'
7
- subject.regenerate_permalink
8
- subject.permalink.should == 'a-big-long-post-title'
9
- end
10
- end
3
+ module Crowdblog
4
+ describe Post do
5
+ describe 'Class Methods' do
6
+ describe '#self.all_posts_json' do
7
+ it 'convert ordered posts to JSON' do
8
+ Post.should_receive(:order_by_publish_date).and_return Post
9
+ Post.should_receive(:to_json)
10
+ Post.all_posts_json
11
+ end
12
+ end
11
13
 
12
- describe "#allowed_to_update_permalink?" do
13
- context "post is published" do
14
- before do
15
- subject.state = 'published'
14
+ describe '#self.last_published' do
15
+ it 'should find the last given post published, ordered' do
16
+ Post.should_receive(:published_and_ordered).and_return Post
17
+ Post.should_receive(:limit).with(11)
18
+ Post.last_published(11)
19
+ end
16
20
  end
17
21
 
18
- it "returns false" do
19
- subject.allowed_to_update_permalink?.should be_false
22
+ describe '#self.order_by_publish_date' do
23
+ it 'should order by published' do
24
+ Post.should_receive(:order).with('published_at DESC, created_at DESC, id DESC')
25
+ Post.order_by_publish_date
26
+ end
20
27
  end
21
- end
22
28
 
23
- context "post is not published" do
24
- before do
25
- subject.state = 'draft'
29
+ describe '#self.published' do
30
+ it 'should only find Published Posts' do
31
+ Post.should_receive(:where).with(state: 'published')
32
+ Post.published
33
+ end
26
34
  end
27
35
 
28
- it "returns true" do
29
- subject.allowed_to_update_permalink?.should be_true
36
+ describe '#self.published_and_ordered' do
37
+ it 'should find published posts and order them by published date (FILO)' do
38
+ Post.should_receive(:published).and_return Post
39
+ Post.should_receive(:order_by_publish_date).and_return Post
40
+ Post.should_receive(:includes).with(:author)
41
+ Post.published_and_ordered
42
+ end
43
+ end
44
+
45
+ describe '#self.scoped_for' do
46
+ let(:user) { mock_model User, is_publisher?: true }
47
+
48
+ context 'user is publisher' do
49
+ it 'should see all the Posts' do
50
+ Post.scoped_for(user).should == Post
51
+ end
52
+ end
53
+
54
+ context 'user is not publisher' do
55
+ before { user.should_receive(:is_publisher?).and_return false }
56
+
57
+ it 'should see my own Posts only' do
58
+ user.should_receive(:authored_posts)
59
+ Post.scoped_for(user)
60
+ end
61
+ end
30
62
  end
31
63
  end
32
- end
33
64
 
34
- describe "#formatted_published_date" do
35
- it "Formats the published_at date" do
36
- subject.published_at = Time.at(1329619863)
37
- subject.formatted_published_date.should == 'Feb 18, 2012'
65
+ describe "#allowed_to_update_permalink?" do
66
+ context "post is published" do
67
+ before do
68
+ subject.state = 'published'
69
+ end
70
+
71
+ it "returns false" do
72
+ subject.allowed_to_update_permalink?.should be_false
73
+ end
74
+ end
75
+
76
+ context "post is not published" do
77
+ before do
78
+ subject.state = 'draft'
79
+ end
80
+
81
+ it "returns true" do
82
+ subject.allowed_to_update_permalink?.should be_true
83
+ end
84
+ end
38
85
  end
39
- end
40
86
 
41
- describe "#publish_if_allowed" do
42
- let(:user) { Crowdblog::User.new }
43
- context "user is publisher" do
44
- before do
45
- user.is_publisher = true
87
+ describe "#day" do
88
+ context "published at in february" do
89
+ before do
90
+ subject.published_at = stub(:day => 2)
91
+ end
92
+
93
+ it "returns 02" do
94
+ subject.day.should == "02"
95
+ end
46
96
  end
97
+ end
47
98
 
48
- it "changes its state" do
49
- subject.should_receive('publish')
50
- subject.publish_if_allowed('publish', user)
99
+ describe "#formatted_published_date" do
100
+ it "Formats the published_at date" do
101
+ subject.published_at = Time.zone.parse('2012/02/18')
102
+ subject.formatted_published_date.should == 'Feb 18, 2012'
51
103
  end
104
+ end
52
105
 
53
- it "sets the user as publisher" do
54
- subject.publish_if_allowed('publish', user)
55
- subject.publisher.should be(user)
106
+ describe '#html_body' do
107
+ before { subject.should_receive(:body).and_return '**w00t**' }
108
+
109
+ it 'should parse the Markdown in the body' do
110
+ subject.html_body.should =~ /<strong>w00t<\/strong>/
56
111
  end
57
112
  end
58
113
 
59
- context "user is not publisher" do
114
+ describe '#legacy' do
115
+ let(:string) { '2012-12-29-This_is_a_test' }
60
116
  before do
61
- user.is_publisher = false
117
+ subject.should_receive(:published_at=).with('2012-12-29')
118
+ User.should_receive(:find_by_email).and_return 'FOO'
119
+ subject.should_receive(:author=).with('FOO')
120
+ subject.should_receive(:save)
121
+ subject.should_receive(:publish)
122
+ subject.should_receive(:update_attribute).with(:permalink, 'This_is_a_test')
62
123
  end
63
124
 
64
- it "does not change its state" do
65
- subject.should_not_receive('publish')
66
- subject.publish_if_allowed('publish', user)
125
+ it 'should update a Post from legacy URL' do
126
+ subject.legacy(string, 'foo@bar.com')
67
127
  end
68
128
  end
69
- end
70
129
 
71
- describe "#month" do
72
- context "published at in february" do
73
- before do
74
- subject.published_at = stub(:month => 2)
130
+ describe "#month" do
131
+ context "published at in february" do
132
+ before do
133
+ subject.published_at = stub(:month => 2)
134
+ end
135
+
136
+ it "returns 02" do
137
+ subject.month.should == "02"
138
+ end
139
+ end
140
+ end
141
+
142
+ describe "#publish_if_allowed" do
143
+ let(:user) { Crowdblog::User.new }
144
+ context "user is publisher" do
145
+ before do
146
+ user.is_publisher = true
147
+ end
148
+
149
+ it "changes its state" do
150
+ subject.should_receive('publish')
151
+ subject.publish_if_allowed('publish', user)
152
+ end
153
+
154
+ it "sets the user as publisher" do
155
+ subject.publish_if_allowed('publish', user)
156
+ subject.publisher.should be(user)
157
+ end
75
158
  end
76
159
 
77
- it "returns 02" do
78
- subject.month.should == "02"
160
+ context "user is not publisher" do
161
+ before do
162
+ user.is_publisher = false
163
+ end
164
+
165
+ it "does not change its state" do
166
+ subject.should_not_receive('publish')
167
+ subject.publish_if_allowed('publish', user)
168
+ end
79
169
  end
80
170
  end
81
- end
82
171
 
83
- describe "#day" do
84
- context "published at in february" do
85
- before do
86
- subject.published_at = stub(:day => 2)
172
+ describe "#regenerate_permalink" do
173
+ it "generates the permalink based on the post title" do
174
+ subject.title = 'A big long post title'
175
+ subject.regenerate_permalink
176
+ subject.permalink.should == 'a-big-long-post-title'
87
177
  end
178
+ end
88
179
 
89
- it "returns 02" do
90
- subject.day.should == "02"
180
+ describe '#url_params' do
181
+ before { subject.stub(year: 'YEAR', month: 'MONTH',
182
+ day: 'DAY', permalink: 'PERMALINK') }
183
+
184
+ it 'should return the array for permalink (year/month/day/permalink)' do
185
+ subject.url_params.should == %w(YEAR MONTH DAY PERMALINK html)
91
186
  end
92
187
  end
188
+
93
189
  end
94
190
  end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ module Crowdblog
4
+ describe User do
5
+
6
+ describe '#gravatar_email' do
7
+ context 'when using a Gravatar' do
8
+ before { subject.should_receive(:gravatar_alias).and_return 'GRAVATAR' }
9
+
10
+ it 'should use the alias' do
11
+ subject.gravatar_email.should == 'GRAVATAR'
12
+ end
13
+ end
14
+
15
+ context 'when not using a Gravatar' do
16
+ before do
17
+ subject.should_receive(:gravatar_alias)
18
+ subject.should_receive(:email).and_return 'EMAIL'
19
+ end
20
+
21
+ it 'should use the email' do
22
+ subject.gravatar_email.should == 'EMAIL'
23
+ end
24
+ end
25
+ end
26
+
27
+ describe '#last_post_at' do
28
+ context 'when has posts' do
29
+ let(:post) { mock_model Post }
30
+
31
+ before do
32
+ subject.should_receive(:last_post).and_return post
33
+ post.should_receive(:published_at).and_return '2012-06-31'
34
+ end
35
+
36
+ it 'should be the published post date' do
37
+ subject.last_post_at.should == '2012-06-31'
38
+ end
39
+ end
40
+
41
+ context 'when no posts' do
42
+ it 'should be nil' do
43
+ subject.should_receive(:last_post)
44
+ subject.last_post_at.should be_nil
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#publisher!' do
50
+ it 'should make User a Publisher' do
51
+ subject.should_receive(:update_attribute).with(:is_publisher, true)
52
+ subject.publisher!
53
+ end
54
+ end
55
+
56
+ end
57
+ end