timesheet_plugin 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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