1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
|
require 'spec_helper.rb'
describe Answer do
include Permissions::TestPermissions
it 'any user (not guest) should be allowed to create, read, update and delete owned answers' do
for user in fabricate_all_roles
new_answer = Factory(:answer, :owner => user)
cud_allowed([user], new_answer)
view_allowed([user], new_answer)
end
end
it 'should be prohibited to create, update and delete answers someone else owns' do
for user in fabricate_all_roles
ud_denied(fabricate_all_roles + [Guest.new], Factory(:answer, :owner => user))
# updatable_by? blocks changing db
# mentor is covered in separate test
end
end
it 'should be creatable by any logged in user' do
for user in fabricate_all_roles
new_answer = Answer.new(:owner => user)
new_answer.should be_creatable_by user
end
end
it 'should not be creatable by guest' do
Factory(:answer).should_not be_creatable_by Guest.new
end
it 'should allow owner to edit answer as whole and content field' do
for user in fabricate_all_roles
new_answer = Answer.new(:owner => user)
new_answer.should be_editable_by user
new_answer.should be_editable_by user, :content
end
end
it 'should prohibited editing of non-reference answer as whole and content field to non-owners' do
for user in fabricate_all_roles
new_answer = Answer.new(:owner => user)
edit_denied(fabricate_all_roles, new_answer)
edit_denied(fabricate_all_roles, new_answer, :content)
end
end
it 'should be prohibited for non-recruiters to view answers someone else owns' do
for user in fabricate_all_roles
new_answer = Answer.new(:owner => user)
view_denied(fabricate_users(:recruit, :mentor)+ [Guest.new], new_answer)
end
end
it 'should be allowed for recruiters to view all answers' do
for user in fabricate_all_roles
new_answer = Answer.new(:owner => user)
view_allowed(fabricate_users(:recruiter, :administrator), new_answer)
end
end
it "should be viewable by mentor of it's owner" do
mentor = Factory(:mentor)
recruit = Factory(:recruit, :mentor => mentor)
new_answer = Factory(:answer, :owner => recruit)
view_allowed([mentor], new_answer)
end
it { should belong_to(:question) }
it { should have_readonly_attribute(:owner) }
it "should prohibit CUD and view of reference ans to non-recruiters" do
new_answer = Factory(:answer, :reference => true)
cud_denied(fabricate_users(:recruit, :mentor), new_answer)
view_denied(fabricate_users(:recruit, :mentor), new_answer)
end
it "should allow CUD, view and edit of reference answers to recruiters" do
new_answer = Factory(:answer, :reference => true)
cud_allowed(fabricate_users(:recruiter, :administrator), new_answer)
edit_allowed(fabricate_users(:recruiter, :administrator), new_answer)
edit_allowed(fabricate_users(:recruiter, :administrator), new_answer, :content)
end
it "should allow mentor of owner to approve and disapprove" do
r = recruit_with_answers_in_categories(nil, 1, 1)
answer = r.all_answers.first
for i in 1..2
answer.approved = !answer.approved
answer.should be_updatable_by(r.mentor)
answer.should be_editable_by(r.mentor)
answer.should be_editable_by(r.mentor, :approved)
answer.save!
end
end
it "should prohibit mentor of owner to edit content" do
answer = Factory(:answer)
answer.content = "changed"
answer.should_not be_updatable_by(answer.owner.mentor)
end
it "should prohibit owner to save changed answer as approved" do
answer = Factory(:answer)
answer.approved = true
answer.save!
answer.content = "changed"
answer.should_not be_updatable_by(answer.owner)
end
it "should allow owner to save changed answer as unapproved" do
answer = Factory(:answer)
answer.approved = true
answer.save!
answer.content = "changed"
answer.approved = false
answer.should be_updatable_by(answer.owner)
end
it "should mark questions with changed content as unapproved" do
answer = Factory(:answer)
answer.approved = true
answer.save!
answer.content = "changed"
answer.save!
answer.approved.should be_false
end
it "should send email notification to mentor when created" do
question = Factory(:question)
recruit = Factory(:recruit)
#can't use Factory Girl here, because we want to save it after setting expectation to get email
answer = Answer.new(:owner => recruit, :question => question, :content => "Some answer.")
UserMailer.should_receive_delayed(:deliver_new_answer, recruit.mentor, answer)
answer.save!
end
it "should send email notification to mentor when changed" do
answer = Factory(:answer)
UserMailer.should_receive_delayed(:deliver_changed_answer, answer.owner.mentor, answer)
answer.content = "changed"
answer.save!
end
it "shouldn't try to send notifications to mentor of mentorless recruit" do
recruit = Factory(:recruit, :mentor => nil)
UserMailer.should_not_receive(:deliver_changed_answer)
answer = Factory(:answer, :owner => recruit)
answer.save!
answer.content = "changed"
answer.save!
end
it "should prohibit editing of reference and approved fields to recruits" do
answer = Factory(:answer)
answer.should_not be_editable_by(answer.owner, :approved)
answer.should_not be_editable_by(answer.owner, :reference)
end
it "should return proper answers_of_mentored_by" do
mentor = Factory(:mentor)
r1 = recruit_with_answers_in_categories(mentor)
r2 = recruit_with_answers_in_categories(mentor)
r3 = recruit_with_answers_in_categories
for ans in (r1.all_answers + r2.all_answers)
Answer.of_mentored_by(mentor).include?(ans).should be_true
end
for ans in r3.all_answers
Answer.of_mentored_by(mentor).include?(ans).should be_false
end
end
it "should return in_category" do
n_categories = 5
r = recruit_with_answers_in_categories(nil, n_categories)
for i in 0..(n_categories-1)
cat = r.categories[i]
ans = r.answers_in_cat[i]
for answer in ans
Answer.in_category(cat).include?(answer).should be_true
end
for answer in r.all_answers - ans
Answer.in_category(cat).include?(answer).should be_false
end
Answer.in_category(cat).should ==
Answer.in_category(cat).uniq
end
end
it "should allow only owner to change feedback" do
ans = Factory(:answer)
owner = ans.owner
others = fabricate_users(:administrator, :recruit, :mentor, :recruiter) + [Guest.new, ans.owner.mentor]
ans.should be_editable_by(owner, :feedback)
edit_denied(others, ans, :feedback)
ans.feedback = 'changed'
ans.should be_updatable_by(owner)
ud_denied(others, ans)
end
it "should allow editing of reference only to recruiters on new answers" do
answer = Answer.new(:reference => true, :owner => Factory(:recruiter))
answer.should be_editable_by(Factory(:recruiter), :reference)
answer.should_not be_editable_by(Factory(:recruit), :reference)
answer.should_not be_editable_by(Factory(:mentor), :reference)
answer.should_not be_editable_by(Guest.new, :reference)
end
it "should produce proper answer from params" do
ans_hash = { 'reference' => false, 'owner_id' => Factory(:recruit).id,
'approved' => false, 'content' => 'example' }
produced_ans = Answer.new_from("answer" => ans_hash)
produced_ans.class.should == Answer
for i in ans_hash
if i[1]
produced_ans.attributes[i[0]].should == i[1]
else
(!produced_ans.attributes[i[0]]).should be_true # it can be nil or false
end
end
ans_hash = { 'reference' => false, 'owner_id' => Factory(:recruit).id,
'approved' => false, 'content' => 'example' }
produced_ans = Answer.new_from("multiple_choice_answer" => ans_hash)
produced_ans.class.should == MultipleChoiceAnswer
for i in ans_hash
if i[1]
produced_ans.attributes[i[0]].should == i[1]
else
(!produced_ans.attributes[i[0]]).should be_true # it can be nil or false
end
end
end
it "should produce proper updated answer from params" do
ans = Factory(:answer)
upd = Answer.update_from('id' => ans.id.to_s, 'answer' => { 'content' => 'changed' })
upd['id'].should == ans.id
upd['owner_id'].should == ans.owner_id
upd['content'].should == 'changed'
ans = Factory(:multiple_choice_answer)
upd = Answer.update_from('id' => ans.id.to_s, 'multiple_choice_answer' => { 'content' => 'changed' })
upd['id'].should == ans.id
upd['owner_id'].should == ans.owner_id
upd['content'].should == 'changed'
end
it "should properly return wrong answers of recruit" do
recruit = Factory(:recruit)
cat = Factory(:category)
q1 = Factory(:question_category, :category => cat).question
q2 = Factory(:question_category, :category => cat).question
q3 = Factory(:question_category, :category => cat).question
q4 = Factory(:question_category, :category => cat).question
Factory(:question_content_text, :question => q4)
for i in [q1, q2, q3]
Factory(:question_content_multiple_choice, :question => i)
i.reload
["1", "2", "3"].each{ |j| Factory(:option, :option_owner => i.content, :content => j) }
i.reload
Factory(:multiple_choice_answer, :question => i,
:options => [i.content.options.first.id], :reference => true)
end
wrong_ans = []
not_wrong_ans = []
wrong_ans.push Factory(:multiple_choice_answer, :question => q1,
:options => [q1.content.options.second.id], :owner => recruit)
wrong_ans.push Factory(:multiple_choice_answer, :question => q2,
:options => [q1.content.options.first.id, q1.content.options.second.id],
:owner => recruit)
not_wrong_ans.push Factory(:multiple_choice_answer, :question => q3,
:options => [q1.content.options.first.id])
not_wrong_ans.push Factory(:answer, :question => q4,
:content => "wrong",
:owner => recruit)
not_wrong_ans.push Factory(:answer, :question => q4,
:content => "good",
:reference => true)
for i in wrong_ans
Answer.wrong_answers_of(recruit).include?(i).should be_true
end
for i in not_wrong_ans
Answer.wrong_answers_of(recruit).include?(i).should be_false
end
Answer.wrong_answers_of(recruit).count.should == Answer.wrong_answers_of(recruit).uniq.count
end
it "should prohibit mentor of owner to destroy" do
a = Factory(:answer)
a.should_not be_destroyable_by(a.owner.mentor)
end
it "should allow editing of reference only to recruiters" do
for user in fabricate_users(:recruit, :mentor)
Answer.new(:owner => user).should_not be_editable_by(user, :reference)
end
for user in fabricate_users(:recruiter, :administrator)
Answer.new(:owner => user).should be_editable_by(user, :reference)
end
end
it "should properly return answers with feedback" do
with_feedback = (Answer.new.feedback.class.values - ['']).collect do |fb|
Factory(:answer, :feedback => fb)
end
without_feedback = ['', nil].collect do |fb|
Factory(:answer, :feedback => fb)
end
with_feedback.each{ |ans| Answer.with_some_feedback.include?(ans).should be_true }
without_feedback.each{ |ans| Answer.with_some_feedback.include?(ans).should be_false }
Answer.with_some_feedback.count.should == Answer.with_some_feedback.uniq.count
end
end
|