be_taskable 0.5.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.
@@ -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