timesheet_plugin 0.5.0 → 0.6.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 (44) hide show
  1. data/README.rdoc +1 -0
  2. data/Rakefile +2 -2
  3. data/VERSION +1 -1
  4. data/app/controllers/timesheet_controller.rb +16 -3
  5. data/app/helpers/timesheet_helper.rb +13 -8
  6. data/app/models/timesheet.rb +120 -12
  7. data/app/views/timesheet/_form.rhtml +5 -31
  8. data/app/views/timesheet/_issue_time_entries.rhtml +9 -2
  9. data/app/views/timesheet/index.rhtml +2 -5
  10. data/app/views/timesheet/report.rhtml +2 -5
  11. data/assets/images/csv.png +0 -0
  12. data/assets/javascripts/timesheet.js +17 -0
  13. data/assets/stylesheets/timesheet.css +6 -0
  14. data/config/locales/hu.yml +1 -1
  15. data/config/locales/hy.yml +9 -0
  16. data/config/locales/ja.yml +10 -0
  17. data/config/locales/pt-br.yml +10 -0
  18. data/config/locales/ru.yml +1 -0
  19. data/config/locales/sr.yml +10 -0
  20. data/config/locales/sv.yml +10 -0
  21. data/config/locales/uk.yml +10 -0
  22. data/config/routes.rb +4 -0
  23. data/init.rb +47 -1
  24. data/lang/hu.yml +1 -1
  25. data/lang/hy.yml +8 -0
  26. data/lang/ja.yml +9 -0
  27. data/lang/pt-br.yml +9 -0
  28. data/lang/ru.yml +1 -0
  29. data/lang/sr.yml +9 -0
  30. data/lang/sv.yml +9 -0
  31. data/lang/uk.yml +9 -0
  32. data/lib/timesheet_compatibility.rb +12 -1
  33. data/rails/init.rb +1 -29
  34. data/test/functional/timesheet_controller_test.rb +256 -0
  35. data/test/integration/timesheet_menu_test.rb +53 -0
  36. data/test/test_helper.rb +24 -0
  37. data/test/unit/sanity_test.rb +20 -0
  38. data/test/unit/timesheet_test.rb +653 -0
  39. metadata +28 -7
  40. data/lib/tasks/plugin_stat.rake +0 -38
  41. data/spec/controllers/timesheet_controller_spec.rb +0 -263
  42. data/spec/models/timesheet_spec.rb +0 -537
  43. data/spec/sanity_spec.rb +0 -7
  44. data/spec/spec_helper.rb +0 -40
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+
3
+ class TimesheetMenuTest < ActionController::IntegrationTest
4
+ context "as an admin" do
5
+ setup do
6
+ @admin_user = User.generate_with_protected!(:admin => true, :password => 'testing', :password_confirmation => 'testing')
7
+ log_user(@admin_user.login, 'testing')
8
+ end
9
+
10
+ should_see_the_timesheet_menu
11
+ end
12
+
13
+ context "as a user with See Project Timesheets on a project" do
14
+ setup do
15
+ @manager_user = User.generate_with_protected!(:admin => false, :password => 'testing', :password_confirmation => 'testing')
16
+
17
+ @manager_role = Role.generate!(:permissions => [:view_time_entries, :see_project_timesheets])
18
+ @project = Project.generate!
19
+ Member.generate!(:principal => @manager_user, :project => @project, :roles => [@manager_role])
20
+
21
+ log_user(@manager_user.login, 'testing')
22
+ end
23
+
24
+ should_see_the_timesheet_menu
25
+ end
26
+
27
+ context "as a user with View Time Entries on a project" do
28
+ setup do
29
+ @user = User.generate_with_protected!(:admin => false, :password => 'testing', :password_confirmation => 'testing')
30
+
31
+ @role = Role.generate!(:permissions => [:view_time_entries])
32
+ @project = Project.generate!
33
+ Member.generate!(:principal => @user, :project => @project, :roles => [@role])
34
+
35
+ log_user(@user.login, 'testing')
36
+ end
37
+
38
+ should_see_the_timesheet_menu
39
+ end
40
+
41
+ context "as a user with without See Project Timesheets or View Time Entries on a project" do
42
+ setup do
43
+ @user = User.generate_with_protected!(:admin => false, :password => 'testing', :password_confirmation => 'testing')
44
+ log_user(@user.login, 'testing')
45
+ end
46
+
47
+ should_not_see_the_timesheet_menu
48
+ end
49
+
50
+ context "as the anonymous user" do
51
+ should_not_see_the_timesheet_menu
52
+ end
53
+ end
@@ -0,0 +1,24 @@
1
+ # Load the normal Rails helper
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper')
3
+
4
+ # Ensure that we are using the temporary fixture path
5
+ Engines::Testing.set_fixture_path
6
+
7
+ # shoulda
8
+ class Test::Unit::TestCase
9
+ def self.should_see_the_timesheet_menu
10
+ should "see the timesheet menu" do
11
+ get '/'
12
+
13
+ assert_select '#top-menu a.timesheet'
14
+ end
15
+ end
16
+
17
+ def self.should_not_see_the_timesheet_menu
18
+ should "not see the timesheet menu" do
19
+ get '/'
20
+
21
+ assert_select '#top-menu a.timesheet', :count => 0
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class SanityTest < ActiveSupport::TestCase
4
+ def test_is_sane
5
+ assert true
6
+ end
7
+
8
+ should "be true" do
9
+ assert true
10
+ end
11
+
12
+ should "mixin ObjectDaddy" do
13
+ assert User.included_modules.include?(ObjectDaddy)
14
+ end
15
+
16
+ should "connect to database" do
17
+ User.generate_with_protected!(:firstname => 'Testing connection')
18
+ assert_equal 1, User.count(:all, :conditions => {:firstname => 'Testing connection'})
19
+ end
20
+ end
@@ -0,0 +1,653 @@
1
+ require File.dirname(__FILE__) + '/../test_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
+ timesheet.allowed_projects = options[:projects] if options[:projects]
9
+ timesheet.projects = options[:projects] if options[:projects]
10
+
11
+ return timesheet
12
+ end
13
+
14
+ def project_factory(id, options = { })
15
+ object_options = {
16
+ :id => id,
17
+ :trackers => [@tracker]
18
+ }.merge(options)
19
+
20
+ project = Project.generate!(object_options)
21
+ project_te1 = TimeEntry.generate!(:project => project, :hours => '5', :activity => @activity, :spent_on => Date.today)
22
+ project_te2 = TimeEntry.generate!(:project => project, :hours => '10', :activity => @activity, :spent_on => Date.today)
23
+
24
+ return project
25
+ end
26
+
27
+ def time_entry_factory(id, options = { })
28
+ object_options = {
29
+ :id => id,
30
+ :spent_on => Date.today,
31
+ }.merge(options)
32
+
33
+ time_entry = TimeEntry.generate!(object_options)
34
+ return time_entry
35
+ end
36
+
37
+ def stub_non_member_user(projects)
38
+ @current_user = User.generate_with_protected!(:admin => false, :firstname => "Non", :lastname => "Member")
39
+ User.current = @current_user
40
+ end
41
+
42
+ def stub_normal_user(projects)
43
+ @current_user = User.generate_with_protected!(:admin => false, :firstname => "Non", :lastname => "Member")
44
+ projects.each do |project|
45
+ Member.generate!(:principal => @current_user, :project => project, :roles => [@normal_role])
46
+ end
47
+ User.current = @current_user
48
+ end
49
+
50
+ def stub_manager_user(projects)
51
+ @current_user = User.generate_with_protected!(:admin => false, :firstname => "Non", :lastname => "Member")
52
+ projects.each do |project|
53
+ Member.generate!(:principal => @current_user, :project => project, :roles => [@manager_role])
54
+ end
55
+ User.current = @current_user
56
+ end
57
+
58
+ def stub_admin_user
59
+ @current_user = User.generate_with_protected!(:admin => true, :firstname => "Administrator", :lastname => "Bob")
60
+ assert @current_user.admin?
61
+ User.current = @current_user
62
+ end
63
+
64
+ def stub_common_csv_records(options={})
65
+ @csv_tracker = @tracker
66
+ @csv_project = options[:project] || Project.generate!(:name => 'Project Name', :trackers => [@csv_tracker])
67
+ @csv_issue = options[:issue] # || Issue.generate_for_project!(@csv_project, :tracker => @csv_tracker, :priority => @issue_priority)
68
+ @csv_activity ||= options[:activity] || TimeEntryActivity.generate!(:name => 'activity')
69
+ @csv_user = options[:user] || User.current
70
+ {
71
+ :user => @csv_user,
72
+ :activity => @csv_activity,
73
+ :spent_on => '2009-04-05',
74
+ :project => @csv_project,
75
+ :comments => 'comments',
76
+ :hours => 10.0,
77
+ :issue => @csv_issue
78
+ }
79
+ end
80
+ end
81
+
82
+ class TimesheetTest < ActiveSupport::TestCase
83
+ include TimesheetSpecHelper
84
+
85
+ def setup
86
+ @issue_priority = IssuePriority.generate!(:name => 'common_csv_records')
87
+ @tracker = Tracker.generate!(:name => 'Tracker')
88
+ @activity = TimeEntryActivity.generate!(:name => 'activity')
89
+ @normal_role = Role.generate!(:name => 'Normal User', :permissions => [:view_time_entries, :log_time])
90
+ @manager_role = Role.generate!(:permissions => [:view_time_entries, :see_project_timesheets])
91
+ end
92
+
93
+ should 'not be an ActiveRecord class' do
94
+ assert !Timesheet.new.is_a?(ActiveRecord::Base)
95
+ end
96
+
97
+ context "initializing" do
98
+ should 'should initialize time_entries to an empty Hash' do
99
+ timesheet = Timesheet.new
100
+ assert_kind_of Hash, timesheet.time_entries
101
+ assert timesheet.time_entries.empty?
102
+ end
103
+
104
+ should 'should initialize projects to an empty Array' do
105
+ timesheet = Timesheet.new
106
+ assert_kind_of Array, timesheet.projects
107
+ assert timesheet.projects.empty?
108
+ end
109
+
110
+ should 'should initialize allowed_projects to an empty Array' do
111
+ timesheet = Timesheet.new
112
+ assert_kind_of Array, timesheet.allowed_projects
113
+ assert timesheet.allowed_projects.empty?
114
+ end
115
+
116
+ should 'should initialize activities to an Array' do
117
+ timesheet = Timesheet.new
118
+ assert_kind_of Array, timesheet.activities
119
+ end
120
+
121
+ context "users" do
122
+ setup do
123
+ project = Project.generate!
124
+ @user_with_permission1 = User.generate_with_protected!
125
+ @user_with_permission2 = User.generate_with_protected!
126
+ @user_without_permission = User.generate_with_protected!
127
+
128
+ Member.generate!(:principal => @user_with_permission1, :project => project, :roles => [@normal_role])
129
+ Member.generate!(:principal => @user_with_permission2, :project => project, :roles => [@normal_role])
130
+
131
+ @timesheet = Timesheet.new
132
+ end
133
+
134
+ should 'initialize users to an Array' do
135
+ assert_kind_of Array, @timesheet.users
136
+ end
137
+
138
+ should 'only include users who have the "log time" permission' do
139
+ assert_contains @timesheet.users, @user_with_permission1.id
140
+ assert_contains @timesheet.users, @user_with_permission2.id
141
+ end
142
+
143
+ end
144
+
145
+ should 'should initialize sort to :project' do
146
+ timesheet = Timesheet.new
147
+ assert_equal :project, timesheet.sort
148
+ end
149
+
150
+ should 'should initialize time_entries to the passed in options' do
151
+ data = { :test => true }
152
+ timesheet = Timesheet.new({ :time_entries => data })
153
+ assert !timesheet.time_entries.empty?
154
+ assert_equal data, timesheet.time_entries
155
+ end
156
+
157
+ should 'should initialize allowed_projects to the passed in options' do
158
+ data = ['project1', 'project2']
159
+ timesheet = Timesheet.new({ :allowed_projects => data })
160
+ assert !timesheet.allowed_projects.empty?
161
+ assert_equal data, timesheet.allowed_projects
162
+ end
163
+
164
+ should 'should initialize activities to the integers of the passed in options' do
165
+ act1 = TimeEntryActivity.generate!
166
+ act2 = TimeEntryActivity.generate!
167
+
168
+ data = [act1.id, act2.id]
169
+ timesheet = Timesheet.new({ :activities => data })
170
+ assert !timesheet.activities.empty?
171
+ assert_equal [act1.id, act2.id], timesheet.activities
172
+ end
173
+
174
+ should 'should initialize users to the ids of the passed in options' do
175
+ user1 = User.generate_with_protected!
176
+ user2 = User.generate_with_protected!
177
+ data = [user1.id, user2.id]
178
+
179
+ timesheet = Timesheet.new({ :users => data })
180
+ assert !timesheet.users.empty?
181
+ assert_equal [user1.id, user2.id], timesheet.users
182
+ end
183
+
184
+ should 'should initialize sort to the :user option when passed :user' do
185
+ timesheet = Timesheet.new({ :sort => :user })
186
+ assert_equal :user, timesheet.sort
187
+ end
188
+
189
+ should 'should initialize sort to the :project option when passed :project' do
190
+ timesheet = Timesheet.new({ :sort => :project })
191
+ assert_equal :project, timesheet.sort
192
+ end
193
+
194
+ should 'should initialize sort to the :issue option when passed :issue' do
195
+ timesheet = Timesheet.new({ :sort => :issue })
196
+ assert_equal :issue, timesheet.sort
197
+ end
198
+
199
+ should 'should initialize sort to the :project option when passed an invalid sort' do
200
+ timesheet = Timesheet.new({ :sort => :invalid })
201
+ assert_equal :project, timesheet.sort
202
+ end
203
+ end
204
+
205
+ context "#fetch_time_entries" do
206
+ setup do
207
+ stub_admin_user
208
+ @project1 = Project.generate!(:name => 'Project 1')
209
+ @te1 = TimeEntry.generate!(:project => @project1, :activity => @activity, :spent_on => Date.today, :user => @current_user)
210
+
211
+ @project2 = Project.generate!(:name => 'Project 2')
212
+ @te2 = TimeEntry.generate!(:project => @project2, :activity => @activity, :spent_on => Date.today, :user => @current_user)
213
+
214
+ @timesheet = timesheet_factory(:activities => [@activity.id], :projects => [@project1, @project2])
215
+ end
216
+
217
+ should 'should clear .time_entries' do
218
+ timesheet = Timesheet.new
219
+ timesheet.time_entries = { :filled => 'data' }
220
+
221
+ previous = timesheet.time_entries
222
+
223
+ timesheet.fetch_time_entries
224
+
225
+ assert_not_same previous, timesheet.time_entries
226
+ end
227
+
228
+ should 'should add a time_entry Hash for each project' do
229
+ @timesheet.fetch_time_entries
230
+
231
+ assert !@timesheet.time_entries.empty?
232
+ assert_equal 2, @timesheet.time_entries.size
233
+ end
234
+
235
+ should 'should use the project name for each time_entry key' do
236
+ @timesheet.fetch_time_entries
237
+
238
+ assert_contains @timesheet.time_entries.keys, "Project 1"
239
+ assert_contains @timesheet.time_entries.keys, "Project 2"
240
+ end
241
+
242
+ should 'should add the parent project name for each time_entry array for sub-projects' do
243
+ @project2.set_parent!(@project1)
244
+
245
+ @timesheet.fetch_time_entries
246
+
247
+ assert_contains @timesheet.time_entries.keys, "Project 1"
248
+ assert_contains @timesheet.time_entries.keys, "Project 1 / Project 2"
249
+ end
250
+
251
+ should 'should fetch all the time entries on a project in the date range'
252
+ should 'should fetch all the time entries on a project matching the activities'
253
+ should 'should fetch all the time entries on a project matching the users'
254
+ end
255
+
256
+ context "#fetch_time_entries with user sorting" do
257
+ setup do
258
+ @project = Project.generate!(:trackers => [@tracker], :name => 'Project Name')
259
+ stub_admin_user
260
+ @timesheet = timesheet_factory(:sort => :user, :users => [User.current.id], :projects => [@project], :activities => [@activity.id])
261
+
262
+ TimeEntry.generate!(:user => User.current, :project => @project, :activity => @activity)
263
+ TimeEntry.generate!(:user => User.current, :project => @project, :activity => @activity)
264
+ TimeEntry.generate!(:user => User.current, :project => @project, :activity => @activity)
265
+
266
+ end
267
+
268
+ should 'should clear .time_entries' do
269
+ @timesheet.time_entries = { :filled => 'data' }
270
+
271
+ previous = @timesheet.time_entries
272
+ @timesheet.fetch_time_entries
273
+ assert_not_same previous, @timesheet.time_entries
274
+ end
275
+
276
+ should 'should add a time_entry array for each user' do
277
+ @timesheet.fetch_time_entries
278
+
279
+ assert !@timesheet.time_entries.empty?
280
+ assert_equal 1, @timesheet.time_entries.size # One user
281
+ end
282
+
283
+ should 'should use the user name for each time_entry array' do
284
+ @timesheet.fetch_time_entries
285
+
286
+ assert_contains @timesheet.time_entries.keys, "Administrator Bob"
287
+ end
288
+ end
289
+
290
+ context '#fetch_time_entries with issue sorting' do
291
+ setup do
292
+ stub_admin_user
293
+ @project = project_factory(1)
294
+ @timesheet = timesheet_factory(:sort => :issue, :users => [User.current.id])
295
+ @timesheet.projects = [@project]
296
+
297
+ @issue1 = Issue.generate_for_project!(@project, :priority => @issue_priority)
298
+ @issue2 = Issue.generate_for_project!(@project, :priority => @issue_priority)
299
+ @issue3 = Issue.generate_for_project!(@project, :priority => @issue_priority)
300
+
301
+ TimeEntry.generate!(:user => User.current, :project => @project, :activity => @activity, :issue => @issue1)
302
+ TimeEntry.generate!(:user => User.current, :project => @project, :activity => @activity, :issue => @issue1)
303
+ TimeEntry.generate!(:user => User.current, :project => @project, :activity => @activity, :issue => @issue2)
304
+ TimeEntry.generate!(:user => User.current, :project => @project, :activity => @activity, :issue => @issue2)
305
+ TimeEntry.generate!(:user => User.current, :project => @project, :activity => @activity, :issue => @issue3)
306
+
307
+ end
308
+
309
+ should 'should clear .time_entries' do
310
+ @timesheet.time_entries = { :filled => 'data' }
311
+
312
+ previous = @timesheet.time_entries
313
+
314
+ @timesheet.fetch_time_entries
315
+
316
+ assert_not_same previous, @timesheet.time_entries
317
+ end
318
+
319
+ should 'should add a time_entry array for each project' do
320
+ @timesheet.fetch_time_entries
321
+
322
+ assert !@timesheet.time_entries.empty?
323
+ assert_equal 1, @timesheet.time_entries.size
324
+ end
325
+
326
+ should 'should use the project for each time_entry array' do
327
+ @timesheet.fetch_time_entries
328
+ assert_contains @timesheet.time_entries.keys, @project
329
+ end
330
+ end
331
+
332
+ context "#fetch_time_entries as an administrator" do
333
+
334
+ should 'should collect time entries for all users on each project' do
335
+ project1 = Project.generate!(:name => "Project 1", :trackers => [@tracker])
336
+ project2 = Project.generate!(:name => "Project 2", :trackers => [@tracker])
337
+ project3 = Project.generate!(:name => "Project 3", :trackers => [@tracker])
338
+
339
+ stub_admin_user
340
+ @other_user = User.generate_with_protected!(:admin => false, :firstname => "Non", :lastname => "Member")
341
+
342
+ timesheet = timesheet_factory(:activities => [@activity.id], :projects => [project1, project2, project3], :users => [User.current.id, @other_user.id])
343
+
344
+ @te1 = TimeEntry.generate!(:project => project1, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => @current_user)
345
+ @te2 = TimeEntry.generate!(:project => project2, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => @other_user)
346
+ @te3 = TimeEntry.generate!(:project => project3, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => @other_user)
347
+
348
+ timesheet.fetch_time_entries
349
+
350
+ assert timesheet.time_entries.present?
351
+ assert_same_elements timesheet.time_entries.keys, ["Project 1", "Project 2", "Project 3"]
352
+ logs1 = timesheet.time_entries["Project 1"][:logs]
353
+ assert_equal 1, logs1.size
354
+ assert_same_elements logs1, [@te1]
355
+ logs2 = timesheet.time_entries["Project 2"][:logs]
356
+ assert_equal 1, logs2.size
357
+ assert_same_elements logs2, [@te2]
358
+ logs3 = timesheet.time_entries["Project 3"][:logs]
359
+ assert_equal 1, logs3.size
360
+ assert_same_elements logs3, [@te3]
361
+
362
+ users1 = timesheet.time_entries["Project 1"][:users]
363
+ assert_equal 1, users1.size
364
+ assert_same_elements users1, [User.current]
365
+ users2 = timesheet.time_entries["Project 2"][:users]
366
+ assert_equal 1, users2.size
367
+ assert_same_elements users2, [@other_user]
368
+ users3 = timesheet.time_entries["Project 3"][:users]
369
+ assert_equal 1, users3.size
370
+ assert_same_elements users3, [@other_user]
371
+ end
372
+ end
373
+
374
+ context '#fetch_time_entries as a user with see_project_timesheet permission on a project' do
375
+
376
+ should 'should collect time entries for all users' do
377
+ project1 = Project.generate!(:name => "Project 1", :trackers => [@tracker])
378
+ project2 = Project.generate!(:name => "Project 2", :trackers => [@tracker])
379
+ project3 = Project.generate!(:name => "Project 3", :trackers => [@tracker])
380
+
381
+ stub_manager_user([project1, project2])
382
+ @other_user = User.generate_with_protected!(:admin => false, :firstname => "Non", :lastname => "Member")
383
+
384
+ timesheet = timesheet_factory(:activities => [@activity.id], :projects => [project1, project2, project3], :users => [User.current.id, @other_user.id])
385
+
386
+ @te1 = TimeEntry.generate!(:project => project1, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => @current_user)
387
+ @te2 = TimeEntry.generate!(:project => project2, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => @other_user)
388
+ @te3 = TimeEntry.generate!(:project => project3, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => @other_user)
389
+
390
+ timesheet.fetch_time_entries
391
+
392
+ assert timesheet.time_entries.present?
393
+ assert_same_elements timesheet.time_entries.keys, ["Project 1", "Project 2"]
394
+ logs1 = timesheet.time_entries["Project 1"][:logs]
395
+ assert_equal 1, logs1.size
396
+ assert_same_elements logs1, [@te1]
397
+ logs2 = timesheet.time_entries["Project 2"][:logs]
398
+ assert_equal 1, logs2.size
399
+ assert_same_elements logs2, [@te2]
400
+
401
+ users1 = timesheet.time_entries["Project 1"][:users]
402
+ assert_equal 1, users1.size
403
+ assert_same_elements users1, [User.current]
404
+ users2 = timesheet.time_entries["Project 2"][:users]
405
+ assert_equal 1, users2.size
406
+ assert_same_elements users2, [@other_user]
407
+ end
408
+
409
+ context "with the 'see project timesheet' permission" do
410
+ should 'xxx return the time entries for all users on that project' do
411
+ manager_project = Project.generate!(:name => "Manager Project", :trackers => [@tracker])
412
+ user_project = Project.generate!(:name => "User Project", :trackers => [@tracker])
413
+
414
+ stub_manager_user([manager_project])
415
+ Member.generate!(:principal => @current_user, :project => user_project, :roles => [@normal_role])
416
+
417
+ other_user = User.generate_with_protected!(:admin => false, :firstname => "Other", :lastname => "Member")
418
+
419
+ @timesheet = timesheet_factory(:sort => :user, :activities => [@activity.id], :projects => [manager_project, user_project], :users => [User.current.id, other_user.id])
420
+
421
+ @te1 = TimeEntry.generate!(:project => manager_project, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => @current_user)
422
+ @te2 = TimeEntry.generate!(:project => manager_project, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => other_user)
423
+ @te3 = TimeEntry.generate!(:project => user_project, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => other_user)
424
+
425
+ @timesheet.fetch_time_entries
426
+
427
+ assert @timesheet.time_entries.present?
428
+ assert_same_elements @timesheet.time_entries.keys, [@current_user.name, other_user.name]
429
+
430
+ current_user_logs = @timesheet.time_entries[@current_user.name][:logs]
431
+ assert_equal 1, current_user_logs.size
432
+ assert_same_elements current_user_logs, [@te1]
433
+
434
+ other_user_logs = @timesheet.time_entries[other_user.name][:logs]
435
+ assert_equal 1, other_user_logs.size
436
+ assert_same_elements other_user_logs, [@te2]
437
+ assert !other_user_logs.include?(@te3), "Showing other user logs for project which the user doesn't have permission to see"
438
+ end
439
+ end
440
+ end
441
+
442
+ context '#fetch_time_entries as a user with view_time_entries permission on a project' do
443
+
444
+ should 'should collect time entries for only themself' do
445
+ project1 = project_factory(1, :name => 'Project 1')
446
+ project2 = project_factory(2, :name => 'Project 2')
447
+ timesheet = timesheet_factory(:activities => [@activity.id], :projects => [project1, project2])
448
+ stub_normal_user([project1, project2])
449
+ @te1 = TimeEntry.generate!(:project => project1, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => @current_user)
450
+ @te2 = TimeEntry.generate!(:project => project1, :hours => 5, :activity => @activity, :spent_on => Date.today, :user => @current_user)
451
+
452
+ timesheet.fetch_time_entries
453
+
454
+ assert timesheet.time_entries.present?
455
+ assert_equal ["Project 1"], timesheet.time_entries.keys
456
+ logs = timesheet.time_entries["Project 1"][:logs]
457
+ assert_equal 2, logs.size
458
+ assert_same_elements logs, [@te1, @te2]
459
+ users = timesheet.time_entries["Project 1"][:users]
460
+ assert_equal 1, users.size
461
+ assert_same_elements users, [User.current]
462
+ end
463
+ end
464
+
465
+ context '#fetch_time_entries as a non-member of a project' do
466
+
467
+ should 'should get no time entries' do
468
+ timesheet = timesheet_factory
469
+
470
+ project1 = project_factory(1, :name => 'Proejct 1')
471
+ project2 = project_factory(2, :name => 'Project 2')
472
+
473
+ stub_non_member_user([project1, project2])
474
+ timesheet.projects = [project1, project2]
475
+
476
+ timesheet.fetch_time_entries
477
+ assert timesheet.time_entries.empty?
478
+ end
479
+ end
480
+
481
+ context '#period=' do
482
+
483
+ context 'should set the date_to and date_from for' do
484
+ setup do
485
+ @date = Date.new(2009,2,4)
486
+ Date.stubs(:today).returns(@date)
487
+ @timesheet = Timesheet.new(:period_type => Timesheet::ValidPeriodType[:default])
488
+ end
489
+
490
+ should 'today' do
491
+ @timesheet.period = 'today'
492
+ assert_equal @date, @timesheet.date_from
493
+ assert_equal @date, @timesheet.date_to
494
+ end
495
+
496
+ should 'yesterday' do
497
+ @timesheet.period = 'yesterday'
498
+ assert_equal @date.yesterday, @timesheet.date_from
499
+ assert_equal @date.yesterday, @timesheet.date_to
500
+ end
501
+
502
+ should 'current_week' do
503
+ @timesheet.period = 'current_week'
504
+ assert_equal Date.new(2009,2,2), @timesheet.date_from
505
+ assert_equal Date.new(2009,2,8), @timesheet.date_to
506
+ end
507
+
508
+ should 'last_week' do
509
+ @timesheet.period = 'last_week'
510
+ assert_equal Date.new(2009,1,26), @timesheet.date_from
511
+ assert_equal Date.new(2009,2,1), @timesheet.date_to
512
+ end
513
+
514
+ should '7_days' do
515
+ @timesheet.period = '7_days'
516
+ assert_equal @date - 7, @timesheet.date_from
517
+ assert_equal @date, @timesheet.date_to
518
+ end
519
+
520
+ should 'current_month' do
521
+ @timesheet.period = 'current_month'
522
+ assert_equal Date.new(2009,2,1), @timesheet.date_from
523
+ assert_equal Date.new(2009,2,28), @timesheet.date_to
524
+ end
525
+
526
+ should 'last_month' do
527
+ @timesheet.period = 'last_month'
528
+ assert_equal Date.new(2009,1,1), @timesheet.date_from
529
+ assert_equal Date.new(2009,1,31), @timesheet.date_to
530
+ end
531
+
532
+ should '30_days' do
533
+ @timesheet.period = '30_days'
534
+ assert_equal @date - 30, @timesheet.date_from
535
+ assert_equal @date, @timesheet.date_to
536
+ end
537
+
538
+ should 'current_year' do
539
+ @timesheet.period = 'current_year'
540
+ assert_equal Date.new(2009,1,1), @timesheet.date_from
541
+ assert_equal Date.new(2009,12,31), @timesheet.date_to
542
+ end
543
+
544
+ should 'all' do
545
+ @timesheet.period = 'all'
546
+ assert_equal nil, @timesheet.date_from
547
+ assert_equal nil, @timesheet.date_to
548
+ end
549
+ end
550
+ end
551
+
552
+ context '#to_csv' do
553
+ setup do
554
+ stub_admin_user
555
+ @another_user = User.generate_with_protected!(:admin => true, :firstname => 'Another', :lastname => 'user')
556
+ @project = Project.generate!(:trackers => [@tracker], :name => 'Project Name')
557
+ end
558
+
559
+ context "sorted by :user" do
560
+ should "should return a csv grouped by user" do
561
+ timesheet = timesheet_factory(:sort => :user, :users => [User.current.id, @another_user.id], :projects => [@project.id], :activities => [@activity.id], :date_from => '2009-04-05', :date_to => '2009-04-05')
562
+ issue = Issue.generate_for_project!(@project, :tracker => @tracker, :priority => @issue_priority)
563
+
564
+ time_entries = [
565
+ time_entry_factory(1, stub_common_csv_records(:activity => @activity, :project => @project,:issue => issue).merge({})),
566
+ time_entry_factory(3, stub_common_csv_records(:activity => @activity, :project => @project,:issue => issue).merge({})),
567
+ time_entry_factory(4, stub_common_csv_records(:activity => @activity, :project => @project,:issue => issue).merge({})),
568
+ time_entry_factory(5, stub_common_csv_records(:activity => @activity, :project => @project,:issue => nil))
569
+ ]
570
+
571
+ time_entries_another_user = [
572
+ time_entry_factory(2, stub_common_csv_records(:project => @project, :issue => issue).merge({:user => @another_user }))
573
+ ]
574
+
575
+ timesheet.fetch_time_entries
576
+
577
+ # trailing newline
578
+ assert_equal [
579
+ "#,Date,Member,Activity,Project,Issue,Comment,Hours",
580
+ "1,2009-04-05,Administrator Bob,activity,Project Name,Tracker #1,comments,10.0",
581
+ "3,2009-04-05,Administrator Bob,activity,Project Name,Tracker #1,comments,10.0",
582
+ "4,2009-04-05,Administrator Bob,activity,Project Name,Tracker #1,comments,10.0",
583
+ "5,2009-04-05,Administrator Bob,activity,Project Name,,comments,10.0",
584
+ "2,2009-04-05,Another user,activity,Project Name,Tracker #1,comments,10.0",
585
+ ].join("\n") + "\n", timesheet.to_csv
586
+
587
+ end
588
+ end
589
+
590
+ context "sorted by :project" do
591
+ should "should return a csv grouped by project" do
592
+
593
+ another_project = Project.generate!(:trackers => [@tracker], :name => 'Another Project')
594
+ timesheet = timesheet_factory(:sort => :project, :users => [User.current.id, @another_user.id], :projects => [@project, another_project], :activities => [@activity.id], :date_from => '2009-04-05', :date_to => '2009-04-05')
595
+ issue = Issue.generate_for_project!(@project, :tracker => @tracker, :priority => @issue_priority)
596
+ another_issue = Issue.generate_for_project!(another_project, :tracker => @tracker, :priority => @issue_priority)
597
+
598
+ project_a_time_entries = [
599
+ time_entry_factory(1, stub_common_csv_records({:activity => @activity, :project => @project,:issue => issue})),
600
+ time_entry_factory(3, stub_common_csv_records({:activity => @activity, :project => @project,:issue => issue})),
601
+ time_entry_factory(5, stub_common_csv_records({:activity => @activity, :project => @project,:issue => nil}))
602
+ ]
603
+
604
+ another_project_time_entries = [
605
+ time_entry_factory(2, stub_common_csv_records({:activity => @activity,:user => @another_user, :project => another_project,:issue => another_issue })),
606
+ time_entry_factory(4, stub_common_csv_records({:activity => @activity, :project => another_project,:issue => another_issue}))
607
+
608
+ ]
609
+
610
+ timesheet.fetch_time_entries
611
+ # trailing newline
612
+ assert_equal [
613
+ "#,Date,Member,Activity,Project,Issue,Comment,Hours",
614
+ "2,2009-04-05,Another user,activity,Another Project,Tracker #2,comments,10.0",
615
+ "4,2009-04-05,Administrator Bob,activity,Another Project,Tracker #2,comments,10.0",
616
+ "1,2009-04-05,Administrator Bob,activity,Project Name,Tracker #1,comments,10.0",
617
+ "3,2009-04-05,Administrator Bob,activity,Project Name,Tracker #1,comments,10.0",
618
+ "5,2009-04-05,Administrator Bob,activity,Project Name,,comments,10.0",
619
+ ].join("\n") + "\n", timesheet.to_csv
620
+ end
621
+ end
622
+
623
+ context "sorted by :issue" do
624
+ should "should return a csv grouped by issue" do
625
+ another_project = Project.generate!(:trackers => [@tracker], :name => 'Another Project')
626
+
627
+ @issue1 = Issue.generate_for_project!(@project, :tracker => @tracker, :priority => @issue_priority)
628
+ @issue1.time_entries << time_entry_factory(1, stub_common_csv_records({:activity => @activity, :project => @project}))
629
+
630
+ @issue2 = Issue.generate_for_project!(@project, :tracker => @tracker, :priority => @issue_priority)
631
+ @issue2.time_entries << time_entry_factory(3, stub_common_csv_records({:activity => @activity, :project => @project}))
632
+
633
+ @issue3 = Issue.generate_for_project!(another_project, :tracker => @tracker, :priority => @issue_priority)
634
+ @issue3.time_entries << time_entry_factory(2, stub_common_csv_records({:user => @another_user, :activity => @activity, :project => another_project}))
635
+
636
+ @issue4 = Issue.generate_for_project!(another_project, :tracker => @tracker, :priority => @issue_priority)
637
+ @issue4.time_entries << time_entry_factory(4, stub_common_csv_records({:activity => @activity, :project => another_project}))
638
+
639
+ timesheet = timesheet_factory(:sort => :issue, :users => [User.current.id, @another_user.id], :projects => [@project, another_project], :activities => [@activity.id], :date_from => '2009-04-05', :date_to => '2009-04-05')
640
+
641
+ timesheet.fetch_time_entries
642
+ assert_equal [
643
+ "#,Date,Member,Activity,Project,Issue,Comment,Hours",
644
+ "2,2009-04-05,Another user,activity,Another Project,Tracker #3,comments,10.0",
645
+ "4,2009-04-05,Administrator Bob,activity,Another Project,Tracker #4,comments,10.0",
646
+ "1,2009-04-05,Administrator Bob,activity,Project Name,Tracker #1,comments,10.0",
647
+ "3,2009-04-05,Administrator Bob,activity,Project Name,Tracker #2,comments,10.0",
648
+ ].join("\n") + "\n", timesheet.to_csv
649
+
650
+ end
651
+ end
652
+ end
653
+ end