radiant-banner_rotator-extension 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitmodules +3 -0
- data/HELP.textile +87 -0
- data/README.textile +68 -0
- data/Rakefile +136 -0
- data/VERSION +1 -0
- data/app/controllers/admin/banners_controller.rb +61 -0
- data/app/helpers/admin/banners_helper.rb +62 -0
- data/app/models/banner.rb +101 -0
- data/app/models/banner_placement.rb +7 -0
- data/app/views/admin/banners/_form.html.haml +76 -0
- data/app/views/admin/banners/_modify_banner.html.haml +8 -0
- data/app/views/admin/banners/deactivate.html.haml +10 -0
- data/app/views/admin/banners/edit.html.haml +8 -0
- data/app/views/admin/banners/index.html.haml +118 -0
- data/app/views/admin/banners/new.html.haml +5 -0
- data/app/views/admin/banners/remove.html.haml +12 -0
- data/app/views/admin/pages/_banner_info.html.haml +28 -0
- data/app/views/admin/pages/_banners_column.html.haml +11 -0
- data/app/views/admin/pages/_banners_column_header.html.haml +9 -0
- data/banner_rotator_extension.rb +41 -0
- data/config/initializers/radiant_config.rb +3 -0
- data/config/locales/en.yml +34 -0
- data/config/routes.rb +5 -0
- data/db/migrate/001_create_banners.rb +31 -0
- data/db/migrate/002_change_banners_default.rb +9 -0
- data/db/migrate/003_add_description.rb +9 -0
- data/lib/banner_rotator/page_extensions.rb +47 -0
- data/lib/banner_rotator/tags.rb +67 -0
- data/lib/tasks/banner_rotator_extension_tasks.rake +29 -0
- data/public/images/admin/deactivate.png +0 -0
- data/public/images/admin/pictures.png +0 -0
- data/public/images/admin/text_list_numbers.png +0 -0
- data/public/javascripts/lowpro.js +320 -0
- data/spec/controllers/admin_banners_controller_spec.rb +231 -0
- data/spec/datasets/banners_dataset.rb +26 -0
- data/spec/helpers/admin/banners_helper_spec.rb +9 -0
- data/spec/models/banner_placement_spec.rb +44 -0
- data/spec/models/banner_spec.rb +47 -0
- data/spec/models/page_extensions_spec.rb +25 -0
- data/spec/models/tags_spec.rb +69 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +36 -0
- metadata +124 -0
@@ -0,0 +1,231 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require_dependency 'admin/banners_controller'
|
3
|
+
class Admin::BannersController < Admin::ResourceController; def rescue_action(e); raise e; end end
|
4
|
+
|
5
|
+
describe Admin::BannersController do
|
6
|
+
# Uses Admin::ResourceController, built into Radiant
|
7
|
+
dataset :users, :banners
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
@banner = banners(:first)
|
11
|
+
@count = Banner.count
|
12
|
+
login_as(:admin)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should require login" do
|
16
|
+
logout
|
17
|
+
lambda { get :index }.should require_login
|
18
|
+
lambda { get :show, :id => 1 }.should require_login
|
19
|
+
lambda { get :new }.should require_login
|
20
|
+
lambda { post :create}.should require_login
|
21
|
+
lambda { get :edit, :id => 1 }.should require_login
|
22
|
+
lambda { put :update, :id => 1 }.should require_login
|
23
|
+
lambda { get :remove, :id => 1 }.should require_login
|
24
|
+
lambda { delete :destroy, :id => 1 }.should require_login
|
25
|
+
lambda { post :deactivate, :id => 1 }.should require_login
|
26
|
+
end
|
27
|
+
|
28
|
+
it "'create' should add 1 banner and redirect to index" do
|
29
|
+
post :create, :banner => min_valid_banner_params
|
30
|
+
Banner.count.should == @count + 1
|
31
|
+
response.should be_redirect
|
32
|
+
response.should redirect_to(admin_banners_path)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "'update' should redirect to index" do
|
36
|
+
put :update, :id => @banner.id
|
37
|
+
Banner.count.should == @count
|
38
|
+
response.should be_redirect
|
39
|
+
response.should redirect_to(admin_banners_path)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "'deactivate' should remove all banner placements and redirect to index" do
|
43
|
+
@banner.active?.should be_true
|
44
|
+
post :deactivate, :id => @banner.id
|
45
|
+
@banner.inactive?.should be_true
|
46
|
+
Banner.count.should == @count
|
47
|
+
response.should be_redirect
|
48
|
+
response.should redirect_to(admin_banners_path)
|
49
|
+
# flash notices are largely deprecated in as of 0.9
|
50
|
+
# flash[:notice].should include("Banner \"#{@banner.name}\" has been deactivated.")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "'delete' should remove 1 banner and redirect to index" do
|
54
|
+
delete :destroy, :id => @banner.id
|
55
|
+
Banner.count.should == @count - 1
|
56
|
+
response.should be_redirect
|
57
|
+
response.should redirect_to(admin_banners_path)
|
58
|
+
# flash notices are largely deprecated in as of 0.9
|
59
|
+
# flash[:notice].should include("Banner has been deleted.")
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "protected banners" do
|
63
|
+
|
64
|
+
def protected_banner_behavior_on_deactivate
|
65
|
+
response.should be_redirect
|
66
|
+
response.should redirect_to(admin_banners_path)
|
67
|
+
flash[:error].should == @banner.cannot_be_deactivated_msg
|
68
|
+
@banner.active?.should be_true
|
69
|
+
@banner.protected?.should be_true
|
70
|
+
end
|
71
|
+
|
72
|
+
def protected_banner_behavior_on_remove
|
73
|
+
response.should be_redirect
|
74
|
+
response.should redirect_to(admin_banners_path)
|
75
|
+
flash[:error].should == @banner.cannot_be_removed_msg
|
76
|
+
Banner.count.should == @count
|
77
|
+
end
|
78
|
+
|
79
|
+
def protected_from_removal_tests
|
80
|
+
get :remove, :id => @banner.id
|
81
|
+
protected_banner_behavior_on_remove
|
82
|
+
delete :destroy, :id => @banner.id
|
83
|
+
protected_banner_behavior_on_remove
|
84
|
+
end
|
85
|
+
|
86
|
+
def protected_from_deactivation_tests
|
87
|
+
get :deactivate, :id => @banner.id
|
88
|
+
protected_banner_behavior_on_deactivate
|
89
|
+
post :deactivate, :id => @banner.id
|
90
|
+
protected_banner_behavior_on_deactivate
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should protect banners with 'protected' in the banner name from removal" do
|
94
|
+
@banner = banners(:protected)
|
95
|
+
protected_from_removal_tests
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should protect banners with 'protected' in the banner name from deactivation" do
|
99
|
+
@banner = banners(:protected)
|
100
|
+
protected_from_deactivation_tests
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should protect banners named in Radiant::Config['admin.protected_banners'] from removal" do
|
104
|
+
@banner = banners(:child_2_1)
|
105
|
+
Radiant::Config['admin.protected_banners'] = @banner.name
|
106
|
+
protected_from_removal_tests
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should protect banners named in Radiant::Config['admin.protected_banners'] from deactivation" do
|
110
|
+
@banner = banners(:child_2_1)
|
111
|
+
Radiant::Config['admin.protected_banners'] = @banner.name
|
112
|
+
protected_from_deactivation_tests
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
[:admin, :designer].each do |user|
|
118
|
+
describe "#{user} user" do
|
119
|
+
before :each do
|
120
|
+
@banner = Banner.find(:first)
|
121
|
+
login_as user
|
122
|
+
end
|
123
|
+
|
124
|
+
def redirects_to_index
|
125
|
+
response.should be_redirect
|
126
|
+
response.should redirect_to(admin_banners_url)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should have access to the index action' do
|
130
|
+
get :index
|
131
|
+
response.should be_success
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should have access to the show action' do
|
135
|
+
get :show, :id => @banner.id
|
136
|
+
response.should be_redirect
|
137
|
+
response.should redirect_to(edit_admin_banner_url(@banner))
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should have access to the new action' do
|
141
|
+
get :new
|
142
|
+
response.should be_success
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should have access to the create action' do
|
146
|
+
post :create, :banner => min_valid_banner_params
|
147
|
+
redirects_to_index
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should have access to the edit action' do
|
151
|
+
get :edit, :id => 1
|
152
|
+
response.should be_success
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should have access to the update action' do
|
156
|
+
put :update, :id => 1
|
157
|
+
redirects_to_index
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should have access to the remove action" do
|
161
|
+
get :remove, :id => 1
|
162
|
+
response.should be_success
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should have access to the destroy action' do
|
166
|
+
delete :destroy, :id => 1
|
167
|
+
redirects_to_index
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should have access to the deactivate action' do
|
171
|
+
post :deactivate, :id => 1
|
172
|
+
redirects_to_index
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
[:existing, :non_admin].each do |user|
|
178
|
+
describe "#{user} user" do
|
179
|
+
before :each do
|
180
|
+
login_as user
|
181
|
+
end
|
182
|
+
|
183
|
+
def redirects_to_pages
|
184
|
+
response.should be_redirect
|
185
|
+
response.should redirect_to(admin_pages_path)
|
186
|
+
flash[:error].should == 'You must have designer privileges to perform this action.'
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should not have access to the index action' do
|
190
|
+
get :index
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should not have access to the show action' do
|
194
|
+
get :show, :id => 1
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should not have access to the new action' do
|
198
|
+
get :new
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'should not have access to the create action' do
|
202
|
+
post :create
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'should not have access to the edit action' do
|
206
|
+
get :edit, :id => 1
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'should not have access to the update action' do
|
210
|
+
put :update, :id => 1
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'should not have access to the remove action' do
|
214
|
+
put :remove, :id => 1
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should not have access to the destroy action' do
|
218
|
+
delete :destroy, :id => 1
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'should not have access to the deactivate action' do
|
222
|
+
post :deactivate, :id => 1
|
223
|
+
end
|
224
|
+
|
225
|
+
after :each do
|
226
|
+
redirects_to_pages
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class BannersDataset < Dataset::Base
|
2
|
+
uses :pages
|
3
|
+
|
4
|
+
def load
|
5
|
+
create_model Banner, :first, :id => 1, :name => "First", :background_image => "test.jpg", :foreground_image => 'front.jpg', :link_target => "_blank", :link_url => "/en/", :image_style => "text-align:right"
|
6
|
+
create_model Banner, :protected, :id => 2, :name => "First_protected", :background_image => "test.jpg", :foreground_image => 'front.jpg', :link_target => "_blank", :link_url => "/en/protected/", :image_style => "text-align:right"
|
7
|
+
create_model BannerPlacement, :first, :page_id => page_id(:home), :banner_id => banner_id(:first), :weight => 5
|
8
|
+
create_model BannerPlacement, :protected, :page_id => page_id(:home), :banner_id => banner_id(:protected), :weight => 5
|
9
|
+
Page.update_all({:show_banner => ! Page.columns_hash['show_banner'].default }, {:id => page_id(:radius)})
|
10
|
+
create_model Banner, :child_2_1, :name => "Child-2 first", :background_image => "test.jpg"
|
11
|
+
create_model BannerPlacement, :child_2_1, :page_id => page_id(:child_2), :banner_id => banner_id(:child_2_1), :weight => 1
|
12
|
+
create_model Banner, :child_2_2, :name => "Child-2 second", :background_image => "test.jpg"
|
13
|
+
create_model BannerPlacement, :child_2_2, :page_id => page_id(:child_2), :banner_id => banner_id(:child_2_2), :weight => 1
|
14
|
+
create_model Banner, :blank, min_valid_banner_params
|
15
|
+
create_model BannerPlacement, :blank, :page_id => page_id(:another), :banner_id => banner_id(:blank), :weight => 1
|
16
|
+
end
|
17
|
+
|
18
|
+
helpers do
|
19
|
+
def min_valid_banner_params
|
20
|
+
{ :name => 'New Banner',
|
21
|
+
:background_image => 'pic.png'
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Admin::BannersHelper do
|
4
|
+
dataset :home_page
|
5
|
+
|
6
|
+
it "should create options for the placements select box from existing pages" do
|
7
|
+
helper.pages_for_select.should == [["Home", page_id(:home)]]
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe BannerPlacement do
|
4
|
+
|
5
|
+
dataset :banners
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@placement = banner_placements(:first)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should require a page" do
|
12
|
+
@placement.page_id = nil
|
13
|
+
@placement.should_not be_valid
|
14
|
+
@placement.should have(1).error_on(:page_id)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should require a banner" do
|
18
|
+
@placement.banner_id = nil
|
19
|
+
@placement.should_not be_valid
|
20
|
+
@placement.should have(1).error_on(:banner_id)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should require a weight" do
|
24
|
+
@placement.weight = nil
|
25
|
+
@placement.should_not be_valid
|
26
|
+
@placement.should have(1).error_on(:weight)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should require weight to be a number" do
|
30
|
+
@placement.weight = 'foo'
|
31
|
+
@placement.should_not be_valid
|
32
|
+
@placement.should have(1).error_on(:weight)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be unique to a given page and banner" do
|
36
|
+
@placement.page_id = page_id(:home)
|
37
|
+
@placement.banner_id = banner_id(:protected)
|
38
|
+
@placement.should_not be_valid
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be valid with required parameters" do
|
42
|
+
@placement.should be_valid
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Banner do
|
4
|
+
|
5
|
+
dataset :banners
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@banner = banners(:first)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should require a name" do
|
12
|
+
@banner.name = nil
|
13
|
+
@banner.should_not be_valid
|
14
|
+
@banner.should have(1).error_on(:name)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should require a background image" do
|
18
|
+
@banner.background_image = nil
|
19
|
+
@banner.should_not be_valid
|
20
|
+
@banner.should have(1).error_on(:background_image)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be valid with required parameters" do
|
24
|
+
@banner.should be_valid
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "with page placements" do
|
28
|
+
before(:each) do
|
29
|
+
@banner.placements = [{'page_id' => '1', 'weight' => '10'}, {'page_id' => '2', 'weight' => '5'}]
|
30
|
+
@banner.save.should be_true
|
31
|
+
end
|
32
|
+
it "should save associated page placements" do
|
33
|
+
@banner.active?.should be_true
|
34
|
+
@banner.inactive?.should be_false
|
35
|
+
@banner.should have(2).banner_placements
|
36
|
+
@banner.placements.should be_all{|p| p.valid? }
|
37
|
+
end
|
38
|
+
it "should remove all page placements" do
|
39
|
+
@banner.remove_all_placements!
|
40
|
+
@banner.save.should be_true
|
41
|
+
@banner.active?.should be_false
|
42
|
+
@banner.inactive?.should be_true
|
43
|
+
@banner.should have(0).banner_placements
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe "BannerRotator::PageExtensions" do
|
4
|
+
dataset :pages, :banners
|
5
|
+
|
6
|
+
it "should have some banner and banner placements" do
|
7
|
+
pages(:home).should respond_to(:banners)
|
8
|
+
pages(:home).should respond_to(:banner_placements)
|
9
|
+
pages(:home).should have(2).banners
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should select a banner" do
|
13
|
+
[ banners(:first), banners(:protected) ].should include(pages(:home).select_banner)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should inherit banners from its ancestors" do
|
17
|
+
pages(:article).banner_placements.should == pages(:home).banner_placements
|
18
|
+
[ banners(:first), banners(:protected) ].should include(pages(:article).select_banner)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should not delete its parent's banner placements when destroyed" do
|
22
|
+
pages(:home).should == pages(:radius).parent
|
23
|
+
lambda { pages(:radius).destroy }.should_not change(BannerPlacement, :count)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe "BannerRotator::Tags" do
|
4
|
+
dataset :pages, :banners
|
5
|
+
|
6
|
+
describe "<r:banner> defaults and updating show_banner attribute" do
|
7
|
+
if Page.columns_hash['show_banner'].default == true
|
8
|
+
it "should show a banner if show_banner is true (default)" do
|
9
|
+
pages(:home).should render('<r:banner>true</r:banner>').as('true')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should not show a banner if show_banner is false" do
|
13
|
+
pages(:radius).should render('<r:banner>true</r:banner>').as('')
|
14
|
+
end
|
15
|
+
else
|
16
|
+
it "should not show a banner if show_banner is false (default)" do
|
17
|
+
pages(:home).should render('<r:banner>true</r:banner>').as('')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should show a banner if show_banner is true" do
|
21
|
+
pages(:radius).should render('<r:banner>true</r:banner>').as('true')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "<r:banner> selection and inheritance" do
|
27
|
+
before :each do
|
28
|
+
Page.update_all({:show_banner => true })
|
29
|
+
banners(:protected).remove_all_placements! #deal with only 1 active banner for predictable results
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should select a random banner from the associated banners" do
|
33
|
+
pages(:child_2).should render('<r:banner:name />').matching(/^Child\-2 (first|second)$/)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should inherit a banner placement from an ancestor" do
|
37
|
+
pages(:child).should render('<r:banner:name />').as('First')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "banner attributes, if_ and unless_ tags" do
|
42
|
+
before :each do
|
43
|
+
Page.update_all({:show_banner => true })
|
44
|
+
banners(:protected).remove_all_placements! #deal with only 1 active banner for predictable results
|
45
|
+
end
|
46
|
+
%w{name background_image foreground_image link_url link_target image_style}.each do |att|
|
47
|
+
describe "<r:banner:#{att}>" do
|
48
|
+
it "should render the '#{att}' attribute of the selected banner" do
|
49
|
+
pages(:home).should render("<r:banner:#{att} />").as(pages(:home).banners[0][att])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
describe "<r:banner:if_#{att}>" do
|
53
|
+
it "should expand the tag contents if the '#{att}' attribute of the selected banner is not blank" do
|
54
|
+
pages(:home).should render("<r:banner:if_#{att}>Content</r:banner:if_#{att}>").as("Content")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
describe "<r:banner:unless_#{att}>" do
|
58
|
+
it "should expand the tag contents if the '#{att}' attribute of the selected banner is blank" do
|
59
|
+
if pages(:another).banners[0][att].blank?
|
60
|
+
pages(:another).should render("<r:banner:unless_#{att}>Content</r:banner:unless_#{att}>").as("Content")
|
61
|
+
else
|
62
|
+
pages(:another).should render("<r:banner:unless_#{att}>Content</r:banner:unless_#{att}>").as("")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|