timesheet_plugin 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.
Files changed (55) hide show
  1. data/COPYRIGHT.txt +16 -0
  2. data/CREDITS.txt +21 -0
  3. data/GPL.txt +339 -0
  4. data/README.rdoc +56 -0
  5. data/Rakefile +33 -0
  6. data/VERSION +1 -0
  7. data/app/controllers/timesheet_controller.rb +145 -0
  8. data/app/helpers/timesheet_helper.rb +42 -0
  9. data/app/models/timesheet.rb +277 -0
  10. data/app/views/settings/_timesheet_settings.rhtml +4 -0
  11. data/app/views/timesheet/_by_issue.rhtml +35 -0
  12. data/app/views/timesheet/_form.rhtml +90 -0
  13. data/app/views/timesheet/_issue_time_entries.rhtml +43 -0
  14. data/app/views/timesheet/_time_entry.rhtml +31 -0
  15. data/app/views/timesheet/_timesheet_group.rhtml +21 -0
  16. data/app/views/timesheet/context_menu.html.erb +4 -0
  17. data/app/views/timesheet/index.rhtml +11 -0
  18. data/app/views/timesheet/no_projects.rhtml +5 -0
  19. data/app/views/timesheet/report.rhtml +52 -0
  20. data/app/views/timesheet/timelog.rhtml +5 -0
  21. data/assets/images/toggle-arrow-closed.gif +0 -0
  22. data/assets/images/toggle-arrow-open.gif +0 -0
  23. data/config/locales/ca.yml +9 -0
  24. data/config/locales/cs.yml +7 -0
  25. data/config/locales/da.yml +10 -0
  26. data/config/locales/de.yml +10 -0
  27. data/config/locales/en.yml +10 -0
  28. data/config/locales/es.yml +9 -0
  29. data/config/locales/fr.yml +10 -0
  30. data/config/locales/hu.yml +10 -0
  31. data/config/locales/it.yml +7 -0
  32. data/config/locales/lt.yml +9 -0
  33. data/config/locales/pl.yml +10 -0
  34. data/config/locales/ru.yml +9 -0
  35. data/init.rb +2 -0
  36. data/lang/ca.yml +8 -0
  37. data/lang/cs.yml +6 -0
  38. data/lang/da.yml +9 -0
  39. data/lang/de.yml +9 -0
  40. data/lang/en.yml +9 -0
  41. data/lang/es.yml +8 -0
  42. data/lang/fr.yml +9 -0
  43. data/lang/hu.yml +9 -0
  44. data/lang/it.yml +6 -0
  45. data/lang/lt.yml +8 -0
  46. data/lang/pl.yml +9 -0
  47. data/lang/ru.yml +8 -0
  48. data/lib/tasks/plugin_stat.rake +38 -0
  49. data/lib/timesheet_compatibility.rb +14 -0
  50. data/rails/init.rb +29 -0
  51. data/spec/controllers/timesheet_controller_spec.rb +263 -0
  52. data/spec/models/timesheet_spec.rb +537 -0
  53. data/spec/sanity_spec.rb +7 -0
  54. data/spec/spec_helper.rb +40 -0
  55. metadata +107 -0
@@ -0,0 +1,537 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ module TimesheetSpecHelper
4
+ def timesheet_factory(options={ })
5
+ timesheet = Timesheet.new(options)
6
+ timesheet.date_from ||= Date.today.to_s
7
+ timesheet.date_to ||= Date.today.to_s
8
+
9
+ return timesheet
10
+ end
11
+
12
+ def project_factory(id, options = { })
13
+ object_options = {
14
+ :parent => nil,
15
+ :id => id,
16
+ :to_param => id.to_s
17
+ }.merge(options)
18
+
19
+ project = mock_model(Project, object_options)
20
+ project_te1 = mock_model(TimeEntry, :id => '100' + id.to_s, :project_id => project.id, :issue_id => '1', :hours => '5', :activity_id => '1', :spent_on => Date.today, :user => 1)
21
+ project_te2 = mock_model(TimeEntry, :id => '101' + id.to_s, :project_id => project.id, :issue_id => '1', :hours => '10', :activity_id => '1', :spent_on => Date.today, :user => 1)
22
+ project_time_entries_mock = mock('project_time_entries_mock')
23
+ project_time_entries_mock.stub!(:find).and_return([project_te1, project_te2])
24
+ project.stub!(:time_entries).and_return(project_time_entries_mock)
25
+ project.stub!(:name).and_return('Project ' + id.to_s)
26
+
27
+ return project
28
+ end
29
+
30
+ def time_entry_factory(id, options = { })
31
+ object_options = {
32
+ :id => id,
33
+ :to_param => id.to_s,
34
+ :spent_on => Date.today,
35
+ }.merge(options)
36
+
37
+ time_entry = mock_model(TimeEntry, object_options)
38
+ time_entry.stub!(:issue).and_return(options[:issue]) unless options[:issue].nil?
39
+ return time_entry
40
+ end
41
+
42
+ def stub_non_member_user(projects)
43
+ @current_user = mock_model(User)
44
+ @current_user.stub!(:admin?).and_return(false)
45
+ projects.each do |project|
46
+ @current_user.stub!(:allowed_to?).with(:view_time_entries, project).and_return(false)
47
+ @current_user.stub!(:allowed_to?).with(:see_project_timesheets, project).and_return(false)
48
+ end
49
+ User.stub!(:current).and_return(@current_user)
50
+ end
51
+
52
+ def stub_normal_user(projects)
53
+ @current_user = mock_model(User)
54
+ @current_user.stub!(:admin?).and_return(false)
55
+ projects.each do |project|
56
+ @current_user.stub!(:allowed_to?).with(:view_time_entries, project).and_return(true)
57
+ @current_user.stub!(:allowed_to?).with(:see_project_timesheets, project).and_return(false)
58
+ end
59
+ User.stub!(:current).and_return(@current_user)
60
+ end
61
+
62
+ def stub_manager_user(projects)
63
+ @current_user = mock_model(User)
64
+ @current_user.stub!(:admin?).and_return(false)
65
+ projects.each do |project|
66
+ @current_user.stub!(:allowed_to?).with(:view_time_entries, project).and_return(true)
67
+ @current_user.stub!(:allowed_to?).with(:see_project_timesheets, project).and_return(true)
68
+ end
69
+ User.stub!(:current).and_return(@current_user)
70
+ end
71
+
72
+ def stub_admin_user
73
+ @current_user = mock_model(User)
74
+ @current_user.stub!(:admin?).and_return(true)
75
+ @current_user.stub!(:allowed_to?).and_return(true)
76
+ @current_user.stub!(:name).and_return("Administrator Bob")
77
+ User.stub!(:current).and_return(@current_user)
78
+ end
79
+ end
80
+
81
+ describe Timesheet do
82
+ it 'should not be an ActiveRecord class' do
83
+ Timesheet.should_not be_a_kind_of(ActiveRecord::Base)
84
+ end
85
+ end
86
+
87
+ describe Timesheet, 'initializing' do
88
+ it 'should initialize time_entries to an empty Hash' do
89
+ timesheet = Timesheet.new
90
+ timesheet.time_entries.should be_a_kind_of(Hash)
91
+ timesheet.time_entries.should be_empty
92
+ end
93
+
94
+ it 'should initialize projects to an empty Array' do
95
+ timesheet = Timesheet.new
96
+ timesheet.projects.should be_a_kind_of(Array)
97
+ timesheet.projects.should be_empty
98
+ end
99
+
100
+ it 'should initialize allowed_projects to an empty Array' do
101
+ timesheet = Timesheet.new
102
+ timesheet.allowed_projects.should be_a_kind_of(Array)
103
+ timesheet.allowed_projects.should be_empty
104
+ end
105
+
106
+ it 'should initialize activities to an Array' do
107
+ timesheet = Timesheet.new
108
+ timesheet.activities.should be_a_kind_of(Array)
109
+ end
110
+
111
+ it 'should initialize users to an Array' do
112
+ timesheet = Timesheet.new
113
+ timesheet.users.should be_a_kind_of(Array)
114
+ end
115
+
116
+ it 'should initialize sort to :project' do
117
+ timesheet = Timesheet.new
118
+ timesheet.sort.should eql(:project)
119
+ end
120
+
121
+ it 'should initialize time_entries to the passed in options' do
122
+ data = { :test => true }
123
+ timesheet = Timesheet.new({ :time_entries => data })
124
+ timesheet.time_entries.should_not be_empty
125
+ timesheet.time_entries.should eql(data)
126
+ end
127
+
128
+ it 'should initialize allowed_projects to the passed in options' do
129
+ data = ['project1', 'project2']
130
+ timesheet = Timesheet.new({ :allowed_projects => data })
131
+ timesheet.allowed_projects.should_not be_empty
132
+ timesheet.allowed_projects.should eql(data)
133
+ end
134
+
135
+ it 'should initialize activities to the integers of the passed in options' do
136
+ act1 = mock('act1')
137
+ act1.stub!(:to_i).and_return(200)
138
+ act2 = mock('act2')
139
+ act2.stub!(:to_i).and_return(300)
140
+ data = [act1, act2]
141
+ timesheet = Timesheet.new({ :activities => data })
142
+ timesheet.activities.should_not be_empty
143
+ timesheet.activities.should eql([200, 300])
144
+ end
145
+
146
+ it 'should initialize users to the ids of the passed in options' do
147
+ user1 = mock('user1')
148
+ user1.stub!(:to_i).and_return(100)
149
+ user2 = mock('user2')
150
+ user2.stub!(:to_i).and_return(101)
151
+ data = [user1, user2]
152
+ timesheet = Timesheet.new({ :users => data })
153
+ timesheet.users.should_not be_empty
154
+ timesheet.users.should eql([100, 101])
155
+ end
156
+
157
+ it 'should initialize sort to the :user option when passed :user' do
158
+ timesheet = Timesheet.new({ :sort => :user })
159
+ timesheet.sort.should eql(:user)
160
+ end
161
+
162
+ it 'should initialize sort to the :project option when passed :project' do
163
+ timesheet = Timesheet.new({ :sort => :project })
164
+ timesheet.sort.should eql(:project)
165
+ end
166
+
167
+ it 'should initialize sort to the :issue option when passed :issue' do
168
+ timesheet = Timesheet.new({ :sort => :issue })
169
+ timesheet.sort.should eql(:issue)
170
+ end
171
+
172
+ it 'should initialize sort to the :project option when passed an invalid sort' do
173
+ timesheet = Timesheet.new({ :sort => :invalid })
174
+ timesheet.sort.should eql(:project)
175
+ end
176
+ end
177
+
178
+ describe Timesheet,'.fetch_time_entries' do
179
+ include TimesheetSpecHelper
180
+
181
+ it 'should clear .time_entries' do
182
+ timesheet = Timesheet.new
183
+ timesheet.time_entries = { :filled => 'data' }
184
+ proc {
185
+ timesheet.fetch_time_entries
186
+ }.should change(timesheet, :time_entries)
187
+
188
+ end
189
+
190
+ it 'should add a time_entry Hash for each project' do
191
+ timesheet = timesheet_factory
192
+
193
+ project1 = project_factory(1)
194
+ project2 = project_factory(2)
195
+
196
+ stub_admin_user
197
+ timesheet.projects = [project1, project2]
198
+
199
+ timesheet.fetch_time_entries
200
+ timesheet.time_entries.should_not be_empty
201
+ timesheet.time_entries.should have(2).things
202
+ end
203
+
204
+ it 'should use the project name for each time_entry key' do
205
+
206
+ timesheet = timesheet_factory
207
+
208
+ project1 = project_factory(1)
209
+ project1.should_receive(:name).and_return('Project 1')
210
+ project2 = project_factory(2)
211
+ project2.should_receive(:name).and_return('Project 2')
212
+
213
+ stub_admin_user
214
+ timesheet.projects = [project1, project2]
215
+
216
+ timesheet.fetch_time_entries
217
+ timesheet.time_entries.keys.should include("Project 1")
218
+ timesheet.time_entries.keys.should include("Project 2")
219
+ end
220
+
221
+ it 'should add the parent project name for each time_entry array for sub-projects' do
222
+ timesheet = timesheet_factory
223
+
224
+ project1 = project_factory(1)
225
+ project1.should_receive(:name).twice.and_return('Project 1')
226
+ project2 = project_factory(2, :parent => project1 )
227
+ project2.should_receive(:name).and_return('Project 2')
228
+
229
+ stub_admin_user
230
+ timesheet.projects = [project1, project2]
231
+
232
+ timesheet.fetch_time_entries
233
+ timesheet.time_entries.keys.should include("Project 1")
234
+ timesheet.time_entries.keys.should include("Project 1 / Project 2")
235
+ end
236
+
237
+ it 'should fetch all the time entries on a project in the date range'
238
+ it 'should fetch all the time entries on a project matching the activities'
239
+ it 'should fetch all the time entries on a project matching the users'
240
+ end
241
+
242
+ describe Timesheet,'.fetch_time_entries with user sorting' do
243
+ include TimesheetSpecHelper
244
+
245
+ it 'should clear .time_entries' do
246
+ timesheet = Timesheet.new({ :sort => :user })
247
+ timesheet.time_entries = { :filled => 'data' }
248
+ proc {
249
+ timesheet.fetch_time_entries
250
+ }.should change(timesheet, :time_entries)
251
+
252
+ end
253
+
254
+ it 'should add a time_entry array for each user' do
255
+ stub_admin_user
256
+ timesheet = timesheet_factory(:sort => :user, :users => [User.current.id])
257
+
258
+ time_entries = [
259
+ time_entry_factory(1, { :user => User.current }),
260
+ time_entry_factory(2, { :user => User.current }),
261
+ time_entry_factory(3, { :user => User.current }),
262
+ time_entry_factory(4, { :user => User.current }),
263
+ time_entry_factory(5, { :user => User.current })
264
+ ]
265
+
266
+ TimeEntry.stub!(:find).and_return(time_entries)
267
+ User.stub!(:find_by_id).and_return(User.current)
268
+
269
+ timesheet.fetch_time_entries
270
+ timesheet.time_entries.should_not be_empty
271
+ timesheet.time_entries.should have(1).thing # One user
272
+ end
273
+
274
+ it 'should use the user name for each time_entry array' do
275
+ stub_admin_user
276
+ timesheet = timesheet_factory(:sort => :user, :users => [User.current.id])
277
+
278
+ time_entries = [
279
+ time_entry_factory(1, { :user => User.current }),
280
+ time_entry_factory(2, { :user => User.current }),
281
+ time_entry_factory(3, { :user => User.current }),
282
+ time_entry_factory(4, { :user => User.current }),
283
+ time_entry_factory(5, { :user => User.current })
284
+ ]
285
+
286
+ TimeEntry.stub!(:find).and_return(time_entries)
287
+ User.stub!(:find_by_id).and_return(User.current)
288
+
289
+ timesheet.fetch_time_entries
290
+ timesheet.time_entries.keys.should include("Administrator Bob")
291
+ end
292
+ end
293
+
294
+ describe Timesheet,'.fetch_time_entries with issue sorting' do
295
+ include TimesheetSpecHelper
296
+
297
+ it 'should clear .time_entries' do
298
+ timesheet = Timesheet.new({ :sort => :issue })
299
+ timesheet.time_entries = { :filled => 'data' }
300
+ proc {
301
+ timesheet.fetch_time_entries
302
+ }.should change(timesheet, :time_entries)
303
+
304
+ end
305
+
306
+ it 'should add a time_entry array for each project' do
307
+ stub_admin_user
308
+ project1 = project_factory(1)
309
+ timesheet = timesheet_factory(:sort => :issue, :users => [User.current.id])
310
+ timesheet.projects = [project1]
311
+
312
+ @issue1 = mock_model(Issue, :id => 1, :to_param => '1', :project => project1)
313
+ @issue2 = mock_model(Issue, :id => 1, :to_param => '1', :project => project1)
314
+ @issue3 = mock_model(Issue, :id => 1, :to_param => '1', :project => project1)
315
+
316
+ time_entry1 = time_entry_factory(1, { :user => User.current, :issue => @issue1 })
317
+ time_entry2 = time_entry_factory(2, { :user => User.current, :issue => @issue1 })
318
+ time_entry3 = time_entry_factory(3, { :user => User.current, :issue => @issue2 })
319
+ time_entry4 = time_entry_factory(4, { :user => User.current, :issue => @issue2 })
320
+ time_entry5 = time_entry_factory(5, { :user => User.current, :issue => @issue3 })
321
+
322
+ project1.should_receive(:issues).and_return([@issue1, @issue2, @issue3])
323
+
324
+ time_entries = [
325
+ time_entry1,
326
+ time_entry2,
327
+ time_entry3,
328
+ time_entry4,
329
+ time_entry5
330
+ ]
331
+
332
+ timesheet.should_receive(:issue_time_entries_for_all_users).with(@issue1).and_return([time_entry1, time_entry2])
333
+ timesheet.should_receive(:issue_time_entries_for_all_users).with(@issue2).and_return([time_entry3, time_entry4])
334
+ timesheet.should_receive(:issue_time_entries_for_all_users).with(@issue3).and_return([time_entry5])
335
+
336
+ timesheet.fetch_time_entries
337
+ timesheet.time_entries.should_not be_empty
338
+ timesheet.time_entries.should have(1).thing
339
+ end
340
+
341
+ it 'should use the project for each time_entry array' do
342
+ stub_admin_user
343
+ project1 = project_factory(1)
344
+ timesheet = timesheet_factory(:sort => :issue, :users => [User.current.id])
345
+ timesheet.projects = [project1]
346
+
347
+ @issue1 = mock_model(Issue, :id => 1, :to_param => '1', :project => project1)
348
+ @issue2 = mock_model(Issue, :id => 1, :to_param => '1', :project => project1)
349
+ @issue3 = mock_model(Issue, :id => 1, :to_param => '1', :project => project1)
350
+
351
+ time_entry1 = time_entry_factory(1, { :user => User.current, :issue => @issue1 })
352
+ time_entry2 = time_entry_factory(2, { :user => User.current, :issue => @issue1 })
353
+ time_entry3 = time_entry_factory(3, { :user => User.current, :issue => @issue2 })
354
+ time_entry4 = time_entry_factory(4, { :user => User.current, :issue => @issue2 })
355
+ time_entry5 = time_entry_factory(5, { :user => User.current, :issue => @issue3 })
356
+
357
+ project1.should_receive(:issues).and_return([@issue1, @issue2, @issue3])
358
+
359
+ time_entries = [
360
+ time_entry1,
361
+ time_entry2,
362
+ time_entry3,
363
+ time_entry4,
364
+ time_entry5
365
+ ]
366
+
367
+ timesheet.should_receive(:issue_time_entries_for_all_users).with(@issue1).and_return([time_entry1, time_entry2])
368
+ timesheet.should_receive(:issue_time_entries_for_all_users).with(@issue2).and_return([time_entry3, time_entry4])
369
+ timesheet.should_receive(:issue_time_entries_for_all_users).with(@issue3).and_return([time_entry5])
370
+
371
+ timesheet.fetch_time_entries
372
+ timesheet.time_entries.keys.should include(project1)
373
+ end
374
+ end
375
+
376
+ describe Timesheet,'.fetch_time_entries as an administrator' do
377
+ include TimesheetSpecHelper
378
+
379
+ it 'should collect time entries for all users on each project' do
380
+ timesheet = timesheet_factory
381
+
382
+ project1 = project_factory(1)
383
+ project1.stub!(:name).and_return('Project 1')
384
+ project2 = project_factory(2)
385
+ project2.stub!(:name).and_return('Project 2')
386
+
387
+ stub_admin_user
388
+ timesheet.projects = [project1, project2]
389
+
390
+ timesheet.should_receive(:time_entries_for_all_users).with(project1).and_return([ ])
391
+ timesheet.should_receive(:time_entries_for_all_users).with(project2).and_return([ ])
392
+ timesheet.fetch_time_entries
393
+ end
394
+ end
395
+
396
+ describe Timesheet,'.fetch_time_entries as a user with see_project_timesheet permission on a project' do
397
+ include TimesheetSpecHelper
398
+
399
+ it 'should collect time entries for all users' do
400
+ timesheet = timesheet_factory
401
+
402
+ project1 = project_factory(1)
403
+ project1.stub!(:name).and_return('Project 1')
404
+ project2 = project_factory(2)
405
+ project2.stub!(:name).and_return('Project 2')
406
+ project3 = project_factory(3)
407
+ project3.stub!(:name).and_return('Project 3')
408
+
409
+ stub_manager_user([project1, project2])
410
+ # Make user a 'non-manager' on project3
411
+ @current_user.stub!(:allowed_to?).with(:view_time_entries, project3).and_return(true)
412
+ @current_user.stub!(:allowed_to?).with(:see_project_timesheets, project3).and_return(false)
413
+ User.stub!(:current).and_return(@current_user)
414
+
415
+ timesheet.projects = [project1, project2, project3]
416
+
417
+ timesheet.should_receive(:time_entries_for_all_users).with(project1).and_return([ ])
418
+ timesheet.should_receive(:time_entries_for_all_users).with(project2).and_return([ ])
419
+ timesheet.should_receive(:time_entries_for_current_user).with(project3).and_return([ ])
420
+ timesheet.fetch_time_entries
421
+ end
422
+ end
423
+
424
+ describe Timesheet,'.fetch_time_entries as a user with view_time_entries permission on a project' do
425
+ include TimesheetSpecHelper
426
+
427
+ it 'should collect time entries for only themself' do
428
+ timesheet = timesheet_factory
429
+
430
+ project1 = project_factory(1)
431
+ project1.stub!(:name).and_return('Project 1')
432
+ project2 = project_factory(2)
433
+ project2.stub!(:name).and_return('Project 2')
434
+
435
+ stub_normal_user([project1, project2])
436
+ timesheet.projects = [project1, project2]
437
+
438
+ timesheet.should_receive(:time_entries_for_current_user).with(project1).and_return([ ])
439
+ timesheet.should_receive(:time_entries_for_current_user).with(project2).and_return([ ])
440
+ timesheet.fetch_time_entries
441
+ end
442
+ end
443
+
444
+ describe Timesheet,'.fetch_time_entries as a non-member of a project' do
445
+ include TimesheetSpecHelper
446
+
447
+ it 'should get no time entries' do
448
+ timesheet = timesheet_factory
449
+
450
+ project1 = project_factory(1)
451
+ project1.stub!(:name).and_return('Project 1')
452
+ project2 = project_factory(2)
453
+ project2.stub!(:name).and_return('Project 2')
454
+
455
+ stub_non_member_user([project1, project2])
456
+ timesheet.projects = [project1, project2]
457
+
458
+ timesheet.should_not_receive(:time_entries_for_current_user).with(project1).and_return([ ])
459
+ timesheet.should_not_receive(:time_entries_for_current_user).with(project2).and_return([ ])
460
+ timesheet.fetch_time_entries
461
+ end
462
+ end
463
+
464
+ describe Timesheet, '#period=' do
465
+ include TimesheetSpecHelper
466
+ describe 'should set the date_to and date_from for' do
467
+ before(:each) do
468
+ @date = Date.new(2009,2,4)
469
+ Date.stub!(:today).and_return(@date)
470
+ @timesheet = Timesheet.new(:period_type => Timesheet::ValidPeriodType[:default])
471
+ end
472
+
473
+ it 'today' do
474
+ @timesheet.should_receive(:date_from=).with(@date)
475
+ @timesheet.should_receive(:date_to=).with(@date)
476
+ @timesheet.period = 'today'
477
+ end
478
+
479
+ it 'yesterday' do
480
+ @timesheet.should_receive(:date_from=).with(@date.yesterday)
481
+ @timesheet.should_receive(:date_to=).with(@date.yesterday)
482
+ @timesheet.period = 'yesterday'
483
+ end
484
+
485
+ it 'current_week' do
486
+ @timesheet.should_receive(:date_from=).with(Date.new(2009, 2, 2))
487
+ @timesheet.should_receive(:date_from).and_return(Date.new(2009, 2, 2))
488
+ @timesheet.should_receive(:date_to=).with(Date.new(2009, 2, 8))
489
+ @timesheet.period = 'current_week'
490
+ end
491
+
492
+ it 'last_week' do
493
+ @timesheet.should_receive(:date_from=).with(Date.new(2009, 1, 26))
494
+ @timesheet.should_receive(:date_from).and_return(Date.new(2009, 1, 26))
495
+ @timesheet.should_receive(:date_to=).with(Date.new(2009, 2, 1))
496
+ @timesheet.period = 'last_week'
497
+ end
498
+
499
+ it '7_days' do
500
+ @timesheet.should_receive(:date_from=).with(@date - 7)
501
+ @timesheet.should_receive(:date_to=).with(@date)
502
+ @timesheet.period = '7_days'
503
+ end
504
+
505
+ it 'current_month' do
506
+ @timesheet.should_receive(:date_from=).with(Date.new(2009, 2, 1))
507
+ @timesheet.should_receive(:date_from).and_return(Date.new(2009, 2, 1))
508
+ @timesheet.should_receive(:date_to=).with(Date.new(2009, 2, 28))
509
+ @timesheet.period = 'current_month'
510
+ end
511
+
512
+ it 'last_month' do
513
+ @timesheet.should_receive(:date_from=).with(Date.new(2009, 1, 1))
514
+ @timesheet.should_receive(:date_from).and_return(Date.new(2009, 1, 1))
515
+ @timesheet.should_receive(:date_to=).with(Date.new(2009, 1, 31))
516
+ @timesheet.period = 'last_month'
517
+ end
518
+
519
+ it '30_days' do
520
+ @timesheet.should_receive(:date_from=).with(@date - 30)
521
+ @timesheet.should_receive(:date_to=).with(@date)
522
+ @timesheet.period = '30_days'
523
+ end
524
+
525
+ it 'current_year' do
526
+ @timesheet.should_receive(:date_from=).with(Date.new(2009,1,1))
527
+ @timesheet.should_receive(:date_to=).with(Date.new(2009,12,31))
528
+ @timesheet.period = 'current_year'
529
+ end
530
+
531
+ it 'all' do
532
+ @timesheet.should_receive(:date_from=).with(nil)
533
+ @timesheet.should_receive(:date_to=).with(nil)
534
+ @timesheet.period = 'all'
535
+ end
536
+ end
537
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Class do
4
+ it "should be a class of Class" do
5
+ Class.class.should eql(Class)
6
+ end
7
+ end
@@ -0,0 +1,40 @@
1
+ # This file is copied to ~/spec when you run 'ruby script/generate rspec'
2
+ # from the project root directory.
3
+ ENV["RAILS_ENV"] = "test"
4
+ require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment")
5
+ require 'spec'
6
+ require 'spec/rails'
7
+ require 'ruby-debug'
8
+
9
+ Spec::Runner.configure do |config|
10
+ # If you're not using ActiveRecord you should remove these
11
+ # lines, delete config/database.yml and disable :active_record
12
+ # in your config/boot.rb
13
+ config.use_transactional_fixtures = true
14
+ config.use_instantiated_fixtures = false
15
+ config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
16
+
17
+ # == Fixtures
18
+ #
19
+ # You can declare fixtures for each example_group like this:
20
+ # describe "...." do
21
+ # fixtures :table_a, :table_b
22
+ #
23
+ # Alternatively, if you prefer to declare them only once, you can
24
+ # do so right here. Just uncomment the next line and replace the fixture
25
+ # names with your fixtures.
26
+ #
27
+ # config.global_fixtures = :table_a, :table_b
28
+ #
29
+ # If you declare global fixtures, be aware that they will be declared
30
+ # for all of your examples, even those that don't use them.
31
+ #
32
+ # == Mock Framework
33
+ #
34
+ # RSpec uses it's own mocking framework by default. If you prefer to
35
+ # use mocha, flexmock or RR, uncomment the appropriate line:
36
+ #
37
+ # config.mock_with :mocha
38
+ # config.mock_with :flexmock
39
+ # config.mock_with :rr
40
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: timesheet_plugin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Eric Davis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-03 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A plugin to show and filter timelogs across all projects in Redmine.
17
+ email: edavis@littlestreamsoftware.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - COPYRIGHT.txt
26
+ - CREDITS.txt
27
+ - GPL.txt
28
+ - README.rdoc
29
+ - Rakefile
30
+ - VERSION
31
+ - app/controllers/timesheet_controller.rb
32
+ - app/helpers/timesheet_helper.rb
33
+ - app/models/timesheet.rb
34
+ - app/views/settings/_timesheet_settings.rhtml
35
+ - app/views/timesheet/_by_issue.rhtml
36
+ - app/views/timesheet/_form.rhtml
37
+ - app/views/timesheet/_issue_time_entries.rhtml
38
+ - app/views/timesheet/_time_entry.rhtml
39
+ - app/views/timesheet/_timesheet_group.rhtml
40
+ - app/views/timesheet/context_menu.html.erb
41
+ - app/views/timesheet/index.rhtml
42
+ - app/views/timesheet/no_projects.rhtml
43
+ - app/views/timesheet/report.rhtml
44
+ - app/views/timesheet/timelog.rhtml
45
+ - assets/images/toggle-arrow-closed.gif
46
+ - assets/images/toggle-arrow-open.gif
47
+ - config/locales/ca.yml
48
+ - config/locales/cs.yml
49
+ - config/locales/da.yml
50
+ - config/locales/de.yml
51
+ - config/locales/en.yml
52
+ - config/locales/es.yml
53
+ - config/locales/fr.yml
54
+ - config/locales/hu.yml
55
+ - config/locales/it.yml
56
+ - config/locales/lt.yml
57
+ - config/locales/pl.yml
58
+ - config/locales/ru.yml
59
+ - init.rb
60
+ - lang/ca.yml
61
+ - lang/cs.yml
62
+ - lang/da.yml
63
+ - lang/de.yml
64
+ - lang/en.yml
65
+ - lang/es.yml
66
+ - lang/fr.yml
67
+ - lang/hu.yml
68
+ - lang/it.yml
69
+ - lang/lt.yml
70
+ - lang/pl.yml
71
+ - lang/ru.yml
72
+ - lib/tasks/plugin_stat.rake
73
+ - lib/timesheet_compatibility.rb
74
+ - rails/init.rb
75
+ has_rdoc: true
76
+ homepage: https://projects.littlestreamsoftware.com/projects/redmine-timesheet
77
+ licenses: []
78
+
79
+ post_install_message:
80
+ rdoc_options:
81
+ - --charset=UTF-8
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ version:
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ version:
96
+ requirements: []
97
+
98
+ rubyforge_project:
99
+ rubygems_version: 1.3.5
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: A Timesheet plugin for Redmine to show timelogs for all projects
103
+ test_files:
104
+ - spec/models/timesheet_spec.rb
105
+ - spec/spec_helper.rb
106
+ - spec/controllers/timesheet_controller_spec.rb
107
+ - spec/sanity_spec.rb