radiant-polls-extension 1.0.0
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.
- data/CHANGELOG +27 -0
- data/HELP.textile +71 -0
- data/LICENSE +21 -0
- data/README.textile +112 -0
- data/Rakefile +129 -0
- data/VERSION +1 -0
- data/app/controllers/admin/polls_controller.rb +25 -0
- data/app/controllers/poll_response_controller.rb +35 -0
- data/app/models/option.rb +22 -0
- data/app/models/poll.rb +67 -0
- data/app/views/admin/polls/_form.html.haml +67 -0
- data/app/views/admin/polls/_option.html.haml +9 -0
- data/app/views/admin/polls/edit.html.haml +5 -0
- data/app/views/admin/polls/index.html.haml +72 -0
- data/app/views/admin/polls/new.html.haml +5 -0
- data/app/views/admin/polls/remove.html.haml +17 -0
- data/config/locales/en.yml +25 -0
- data/config/locales/en_available_tags.yml +187 -0
- data/config/routes.rb +6 -0
- data/db/migrate/001_create_polls.rb +12 -0
- data/db/migrate/002_create_options.rb +14 -0
- data/db/migrate/003_add_start_date_to_polls.rb +9 -0
- data/lib/poll_process.rb +23 -0
- data/lib/poll_tags.rb +408 -0
- data/lib/tasks/polls_extension_tasks.rake +56 -0
- data/polls_extension.rb +51 -0
- data/public/images/admin/new-poll.png +0 -0
- data/public/images/admin/poll.png +0 -0
- data/public/images/admin/recycle.png +0 -0
- data/public/images/admin/reset.png +0 -0
- data/public/javascripts/admin/date_selector.js +177 -0
- data/public/javascripts/admin/polls.js +47 -0
- data/public/javascripts/poll_check.js +52 -0
- data/public/stylesheets/admin/polls.css +93 -0
- data/public/stylesheets/polls.css +9 -0
- data/radiant-polls-extension.gemspec +83 -0
- data/spec/controllers/admin/polls_controller_spec.rb +16 -0
- data/spec/controllers/poll_response_controller_spec.rb +149 -0
- data/spec/integration/page_caching_spec.rb +76 -0
- data/spec/lib/poll_tags_spec.rb +415 -0
- data/spec/models/poll_spec.rb +50 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +42 -0
- metadata +141 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "radiant-polls-extension"
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Chase James", "David Cato", "Andrew vonderLuft"]
|
12
|
+
s.date = "2013-02-27"
|
13
|
+
s.description = "Enables polls on pages. Uses cookies instead of sessions"
|
14
|
+
s.email = "avonderluft@avlux.net"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.textile"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"CHANGELOG",
|
21
|
+
"HELP.textile",
|
22
|
+
"LICENSE",
|
23
|
+
"README.textile",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"app/controllers/admin/polls_controller.rb",
|
27
|
+
"app/controllers/poll_response_controller.rb",
|
28
|
+
"app/models/option.rb",
|
29
|
+
"app/models/poll.rb",
|
30
|
+
"app/views/admin/polls/_form.html.haml",
|
31
|
+
"app/views/admin/polls/_option.html.haml",
|
32
|
+
"app/views/admin/polls/edit.html.haml",
|
33
|
+
"app/views/admin/polls/index.html.haml",
|
34
|
+
"app/views/admin/polls/new.html.haml",
|
35
|
+
"app/views/admin/polls/remove.html.haml",
|
36
|
+
"config/locales/en.yml",
|
37
|
+
"config/locales/en_available_tags.yml",
|
38
|
+
"config/routes.rb",
|
39
|
+
"db/migrate/001_create_polls.rb",
|
40
|
+
"db/migrate/002_create_options.rb",
|
41
|
+
"db/migrate/003_add_start_date_to_polls.rb",
|
42
|
+
"lib/poll_process.rb",
|
43
|
+
"lib/poll_tags.rb",
|
44
|
+
"lib/tasks/polls_extension_tasks.rake",
|
45
|
+
"polls_extension.rb",
|
46
|
+
"public/images/admin/new-poll.png",
|
47
|
+
"public/images/admin/poll.png",
|
48
|
+
"public/images/admin/recycle.png",
|
49
|
+
"public/images/admin/reset.png",
|
50
|
+
"public/javascripts/admin/date_selector.js",
|
51
|
+
"public/javascripts/admin/polls.js",
|
52
|
+
"public/javascripts/poll_check.js",
|
53
|
+
"public/stylesheets/admin/polls.css",
|
54
|
+
"public/stylesheets/polls.css",
|
55
|
+
"spec/controllers/admin/polls_controller_spec.rb",
|
56
|
+
"spec/controllers/poll_response_controller_spec.rb",
|
57
|
+
"spec/integration/page_caching_spec.rb",
|
58
|
+
"spec/lib/poll_tags_spec.rb",
|
59
|
+
"spec/models/poll_spec.rb",
|
60
|
+
"spec/spec.opts",
|
61
|
+
"spec/spec_helper.rb"
|
62
|
+
]
|
63
|
+
s.homepage = "https://github.com/avonderluft/radiant-polls-extension"
|
64
|
+
s.require_paths = ["lib"]
|
65
|
+
s.rubygems_version = "1.8.24"
|
66
|
+
s.summary = "Polls Extension for Radiant CMS"
|
67
|
+
|
68
|
+
if s.respond_to? :specification_version then
|
69
|
+
s.specification_version = 3
|
70
|
+
|
71
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
72
|
+
s.add_runtime_dependency(%q<radiant>, [">= 1.1.3"])
|
73
|
+
s.add_runtime_dependency(%q<radiant-cache_by_page-extension>, [">= 1.0.2"])
|
74
|
+
else
|
75
|
+
s.add_dependency(%q<radiant>, [">= 1.1.3"])
|
76
|
+
s.add_dependency(%q<radiant-cache_by_page-extension>, [">= 1.0.2"])
|
77
|
+
end
|
78
|
+
else
|
79
|
+
s.add_dependency(%q<radiant>, [">= 1.1.3"])
|
80
|
+
s.add_dependency(%q<radiant-cache_by_page-extension>, [">= 1.0.2"])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Admin::PollsController do
|
4
|
+
dataset :users
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
login_as :existing
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "index" do
|
11
|
+
it "should show the index template" do
|
12
|
+
get :index
|
13
|
+
response.should render_template('admin/polls/index')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PollResponseController do
|
4
|
+
|
5
|
+
describe 'routing' do
|
6
|
+
|
7
|
+
it 'should route to the index action' do
|
8
|
+
params_from(:get, '/pages/1/poll_response').should == {
|
9
|
+
:controller => 'poll_response',
|
10
|
+
:action => 'index',
|
11
|
+
:page_id => '1'
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should route to the create action' do
|
16
|
+
params_from(:post, '/pages/1/poll_response').should == {
|
17
|
+
:controller => 'poll_response',
|
18
|
+
:action => 'create',
|
19
|
+
:page_id => '1'
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe :create do
|
26
|
+
|
27
|
+
before :each do
|
28
|
+
@page = mock_model(Page, :id => 1, :poll_cookies => [], :submitted_polls => [])
|
29
|
+
@poll = mock_model(Poll, :id => 42)
|
30
|
+
@cookies = mock('cookies')
|
31
|
+
@cookies.stub!(:[])
|
32
|
+
@cookies.stub!(:[]=)
|
33
|
+
controller.stub!(:cookies).and_return(@cookies)
|
34
|
+
@page.should_receive(:request=).with(an_instance_of(ActionController::TestRequest))
|
35
|
+
@page.should_receive(:response=).with(an_instance_of(ActionController::TestResponse))
|
36
|
+
@page.should_receive(:poll_cookies).with(@cookies).and_return([])
|
37
|
+
Page.should_receive(:find).with(duck_type(:to_i)).and_return(@page)
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'poll has not been previously submitted' do
|
41
|
+
|
42
|
+
before :each do
|
43
|
+
Poll.should_receive(:find).with(duck_type(:to_i)).and_return(@poll)
|
44
|
+
@page.should_receive(:submitted_polls=).with(@page.poll_cookies)
|
45
|
+
@page.should_receive(:url).once.and_return('/')
|
46
|
+
@cookies.should_receive(:[]=).with("poll_#{@poll.id.to_s}", an_instance_of(Hash))
|
47
|
+
@poll.should_receive(:submit_response).with(an_instance_of(Option))
|
48
|
+
@option = mock_model(Option)
|
49
|
+
Option.should_receive(:find).with(duck_type(:to_i)).and_return(@option)
|
50
|
+
@page.should have(0).submitted_polls
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'a current poll does not exist' do
|
54
|
+
|
55
|
+
before :each do
|
56
|
+
Poll.should_receive(:find_current).with(no_args()).and_return(nil)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should not cache the response' do
|
60
|
+
post :create, :page_id => @page.id, :poll_id => @poll.id.to_s, :response_id => '111'
|
61
|
+
response.headers['Cache-Control'].should eql('no-cache')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should instantiate the list of submitted polls with the poll ID' do
|
65
|
+
post :create, :page_id => @page.id, :poll_id => @poll.id.to_s, :response_id => '111'
|
66
|
+
@page.should have(1).submitted_polls
|
67
|
+
@page.submitted_polls.should eql([@poll.id])
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should add the poll to the list of submitted polls' do
|
71
|
+
@page.submitted_polls << @poll.id - 1
|
72
|
+
post :create, :page_id => @page.id, :poll_id => @poll.id.to_s, :response_id => '111'
|
73
|
+
@page.should have(2).submitted_polls
|
74
|
+
@page.submitted_polls.should eql([@poll.id - 1, @poll.id])
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'a current poll exists' do
|
80
|
+
|
81
|
+
before :each do
|
82
|
+
@current_poll = mock_model(Poll, :id => @poll.id)
|
83
|
+
Poll.should_receive(:find_current).with(no_args()).and_return(@current_poll)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should instantiate the list of submitted polls with the poll ID' do
|
87
|
+
post :create, :page_id => @page.id, :poll_id => @poll.id.to_s, :response_id => '111'
|
88
|
+
@page.submitted_polls.should eql([@poll.id])
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
describe 'poll has been previously submitted' do
|
96
|
+
|
97
|
+
before :each do
|
98
|
+
Poll.should_receive(:find).with(duck_type(:to_i)).and_return(@poll)
|
99
|
+
@page.should_receive(:submitted_polls=).with(@page.poll_cookies)
|
100
|
+
@poll.should_not_receive(:submit_response)
|
101
|
+
@page.should_receive(:url).and_return('/')
|
102
|
+
Option.should_not_receive(:find)
|
103
|
+
@page.submitted_polls << @poll.id
|
104
|
+
@page.should have(1).submitted_poll
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'a current poll exists' do
|
108
|
+
|
109
|
+
it 'should not add the poll to the list of submitted polls' do
|
110
|
+
@current_poll = mock_model(Poll, :id => @poll.id)
|
111
|
+
Poll.should_receive(:find_current).with(no_args()).and_return(@current_poll)
|
112
|
+
post :create, :page_id => @page.id, :poll_id => @poll.id.to_s, :response_id => '111'
|
113
|
+
@page.should have(1).submitted_polls
|
114
|
+
@page.submitted_polls.should eql([@poll.id])
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'a current poll does not exist' do
|
120
|
+
|
121
|
+
it 'should not add the poll to the list of submitted polls' do
|
122
|
+
Poll.should_receive(:find_current).with(no_args()).and_return(nil)
|
123
|
+
post :create, :page_id => @page.id, :poll_id => @poll.id.to_s, :response_id => '111'
|
124
|
+
@page.submitted_polls.should eql([@poll.id])
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'poll is out of date' do
|
132
|
+
|
133
|
+
it 'should not alter a past poll' do
|
134
|
+
Poll.should_receive(:find).with(duck_type(:to_i)).and_return(@poll)
|
135
|
+
@page.should_receive(:submitted_polls=).with(@page.poll_cookies)
|
136
|
+
@page.should_receive(:url).and_return('/')
|
137
|
+
@poll.should_not_receive(:submit_response)
|
138
|
+
@current_poll = mock_model(Poll, :id => @poll.id + 1)
|
139
|
+
Poll.should_receive(:find_current).with(no_args()).and_return(@current_poll)
|
140
|
+
@current_poll.should_not_receive(:submit_response)
|
141
|
+
Option.should_not_receive(:find)
|
142
|
+
post :create, :page_id => @page.id, :poll_id => @poll.id.to_s, :response_id => '111'
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Page, "with and without polls present" do
|
4
|
+
|
5
|
+
dataset :pages
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
FileUtils.chdir RAILS_ROOT
|
9
|
+
@cache_dir = "#{RAILS_ROOT}/tmp/cache"
|
10
|
+
@cache_file = "#{@cache_dir}/meta/*/*"
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
before :each do
|
15
|
+
@page = pages(:home)
|
16
|
+
@default = 1.day
|
17
|
+
SiteController.page_cache_directory = @cache_dir
|
18
|
+
SiteController.perform_caching = true
|
19
|
+
SiteController.cache_timeout = @default
|
20
|
+
@expire_mins = @default.to_i/60
|
21
|
+
@cache = Radiant::Cache
|
22
|
+
@cache.clear
|
23
|
+
end
|
24
|
+
|
25
|
+
def page_is_cached(page)
|
26
|
+
if response.nil?
|
27
|
+
@cache.clear
|
28
|
+
false
|
29
|
+
else
|
30
|
+
! response.headers['Cache-Control'].include?('no-cache')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def cache_expires
|
35
|
+
Time.now + `cat #{@cache_file}`.split('max-age=')[1].split(',')[0].to_i rescue nil
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "- fetch of page without a poll" do
|
39
|
+
it "should render a page with default caching" do
|
40
|
+
get "#{@page.slug}"
|
41
|
+
response.should be_success
|
42
|
+
response.cache_timeout.should be_nil
|
43
|
+
page_is_cached(@page).should be_true
|
44
|
+
response.headers['Cache-Control'].should == "max-age=#{@default}, public"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
["single poll", "collection of polls"].each do |test|
|
49
|
+
|
50
|
+
describe "- fetch of page with a #{test}" do
|
51
|
+
|
52
|
+
before :each do
|
53
|
+
Poll.create(:id => 42, :title => "My Older Poll", :response_count => 0, :start_date => 2.days.ago)
|
54
|
+
Poll.create(:id => 43, :title => "My Newer Poll", :response_count => 0, :start_date => 1.day.ago)
|
55
|
+
poll_tag = "<r:poll><r:title/></r:poll>"
|
56
|
+
if test.eql?("collection of polls")
|
57
|
+
poll_tag = "<r:polls><r:each:poll><r:title/></r:each:poll></r:polls>"
|
58
|
+
end
|
59
|
+
@part = PagePart.find_by_page_id_and_name(@page, 'body')
|
60
|
+
@part.content += poll_tag
|
61
|
+
@part.save
|
62
|
+
get "#{@page.slug}"
|
63
|
+
@first_cached_page_expire_time = cache_expires
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should render the page and cache it with defaults" do
|
67
|
+
response.should be_success
|
68
|
+
response.cache_timeout.should be_nil
|
69
|
+
cache_expires.should be_close(@expire_mins.minutes.from_now, 30)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,415 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Poll Tags' do
|
4
|
+
|
5
|
+
dataset :pages
|
6
|
+
|
7
|
+
before do
|
8
|
+
options = { Option.new(:title => 'One') => 0,
|
9
|
+
Option.new(:title => 'Two') => 4,
|
10
|
+
Option.new(:title => 'Three') => 6 }
|
11
|
+
poll = Poll.create(:title => 'Test Poll', :options => options.keys)
|
12
|
+
options.each do |option, response_count|
|
13
|
+
response_count.times do
|
14
|
+
poll.submit_response option
|
15
|
+
end
|
16
|
+
end
|
17
|
+
Poll.create(:title => 'Current Poll',
|
18
|
+
:start_date => Date.today,
|
19
|
+
:options => [ Option.new(:title => 'Foo'),
|
20
|
+
Option.new(:title => 'Bar'),
|
21
|
+
Option.new(:title => 'Baz') ])
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '<r:poll> with no start dates' do
|
25
|
+
|
26
|
+
before do
|
27
|
+
Poll.update_all('start_date = NULL', 'start_date IS NOT NULL')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should not accept an empty tag' do
|
31
|
+
tag = %{<r:poll/>}
|
32
|
+
pages(:home).should render(tag).with_error("'title' attribute required")
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'with no polls' do
|
38
|
+
|
39
|
+
before do
|
40
|
+
Poll.delete_all
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '<r:poll>' do
|
44
|
+
|
45
|
+
it 'should accept a bare tag and generate an error message' do
|
46
|
+
tag = %{<r:poll/>}
|
47
|
+
expected = 'No polls found'
|
48
|
+
pages(:home).should render(tag).as(expected)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should accept a title attribute and generate an error message' do
|
52
|
+
tag = %{<r:poll title="Test Poll"/>}
|
53
|
+
expected = 'No polls found'
|
54
|
+
pages(:home).should render(tag).as(expected)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '<r:poll:title>' do
|
60
|
+
|
61
|
+
it 'should generate an error message and no inner content' do
|
62
|
+
tag = %{<r:poll><h2><r:title/></h2></r:poll>}
|
63
|
+
expected = 'No polls found'
|
64
|
+
pages(:home).should render(tag).as(expected)
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '<r:poll>' do
|
72
|
+
|
73
|
+
it 'should accept an empty tag and generate no output' do
|
74
|
+
tag = %{<r:poll/>}
|
75
|
+
expected = ''
|
76
|
+
pages(:home).should render(tag).as(expected)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should accept a title attribute and generate no output' do
|
80
|
+
tag = %{<r:poll title="Test Poll"/>}
|
81
|
+
expected = ''
|
82
|
+
pages(:home).should render(tag).as(expected)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should accept an id tag and generate no output' do
|
86
|
+
tag = %{<r:poll id="#{Poll.find(:first).id}"/>}
|
87
|
+
expected = ''
|
88
|
+
pages(:home).should render(tag).as(expected)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '<r:poll:title>' do
|
94
|
+
|
95
|
+
it 'should show the title of the specified poll' do
|
96
|
+
title = 'Test Poll'
|
97
|
+
tag = %{<r:poll title="#{title}"><r:title/></r:poll>}
|
98
|
+
pages(:home).should render(tag).as(Poll.marker + title)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should show the title of the current poll' do
|
102
|
+
title = 'Current Poll'
|
103
|
+
tag = %{<r:poll><r:title/></r:poll>}
|
104
|
+
pages(:home).should render(tag).as(Poll.marker + title)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '<r:poll:form>' do
|
110
|
+
|
111
|
+
it 'should generate an empty form' do
|
112
|
+
tag = %{<r:poll title="Test Poll"><r:form/></r:poll>}
|
113
|
+
expected = %r{<form action="/pages/\d+/poll_response" method="post" id="poll_form">\s*<div>\s*<input type="hidden"[^>]*>\s*</div>\s*</form>}
|
114
|
+
pages(:home).should render(tag).matching(expected)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '<r:poll:form:submit>' do
|
120
|
+
|
121
|
+
it 'should generate an empty form with a default submit button' do
|
122
|
+
tag = %{<r:poll title="Test Poll"><r:form><r:submit/></r:form></r:poll>}
|
123
|
+
expected = %r{<form action="/pages/\d+/poll_response" method="post" id="poll_form">\s*<div>\s*<input type="submit".*?value="Submit"[^>]*>\s*<input type="hidden"[^>]*>\s*</div>\s*</form>}
|
124
|
+
pages(:home).should render(tag).matching(expected)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should generate an empty form with a custom submit button' do
|
128
|
+
tag = %{<r:poll title="Test Poll"><r:form><r:submit value="Vote"/></r:form></r:poll>}
|
129
|
+
expected = %r{<form action="/pages/\d+/poll_response" method="post" id="poll_form">\s*<div>\s*<input type="submit".*?value="Vote"[^>]*>\s*<input type="hidden"[^>]*>\s*</div>\s*</form>}
|
130
|
+
pages(:home).should render(tag).matching(expected)
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '<r:poll:form:options>' do
|
136
|
+
|
137
|
+
it 'should generate an empty form' do
|
138
|
+
tag = %{<r:poll title="Test Poll"><r:form><r:options/></r:form></r:poll>}
|
139
|
+
expected = %r{<form action="/pages/\d+/poll_response" method="post" id="poll_form">\s*<div>\s*<input type="hidden"[^>]*>\s*</div>\s*</form>}
|
140
|
+
pages(:home).should render(tag).matching(expected)
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
describe '<r:poll:form:options:each>' do
|
146
|
+
|
147
|
+
it 'should generate an empty form' do
|
148
|
+
tag = %{<r:poll title="Test Poll"><r:form><r:options:each/></r:form></r:poll>}
|
149
|
+
expected = %r{<form action="/pages/\d+/poll_response" method="post" id="poll_form">\s*<div>\s*<input type="hidden"[^>]*>\s*</div>\s*</form>}
|
150
|
+
pages(:home).should render(tag).matching(expected)
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
describe '<r:poll:form:options:each:input>' do
|
156
|
+
|
157
|
+
it 'should generate a form with input options' do
|
158
|
+
tag = %{<r:poll title="Test Poll"><r:form><r:options:each><r:input/></r:options:each></r:form></r:poll>}
|
159
|
+
expected = %r{<form action="/pages/\d+/poll_response" method="post" id="poll_form">\s*<div>\s*(<input type="radio"[^>]*>\s*){3}<input type="hidden"[^>]*>\s*</div>\s*</form>}
|
160
|
+
pages(:home).should render(tag).matching(expected)
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
describe '<r:poll:form:options:each:title>' do
|
166
|
+
|
167
|
+
it 'should show the option titles' do
|
168
|
+
tag = %{<r:poll title="Test Poll"><r:form><r:options:each><r:input/><r:title/></r:options:each></r:form></r:poll>}
|
169
|
+
expected = %r{<form action="/pages/\d+/poll_response" method="post" id="poll_form">\s*<div>\s*(<input type="radio"[^>]*>\s*(One|Two|Three)\s*){3}<input type="hidden"[^>]*>\s*</div>\s*</form>}
|
170
|
+
pages(:home).should render(tag).matching(expected)
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
describe '<r:poll:options:each:title>' do
|
176
|
+
|
177
|
+
it 'should show the option titles in random order' do
|
178
|
+
tag = %{<r:poll title="Test Poll"><r:options order="rand"><r:each><r:title/></r:each></r:options></r:poll>}
|
179
|
+
expected = /OneTwoThree|OneThreeTwo|TwoOneThree|TwoThreeOne|ThreeOneTwo|ThreeTwoOne/
|
180
|
+
pages(:home).should render(tag).matching(expected)
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '<r:poll:options:each:number_responses>' do
|
186
|
+
|
187
|
+
it 'should show the response numbers in descending order' do
|
188
|
+
tag = %{<r:poll title="Test Poll"><r:options order="desc"><r:each><p><r:number_responses/></p></r:each></r:options></r:poll>}
|
189
|
+
expected = Poll.marker + '<p>6</p><p>4</p><p>0</p>'
|
190
|
+
pages(:home).should render(tag).as(expected)
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
describe '<r:poll:options:each:percent_responses>' do
|
196
|
+
|
197
|
+
it 'should show the response percentages in ascending order' do
|
198
|
+
tag = %{<r:poll title="Test Poll"><r:options order="asc"><r:each><p><r:percent_responses/></p></r:each></r:options></r:poll>}
|
199
|
+
expected = Poll.marker + '<p>0.0</p><p>40.0</p><p>60.0</p>'
|
200
|
+
pages(:home).should render(tag).as(expected)
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
describe '<r:poll:options:each:if_first>' do
|
206
|
+
|
207
|
+
it 'should render inner tags only if the current context is the first option' do
|
208
|
+
tag = %{<r:poll title="Test Poll"><ul><r:options order="desc"><r:each><li<r:if_first> class="first"</r:if_first>><r:percent_responses /></li></r:each></r:options></ul></r:poll>}
|
209
|
+
expected = Poll.marker + '<ul><li class="first">60.0</li><li>40.0</li><li>0.0</li></ul>'
|
210
|
+
pages(:home).should render(tag).as(expected)
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
describe '<r:poll:options:each:if_last>' do
|
216
|
+
|
217
|
+
it 'should render inner tags only if the current context is the last option' do
|
218
|
+
tag = %{<r:poll title="Test Poll"><ul><r:options order="desc"><r:each><li<r:if_last> class="last"</r:if_last>><r:percent_responses /></li></r:each></r:options></ul></r:poll>}
|
219
|
+
expected = Poll.marker + '<ul><li>60.0</li><li>40.0</li><li class="last">0.0</li></ul>'
|
220
|
+
pages(:home).should render(tag).as(expected)
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
describe '<r:poll:options:each:unless_first>' do
|
226
|
+
|
227
|
+
it 'should render inner tags only unless the current context is the first option' do
|
228
|
+
tag = %{<r:poll title="Test Poll"><r:options order="desc"><r:each><r:unless_first>,</r:unless_first><r:percent_responses /></r:each></r:options></r:poll>}
|
229
|
+
expected = Poll.marker + '60.0,40.0,0.0'
|
230
|
+
pages(:home).should render(tag).as(expected)
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
describe '<r:poll:options:each:unless_last>' do
|
236
|
+
|
237
|
+
it 'should render inner tags only unless the current context is the last option' do
|
238
|
+
tag = %{<r:poll title="Test Poll"><r:options order="desc"><r:each><r:percent_responses /><r:unless_last>,</r:unless_last></r:each></r:options></r:poll>}
|
239
|
+
expected = Poll.marker + '60.0,40.0,0.0'
|
240
|
+
pages(:home).should render(tag).as(expected)
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
|
245
|
+
## Test poll archives
|
246
|
+
describe '<r:polls>' do
|
247
|
+
|
248
|
+
it 'should accept an empty tag and generate no output' do
|
249
|
+
tag = %{<r:polls/>}
|
250
|
+
expected = ''
|
251
|
+
pages(:home).should render(tag).as(expected)
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'should accept valid options and generate no output' do
|
255
|
+
tag = %{<r:polls per_page="10" by="title" order="asc" show_current="false" />}
|
256
|
+
expected = ''
|
257
|
+
pages(:home).should render(tag).as(expected)
|
258
|
+
end
|
259
|
+
|
260
|
+
describe 'with per_page option' do
|
261
|
+
|
262
|
+
it 'should not accept a non-positive integer and generate an error' do
|
263
|
+
tag = %{<r:polls per_page="-5" />}
|
264
|
+
pages(:home).should render(tag).with_error('the per_page attribute of the polls tag must be a positive integer')
|
265
|
+
end
|
266
|
+
|
267
|
+
it 'should not accept a non-integer value and generate an error' do
|
268
|
+
tag = %{<r:polls per_page="no" />}
|
269
|
+
pages(:home).should render(tag).with_error('the per_page attribute of the polls tag must be a positive integer')
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
273
|
+
|
274
|
+
describe 'with by option' do
|
275
|
+
|
276
|
+
it 'should not accept an invalid field name and generate an error' do
|
277
|
+
tag = %{<r:polls by="foobar"/>}
|
278
|
+
pages(:home).should render(tag).with_error('the by attribute of the polls tag must specify a valid field name')
|
279
|
+
end
|
280
|
+
|
281
|
+
end
|
282
|
+
|
283
|
+
describe 'with order option' do
|
284
|
+
|
285
|
+
it 'should accept "asc" and generate no output' do
|
286
|
+
tag = %{<r:polls order="asc"/>}
|
287
|
+
expected = ''
|
288
|
+
pages(:home).should render(tag).as(expected)
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'should accept "desc" and generate no output' do
|
292
|
+
tag = %{<r:polls order="desc"/>}
|
293
|
+
expected = ''
|
294
|
+
pages(:home).should render(tag).as(expected)
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'should not accept a value other than "asc" or "desc" and generate an error' do
|
298
|
+
tag = %{<r:polls order="xxx"/>}
|
299
|
+
pages(:home).should render(tag).with_error('the order attribute of the polls tag must be either "asc" or "desc"')
|
300
|
+
end
|
301
|
+
|
302
|
+
end
|
303
|
+
|
304
|
+
describe 'with no polls' do
|
305
|
+
|
306
|
+
before do
|
307
|
+
Poll.delete_all
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'should accept a bare tag and generate an error message' do
|
311
|
+
tag = %{<r:polls/>}
|
312
|
+
expected = 'No polls found'
|
313
|
+
pages(:home).should render(tag).as(expected)
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
end
|
319
|
+
|
320
|
+
describe '<r:polls:each>' do
|
321
|
+
|
322
|
+
it 'should generate no output' do
|
323
|
+
tag = %{<r:polls><r:each></r:each></r:polls>}
|
324
|
+
expected = ''
|
325
|
+
pages(:home).should render(tag).as(expected)
|
326
|
+
end
|
327
|
+
|
328
|
+
end
|
329
|
+
|
330
|
+
describe '<r:polls:each:poll>' do
|
331
|
+
|
332
|
+
it 'should generate no output' do
|
333
|
+
tag = %{<r:polls><r:each><r:poll/></r:each></r:polls>}
|
334
|
+
expected = ''
|
335
|
+
pages(:home).should render(tag).as(expected)
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|
339
|
+
|
340
|
+
describe '<r:polls:each:poll:title>' do
|
341
|
+
|
342
|
+
before do
|
343
|
+
# Create a future poll that should never appear in any results
|
344
|
+
Poll.create(:title => 'Next Poll', :start_date => Date.today + 1.week)
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'should generate an ordered list of poll titles in descending order' do
|
348
|
+
tag = %{<r:polls order="desc" show_current="true"><r:each><r:poll><p><r:title/></p></r:poll></r:each></r:polls>}
|
349
|
+
expected = "#{Poll.marker}<p>Test Poll</p><p>Current Poll</p>"
|
350
|
+
pages(:home).should render(tag).as(expected)
|
351
|
+
end
|
352
|
+
|
353
|
+
it 'should generate a list of the one poll that has a non-future start date' do
|
354
|
+
tag = %{<r:polls by="start_date" show_current="true"><r:each><r:poll><p><r:title/></p></r:poll></r:each></r:polls>}
|
355
|
+
expected = "#{Poll.marker}<p>Current Poll</p>"
|
356
|
+
pages(:home).should render(tag).as(expected)
|
357
|
+
end
|
358
|
+
|
359
|
+
it 'should generate an ordered list of poll titles in descending order by start date' do
|
360
|
+
poll = Poll.find_by_title('Test Poll').update_attribute(:start_date, Date.today - 1.week)
|
361
|
+
tag = %{<r:polls by="start_date" order="desc" show_current="true"><r:each><r:poll><p><r:title/></p></r:poll></r:each></r:polls>}
|
362
|
+
expected = "#{Poll.marker}<p>Current Poll</p><p>Test Poll</p>"
|
363
|
+
pages(:home).should render(tag).as(expected)
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
367
|
+
|
368
|
+
describe '<r:polls:each:poll:options:title>' do
|
369
|
+
|
370
|
+
it 'should generate a list containing the current poll with its options' do
|
371
|
+
tag = %{<r:polls by="start_date" show_current="true"><r:each><r:poll><p><r:title/></p><r:options order="desc"><r:each><p><r:title/></p></r:each></r:options></r:poll></r:each></r:polls>}
|
372
|
+
expected = "#{Poll.marker}<p>Current Poll</p><p>Foo</p><p>Bar</p><p>Baz</p>"
|
373
|
+
pages(:home).should render(tag).as(expected)
|
374
|
+
end
|
375
|
+
|
376
|
+
it 'should generate no output when sorting by start date and excluding the current poll' do
|
377
|
+
tag = %{<r:polls by="start_date"><r:each><r:poll><p><r:title/></p><r:options order="desc"><r:each><p><r:title/></p></r:each></r:options></r:poll></r:each></r:polls>}
|
378
|
+
expected = ''
|
379
|
+
pages(:home).should render(tag).as(expected)
|
380
|
+
end
|
381
|
+
|
382
|
+
end
|
383
|
+
|
384
|
+
describe '<r:polls:pages>' do
|
385
|
+
|
386
|
+
describe 'with less than per_page polls' do
|
387
|
+
|
388
|
+
it 'should not generate pagination links' do
|
389
|
+
tag = %{<r:polls by="title"><r:pages/></r:polls>}
|
390
|
+
expected = ''
|
391
|
+
pages(:home).should render(tag).as(expected)
|
392
|
+
end
|
393
|
+
|
394
|
+
end
|
395
|
+
|
396
|
+
describe 'with more than per_page polls' do
|
397
|
+
|
398
|
+
before do
|
399
|
+
(1..20).each do |i|
|
400
|
+
Poll.create(:title => "Poll #{i}",
|
401
|
+
:start_date => Date.today - i.weeks,
|
402
|
+
:options => [ Option.new(:title => "Foo #{i}"),
|
403
|
+
Option.new(:title => "Bar #{i}"),
|
404
|
+
Option.new(:title => "Baz #{i}") ])
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
it 'should generate pagination links' do
|
409
|
+
tag = %{<r:polls per_page="5" by="start_date" order="desc"><r:pages/></r:polls>}
|
410
|
+
expected = %r{<span class="current">1</span>}
|
411
|
+
pages(:home).should render(tag).matching(expected)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
end
|