be_taskable 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,200 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ describe 'BeTaskable::TaskRunner' do
4
+
5
+ let(:resolver) { double.as_null_object }
6
+ let(:taskable) { stub_model(Taskable) }
7
+ let(:task) { BeTaskable::Task.new(taskable: taskable, action: 'review') }
8
+ let(:runner) { BeTaskable::TaskRunner.new(task) }
9
+ let(:assignee1) { stub_model(User) }
10
+ let(:assignee2) { stub_model(User) }
11
+ let(:assignee3) { stub_model(User) }
12
+ let(:assignees) { [assignee1, assignee2] }
13
+ let(:label_for_assigment) { 'Label for assignment' }
14
+ let(:url_for_assignment) { '/url/for/assignment' }
15
+
16
+ before do
17
+ resolver.stub(:due_date_for_assignment).and_return(DateTime.now)
18
+ resolver.stub(:visible_date_for_assignment).and_return(DateTime.now)
19
+ resolver.stub(:label_for_task).and_return('Label for task')
20
+ resolver.stub(:label_for_assignment).and_return(label_for_assigment)
21
+ resolver.stub(:url_for_assignment).and_return(url_for_assignment)
22
+ runner.stub(:resolver).and_return(resolver)
23
+ runner.stub(:_tally)
24
+ end
25
+
26
+ describe "initialize" do
27
+ it "requires a task" do
28
+ expect{ BeTaskable::TaskRunner.new }.to raise_error(ArgumentError)
29
+ end
30
+
31
+ it "requires a task" do
32
+ expect{ BeTaskable::TaskRunner.new(2) }.to raise_error(ArgumentError)
33
+ end
34
+
35
+ it "requires a task" do
36
+ expect{ BeTaskable::TaskRunner.new(task) }.not_to raise_error
37
+ end
38
+
39
+ end
40
+
41
+ describe ".resolver" do
42
+ it "asks the task for the resolver" do
43
+ runner.unstub(:resolver)
44
+ task.should_receive(:resolver)
45
+ runner.resolver
46
+ end
47
+ end
48
+
49
+ describe "._assignees" do
50
+ it "asks the resolver for the assignees" do
51
+ # runner.stub(:resolver).and_return(resolver)
52
+ resolver.should_receive(:assignees_for_task)
53
+ runner._assignees
54
+ end
55
+ end
56
+
57
+ describe ".refresh" do
58
+
59
+ before do
60
+ task.save
61
+ runner.stub(:_assignees).and_return(assignees)
62
+ end
63
+
64
+ it "asks the resolver for relevant status of the task" do
65
+ resolver.should_receive(:is_task_relevant?)
66
+ runner.refresh
67
+ end
68
+
69
+ it "sets the label on the task" do
70
+ l = "Label"
71
+ resolver.stub(:label_for_task).and_return(l)
72
+ runner.refresh
73
+ expect(task.label).to eq(l)
74
+ end
75
+
76
+ it "creates an assignment for all assignees" do
77
+ runner.refresh
78
+ expect(BeTaskable::TaskAssignment.count).to eq(2)
79
+ end
80
+
81
+ it "asks the resolver for the due date" do
82
+ resolver.should_receive(:due_date_for_assignment)
83
+ runner.refresh
84
+ end
85
+
86
+ it "sets the complete_by as given by the resolver" do
87
+ d = DateTime.now + 3.days
88
+ resolver.stub(:due_date_for_assignment).and_return(d)
89
+ runner.refresh
90
+ assignment = BeTaskable::TaskAssignment.first
91
+ expect(assignment.complete_by).to be_within(1.minute).of(d)
92
+ end
93
+
94
+ it "asks the resolver for the visible at date" do
95
+ resolver.should_receive(:visible_date_for_assignment)
96
+ runner.refresh
97
+ end
98
+
99
+ it "sets the visible_at as given by the resolver" do
100
+ d = DateTime.now + 3.days
101
+ resolver.stub(:visible_date_for_assignment).and_return(d)
102
+ runner.refresh
103
+ assignment = BeTaskable::TaskAssignment.first
104
+ expect(assignment.visible_at).to be_within(1.minute).of(d)
105
+ end
106
+
107
+ it "sets the assignment label as given by the resolver" do
108
+ runner.refresh
109
+ assignment = BeTaskable::TaskAssignment.first
110
+ expect(assignment.label).to eq(label_for_assigment)
111
+ end
112
+
113
+ it "sets the assignment url as given by the resolver" do
114
+ runner.refresh
115
+ assignment = BeTaskable::TaskAssignment.first
116
+ expect(assignment.url).to eq(url_for_assignment)
117
+ end
118
+
119
+ it "doesn't create duplicate assignments" do
120
+ runner.refresh
121
+ expect(BeTaskable::TaskAssignment.count).to eq(2)
122
+ runner.refresh
123
+ expect(BeTaskable::TaskAssignment.count).to eq(2)
124
+ end
125
+
126
+ it "deletes an assignment when not relevant anymore" do
127
+ runner.refresh
128
+ expect(BeTaskable::TaskAssignment.count).to eq(2)
129
+ assignees.pop
130
+ runner.refresh
131
+ expect(BeTaskable::TaskAssignment.count).to eq(1)
132
+ end
133
+
134
+ it "creates new assignment if needed" do
135
+ runner.refresh
136
+ expect(BeTaskable::TaskAssignment.count).to eq(2)
137
+ assignees.push(assignee3)
138
+ runner.refresh
139
+ expect(BeTaskable::TaskAssignment.count).to eq(3)
140
+ end
141
+
142
+ it "doesn't delete completed assignments" do
143
+ runner.refresh
144
+ expect(BeTaskable::TaskAssignment.count).to eq(2)
145
+ BeTaskable::TaskAssignment.last.update_attribute(:completed_at, DateTime.now)
146
+ assignees.pop
147
+ runner.refresh
148
+ expect(BeTaskable::TaskAssignment.count).to eq(2)
149
+ end
150
+
151
+ it "marks the task as irrelevant if taskable cannot be found" do
152
+ task.stub(:taskable){ nil }
153
+ runner.refresh
154
+ expect(task).to be_irrelevant
155
+ end
156
+
157
+ context 'irrelevant task' do
158
+ before do
159
+ # task.save
160
+ puts task.errors.full_messages
161
+ resolver.stub(:is_task_relevant?).and_return(false)
162
+ end
163
+
164
+ # it "is persisted" do
165
+ # expect(task).to be_persisted
166
+ # end
167
+
168
+ it "marks the task as irrelevant" do
169
+ # task.should_receive(:make_irrelevant)
170
+
171
+ runner.refresh
172
+ expect(task).to be_irrelevant
173
+ end
174
+
175
+ it "deletes the existing assignments" do
176
+ task.assignments.create
177
+ expect(task.assignments.size).to eq(1)
178
+ runner.refresh
179
+ expect(task.assignments.size).to eq(0)
180
+ end
181
+
182
+ it "doesn't change the state of an already completed task" do
183
+ task.update_attribute(:state, 'completed')
184
+ task.should_not_receive(:make_irrelevant)
185
+ runner.refresh
186
+ end
187
+
188
+ it "doesn't delete assignments on an already completed task" do
189
+ task.update_attribute(:state, 'completed')
190
+ task.assignments.create
191
+ expect(task.assignments.size).to eq(1)
192
+ runner.refresh
193
+ expect(task.assignments.size).to eq(1)
194
+ end
195
+
196
+ end
197
+
198
+ end
199
+
200
+ end
@@ -0,0 +1,490 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ describe 'BeTaskable::Task' do
4
+
5
+ let(:assignee) { stub_model(User) }
6
+ let(:resolver) { double.as_null_object }
7
+ let(:assignment) { double.as_null_object }
8
+ let(:taskable) { Taskable.create }
9
+ let(:action) { 'Publish' }
10
+ let(:task) { BeTaskable::Task.new(taskable: taskable, action: action) }
11
+ let(:runner) { double.as_null_object }
12
+
13
+ before do
14
+ task.stub(:resolver).and_return(resolver)
15
+ resolver.stub(:label_for_task).and_return('Label for task')
16
+ end
17
+
18
+ describe "#completed" do
19
+ it "finds completed tasks" do
20
+ task1 = BeTaskable::Task.create(taskable: taskable, action: 'update', completed_at: DateTime.now)
21
+ task2 = BeTaskable::Task.create(taskable: taskable, action: 'review')
22
+ res = BeTaskable::Task.completed.all
23
+ expect(res).to eq([task1])
24
+ end
25
+ end
26
+
27
+ describe "#uncompleted" do
28
+ it "finds uncompleted tasks" do
29
+ task1 = BeTaskable::Task.create(taskable: taskable, action: 'update', completed_at: DateTime.now)
30
+ task2 = BeTaskable::Task.create(taskable: taskable, action: 'review')
31
+ res = BeTaskable::Task.uncompleted.all
32
+ expect(res).to eq([task2])
33
+ end
34
+ end
35
+
36
+ describe "#expired" do
37
+ it "finds expired tasks" do
38
+ task1 = BeTaskable::Task.create(taskable: taskable, action: 'update', expired_at: DateTime.now)
39
+ task2 = BeTaskable::Task.create(taskable: taskable, action: 'review')
40
+ res = BeTaskable::Task.expired.all
41
+ expect(res).to eq([task1])
42
+ end
43
+ end
44
+
45
+ describe "#unexpired" do
46
+ it "finds unexpired tasks" do
47
+ task1 = BeTaskable::Task.create(taskable: taskable, action: 'update', expired_at: DateTime.now)
48
+ task2 = BeTaskable::Task.create(taskable: taskable, action: 'review')
49
+ # expect(task1).to be_persisted
50
+ # expect(task2).to be_persisted
51
+ res = BeTaskable::Task.unexpired.all
52
+ expect(res).to eq([task2])
53
+ end
54
+ end
55
+
56
+ describe "#current" do
57
+ it "finds current tasks" do
58
+ task1 = BeTaskable::Task.create(taskable: taskable, action: 'update', expired_at: DateTime.now)
59
+ task2 = BeTaskable::Task.create(taskable: taskable, action: 'update', completed_at: DateTime.now)
60
+ task3 = BeTaskable::Task.create(taskable: taskable, action: 'review')
61
+ res = BeTaskable::Task.current.all
62
+ expect(res).to eq([task3])
63
+ end
64
+ end
65
+
66
+ describe "validations" do
67
+ it "can create two task with the same taskable and action" do
68
+ taskable = Taskable.create
69
+ action = 'publish'
70
+ task1 = BeTaskable::Task.create(taskable: taskable, action: action)
71
+ task2 = BeTaskable::Task.create(taskable: taskable, action: action)
72
+
73
+ expect(task2.errors).to be_empty
74
+ end
75
+ end
76
+
77
+ it "can save the task" do
78
+ task.save
79
+ expect(task).to be_persisted
80
+ end
81
+
82
+ describe ".taskable" do
83
+ it "responds to taskable" do
84
+ expect(task).to respond_to('taskable')
85
+ end
86
+
87
+ it "finds taskable" do
88
+ taskable = Taskable.create
89
+ task = taskable.tasks.create
90
+ expect(task.taskable).to eq(taskable)
91
+ end
92
+ end
93
+
94
+ describe ".assignments" do
95
+ it 'responds to assignments' do
96
+ expect(task).to respond_to('assignments')
97
+ end
98
+ end
99
+
100
+ describe ".assignees" do
101
+ it "responds to assignees" do
102
+ expect(task).to respond_to('assignees')
103
+ end
104
+
105
+ it "finds the assignees" do
106
+ user = User.create
107
+ task.save
108
+ task.assignments.create(assignee: user)
109
+
110
+ expect(task.assignees).to eq([user])
111
+ end
112
+ end
113
+
114
+ describe ".resolver" do
115
+
116
+ before do
117
+ task.unstub(:resolver)
118
+ end
119
+
120
+ it "asks the taskable for the resolver" do
121
+ taskable.should_receive(:task_resolver_for_action)
122
+ task.resolver
123
+ end
124
+ end
125
+
126
+ describe "._runner" do
127
+ it "returns a runner" do
128
+ res = task._runner
129
+ expect(res).to be_instance_of(BeTaskable::TaskRunner)
130
+ end
131
+ end
132
+
133
+ describe ".refresh" do
134
+
135
+ before do
136
+ task.stub(:_runner).and_return(runner)
137
+ end
138
+
139
+ it "calls the runner" do
140
+ runner.should_receive(:refresh)
141
+ task.refresh
142
+ end
143
+
144
+ it "doesnt run for completed task" do
145
+ task.stub(:state).and_return('completed')
146
+ runner.should_not_receive(:refresh)
147
+ task.refresh
148
+ end
149
+
150
+ it "runs for open task" do
151
+ task.stub(:state).and_return('open')
152
+ runner.should_receive(:refresh)
153
+ task.refresh
154
+ end
155
+
156
+ it "runs for irrelevant task" do
157
+ task.stub(:state).and_return('irrelevant')
158
+ runner.should_receive(:refresh)
159
+ task.refresh
160
+ end
161
+ end
162
+
163
+ describe ".audit" do
164
+
165
+ before do
166
+ task.save
167
+ end
168
+
169
+ it "calls refresh" do
170
+ task.should_receive(:refresh)
171
+ task.audit
172
+ end
173
+
174
+ it "calls tally" do
175
+ # puts task.inspect
176
+ task.should_receive(:tally)
177
+ task.audit
178
+ end
179
+
180
+ it "doesnt run for completed task" do
181
+ task.stub(:state) { 'completed' }
182
+ task.should_not_receive(:refresh)
183
+ task.audit
184
+ end
185
+
186
+ it "runs for open task" do
187
+ task.stub(:state) { 'open' }
188
+ task.should_receive(:refresh)
189
+ task.audit
190
+ end
191
+
192
+ it "runs for irrelevant task" do
193
+ task.stub(:state) { 'irrelevant' }
194
+ task.should_receive(:refresh)
195
+ task.audit
196
+ end
197
+ end
198
+
199
+ describe ".consensus?" do
200
+ before do
201
+ task.stub(:resolver).and_return(resolver)
202
+ end
203
+
204
+ it "ask the resolver for consensus?" do
205
+ resolver.should_receive(:consensus?)
206
+ task.consensus?
207
+ end
208
+
209
+ it "pases the task to the resolver" do
210
+ # assignments = [1,2]
211
+ # task.stub(:assignments).and_return(assignments)
212
+ resolver.should_receive(:consensus?).with(task)
213
+ task.consensus?
214
+ end
215
+ end
216
+
217
+ describe ".tally" do
218
+ it "doesnt do anything is already completed" do
219
+ task.update_attribute(:state, 'completed')
220
+ task.stub(:consensus?).and_return(true)
221
+ task.should_not_receive(:_on_completion)
222
+ task.tally
223
+ end
224
+
225
+ it "calls on_completion when completed" do
226
+ task.stub(:consensus?).and_return(true)
227
+ task.should_receive(:_on_completion)
228
+ task.tally
229
+ end
230
+
231
+ it "doesn't call _on_completion if not completed" do
232
+ task.stub(:consensus?).and_return(false)
233
+ task.should_not_receive(:_on_completion)
234
+ task.tally
235
+ end
236
+
237
+ it "doesnt run for completed task" do
238
+ task.stub(:state) { 'completed' }
239
+ task.should_not_receive(:complete)
240
+ task.tally
241
+ end
242
+
243
+ it "runs for open task" do
244
+ task.stub(:state) { 'open' }
245
+ task.should_receive(:complete)
246
+ task.tally
247
+ end
248
+
249
+ it "runs for irrelevant task" do
250
+ task.stub(:state) { 'irrelevant' }
251
+ task.should_receive(:complete)
252
+ task.tally
253
+ end
254
+ end
255
+
256
+ describe ".on_creation" do
257
+ it "calls the resolver" do
258
+ resolver.should_receive(:on_creation).with(task)
259
+ task.on_creation
260
+ end
261
+ end
262
+
263
+ describe ".complete" do
264
+ it "changes the state" do
265
+ task.complete
266
+ expect(task).to be_completed
267
+ end
268
+
269
+ it "calls _on_completion" do
270
+ task.should_receive(:_on_completion)
271
+ task.complete
272
+ end
273
+
274
+ it "returns true" do
275
+ res = task.complete
276
+ expect(res).to be_true
277
+ end
278
+ end
279
+
280
+ describe "._on_completion" do
281
+ before do
282
+ task.stub(:resolver).and_return(resolver)
283
+ end
284
+
285
+ it "changes completed_at on the tasks" do
286
+ task._on_completion
287
+ expect(task.completed_at).to be_within(1.minute).of(DateTime.now)
288
+ end
289
+
290
+ it "calls on_completion on the resolver" do
291
+ resolver.should_receive(:on_completion)
292
+ task._on_completion
293
+ end
294
+
295
+ it "marks all assignments as completed" do
296
+ task.save
297
+ a1 = task.assignments.create()
298
+ a2 = task.assignments.create()
299
+ task._on_completion
300
+ a1.reload
301
+ a2.reload
302
+ expect(a1).to be_completed
303
+ expect(a2).to be_completed
304
+ end
305
+ end
306
+
307
+ describe "assignment_for" do
308
+ it "find the assignment for the assignee" do
309
+ task.save
310
+ assignment = task.assignments.create(assignee: assignee)
311
+ res = task.assignment_for(assignee)
312
+ expect(res).to eq(assignment)
313
+ end
314
+ end
315
+
316
+ describe ".complete_by" do
317
+
318
+ let(:assignment) { double.as_null_object }
319
+
320
+ before do
321
+ task.stub(:assignment_for).and_return(assignment)
322
+ end
323
+
324
+ it "requires an assignee" do
325
+ expect{ task.complete_by }.to raise_error(ArgumentError)
326
+ end
327
+
328
+ it "sends complete to the assignment" do
329
+ assignment.should_receive(:complete)
330
+ task.complete_by(assignee)
331
+ end
332
+
333
+ it "returns true" do
334
+ res = task.complete_by(assignee)
335
+ expect(res).to be_true
336
+ end
337
+
338
+ it "returns false if it cannot find the assignment" do
339
+ task.stub(:assignment_for).and_return(nil)
340
+ res = task.complete_by(assignee)
341
+ expect(res).to be_false
342
+ end
343
+ end
344
+
345
+ describe ".expire" do
346
+ it "marks the task as expired" do
347
+ # expect(task).to be_open
348
+ res = task.expire
349
+ # expect(res).to be_true
350
+ # puts task.state
351
+ # task.reload
352
+ expect(task).to be_expired
353
+ end
354
+
355
+ it "calls _on_expiration" do
356
+ task.should_receive(:_on_expiration)
357
+ task.expire
358
+ end
359
+ end
360
+
361
+ describe "._on_expiration" do
362
+
363
+ it "sets the expired date" do
364
+ task.expire
365
+ expect(task.expired_at).to be_within(1.minute).of(DateTime.now)
366
+ end
367
+
368
+ it "marks the assignments as expired" do
369
+ task.stub(:assignments).and_return([assignment])
370
+ assignment.should_receive(:expire)
371
+ task._on_expiration
372
+ end
373
+
374
+ it "calls on_expiration on the resolver" do
375
+ resolver.should_receive(:on_expiration)
376
+ task._on_expiration
377
+ end
378
+ end
379
+
380
+ describe ".on_assignment_completed" do
381
+ it "triggers a tally" do
382
+ task.should_receive(:tally)
383
+ task.on_assignment_completed(assignment)
384
+ end
385
+ end
386
+
387
+ describe ".label!" do
388
+ it "asks the resolver" do
389
+ resolver.should_receive(:label_for_task)
390
+ task.label!
391
+ end
392
+ end
393
+
394
+ describe "consensus helpers" do
395
+
396
+ let(:assignment1) { stub_model(BeTaskable::TaskAssignment) }
397
+ let(:assignment2) { stub_model(BeTaskable::TaskAssignment) }
398
+ let(:assignment3) { stub_model(BeTaskable::TaskAssignment) }
399
+ let(:assignment4) { stub_model(BeTaskable::TaskAssignment) }
400
+ let(:assignments) { [assignment1, assignment2, assignment3, assignment4] }
401
+
402
+ before do
403
+ task.stub(:assignments).and_return(assignments)
404
+ end
405
+
406
+ describe ".majority_of_assignments_done?" do
407
+
408
+ it "is not true if minority done" do
409
+ assignment1.stub(:completed?).and_return(true)
410
+ res = task.majority_of_assignments_done?
411
+ expect(res).to be_false
412
+ end
413
+
414
+ it "is not true if half done" do
415
+ assignment1.stub(:completed?).and_return(true)
416
+ assignment2.stub(:completed?).and_return(true)
417
+ res = task.majority_of_assignments_done?
418
+ expect(res).to be_false
419
+ end
420
+
421
+ it "is true if majority done" do
422
+ assignment1.stub(:completed?).and_return(true)
423
+ assignment2.stub(:completed?).and_return(true)
424
+ assignment3.stub(:completed?).and_return(true)
425
+ res = task.majority_of_assignments_done?
426
+ expect(res).to be_true
427
+ end
428
+
429
+ end
430
+
431
+ describe ".any_assignment_done?" do
432
+
433
+ it "is not false if none done" do
434
+ res = task.any_assignment_done?
435
+ expect(res).to be_false
436
+ end
437
+
438
+ it "is not true if one is done" do
439
+ assignment1.stub(:completed?).and_return(true)
440
+ res = task.any_assignment_done?
441
+ expect(res).to be_true
442
+ end
443
+
444
+ it "is not true if more than one is done" do
445
+ assignment1.stub(:completed?).and_return(true)
446
+ assignment2.stub(:completed?).and_return(true)
447
+ res = task.any_assignment_done?
448
+ expect(res).to be_true
449
+ end
450
+ end
451
+
452
+ describe ".all_assignments_done?" do
453
+
454
+ it "is not false if none done" do
455
+ res = task.all_assignments_done?
456
+ expect(res).to be_false
457
+ end
458
+
459
+ it "is not false if majority done" do
460
+ assignment1.stub(:completed?).and_return(true)
461
+ assignment2.stub(:completed?).and_return(true)
462
+ assignment3.stub(:completed?).and_return(true)
463
+ res = task.all_assignments_done?
464
+ expect(res).to be_false
465
+ end
466
+
467
+ it "is not true if all done" do
468
+ assignment1.stub(:completed?).and_return(true)
469
+ assignment2.stub(:completed?).and_return(true)
470
+ assignment3.stub(:completed?).and_return(true)
471
+ assignment4.stub(:completed?).and_return(true)
472
+ res = task.all_assignments_done?
473
+ expect(res).to be_true
474
+ end
475
+ end
476
+ end
477
+
478
+ describe ".enacted_assignments" do
479
+ it "returns the assignees that actually did the task" do
480
+ user1 = User.create
481
+ user2 = User.create
482
+ task.save
483
+ as1 = task.assignments.create(assignee: user1)
484
+ as2 = task.assignments.create(assignee: user2, enacted: true)
485
+ res = task.enacted_assignments
486
+ expect(res).to eq([as2])
487
+ end
488
+ end
489
+
490
+ end