crowdblog 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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