Commit e6b5fe35992613ac39492bd140c027571360682f
1 parent
d5055b63
Exists in
master
and in
1 other branch
Added reporting functionality to /index of questions and visitors
Showing
10 changed files
with
453 additions
and
165 deletions
Show diff stats
app/controllers/questions_controller.rb
@@ -158,7 +158,7 @@ class QuestionsController < InheritedResources::Base | @@ -158,7 +158,7 @@ class QuestionsController < InheritedResources::Base | ||
158 | elsif object_type == "uploaded_ideas" | 158 | elsif object_type == "uploaded_ideas" |
159 | 159 | ||
160 | uploaded_ideas_by_visitor_id = @question.choices.find(:all, :select => 'creator_id, count(*) as ideas_count', | 160 | uploaded_ideas_by_visitor_id = @question.choices.find(:all, :select => 'creator_id, count(*) as ideas_count', |
161 | - :conditions => "choices.creator_id != #{@question.creator_id}", | 161 | + :conditions => "choices.creator_id != #{@question.creator_id}", |
162 | :group => 'creator_id') | 162 | :group => 'creator_id') |
163 | 163 | ||
164 | count = 0 | 164 | count = 0 |
@@ -307,7 +307,30 @@ class QuestionsController < InheritedResources::Base | @@ -307,7 +307,30 @@ class QuestionsController < InheritedResources::Base | ||
307 | end | 307 | end |
308 | 308 | ||
309 | def index | 309 | def index |
310 | - @questions = current_user.questions.find(:all) | 310 | + @questions = current_user.questions.scoped({}) |
311 | + @questions = @questions.created_by(params[:creator]) if params[:creator] | ||
312 | + | ||
313 | + counts = {} | ||
314 | + if params[:user_ideas] | ||
315 | + counts[:user_ideas] = Choice.count(:joins => :question, | ||
316 | + :conditions => "choices.creator_id <> questions.creator_id", | ||
317 | + :group => "choices.question_id") | ||
318 | + end | ||
319 | + if params[:active_user_ideas] | ||
320 | + counts[:active_user_ideas] = Choice.count(:joins => :question, | ||
321 | + :conditions => "choices.active = 1 AND choices.creator_id <> questions.creator_id", | ||
322 | + :group => "choices.question_id") | ||
323 | + end | ||
324 | + if params[:votes_since] | ||
325 | + counts[:recent_votes] = Vote.count(:joins => :question, | ||
326 | + :conditions => ["votes.created_at > ?", params[:votes_since]], | ||
327 | + :group => "votes.question_id") | ||
328 | + end | ||
329 | + | ||
330 | + counts.each_pair do |attr,hash| | ||
331 | + @questions.each{ |q| q[attr] = hash[q.id] || 0 } | ||
332 | + end | ||
333 | + | ||
311 | index! | 334 | index! |
312 | end | 335 | end |
313 | 336 |
app/controllers/visitors_controller.rb
1 | class VisitorsController < InheritedResources::Base | 1 | class VisitorsController < InheritedResources::Base |
2 | respond_to :xml, :json | 2 | respond_to :xml, :json |
3 | before_filter :authenticate | 3 | before_filter :authenticate |
4 | - actions :none | 4 | + actions :index |
5 | + | ||
6 | + def index | ||
7 | + cond = params[:question_id] ? "question_id = #{params[:question_id]}" : nil | ||
8 | + | ||
9 | + counts = {} | ||
10 | + if params[:votes_count] | ||
11 | + counts[:votes_count] = Vote.count(:conditions => cond, :group => "voter_id") | ||
12 | + end | ||
13 | + if params[:skips_count] | ||
14 | + counts[:skips_count] = Skip.count(:conditions => cond, :group => "skipper_id") | ||
15 | + end | ||
16 | + if params[:ideas_count] | ||
17 | + idea_cond = "choices.creator_id != questions.creator_id" + | ||
18 | + (cond ? " AND #{cond}" : "") | ||
19 | + counts[:ideas_count] = Choice.count(:joins => :question, | ||
20 | + :conditions => idea_cond, | ||
21 | + :group => "choices.creator_id") | ||
22 | + end | ||
23 | + if params[:bounces] | ||
24 | + counts[:bounces] = Appearance.count(:conditions => cond, | ||
25 | + :group => "voter_id", | ||
26 | + :having => "count(answerable_id) = 0") | ||
27 | + end | ||
28 | + if params[:questions_created] | ||
29 | + counts[:questions_created] = Question.count(:group => :creator_id) | ||
30 | + end | ||
31 | + | ||
32 | + # visitors belong to a site, so we can't just scope them to a question. | ||
33 | + # instead, take the union of visitor ids with counted objects | ||
34 | + if counts.empty? | ||
35 | + @visitors = current_user.visitors.scoped({}) | ||
36 | + else | ||
37 | + ids = counts.inject([]){ |ids,(k,v)| ids | v.keys } | ||
38 | + @visitors = current_user.visitors.scoped(:conditions => { :id => ids }) | ||
39 | + end | ||
40 | + | ||
41 | + counts.each_pair do |attr,values| | ||
42 | + @visitors.each{ |v| v[attr] = values[v.id] || 0 } | ||
43 | + end | ||
44 | + | ||
45 | + index! | ||
46 | + end | ||
5 | 47 | ||
6 | def objects_by_session_ids | 48 | def objects_by_session_ids |
7 | session_ids = params[:session_ids] | 49 | session_ids = params[:session_ids] |
app/models/question.rb
@@ -29,6 +29,10 @@ class Question < ActiveRecord::Base | @@ -29,6 +29,10 @@ class Question < ActiveRecord::Base | ||
29 | 29 | ||
30 | attr_readonly :site_id | 30 | attr_readonly :site_id |
31 | 31 | ||
32 | + named_scope :created_by, lambda { |id| | ||
33 | + {:conditions => { :local_identifier => id } } | ||
34 | + } | ||
35 | + | ||
32 | def create_choices_from_ideas | 36 | def create_choices_from_ideas |
33 | if ideas && ideas.any? | 37 | if ideas && ideas.any? |
34 | ideas.each do |idea| | 38 | ideas.each do |idea| |
config/routes.rb
1 | ActionController::Routing::Routes.draw do |map| | 1 | ActionController::Routing::Routes.draw do |map| |
2 | map.resources :densities, :only => :index | 2 | map.resources :densities, :only => :index |
3 | - map.resources :visitors, :only => :none, | 3 | + map.resources :visitors, :only => :index, |
4 | :collection => {:objects_by_session_ids => :post}, | 4 | :collection => {:objects_by_session_ids => :post}, |
5 | :member => {:votes => :get} | 5 | :member => {:votes => :get} |
6 | map.resources :questions, :except => [:edit, :destroy], | 6 | map.resources :questions, :except => [:edit, :destroy], |
spec/factories.rb
@@ -58,6 +58,19 @@ Factory.define(:vote) do |f| | @@ -58,6 +58,19 @@ Factory.define(:vote) do |f| | ||
58 | f.voter {|v| v.question.creator} | 58 | f.voter {|v| v.question.creator} |
59 | end | 59 | end |
60 | 60 | ||
61 | +Factory.define(:skip) do |f| | ||
62 | + f.association :question, :factory => :aoi_question | ||
63 | + f.prompt {|s| s.question.prompts.first} | ||
64 | + f.skipper {|s| s.question.creator} | ||
65 | +end | ||
66 | + | ||
67 | +Factory.define(:appearance) do |f| | ||
68 | + f.association :question, :factory => :aoi_question | ||
69 | + f.prompt {|a| a.question.prompts.rand} | ||
70 | + f.voter {|a| a.question.creator} | ||
71 | + f.answerable { nil } | ||
72 | +end | ||
73 | + | ||
61 | Factory.sequence :email do |n| | 74 | Factory.sequence :email do |n| |
62 | "user#{n}@example.com" | 75 | "user#{n}@example.com" |
63 | end | 76 | end |
spec/integration/choices_spec.rb
@@ -22,7 +22,7 @@ describe "Choices" do | @@ -22,7 +22,7 @@ describe "Choices" do | ||
22 | end | 22 | end |
23 | 23 | ||
24 | after do | 24 | after do |
25 | - post_auth question_choices_path(@question, :format => 'xml'), @params | 25 | + post_auth question_choices_path(@question), @params |
26 | response.should be_success | 26 | response.should be_success |
27 | response.should have_tag "choice" | 27 | response.should have_tag "choice" |
28 | end | 28 | end |
@@ -35,7 +35,7 @@ describe "Choices" do | @@ -35,7 +35,7 @@ describe "Choices" do | ||
35 | :data => "foo", | 35 | :data => "foo", |
36 | :local_identifier => "bar" } } | 36 | :local_identifier => "bar" } } |
37 | 37 | ||
38 | - post_auth question_choices_path(@question, :format => 'xml'), @params | 38 | + post_auth question_choices_path(@question), @params |
39 | 39 | ||
40 | response.should be_success | 40 | response.should be_success |
41 | response.should have_tag "choice creator-id", @visitor.id.to_s | 41 | response.should have_tag "choice creator-id", @visitor.id.to_s |
@@ -52,32 +52,23 @@ describe "Choices" do | @@ -52,32 +52,23 @@ describe "Choices" do | ||
52 | end | 52 | end |
53 | 53 | ||
54 | it "should return the deactivated choice given no arguments" do | 54 | it "should return the deactivated choice given no arguments" do |
55 | - put_auth flag_question_choice_path(@question, @choice, :format => 'xml') | 55 | + put_auth flag_question_choice_path(@question, @choice) |
56 | 56 | ||
57 | response.should be_success | 57 | response.should be_success |
58 | response.should have_tag "choice active", "false" | 58 | response.should have_tag "choice active", "false" |
59 | end | 59 | end |
60 | 60 | ||
61 | it "should return the deactivated choice given an explanation" do | 61 | it "should return the deactivated choice given an explanation" do |
62 | - put_auth flag_question_choice_path(@question, @choice, :format => 'xml'), :explanation => "foo" | 62 | + put_auth flag_question_choice_path(@question, @choice), :explanation => "foo" |
63 | 63 | ||
64 | response.should be_success | 64 | response.should be_success |
65 | response.should have_tag "choice active", "false" | 65 | response.should have_tag "choice active", "false" |
66 | end | 66 | end |
67 | 67 | ||
68 | - context "when trying to flag another site's choices" do | ||
69 | - before do | ||
70 | - # this is ugly | ||
71 | - @orig_user = @api_user | ||
72 | - @api_user = Factory(:email_confirmed_user) | ||
73 | - end | ||
74 | - | ||
75 | - it "should fail" do | ||
76 | - put_auth flag_question_choice_path(@question, @choice, :format => 'xml'), :explanation => "foo" | ||
77 | - response.should_not be_success | ||
78 | - end | ||
79 | - | ||
80 | - after { @api_user = @orig_user } | 68 | + it "should fail when trying to flag another site's choices" do |
69 | + other_user = Factory(:email_confirmed_user) | ||
70 | + put_auth other_user, flag_question_choice_path(@question, @choice), :explanation => "foo" | ||
71 | + response.should_not be_success | ||
81 | end | 72 | end |
82 | end | 73 | end |
83 | 74 | ||
@@ -89,14 +80,14 @@ describe "Choices" do | @@ -89,14 +80,14 @@ describe "Choices" do | ||
89 | end | 80 | end |
90 | 81 | ||
91 | it "should return all active choices given no optional parameters" do | 82 | it "should return all active choices given no optional parameters" do |
92 | - get_auth question_choices_path(@question, :format => 'xml') | 83 | + get_auth question_choices_path(@question) |
93 | 84 | ||
94 | response.should be_success | 85 | response.should be_success |
95 | response.should have_tag "choices choice", 5 | 86 | response.should have_tag "choices choice", 5 |
96 | end | 87 | end |
97 | 88 | ||
98 | it "should return all choices if include_inactive is set" do | 89 | it "should return all choices if include_inactive is set" do |
99 | - get_auth question_choices_path(@question, :format => 'xml'), :include_inactive => true | 90 | + get_auth question_choices_path(@question), :include_inactive => true |
100 | 91 | ||
101 | response.should be_success | 92 | response.should be_success |
102 | response.should have_tag "choices choice", 10 | 93 | response.should have_tag "choices choice", 10 |
@@ -105,31 +96,23 @@ describe "Choices" do | @@ -105,31 +96,23 @@ describe "Choices" do | ||
105 | 96 | ||
106 | 97 | ||
107 | it "should return 3 choices when limt is set to 3" do | 98 | it "should return 3 choices when limt is set to 3" do |
108 | - get_auth question_choices_path(@question, :format => 'xml'), :limit => 3 | 99 | + get_auth question_choices_path(@question), :limit => 3 |
109 | 100 | ||
110 | response.should be_success | 101 | response.should be_success |
111 | response.should have_tag "choices choice", 3 | 102 | response.should have_tag "choices choice", 3 |
112 | end | 103 | end |
113 | 104 | ||
114 | it "should return the remaining choices when offset is provided" do | 105 | it "should return the remaining choices when offset is provided" do |
115 | - get_auth question_choices_path(@question, :format => 'xml'), :offset => 2, :limit => 4 | 106 | + get_auth question_choices_path(@question), :offset => 2, :limit => 4 |
116 | 107 | ||
117 | response.should be_success | 108 | response.should be_success |
118 | response.should have_tag "choices choice", 3 | 109 | response.should have_tag "choices choice", 3 |
119 | end | 110 | end |
120 | 111 | ||
121 | - context "when trying to access another site's choices" do | ||
122 | - before do | ||
123 | - @orig_user = @api_user | ||
124 | - @api_user = Factory(:email_confirmed_user) | ||
125 | - end | ||
126 | - | ||
127 | - it "should fail" do | ||
128 | - get_auth question_choices_path(@question, :format => 'xml'), :offset => 2, :limit => 4 | ||
129 | - response.should_not be_success | ||
130 | - end | ||
131 | - | ||
132 | - after { @api_user = @orig_user } | 112 | + it "should fail when trying to access another site's choices" do |
113 | + other_user = Factory(:email_confirmed_user) | ||
114 | + get_auth other_user, question_choices_path(@question), :offset => 2, :limit => 4 | ||
115 | + response.should_not be_success | ||
133 | end | 116 | end |
134 | 117 | ||
135 | end | 118 | end |
@@ -141,23 +124,16 @@ describe "Choices" do | @@ -141,23 +124,16 @@ describe "Choices" do | ||
141 | end | 124 | end |
142 | 125 | ||
143 | it "should return a choice" do | 126 | it "should return a choice" do |
144 | - get_auth question_choice_path(@question, @choice, :format => 'xml') | 127 | + get_auth question_choice_path(@question, @choice) |
145 | 128 | ||
146 | response.should be_success | 129 | response.should be_success |
147 | response.should have_tag "choice", 1 | 130 | response.should have_tag "choice", 1 |
148 | end | 131 | end |
149 | 132 | ||
150 | - context "when requesting a choice from another site" do | ||
151 | - before do | ||
152 | - @other_user = Factory(:email_confirmed_user) | ||
153 | - @other_question = Factory.create(:aoi_question, :site => @other_user) | ||
154 | - @other_choice = Factory.create(:choice, :question => @other_question) | ||
155 | - end | ||
156 | - | ||
157 | - it "should fail" do | ||
158 | - get_auth question_choice_path(@other_question, @other_choice, :format => 'xml') | ||
159 | - response.should_not be_success | ||
160 | - end | 133 | + it "should fail when requesting a choice from another site" do |
134 | + other_user = Factory(:email_confirmed_user) | ||
135 | + get_auth other_user, question_choice_path(@question, @choice) | ||
136 | + response.should_not be_success | ||
161 | end | 137 | end |
162 | 138 | ||
163 | end | 139 | end |
@@ -171,23 +147,15 @@ describe "Choices" do | @@ -171,23 +147,15 @@ describe "Choices" do | ||
171 | 147 | ||
172 | it "should succeed given valid attributes" do | 148 | it "should succeed given valid attributes" do |
173 | params = { :choice => { :data => "foo" } } | 149 | params = { :choice => { :data => "foo" } } |
174 | - put_auth question_choice_path(@question, @choice, :format => 'xml'), params | 150 | + put_auth question_choice_path(@question, @choice), params |
175 | response.should be_success | 151 | response.should be_success |
176 | end | 152 | end |
177 | 153 | ||
178 | - context "when updatng another site's choice" do | ||
179 | - before do | ||
180 | - @orig_user = @api_user | ||
181 | - @api_user = Factory(:email_confirmed_user) | ||
182 | - end | ||
183 | - | ||
184 | - it "should fail" do | ||
185 | - params = { :choice => { :data => "foo" } } | ||
186 | - put_auth question_choice_path(@question, @choice, :format => 'xml'), params | ||
187 | - response.should_not be_success | ||
188 | - end | ||
189 | - | ||
190 | - after { @api_user = @orig_user } | 154 | + it "should fail when updating another site's choice" do |
155 | + other_user = Factory(:email_confirmed_user) | ||
156 | + params = { :choice => { :data => "foo" } } | ||
157 | + put_auth other_user, question_choice_path(@question, @choice), params | ||
158 | + response.should_not be_success | ||
191 | end | 159 | end |
192 | end | 160 | end |
193 | 161 |
spec/integration/prompts_spec.rb
@@ -13,7 +13,7 @@ describe "Prompts" do | @@ -13,7 +13,7 @@ describe "Prompts" do | ||
13 | end | 13 | end |
14 | 14 | ||
15 | it "returns a prompt object" do | 15 | it "returns a prompt object" do |
16 | - get_auth question_prompt_path(@question, @prompt, :format => 'xml') | 16 | + get_auth question_prompt_path(@question, @prompt) |
17 | response.should be_success | 17 | response.should be_success |
18 | response.should have_tag "prompt", 1 | 18 | response.should have_tag "prompt", 1 |
19 | end | 19 | end |
@@ -31,11 +31,11 @@ describe "Prompts" do | @@ -31,11 +31,11 @@ describe "Prompts" do | ||
31 | :with_prompt => true, | 31 | :with_prompt => true, |
32 | :visitor_identifier => @visitor.identifier ) | 32 | :visitor_identifier => @visitor.identifier ) |
33 | @appearance_id = info[:appearance_id] | 33 | @appearance_id = info[:appearance_id] |
34 | - @prompt_id = info[:picked_prompt_id] | 34 | + @picked_prompt_id = info[:picked_prompt_id] |
35 | end | 35 | end |
36 | 36 | ||
37 | it "should return a new skip object given no optional parameters" do | 37 | it "should return a new skip object given no optional parameters" do |
38 | - post_auth skip_question_prompt_path(@question.id, @prompt_id, :format => 'xml') | 38 | + post_auth skip_question_prompt_path(@question.id, @picked_prompt_id) |
39 | response.should be_success | 39 | response.should be_success |
40 | response.should have_tag "skip", 1 | 40 | response.should have_tag "skip", 1 |
41 | end | 41 | end |
@@ -48,7 +48,7 @@ describe "Prompts" do | @@ -48,7 +48,7 @@ describe "Prompts" do | ||
48 | :skip_reason => "bar", | 48 | :skip_reason => "bar", |
49 | :appearance_lookup => @appearance_id, | 49 | :appearance_lookup => @appearance_id, |
50 | :time_viewed => 47 } } | 50 | :time_viewed => 47 } } |
51 | - post_auth skip_question_prompt_path(@question, @prompt_id, :format => 'xml'), params | 51 | + post_auth skip_question_prompt_path(@question, @picked_prompt_id), params |
52 | response.should be_success | 52 | response.should be_success |
53 | response.should have_tag "skip", 1 | 53 | response.should have_tag "skip", 1 |
54 | response.should have_tag "skip appearance-id", @appearance_id.to_s | 54 | response.should have_tag "skip appearance-id", @appearance_id.to_s |
@@ -65,7 +65,7 @@ describe "Prompts" do | @@ -65,7 +65,7 @@ describe "Prompts" do | ||
65 | :with_appearance => true, | 65 | :with_appearance => true, |
66 | :algorithm => "catchup", | 66 | :algorithm => "catchup", |
67 | :with_visitor_stats => true } } | 67 | :with_visitor_stats => true } } |
68 | - post_auth skip_question_prompt_path(@question, @prompt_id, :format => 'xml'), params | 68 | + post_auth skip_question_prompt_path(@question, @picked_prompt_id), params |
69 | response.should be_success | 69 | response.should be_success |
70 | response.should have_tag "prompt", 1 | 70 | response.should have_tag "prompt", 1 |
71 | response.should have_tag "prompt appearance_id", /.+/ | 71 | response.should have_tag "prompt appearance_id", /.+/ |
@@ -73,19 +73,12 @@ describe "Prompts" do | @@ -73,19 +73,12 @@ describe "Prompts" do | ||
73 | response.should have_tag "prompt visitor_ideas", /\d+/ | 73 | response.should have_tag "prompt visitor_ideas", /\d+/ |
74 | end | 74 | end |
75 | 75 | ||
76 | - context "when trying to skip another site's questions" do | ||
77 | - before do | ||
78 | - @orig_user = @api_user | ||
79 | - @api_user = Factory(:email_confirmed_user) | ||
80 | - end | ||
81 | - | ||
82 | - it "should fail" do | ||
83 | - post_auth skip_question_prompt_path(@question.id, @prompt_id, :format => 'xml') | ||
84 | - response.should_not be_success | ||
85 | - end | ||
86 | - | ||
87 | - after { @api_user = @orig_user } | 76 | + it "should fail when trying to skip another site's questions" do |
77 | + other_user = Factory(:email_confirmed_user) | ||
78 | + post_auth other_user, skip_question_prompt_path(@question, @picked_prompt_id) | ||
79 | + response.should_not be_success | ||
88 | end | 80 | end |
81 | + | ||
89 | end | 82 | end |
90 | 83 | ||
91 | describe "POST 'vote'" do | 84 | describe "POST 'vote'" do |
@@ -101,17 +94,17 @@ describe "Prompts" do | @@ -101,17 +94,17 @@ describe "Prompts" do | ||
101 | :with_prompt => true, | 94 | :with_prompt => true, |
102 | :visitor_identifier => @visitor.identifier ) | 95 | :visitor_identifier => @visitor.identifier ) |
103 | @appearance_id = info[:appearance_id] | 96 | @appearance_id = info[:appearance_id] |
104 | - @prompt_id = info[:picked_prompt_id] | 97 | + @picked_prompt_id = info[:picked_prompt_id] |
105 | end | 98 | end |
106 | 99 | ||
107 | it "should fail without the required 'direction' parameter" do | 100 | it "should fail without the required 'direction' parameter" do |
108 | - post_auth vote_question_prompt_path(@question.id, @prompt_id, :format => 'xml') | 101 | + post_auth vote_question_prompt_path(@question.id, @picked_prompt_id) |
109 | response.should_not be_success | 102 | response.should_not be_success |
110 | end | 103 | end |
111 | 104 | ||
112 | it "should return a new vote object given no optional parameters" do | 105 | it "should return a new vote object given no optional parameters" do |
113 | params = { :vote => { :direction => "left" } } | 106 | params = { :vote => { :direction => "left" } } |
114 | - post_auth vote_question_prompt_path(@question.id, @prompt_id, :format => 'xml'), params | 107 | + post_auth vote_question_prompt_path(@question.id, @picked_prompt_id), params |
115 | response.should be_success | 108 | response.should be_success |
116 | response.should have_tag "vote", 1 | 109 | response.should have_tag "vote", 1 |
117 | end | 110 | end |
@@ -124,7 +117,7 @@ describe "Prompts" do | @@ -124,7 +117,7 @@ describe "Prompts" do | ||
124 | :direction => "right", | 117 | :direction => "right", |
125 | :appearance_lookup => @appearance_id, | 118 | :appearance_lookup => @appearance_id, |
126 | :time_viewed => 47 } } | 119 | :time_viewed => 47 } } |
127 | - post_auth vote_question_prompt_path(@question, @prompt_id, :format => 'xml'), params | 120 | + post_auth vote_question_prompt_path(@question, @picked_prompt_id), params |
128 | response.should be_success | 121 | response.should be_success |
129 | response.should have_tag "vote", 1 | 122 | response.should have_tag "vote", 1 |
130 | response.should have_tag "vote appearance-id", @appearance_id.to_s | 123 | response.should have_tag "vote appearance-id", @appearance_id.to_s |
@@ -143,7 +136,7 @@ describe "Prompts" do | @@ -143,7 +136,7 @@ describe "Prompts" do | ||
143 | :with_appearance => true, | 136 | :with_appearance => true, |
144 | :algorithm => "catchup", | 137 | :algorithm => "catchup", |
145 | :with_visitor_stats => true } } | 138 | :with_visitor_stats => true } } |
146 | - post_auth vote_question_prompt_path(@question, @prompt_id, :format => 'xml'), params | 139 | + post_auth vote_question_prompt_path(@question, @picked_prompt_id), params |
147 | response.should be_success | 140 | response.should be_success |
148 | response.should have_tag "prompt", 1 | 141 | response.should have_tag "prompt", 1 |
149 | response.should have_tag "prompt appearance_id", /.+/ | 142 | response.should have_tag "prompt appearance_id", /.+/ |
@@ -151,19 +144,11 @@ describe "Prompts" do | @@ -151,19 +144,11 @@ describe "Prompts" do | ||
151 | response.should have_tag "prompt visitor_ideas", /\d+/ | 144 | response.should have_tag "prompt visitor_ideas", /\d+/ |
152 | end | 145 | end |
153 | 146 | ||
154 | - context "when trying to vote on another site's questions" do | ||
155 | - before do | ||
156 | - @orig_user = @api_user | ||
157 | - @api_user = Factory(:email_confirmed_user) | ||
158 | - end | ||
159 | - | ||
160 | - it "should fail" do | ||
161 | - params = { :vote => { :direction => "left" } } | ||
162 | - post_auth vote_question_prompt_path(@question.id, @prompt_id, :format => 'xml'), params | ||
163 | - response.should_not be_success | ||
164 | - end | ||
165 | - | ||
166 | - after { @api_user = @orig_user } | 147 | + it "should fail when trying to vote on another site's questions" do |
148 | + other_user = Factory(:email_confirmed_user) | ||
149 | + params = { :vote => { :direction => "left" } } | ||
150 | + post_auth other_user, vote_question_prompt_path(@question.id, @picked_prompt_id), params | ||
151 | + response.should_not be_success | ||
167 | end | 152 | end |
168 | 153 | ||
169 | end | 154 | end |
spec/integration/questions_spec.rb
@@ -3,29 +3,81 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') | @@ -3,29 +3,81 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') | ||
3 | describe "Questions" do | 3 | describe "Questions" do |
4 | include IntegrationSupport | 4 | include IntegrationSupport |
5 | before do | 5 | before do |
6 | - 3.times{ Factory.create(:aoi_question, :site => @api_user) } | 6 | + @user = self.default_user = Factory(:email_confirmed_user) |
7 | + @choices = {} | ||
8 | + @questions = Array.new(5){ Factory(:aoi_question, :site => @user) }.each do |q| | ||
9 | + @choices[q.id] = Array.new(rand(10)){ Factory(:choice, :question => q, :active => (rand(2)==1)) } | ||
10 | + end | ||
7 | end | 11 | end |
8 | 12 | ||
9 | describe "GET 'index'" do | 13 | describe "GET 'index'" do |
10 | it "should return an array of questions" do | 14 | it "should return an array of questions" do |
11 | get_auth questions_path(:format => 'xml') | 15 | get_auth questions_path(:format => 'xml') |
16 | + response.should be_success | ||
17 | + response.body.should have_tag("questions question", @questions.size) | ||
18 | + end | ||
19 | + | ||
20 | + it "should not return other users' questions" do | ||
21 | + other_user = Factory(:email_confirmed_user) | ||
22 | + other_questions = Array.new(5){ Factory(:aoi_question, :site => other_user) } | ||
23 | + | ||
24 | + get_auth other_user, questions_path(:format => 'xml') | ||
25 | + | ||
26 | + response.should be_success | ||
27 | + response.body.should have_tag "questions question site-id", :count => 5, :text => other_user.id.to_s | ||
28 | + response.body.should_not have_tag "site-id", @user.id.to_s | ||
29 | + end | ||
30 | + | ||
31 | + it "should return a list of questions for a specific creator" do | ||
32 | + 3.times{ Factory(:aoi_question, | ||
33 | + :site => @user, | ||
34 | + :local_identifier => "jim") } | ||
35 | + | ||
36 | + get_auth questions_path(:format => 'xml'), {:creator => "jim"} | ||
37 | + response.should be_success | ||
12 | response.body.should have_tag("questions question", 3) | 38 | response.body.should have_tag("questions question", 3) |
39 | + response.body.should have_tag("questions question local-identifier", "jim") | ||
40 | + end | ||
41 | + | ||
42 | + it "should calculate the total number of user-submitted choices" do | ||
43 | + get_auth questions_path(:format => 'xml'), :user_ideas => true | ||
44 | + | ||
13 | response.should be_success | 45 | response.should be_success |
46 | + response.body.should have_tag("question", @questions.size) | ||
47 | + @choices.each_value do |cs| | ||
48 | + response.body.should have_tag("user-ideas", :text => cs.size) | ||
49 | + end | ||
14 | end | 50 | end |
15 | 51 | ||
16 | - context "when calling index as another user" do | ||
17 | - before do | ||
18 | - @orig_user = @api_user | ||
19 | - @api_user = Factory(:email_confirmed_user) | 52 | + it "should calculate the number of active user-submitted choices" do |
53 | + get_auth questions_path(:format => 'xml'), :active_user_ideas => true | ||
54 | + | ||
55 | + response.should be_success | ||
56 | + response.body.should have_tag("question", @questions.size) | ||
57 | + @choices.each_value do |cs| | ||
58 | + count = cs.select{|c| c.active}.size | ||
59 | + response.body.should have_tag "active-user-ideas", :text => count | ||
20 | end | 60 | end |
21 | - | ||
22 | - it "should not return the questions of the original user" do | ||
23 | - get_auth questions_path(:format => 'xml') | ||
24 | - response.should be_success | ||
25 | - response.body.should_not have_tag("question") | 61 | + end |
62 | + | ||
63 | + it "should calculate the number of votes submitted since some date" do | ||
64 | + votes = {} | ||
65 | + @questions.each do |q| | ||
66 | + votes[q.id] = Array.new(20) do | ||
67 | + Factory(:vote, :question => q, :created_at => rand(365).days.ago) | ||
68 | + end | ||
69 | + end | ||
70 | + date = rand(365).days.ago | ||
71 | + get_auth questions_path(:format => 'xml'), :votes_since => date.strftime("%Y-%m-%d") | ||
72 | + | ||
73 | + response.should be_success | ||
74 | + response.body.should have_tag("question", @questions.size) | ||
75 | + votes.each_value do |vs| | ||
76 | + count = vs.select{|v| v.created_at > date}.size | ||
77 | + response.body.should have_tag"recent-votes", :text => count | ||
26 | end | 78 | end |
27 | - after { @api_user = @orig_user } | ||
28 | end | 79 | end |
80 | + | ||
29 | end | 81 | end |
30 | 82 | ||
31 | describe "GET 'new'" do | 83 | describe "GET 'new'" do |
@@ -91,7 +143,7 @@ describe "Questions" do | @@ -91,7 +143,7 @@ describe "Questions" do | ||
91 | 143 | ||
92 | it "should fail given invalid parameters" do | 144 | it "should fail given invalid parameters" do |
93 | params = { :type => "ideas", :response_type => "foo", :redisk_key => "bar" } | 145 | params = { :type => "ideas", :response_type => "foo", :redisk_key => "bar" } |
94 | - post_auth export_question_path(@question, :format => 'xml') | 146 | + post_auth export_question_path(@question) |
95 | response.should be_success | 147 | response.should be_success |
96 | response.body.should =~ /Error/ | 148 | response.body.should =~ /Error/ |
97 | end | 149 | end |
@@ -108,7 +160,7 @@ describe "Questions" do | @@ -108,7 +160,7 @@ describe "Questions" do | ||
108 | before { @question = Factory.create(:aoi_question, :site => @api_user) } | 160 | before { @question = Factory.create(:aoi_question, :site => @api_user) } |
109 | 161 | ||
110 | it "should succeed given no optional parameters" do | 162 | it "should succeed given no optional parameters" do |
111 | - get_auth question_path(@question, :format => 'xml') | 163 | + get_auth question_path(@question) |
112 | response.should be_success | 164 | response.should be_success |
113 | response.should have_tag "question", 1 | 165 | response.should have_tag "question", 1 |
114 | response.should have_tag "question id", @question.id.to_s | 166 | response.should have_tag "question id", @question.id.to_s |
@@ -121,7 +173,7 @@ describe "Questions" do | @@ -121,7 +173,7 @@ describe "Questions" do | ||
121 | :with_prompt => true, | 173 | :with_prompt => true, |
122 | :with_appearance => true, | 174 | :with_appearance => true, |
123 | :with_visitor_stats => true } | 175 | :with_visitor_stats => true } |
124 | - get_auth question_path(@question, :format => 'xml'), params | 176 | + get_auth question_path(@question), params |
125 | response.should be_success | 177 | response.should be_success |
126 | response.should have_tag "question", 1 | 178 | response.should have_tag "question", 1 |
127 | response.should have_tag "question id", @question.id.to_s | 179 | response.should have_tag "question id", @question.id.to_s |
@@ -134,22 +186,15 @@ describe "Questions" do | @@ -134,22 +186,15 @@ describe "Questions" do | ||
134 | it "should fail if 'with_prompt' is set but 'visitor_identifier' not provided" do | 186 | it "should fail if 'with_prompt' is set but 'visitor_identifier' not provided" do |
135 | pending("figure out argument dependencies") do | 187 | pending("figure out argument dependencies") do |
136 | params = { :with_prompt => true } | 188 | params = { :with_prompt => true } |
137 | - get_auth question_path(@question, :format => 'xml'), params | 189 | + get_auth question_path(@question), params |
138 | response.should_not be_success | 190 | response.should_not be_success |
139 | end | 191 | end |
140 | end | 192 | end |
141 | 193 | ||
142 | - context "GET 'show' trying to view others sites' questions" do | ||
143 | - before do | ||
144 | - @orig_user = @api_user | ||
145 | - @api_user = Factory(:email_confirmed_user) | ||
146 | - end | ||
147 | - | ||
148 | - it "should fail" do | ||
149 | - get_auth question_path(@question, :format => 'xml') | ||
150 | - response.should_not be_success | ||
151 | - end | ||
152 | - after { @api_user = @orig_user } | 194 | + it "should fail when trying to view other sites' questions" do |
195 | + other_user = Factory(:email_confirmed_user) | ||
196 | + get_auth other_user, question_path(@question) | ||
197 | + response.should_not be_success | ||
153 | end | 198 | end |
154 | end | 199 | end |
155 | 200 | ||
@@ -163,38 +208,32 @@ describe "Questions" do | @@ -163,38 +208,32 @@ describe "Questions" do | ||
163 | :information => "foo", | 208 | :information => "foo", |
164 | :name => "bar", | 209 | :name => "bar", |
165 | :local_identifier => "baz" } } | 210 | :local_identifier => "baz" } } |
166 | - put_auth question_path(@question, :format => 'xml'), params | 211 | + put_auth question_path(@question), params |
167 | response.should be_success | 212 | response.should be_success |
168 | end | 213 | end |
169 | 214 | ||
170 | it "should not be able to change the site id" do | 215 | it "should not be able to change the site id" do |
171 | original_site_id = @question.site_id | 216 | original_site_id = @question.site_id |
172 | params = { :question => { :site_id => -1 } } | 217 | params = { :question => { :site_id => -1 } } |
173 | - put_auth question_path(@question, :format => 'xml'), params | 218 | + put_auth question_path(@question), params |
174 | @question.reload.site_id.should == original_site_id | 219 | @question.reload.site_id.should == original_site_id |
175 | end | 220 | end |
176 | 221 | ||
177 | it "should ignore protected attributes" do | 222 | it "should ignore protected attributes" do |
178 | params = { :question => { :votes_count => 999 } } | 223 | params = { :question => { :votes_count => 999 } } |
179 | - put_auth question_path(@question, :format => 'xml'), params | 224 | + put_auth question_path(@question), params |
180 | response.should be_success | 225 | response.should be_success |
181 | - @question.reload.site_id.should_not == 999 | 226 | + @question.reload.votes_count.should_not == 999 |
182 | end | 227 | end |
183 | 228 | ||
184 | - context "when updatng another site's question" do | ||
185 | - before do | ||
186 | - @orig_user = @api_user | ||
187 | - @api_user = Factory(:email_confirmed_user) | ||
188 | - end | 229 | + it "should fail when updating another site's question" do |
230 | + other_user = Factory(:email_confirmed_user) | ||
231 | + params = { :question => { :name => "foo" } } | ||
232 | + put_auth other_user, question_path(@question), params | ||
233 | + response.should_not be_success | ||
234 | + end | ||
189 | 235 | ||
190 | - it "should fail" do | ||
191 | - params = { :question => { :name => "foo" } } | ||
192 | - put_auth question_path(@question, :format => 'xml'), params | ||
193 | - response.should_not be_success | ||
194 | - end | ||
195 | 236 | ||
196 | - after { @api_user = @orig_user } | ||
197 | - end | ||
198 | end | 237 | end |
199 | 238 | ||
200 | describe "GET 'all_object_info_totals_by_date'" do | 239 | describe "GET 'all_object_info_totals_by_date'" do |
spec/integration/visitors_spec.rb
@@ -2,7 +2,200 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') | @@ -2,7 +2,200 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') | ||
2 | 2 | ||
3 | describe "Visitors" do | 3 | describe "Visitors" do |
4 | include IntegrationSupport | 4 | include IntegrationSupport |
5 | + | ||
6 | + before do | ||
7 | + @user = self.default_user = Factory(:email_confirmed_user) | ||
8 | + @visitors = @user.visitors << Array.new(30){ Factory(:visitor, :site => @user) } | ||
9 | + @questions = Array.new(3){ Factory(:aoi_question, :site => @user, :creator => @visitors.rand) } | ||
10 | + end | ||
11 | + | ||
12 | + describe "GET 'index'" do | ||
13 | + it "should return an array of visitors" do | ||
14 | + get_auth visitors_path | ||
15 | + response.should be_success | ||
16 | + response.body.should have_tag("visitors visitor", @visitors.size) | ||
17 | + end | ||
18 | + | ||
19 | + it "should not return other sites' visitors" do | ||
20 | + other_user = Factory(:email_confirmed_user) | ||
21 | + other_visitors = other_user.visitors << Array.new(10) do | ||
22 | + Factory(:visitor, :site => other_user) | ||
23 | + end | ||
24 | + get_auth other_user, visitors_path | ||
25 | + | ||
26 | + response.should be_success | ||
27 | + response.body.should have_tag("visitors visitor", other_visitors.size) | ||
28 | + end | ||
29 | + | ||
30 | + it "should return the number of votes for each visitor" do | ||
31 | + counts = Hash.new(0) | ||
32 | + 20.times do | ||
33 | + visitor = @visitors.rand | ||
34 | + Factory(:vote, :question => @questions.rand, :voter => visitor) | ||
35 | + counts[visitor.id] += 1 | ||
36 | + end | ||
37 | + get_auth visitors_path, :votes_count => true | ||
38 | + | ||
39 | + response.should be_success | ||
40 | + response.should have_tag "visitor", counts.size do |nodes| | ||
41 | + nodes.each do |node| | ||
42 | + id = node.content("id").to_i | ||
43 | + node.should have_tag("id"), :text => id | ||
44 | + node.should have_tag("votes-count"), :text => counts[id] | ||
45 | + end | ||
46 | + end | ||
47 | + end | ||
48 | + | ||
49 | + it "should return the number of skips for each visitor" do | ||
50 | + counts = Hash.new(0) | ||
51 | + 20.times do | ||
52 | + visitor = @visitors.rand | ||
53 | + Factory(:skip, :question => @questions.rand, :skipper => visitor) | ||
54 | + counts[visitor.id] += 1 | ||
55 | + end | ||
56 | + get_auth visitors_path, :skips_count => true | ||
57 | + | ||
58 | + response.should be_success | ||
59 | + response.should have_tag "visitor", counts.size do |nodes| | ||
60 | + nodes.each do |node| | ||
61 | + id = node.content("id").to_i | ||
62 | + node.should have_tag("id"), :text => id | ||
63 | + node.should have_tag("skips-count"), :text => counts[id] | ||
64 | + end | ||
65 | + end | ||
66 | + end | ||
67 | + | ||
68 | + it "should return the number of user-submitted choices" do | ||
69 | + 10.times do | ||
70 | + question = @questions.rand | ||
71 | + creator = question.creator | ||
72 | + Factory(:choice, :question => question, :creator => creator) | ||
73 | + end | ||
74 | + counts = Hash.new(0) | ||
75 | + 10.times do | ||
76 | + question = @questions.rand | ||
77 | + creator = (@visitors - [question.creator]).rand | ||
78 | + counts[creator.id] += 1 | ||
79 | + Factory(:choice, :question => question, :creator => creator) | ||
80 | + end | ||
81 | + get_auth visitors_path :ideas_count => true | ||
82 | + | ||
83 | + response.should be_success | ||
84 | + response.should have_tag "visitor", counts.size do |nodes| | ||
85 | + nodes.each do |node| | ||
86 | + id = node.content("id").to_i | ||
87 | + node.should have_tag("id"), :text => id | ||
88 | + node.should have_tag("ideas-count"), :text => counts[id] | ||
89 | + end | ||
90 | + end | ||
91 | + end | ||
92 | + | ||
93 | + it "should show which visitors are bounces" do | ||
94 | + bounce = {} | ||
95 | + @visitors.each do |v| | ||
96 | + if [true,false].rand | ||
97 | + Factory(:appearance, :question => @questions.rand, :voter => v) | ||
98 | + bounce[v.id] = 1 | ||
99 | + else | ||
100 | + vote = Factory(:vote, :question => @questions.rand, :voter => v) | ||
101 | + Factory(:appearance, :question => @questions.rand, | ||
102 | + :voter => v, :answerable => vote) | ||
103 | + end | ||
104 | + end | ||
105 | + get_auth visitors_path, :bounces => true | ||
106 | + | ||
107 | + response.should be_success | ||
108 | + response.should have_tag "visitor", bounce.size do |nodes| | ||
109 | + nodes.each do |node| | ||
110 | + id = node.content("id").to_i | ||
111 | + node.should have_tag "id", :text => id | ||
112 | + node.should have_tag "bounces", :text => 1 | ||
113 | + end | ||
114 | + end | ||
115 | + end | ||
116 | + | ||
117 | + it "should return the number of questions created for each visitor" do | ||
118 | + count = @visitors.inject({}) do |h,v| | ||
119 | + n = @questions.select{ |q| q.creator == v }.size | ||
120 | + h[v.id] = n unless n.zero? | ||
121 | + h | ||
122 | + end | ||
123 | + get_auth visitors_path, :questions_created => true | ||
124 | + | ||
125 | + response.should be_success | ||
126 | + response.should have_tag "visitor", count.size do |nodes| | ||
127 | + nodes.each do |node| | ||
128 | + id = node.content("id").to_i | ||
129 | + node.should have_tag "id", :text => id | ||
130 | + node.should have_tag "questions-created", :text => count[id] | ||
131 | + end | ||
132 | + end | ||
133 | + end | ||
134 | + | ||
135 | + it "should return the visitor counts for a single question" do | ||
136 | + votes, skips, choices = Array.new(3){ Hash.new(0) } | ||
137 | + the_question = @questions.rand | ||
138 | + 20.times do | ||
139 | + question = @questions.rand | ||
140 | + visitor = (@visitors - [question.creator]).rand | ||
141 | + case rand(3) | ||
142 | + when 0 then | ||
143 | + Factory(:vote, :question => question, :voter => visitor) | ||
144 | + votes[visitor.id] += 1 if question == the_question | ||
145 | + when 1 then | ||
146 | + Factory(:skip, :question => question, :skipper => visitor) | ||
147 | + skips[visitor.id] += 1 if question == the_question | ||
148 | + when 2 then | ||
149 | + Factory(:choice, :question => question, :creator => visitor) | ||
150 | + choices[visitor.id] += 1 if question == the_question | ||
151 | + end | ||
152 | + end | ||
153 | + visitors = (votes.keys | skips.keys | choices.keys) | ||
154 | + | ||
155 | + get_auth visitors_path, { | ||
156 | + :votes_count => true, | ||
157 | + :skips_count => true, | ||
158 | + :ideas_count => true, | ||
159 | + :question_id => the_question.id | ||
160 | + } | ||
161 | + | ||
162 | + response.should be_success | ||
163 | + response.should have_tag "visitor", visitors.size do |nodes| | ||
164 | + nodes.each do |node| | ||
165 | + id = node.content("id").to_i | ||
166 | + node.should have_tag "id", :text => id | ||
167 | + node.should have_tag "votes-count", :text => votes[id] | ||
168 | + node.should have_tag "skips-count", :text => skips[id] | ||
169 | + node.should have_tag "ideas-count", :text => choices[id] | ||
170 | + end | ||
171 | + end | ||
172 | + end | ||
173 | + | ||
174 | + it "should return the bounces for a single question" do | ||
175 | + the_question = @questions.rand | ||
176 | + bounces = @visitors.inject({}) do |h,v| | ||
177 | + if v.id.odd? # bounce! | ||
178 | + question = @questions.rand | ||
179 | + Factory(:appearance, :question => question, :voter => v) | ||
180 | + h[v.id] = 1 if question == the_question | ||
181 | + else # appearance w/ answerable | ||
182 | + vote = Factory(:vote, :question => @questions.rand, :voter => v) | ||
183 | + Factory(:appearance, :question => @questions.rand, :voter => v, :answerable => vote) | ||
184 | + end | ||
185 | + h | ||
186 | + end | ||
187 | + | ||
188 | + get_auth visitors_path, :bounces => true, :question_id => the_question.id | ||
189 | + response.should be_success | ||
190 | + response.should have_tag "visitor", bounces.size do |nodes| | ||
191 | + nodes.each do |node| | ||
192 | + id = node.content("id").to_i | ||
193 | + node.should have_tag "id", :text => id | ||
194 | + node.should have_tag "bounces", :text => bounces[id] | ||
195 | + end | ||
196 | + end | ||
197 | + end | ||
198 | + end | ||
5 | 199 | ||
6 | - describe "index" | ||
7 | - | 200 | + |
8 | end | 201 | end |
spec/support/integration_support.rb
1 | module IntegrationSupport | 1 | module IntegrationSupport |
2 | 2 | ||
3 | + @@default_user = nil | ||
4 | + | ||
3 | # todo: make automatically included in integration tests | 5 | # todo: make automatically included in integration tests |
4 | Spec::Runner.configure do |config| | 6 | Spec::Runner.configure do |config| |
5 | config.before(:each, :type => :integration) do | 7 | config.before(:each, :type => :integration) do |
6 | - @api_user = Factory(:email_confirmed_user) | 8 | + # compatibility with old tests using @api_user, remove this |
9 | + @api_user = self.default_user = Factory(:email_confirmed_user) | ||
7 | end | 10 | end |
8 | end | 11 | end |
9 | 12 | ||
10 | - def get_auth(path, parameters = {}, headers = {}) | ||
11 | - auth_wrap(:get, path, parameters, headers) | 13 | + def default_user=(user) |
14 | + @api_user = @@default_user = user | ||
12 | end | 15 | end |
13 | 16 | ||
14 | - def put_auth(path, parameters = {}, headers = {}) | ||
15 | - auth_wrap(:put, path, parameters, headers) | 17 | + # generate _auth variation of get/put/post, etc. to automatically |
18 | + # send requests with the authentication and accept headers set | ||
19 | + %w(get put post delete head).each do |method| | ||
20 | + define_method(method + "_auth") do |*args| | ||
21 | + if args[0].is_a? User | ||
22 | + user, path, parameters, headers, *ignored = *args | ||
23 | + else | ||
24 | + path, parameters, headers, *ignored = *args | ||
25 | + end | ||
26 | + | ||
27 | + user ||= @@default_user | ||
28 | + raise ArgumentError, "No user provided and default user not set" unless user | ||
29 | + | ||
30 | + auth = ActionController::HttpAuthentication:: | ||
31 | + Basic.encode_credentials(user.email, user.password) | ||
32 | + (headers ||= {}).merge!( :authorization => auth, | ||
33 | + :accept => "application/xml" ) | ||
34 | + | ||
35 | + send(method, path, parameters, headers) | ||
36 | + end | ||
16 | end | 37 | end |
17 | 38 | ||
18 | - def post_auth(path, parameters = {}, headers = {} ) | ||
19 | - auth_wrap(:post, path, parameters, headers) | 39 | + # need a way to easily fetch content of a Tag |
40 | + class HTML::Tag | ||
41 | + def content(tag) | ||
42 | + n = self.find(:tag => tag) or return nil | ||
43 | + n.children.each{ |c| return c.content if c.is_a? HTML::Text } | ||
44 | + nil | ||
45 | + end | ||
20 | end | 46 | end |
21 | 47 | ||
22 | - def delete_auth(path, parameters = {}, headers = {}) | ||
23 | - auth_wrap(:delete, path, parameters, headers) | ||
24 | - end | ||
25 | 48 | ||
26 | - def head_auth(path, parameters = {}, headers = {}) | ||
27 | - auth_wrap(:head, path, parameters, headers) | ||
28 | - end | ||
29 | - | ||
30 | - private | ||
31 | - def auth_wrap(method, path, parameters, headers) | ||
32 | - return nil unless [:get, :put, :post, :delete, :head].include? method | ||
33 | - | ||
34 | - auth = ActionController::HttpAuthentication::Basic.encode_credentials(@api_user.email, @api_user.password) | ||
35 | - headers.merge!(:authorization => auth) | ||
36 | - # headers.merge!(:content_type => "application/xml", :authorization => auth) | ||
37 | - # parameters.merge!(:format => 'xml') | 49 | + # have_tag doesn't let you iterate over individual nodes like |
50 | + # assert_select does for some reason, and using css matchers | ||
51 | + # to do this is ugly. Time for a patch! | ||
52 | + class Spec::Rails::Matchers::AssertSelect | ||
53 | + def doc_from_with_node(node) | ||
54 | + return node if node.is_a? HTML::Node | ||
55 | + doc_from_without_node(node) | ||
56 | + end | ||
38 | 57 | ||
39 | - send(method, path, parameters, headers) | 58 | + alias_method_chain :doc_from, :node |
40 | end | 59 | end |
60 | + | ||
61 | + | ||
41 | end | 62 | end |
42 | 63 |