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.
- data/README.rdoc +1 -0
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/app/controllers/timesheet_controller.rb +16 -3
- data/app/helpers/timesheet_helper.rb +13 -8
- data/app/models/timesheet.rb +120 -12
- data/app/views/timesheet/_form.rhtml +5 -31
- data/app/views/timesheet/_issue_time_entries.rhtml +9 -2
- data/app/views/timesheet/index.rhtml +2 -5
- data/app/views/timesheet/report.rhtml +2 -5
- data/assets/images/csv.png +0 -0
- data/assets/javascripts/timesheet.js +17 -0
- data/assets/stylesheets/timesheet.css +6 -0
- data/config/locales/hu.yml +1 -1
- data/config/locales/hy.yml +9 -0
- data/config/locales/ja.yml +10 -0
- data/config/locales/pt-br.yml +10 -0
- data/config/locales/ru.yml +1 -0
- data/config/locales/sr.yml +10 -0
- data/config/locales/sv.yml +10 -0
- data/config/locales/uk.yml +10 -0
- data/config/routes.rb +4 -0
- data/init.rb +47 -1
- data/lang/hu.yml +1 -1
- data/lang/hy.yml +8 -0
- data/lang/ja.yml +9 -0
- data/lang/pt-br.yml +9 -0
- data/lang/ru.yml +1 -0
- data/lang/sr.yml +9 -0
- data/lang/sv.yml +9 -0
- data/lang/uk.yml +9 -0
- data/lib/timesheet_compatibility.rb +12 -1
- data/rails/init.rb +1 -29
- data/test/functional/timesheet_controller_test.rb +256 -0
- data/test/integration/timesheet_menu_test.rb +53 -0
- data/test/test_helper.rb +24 -0
- data/test/unit/sanity_test.rb +20 -0
- data/test/unit/timesheet_test.rb +653 -0
- metadata +28 -7
- data/lib/tasks/plugin_stat.rake +0 -38
- data/spec/controllers/timesheet_controller_spec.rb +0 -263
- data/spec/models/timesheet_spec.rb +0 -537
- data/spec/sanity_spec.rb +0 -7
- 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
|
data/test/test_helper.rb
ADDED
@@ -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
|