timert 1.0.1 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/timert/application.rb +7 -7
- data/lib/timert/argument_parser.rb +10 -10
- data/lib/timert/database.rb +5 -5
- data/lib/timert/date_util.rb +5 -1
- data/lib/timert/day.rb +19 -19
- data/lib/timert/duration.rb +1 -1
- data/lib/timert/report.rb +49 -30
- data/lib/timert/timer.rb +5 -5
- data/spec/application_spec.rb +11 -11
- data/spec/database_file_spec.rb +1 -1
- data/spec/database_spec.rb +5 -5
- data/spec/date_util_spec.rb +4 -0
- data/spec/day_spec.rb +28 -16
- data/spec/duration_spec.rb +3 -3
- data/spec/report_spec.rb +71 -25
- data/spec/timer_spec.rb +7 -7
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NjE3MmI2YWFkMTgzYzgwMDE3Zjg3NDI3NjIzNDM3ZThkYWM5NWM3MQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTUyMzMzOWY4YmNhZjU2MjUwMDA4YmQ1MTk4ZWYxZTc0MjBlYmU2Zg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZWE0NzQ4OGE1OWIxNTE3YWE3ZmEyZTlkMDMxYjYyNWIzZjM1ZjMxMzNkYjJl
|
10
|
+
ZTkzZTcxYjUwZWEwZWM5ZGM5Yjc3YzNmMTM3ZDMwOTk2MDFkODhmNzk5OTQ5
|
11
|
+
MDdkMWQ0NzQwYjAyYmJiZmQwNTU1MmU3MmY2ZDg3NDc2ZGU4ZWQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NDFiNmRmZThmNDVjYjFiNzc1N2M0YzlmMWQ2ZjNhYWRjODAwOWRjNDBkMjA4
|
14
|
+
MGFlOTI5ZTBkNjIzNzYxMTA5ZGI3NDZiNGIwNmIwYzBjZTBiNmNlZjU5Y2Iw
|
15
|
+
M2M5NjRmNDc2OGE5YzQ3NWM2N2YwZDU5NTMxOTZhOTgxNDliZDY=
|
data/lib/timert/application.rb
CHANGED
@@ -11,7 +11,7 @@ module Timert
|
|
11
11
|
attr_reader :result
|
12
12
|
|
13
13
|
def initialize(argv, db_path)
|
14
|
-
@database = Database.new(DatabaseFile.new(db_path))
|
14
|
+
@database = Database.new(DatabaseFile.new(db_path))
|
15
15
|
@timer = Timer.new(@database.today)
|
16
16
|
@result = {}
|
17
17
|
|
@@ -28,7 +28,7 @@ module Timert
|
|
28
28
|
@database.save(@timer.today)
|
29
29
|
else
|
30
30
|
add_message("timer already started at #{format_hour(timer_result[:time])}")
|
31
|
-
end
|
31
|
+
end
|
32
32
|
rescue ArgumentError => e
|
33
33
|
add_message(e.message)
|
34
34
|
end
|
@@ -37,22 +37,22 @@ module Timert
|
|
37
37
|
def stop(time = nil)
|
38
38
|
begin
|
39
39
|
timer_result = @timer.stop(time)
|
40
|
-
if timer_result[:stopped]
|
40
|
+
if timer_result[:stopped]
|
41
41
|
add_message("stop timer at #{format_hour(timer_result[:time])}")
|
42
42
|
@database.save(@timer.today)
|
43
43
|
else
|
44
44
|
add_message("timer isn't started yet")
|
45
|
-
end
|
45
|
+
end
|
46
46
|
rescue ArgumentError => e
|
47
47
|
add_message(e.message)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def report(time_expression)
|
51
|
+
def report(time_expression = "")
|
52
52
|
add_message(Report.generate(@database, time_expression))
|
53
53
|
end
|
54
54
|
|
55
|
-
def add_task(task)
|
55
|
+
def add_task(task)
|
56
56
|
add_message("added task: #{task}")
|
57
57
|
@timer.add_task(task)
|
58
58
|
@database.save(@timer.today)
|
@@ -68,6 +68,6 @@ module Timert
|
|
68
68
|
|
69
69
|
def add_message(msg)
|
70
70
|
@result["message"] = msg
|
71
|
-
end
|
71
|
+
end
|
72
72
|
end
|
73
73
|
end
|
@@ -8,9 +8,9 @@ module Timert
|
|
8
8
|
if args.empty?
|
9
9
|
@action = "help"
|
10
10
|
@argument = nil
|
11
|
-
elsif is_api?(args[0])
|
12
|
-
@action = args[0]
|
13
|
-
@argument = api_argument(@action, args[1])
|
11
|
+
elsif is_api?(args[0])
|
12
|
+
@action = args[0]
|
13
|
+
@argument = api_argument(@action, *args[1..-1])
|
14
14
|
else
|
15
15
|
@action = 'add_task'
|
16
16
|
@argument = args.join(" ")
|
@@ -22,11 +22,11 @@ module Timert
|
|
22
22
|
["start", "stop", "report"].include?(method_name)
|
23
23
|
end
|
24
24
|
|
25
|
-
def api_argument(action,
|
25
|
+
def api_argument(action, *args)
|
26
26
|
if is_time_method?(action)
|
27
|
-
parse_time(
|
27
|
+
parse_time(args[0])
|
28
28
|
elsif is_report?(action)
|
29
|
-
parse_report_arg(
|
29
|
+
parse_report_arg(args)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -38,12 +38,12 @@ module Timert
|
|
38
38
|
method_name == "report"
|
39
39
|
end
|
40
40
|
|
41
|
-
def is_month_or_week?(
|
42
|
-
|
41
|
+
def is_month_or_week?(args)
|
42
|
+
args.include?("month") || args.include?("week")
|
43
43
|
end
|
44
44
|
|
45
|
-
def parse_report_arg(
|
46
|
-
is_month_or_week?(
|
45
|
+
def parse_report_arg(args)
|
46
|
+
is_month_or_week?(args) ? args.join(" ") : args[0]
|
47
47
|
end
|
48
48
|
|
49
49
|
def parse_time(arg)
|
data/lib/timert/database.rb
CHANGED
@@ -3,7 +3,7 @@ require_relative 'day'
|
|
3
3
|
|
4
4
|
module Timert
|
5
5
|
class Database
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(file)
|
8
8
|
@file = file
|
9
9
|
end
|
@@ -12,7 +12,7 @@ module Timert
|
|
12
12
|
day
|
13
13
|
end
|
14
14
|
|
15
|
-
def day(date = Date.today)
|
15
|
+
def day(date = Date.today)
|
16
16
|
hash_to_day(load_data[key(date)], date)
|
17
17
|
end
|
18
18
|
|
@@ -24,7 +24,7 @@ module Timert
|
|
24
24
|
if range.include?(day.date)
|
25
25
|
result << day
|
26
26
|
end
|
27
|
-
end
|
27
|
+
end
|
28
28
|
result
|
29
29
|
end
|
30
30
|
|
@@ -35,7 +35,7 @@ module Timert
|
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
38
|
-
|
38
|
+
|
39
39
|
def load_data
|
40
40
|
@file.load
|
41
41
|
end
|
@@ -51,7 +51,7 @@ module Timert
|
|
51
51
|
def hash_to_day(day_hash, date)
|
52
52
|
if day_hash
|
53
53
|
Day.new(
|
54
|
-
intervals: day_hash["intervals"],
|
54
|
+
intervals: day_hash["intervals"],
|
55
55
|
tasks: day_hash["tasks"],
|
56
56
|
date: date)
|
57
57
|
else
|
data/lib/timert/date_util.rb
CHANGED
@@ -2,7 +2,7 @@ require 'date'
|
|
2
2
|
|
3
3
|
module Timert
|
4
4
|
class DateUtil
|
5
|
-
|
5
|
+
|
6
6
|
def self.format_hour(timestamp)
|
7
7
|
timestamp ? Time.at(timestamp).strftime("%H:%M:%S") : ""
|
8
8
|
end
|
@@ -11,6 +11,10 @@ module Timert
|
|
11
11
|
date ? date.strftime("%Y-%m-%d") : ""
|
12
12
|
end
|
13
13
|
|
14
|
+
def self.format_month(date)
|
15
|
+
date ? date.strftime("%Y-%m") : ""
|
16
|
+
end
|
17
|
+
|
14
18
|
def self.parse_time(arg)
|
15
19
|
if arg
|
16
20
|
hours, minutes = arg.split(":")
|
data/lib/timert/day.rb
CHANGED
@@ -4,37 +4,37 @@ module Timert
|
|
4
4
|
attr_reader :intervals, :tasks, :date
|
5
5
|
attr_accessor :on
|
6
6
|
|
7
|
-
def initialize(args = {})
|
7
|
+
def initialize(args = {})
|
8
8
|
@intervals = args[:intervals] || []
|
9
|
-
@tasks = args[:tasks] || []
|
9
|
+
@tasks = args[:tasks] || []
|
10
10
|
@date = args[:date]
|
11
|
-
|
11
|
+
|
12
12
|
raise ArgumentError.new("intervals should be an array") if !@intervals.is_a?(Array)
|
13
|
-
raise ArgumentError.new("tasks should be an array") if !@tasks.is_a?(Array)
|
13
|
+
raise ArgumentError.new("tasks should be an array") if !@tasks.is_a?(Array)
|
14
14
|
end
|
15
15
|
|
16
16
|
def add_start(time)
|
17
|
-
if !is_interval_started?
|
17
|
+
if !is_interval_started?
|
18
18
|
if time <= last_start
|
19
19
|
raise ArgumentError.new("Invalid start time")
|
20
20
|
elsif time < last_stop
|
21
|
-
raise ArgumentError.new("Invalid start time. It's before the last stop time.")
|
21
|
+
raise ArgumentError.new("Invalid start time. It's before the last stop time.")
|
22
22
|
elsif !is_date_correct?(time)
|
23
23
|
raise ArgumentError.new("Invalid date")
|
24
24
|
end
|
25
|
-
@intervals.push({"start" => time})
|
25
|
+
@intervals.push({"start" => time})
|
26
26
|
time
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
30
|
def add_stop(time)
|
31
|
-
if is_interval_started?
|
31
|
+
if is_interval_started?
|
32
32
|
if time < last_start
|
33
33
|
raise ArgumentError.new("Invalid stop time")
|
34
34
|
elsif !is_date_correct?(time)
|
35
35
|
raise ArgumentError.new("Invalid date")
|
36
36
|
end
|
37
|
-
@intervals.last["stop"] = time
|
37
|
+
@intervals.last["stop"] = time
|
38
38
|
time
|
39
39
|
end
|
40
40
|
end
|
@@ -57,8 +57,8 @@ module Timert
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def is_interval_started?
|
60
|
-
@intervals.length > 0 &&
|
61
|
-
@intervals.last["start"] &&
|
60
|
+
@intervals.length > 0 &&
|
61
|
+
@intervals.last["start"] &&
|
62
62
|
!@intervals.last["stop"]
|
63
63
|
end
|
64
64
|
|
@@ -68,18 +68,18 @@ module Timert
|
|
68
68
|
|
69
69
|
def last_start
|
70
70
|
last_interval['start'].to_i
|
71
|
-
end
|
71
|
+
end
|
72
72
|
|
73
73
|
def last_stop
|
74
74
|
last_interval['stop'].to_i
|
75
75
|
end
|
76
76
|
|
77
|
-
private
|
78
|
-
def interval_duration(interval)
|
77
|
+
private
|
78
|
+
def interval_duration(interval)
|
79
79
|
start, stop = interval["start"], interval["stop"]
|
80
|
-
if start
|
80
|
+
if start
|
81
81
|
stop ||= interval_end_when_start(start)
|
82
|
-
stop.to_i - start.to_i
|
82
|
+
stop.to_i - start.to_i
|
83
83
|
else
|
84
84
|
0
|
85
85
|
end
|
@@ -90,11 +90,11 @@ module Timert
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def is_date_correct?(timestamp)
|
93
|
-
!@date || Time.at(timestamp).to_date == @date
|
93
|
+
!@date || Time.at(timestamp).to_date == @date
|
94
94
|
end
|
95
95
|
|
96
96
|
def interval_end_when_start(timestamp)
|
97
|
-
day_is_today?(timestamp) ? Time.now.to_i : last_second_of_day(timestamp)
|
97
|
+
day_is_today?(timestamp) ? Time.now.to_i : last_second_of_day(timestamp)
|
98
98
|
end
|
99
99
|
|
100
100
|
def day_is_today?(timestamp)
|
@@ -103,7 +103,7 @@ module Timert
|
|
103
103
|
|
104
104
|
def last_second_of_day(timestamp)
|
105
105
|
time = Time.at(timestamp)
|
106
|
-
Time.new(time.year, time.month, time.day
|
106
|
+
Time.new(time.year, time.month, time.day, 23, 59, 60)
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
data/lib/timert/duration.rb
CHANGED
data/lib/timert/report.rb
CHANGED
@@ -5,49 +5,56 @@ require_relative 'duration'
|
|
5
5
|
|
6
6
|
module Timert
|
7
7
|
class Report
|
8
|
-
|
8
|
+
|
9
9
|
def self.generate(database, time_expression = "")
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
time_expression = time_expression.to_s
|
11
|
+
if time_expression.include?("month")
|
12
|
+
report_for_month(database, time_expression)
|
13
|
+
elsif time_expression.include?("week")
|
14
|
+
report_for_week(database, time_expression)
|
15
|
+
else
|
15
16
|
report_for_day(database, time_expression.to_i)
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
19
20
|
private
|
20
|
-
def self.report_for_week(database)
|
21
|
+
def self.report_for_week(database, time_expression = "")
|
22
|
+
week_nr = extract_time_modifier(time_expression)
|
21
23
|
today = Date.today
|
22
|
-
first = today - today.cwday
|
24
|
+
first = today - today.cwday + 1 + week_nr * 7
|
23
25
|
last = first + 6
|
24
|
-
|
26
|
+
|
27
|
+
title = week_nr != 0 ? "REPORT FOR WEEK #{format_date(first)} - #{format_date(last)}" : "REPORT FOR THIS WEEK"
|
28
|
+
"#{title}\n".blue +
|
25
29
|
report_for_range(Range.new(first, last), database)
|
26
30
|
end
|
27
31
|
|
28
|
-
def self.report_for_month(database)
|
32
|
+
def self.report_for_month(database, time_expression = "")
|
33
|
+
month_nr = extract_time_modifier(time_expression)
|
29
34
|
today = Date.today
|
30
|
-
first = Date.new(today.year, today.month, 1)
|
31
|
-
last = Date.new(today.year, today.month, -1)
|
32
|
-
|
35
|
+
first = Date.new(today.year, today.month, 1) << -month_nr
|
36
|
+
last = Date.new(today.year, today.month, -1) << -month_nr
|
37
|
+
|
38
|
+
title = month_nr != 0 ? "REPORT FOR MONTH #{format_month(first)}" : "REPORT FOR THIS MONTH"
|
39
|
+
"#{title}\n".blue +
|
33
40
|
report_for_range(Range.new(first, last), database)
|
34
41
|
end
|
35
42
|
|
36
43
|
def self.report_for_range(range, database)
|
37
44
|
days = database.days(range)
|
38
|
-
|
45
|
+
|
39
46
|
s = "\nDay/time elapsed\n".green
|
40
47
|
total_time, total_rounded_duration = 0, 0
|
41
|
-
|
48
|
+
|
42
49
|
days.each do |day|
|
43
50
|
duration = duration(day.total_elapsed_time)
|
44
|
-
s += "#{format_date(day.date)}: ".yellow +
|
51
|
+
s += "#{format_date(day.date)}: ".yellow +
|
45
52
|
"#{duration.to_s} / #{duration.round} " +
|
46
53
|
"(#{format_tasks(day)})\n"
|
47
54
|
total_time += duration.value
|
48
55
|
total_rounded_duration += duration.round.to_f
|
49
56
|
end
|
50
|
-
|
57
|
+
|
51
58
|
s += "\nTotal:\n".green
|
52
59
|
s += "#{parse_duration(total_time)} / #{total_rounded_duration}"
|
53
60
|
s
|
@@ -56,18 +63,18 @@ module Timert
|
|
56
63
|
def self.report_for_day(database, day_counter = 0)
|
57
64
|
date = Date.today + day_counter
|
58
65
|
day = database.day(date)
|
59
|
-
if day
|
60
|
-
"REPORT FOR #{format_date(date)}\n".blue +
|
61
|
-
"\nTasks:\n".green +
|
62
|
-
"#{format_tasks(day)}\n" +
|
63
|
-
"\nWork time:\n".green +
|
64
|
-
"#{format_intervals(day)}" +
|
65
|
-
"\nTotal elapsed time:\n".green +
|
66
|
-
"#{parse_duration(day.total_elapsed_time)}\n" +
|
67
|
-
"\nSummary:\n".red +
|
66
|
+
if day
|
67
|
+
"REPORT FOR #{format_date(date)}\n".blue +
|
68
|
+
"\nTasks:\n".green +
|
69
|
+
"#{format_tasks(day)}\n" +
|
70
|
+
"\nWork time:\n".green +
|
71
|
+
"#{format_intervals(day)}" +
|
72
|
+
"\nTotal elapsed time:\n".green +
|
73
|
+
"#{parse_duration(day.total_elapsed_time)}\n" +
|
74
|
+
"\nSummary:\n".red +
|
68
75
|
"#{round_duration(day.total_elapsed_time)} #{format_tasks(day)}"
|
69
76
|
else
|
70
|
-
"No data"
|
77
|
+
"No data"
|
71
78
|
end
|
72
79
|
end
|
73
80
|
|
@@ -77,18 +84,22 @@ module Timert
|
|
77
84
|
|
78
85
|
def self.format_intervals(day)
|
79
86
|
s = ""
|
80
|
-
day.intervals.each do |i|
|
87
|
+
day.intervals.each do |i|
|
81
88
|
start = DateUtil.format_hour(i["start"])
|
82
89
|
stop = DateUtil.format_hour(i["stop"])
|
83
90
|
s += "#{start} - #{stop}\n"
|
84
91
|
end
|
85
92
|
s
|
86
|
-
end
|
93
|
+
end
|
87
94
|
|
88
95
|
def self.format_date(date)
|
89
96
|
DateUtil.format_date(date)
|
90
97
|
end
|
91
98
|
|
99
|
+
def self.format_month(date)
|
100
|
+
DateUtil.format_month(date)
|
101
|
+
end
|
102
|
+
|
92
103
|
def self.parse_duration(duration)
|
93
104
|
duration(duration).to_s
|
94
105
|
end
|
@@ -100,5 +111,13 @@ module Timert
|
|
100
111
|
def self.round_duration(duration)
|
101
112
|
duration(duration).round
|
102
113
|
end
|
114
|
+
|
115
|
+
def self.extract_time_modifier(time_expression)
|
116
|
+
if time_expression.include?(" ")
|
117
|
+
time_expression.split(" ")[1].to_i
|
118
|
+
else
|
119
|
+
0
|
120
|
+
end
|
121
|
+
end
|
103
122
|
end
|
104
|
-
end
|
123
|
+
end
|
data/lib/timert/timer.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Timert
|
2
|
-
class Timer
|
2
|
+
class Timer
|
3
3
|
attr_reader :path, :today
|
4
4
|
|
5
5
|
def initialize(today)
|
@@ -9,7 +9,7 @@ module Timert
|
|
9
9
|
def start(time = nil)
|
10
10
|
if !on?
|
11
11
|
started = true
|
12
|
-
today.add_start(time || now)
|
12
|
+
today.add_start(time || now)
|
13
13
|
end
|
14
14
|
{time: today.last_start, started: started}
|
15
15
|
end
|
@@ -23,16 +23,16 @@ module Timert
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def add_task(task)
|
26
|
-
today.add_task(task)
|
26
|
+
today.add_task(task)
|
27
27
|
end
|
28
28
|
|
29
|
-
private
|
29
|
+
private
|
30
30
|
def now
|
31
31
|
Time.now.to_i
|
32
32
|
end
|
33
33
|
|
34
34
|
def on?
|
35
35
|
today.is_interval_started?
|
36
|
-
end
|
36
|
+
end
|
37
37
|
end
|
38
38
|
end
|
data/spec/application_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe Timert::Application do
|
|
7
7
|
let(:path) { './spec/data/timert' }
|
8
8
|
let(:database) { Timert::Database.new(Timert::DatabaseFile.new(path)) }
|
9
9
|
let(:app_with_no_args) { Timert::Application.new([], path) }
|
10
|
-
|
10
|
+
|
11
11
|
after(:each) do
|
12
12
|
File.delete(path)
|
13
13
|
end
|
@@ -21,13 +21,13 @@ describe Timert::Application do
|
|
21
21
|
context 'when initialized with start argument' do
|
22
22
|
before do
|
23
23
|
Timecop.freeze(Time.new(2013, 6, 12, 13, 56))
|
24
|
-
@app = Timert::Application.new(["start"], path)
|
24
|
+
@app = Timert::Application.new(["start"], path)
|
25
25
|
end
|
26
26
|
|
27
27
|
after do
|
28
28
|
Timecop.return
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
it 'should perform start operation' do
|
32
32
|
expect(database.today.last_start).to eq(Time.now.to_i)
|
33
33
|
end
|
@@ -39,13 +39,13 @@ describe Timert::Application do
|
|
39
39
|
context 'and then initialized with stop argument' do
|
40
40
|
before do
|
41
41
|
Timecop.freeze(Time.new(2013, 6, 12, 14, 34))
|
42
|
-
@app = Timert::Application.new(["stop"], path)
|
42
|
+
@app = Timert::Application.new(["stop"], path)
|
43
43
|
end
|
44
44
|
|
45
45
|
after do
|
46
46
|
Timecop.return
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
it 'should perform stop operation' do
|
50
50
|
expect(database.today.last_stop).to eq(Time.now.to_i)
|
51
51
|
end
|
@@ -92,18 +92,18 @@ describe Timert::Application do
|
|
92
92
|
|
93
93
|
it 'should start with given time' do
|
94
94
|
expect(database.today.last_start).to eq(Time.now.to_i - 60)
|
95
|
-
end
|
95
|
+
end
|
96
96
|
end
|
97
97
|
|
98
98
|
context 'when initialized with start and invalid time argument' do
|
99
|
-
before do
|
99
|
+
before do
|
100
100
|
Timecop.freeze(Time.new(2013, 1, 10, 15)) do
|
101
101
|
Timert::Application.new(["start"], path)
|
102
102
|
end
|
103
103
|
Timecop.freeze(Time.new(2013, 1, 10, 16)) do
|
104
104
|
Timert::Application.new(["stop"], path)
|
105
105
|
end
|
106
|
-
end
|
106
|
+
end
|
107
107
|
|
108
108
|
it 'should not raise an error' do
|
109
109
|
Timecop.freeze(2013, 1, 10, 17, 00) do
|
@@ -114,7 +114,7 @@ describe Timert::Application do
|
|
114
114
|
|
115
115
|
context 'when initialized with report argument' do
|
116
116
|
before do
|
117
|
-
@app = Timert::Application.new(["report"], path)
|
117
|
+
@app = Timert::Application.new(["report"], path)
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'should have a method that returns hash result' do
|
@@ -124,7 +124,7 @@ describe Timert::Application do
|
|
124
124
|
|
125
125
|
context 'when initialized with argument other than start, stop or report' do
|
126
126
|
before do
|
127
|
-
@app = Timert::Application.new(["testing the new app"], path)
|
127
|
+
@app = Timert::Application.new(["testing the new app"], path)
|
128
128
|
end
|
129
129
|
|
130
130
|
it 'should add task' do
|
@@ -134,7 +134,7 @@ describe Timert::Application do
|
|
134
134
|
context 'and then initialized with argument that fullfills the same requirements' do
|
135
135
|
before do
|
136
136
|
@app = Timert::Application.new(["writing emails"], path)
|
137
|
-
end
|
137
|
+
end
|
138
138
|
|
139
139
|
it 'should add another task' do
|
140
140
|
expect(database.today.tasks).to eq(["testing the new app", "writing emails"])
|
data/spec/database_file_spec.rb
CHANGED
data/spec/database_spec.rb
CHANGED
@@ -16,7 +16,7 @@ describe Timert::Database do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'should have a method for getting the current day' do
|
19
|
-
write_day = Timert::Day.new(tasks: ["emails"])
|
19
|
+
write_day = Timert::Day.new(tasks: ["emails"])
|
20
20
|
@db.save(write_day)
|
21
21
|
read_day = @db.day
|
22
22
|
expect(write_day.to_hash).to eq(read_day.to_hash)
|
@@ -24,7 +24,7 @@ describe Timert::Database do
|
|
24
24
|
|
25
25
|
it 'should have a method for getting one of the past days' do
|
26
26
|
write_day = Timecop.freeze(Time.new(2013, 8, 12, 12)) do
|
27
|
-
@db.save(Timert::Day.new(tasks: ["meeting"]))
|
27
|
+
@db.save(Timert::Day.new(tasks: ["meeting"]))
|
28
28
|
@db.day
|
29
29
|
end
|
30
30
|
read_day = Timecop.freeze(Time.new(2013, 8, 14, 12)) do
|
@@ -42,17 +42,17 @@ describe Timert::Database do
|
|
42
42
|
it 'should have a method for getting a range of days' do
|
43
43
|
first = Timert::Day.new(tasks: ["emails"], date: Date.new(2013, 9, 10))
|
44
44
|
second = Timert::Day.new(tasks: ["meetings"], date: Date.new(2013, 9, 11))
|
45
|
-
|
45
|
+
|
46
46
|
past = Timecop.freeze(first.date) do
|
47
47
|
@db.save(first)
|
48
48
|
Date.today - 5
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
present = Timecop.freeze(second.date) do
|
52
52
|
@db.save(second)
|
53
53
|
Date.today
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
expect(@db.days(Range.new(past, present))).to eq([first, second])
|
57
57
|
end
|
58
58
|
end
|
data/spec/date_util_spec.rb
CHANGED
@@ -11,6 +11,10 @@ describe Timert::DateUtil do
|
|
11
11
|
expect(Timert::DateUtil.format_date(Date.new(2013, 3, 14))).to eq("2013-03-14")
|
12
12
|
end
|
13
13
|
|
14
|
+
it 'should return formatted month' do
|
15
|
+
expect(Timert::DateUtil.format_month(Date.new(2013, 1, 22))).to eq("2013-01")
|
16
|
+
end
|
17
|
+
|
14
18
|
it 'should parse time' do
|
15
19
|
Timecop.freeze(Time.new(2013, 2, 28)) do
|
16
20
|
expect(Timert::DateUtil.parse_time("11:14")).to eq(Time.new(2013, 2, 28, 11, 14).to_i)
|
data/spec/day_spec.rb
CHANGED
@@ -6,7 +6,7 @@ require_relative '../lib/timert/day'
|
|
6
6
|
describe Timert::Day do
|
7
7
|
let(:now) { Time.now.to_i}
|
8
8
|
let(:day) { Timert::Day.new }
|
9
|
-
|
9
|
+
|
10
10
|
it 'should have method intervals that returns array' do
|
11
11
|
expect(day.intervals.instance_of?(Array)).to eq(true)
|
12
12
|
end
|
@@ -18,7 +18,7 @@ describe Timert::Day do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'should have a method intervals that returns an array with start and stop times' do
|
21
|
-
expect(day.intervals).to eq([{"start" => now, "stop" => now + 100}])
|
21
|
+
expect(day.intervals).to eq([{"start" => now, "stop" => now + 100}])
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'should have a method that returns total elapsed time' do
|
@@ -36,7 +36,7 @@ describe Timert::Day do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'should have a method that returns the time of the last start' do
|
39
|
-
expect(day.last_start).to eq(now)
|
39
|
+
expect(day.last_start).to eq(now)
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'should have a method that returns the time of the last stop' do
|
@@ -57,13 +57,13 @@ describe Timert::Day do
|
|
57
57
|
day.add_start(Time.new(2013, 6, 10, 12, 34).to_i)
|
58
58
|
day.add_stop(Time.new(2013, 6, 10, 14, 51, 10).to_i)
|
59
59
|
day.add_start(Time.new(2013, 6, 10, 16, 10, 20).to_i)
|
60
|
-
day.add_stop(Time.new(2013, 6, 10, 17, 15, 41).to_i)
|
60
|
+
day.add_stop(Time.new(2013, 6, 10, 17, 15, 41).to_i)
|
61
61
|
expect(day.total_elapsed_time).to eq(duration(3, 22, 31))
|
62
62
|
end
|
63
63
|
|
64
64
|
context "when calculating total elapsed time and when last interval isn't finished" do
|
65
65
|
let(:now) { Time.new(2013, 6, 10, 18, 10) }
|
66
|
-
|
66
|
+
|
67
67
|
context 'and the day is today' do
|
68
68
|
let(:start_of_work) { Time.new(2013, 6, 10, 12, 0) }
|
69
69
|
|
@@ -86,11 +86,23 @@ describe Timert::Day do
|
|
86
86
|
expect(day.total_elapsed_time).to eq(duration(10, 30, 0))
|
87
87
|
end
|
88
88
|
end
|
89
|
+
|
90
|
+
context "and yesterday was the last day of the year" do
|
91
|
+
let(:new_years_eve) { Time.new(2013, 12, 31, 12, 30) }
|
92
|
+
let(:new_year) { Time.new(2014, 1, 1, 11, 0) }
|
93
|
+
|
94
|
+
it "should not raise an error" do
|
95
|
+
day.add_start(new_years_eve.to_i)
|
96
|
+
Timecop.freeze(new_year) do
|
97
|
+
expect{ day.total_elapsed_time }.not_to raise_error
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
89
101
|
end
|
90
102
|
end
|
91
103
|
|
92
104
|
it 'should have tasks method that returns an array' do
|
93
|
-
expect(day.tasks.instance_of?(Array)).to eq(true)
|
105
|
+
expect(day.tasks.instance_of?(Array)).to eq(true)
|
94
106
|
end
|
95
107
|
|
96
108
|
it 'should add tasks' do
|
@@ -101,16 +113,16 @@ describe Timert::Day do
|
|
101
113
|
|
102
114
|
context 'after initialized with hash data' do
|
103
115
|
let(:valid_params) do
|
104
|
-
{
|
116
|
+
{
|
105
117
|
intervals: [{"start" => now, "stop" => now + 300}],
|
106
118
|
tasks: ["debugging", "emails"],
|
107
119
|
date: Time.now.to_date
|
108
|
-
}
|
120
|
+
}
|
109
121
|
end
|
110
122
|
|
111
123
|
let(:day) { Timert::Day.new(valid_params) }
|
112
124
|
|
113
|
-
it "should raise error if tasks aren't an array" do
|
125
|
+
it "should raise error if tasks aren't an array" do
|
114
126
|
expect { Timert::Day.new(valid_params.merge(tasks: "mails")) }.to raise_error
|
115
127
|
end
|
116
128
|
|
@@ -123,19 +135,19 @@ describe Timert::Day do
|
|
123
135
|
end
|
124
136
|
|
125
137
|
it 'should have a method tasks that returns an array of tasks' do
|
126
|
-
expect(day.tasks).to eq(["debugging", "emails"])
|
138
|
+
expect(day.tasks).to eq(["debugging", "emails"])
|
127
139
|
end
|
128
140
|
|
129
141
|
it "should have a method that returns the day's date" do
|
130
|
-
expect(day.date).to eq(Time.now.to_date)
|
142
|
+
expect(day.date).to eq(Time.now.to_date)
|
131
143
|
end
|
132
144
|
|
133
145
|
it "should have to_hash method that returns day's state" do
|
134
146
|
hash = {
|
135
147
|
"intervals" => [{"start" => now, "stop" => now + 300}],
|
136
|
-
"tasks" => ["debugging", "emails"]
|
148
|
+
"tasks" => ["debugging", "emails"]
|
137
149
|
}
|
138
|
-
expect(day.to_hash).to eq(hash)
|
150
|
+
expect(day.to_hash).to eq(hash)
|
139
151
|
end
|
140
152
|
end
|
141
153
|
|
@@ -186,7 +198,7 @@ describe Timert::Day do
|
|
186
198
|
context "when it's initialized with date" do
|
187
199
|
let(:day) { Timert::Day.new(date: Date.new(2013, 5, 12)) }
|
188
200
|
before do
|
189
|
-
Timecop.freeze(Time.new(2013, 5, 12, 12, 30))
|
201
|
+
Timecop.freeze(Time.new(2013, 5, 12, 12, 30))
|
190
202
|
end
|
191
203
|
|
192
204
|
after do
|
@@ -198,7 +210,7 @@ describe Timert::Day do
|
|
198
210
|
end
|
199
211
|
|
200
212
|
it "should raise error if a stop time with a different date is added" do
|
201
|
-
day.add_start(now)
|
213
|
+
day.add_start(now)
|
202
214
|
expect { day.add_stop(Time.new(2013, 6, 14, 12).to_i) }.to raise_error
|
203
215
|
end
|
204
216
|
end
|
@@ -206,7 +218,7 @@ describe Timert::Day do
|
|
206
218
|
context "when a task is added more than once" do
|
207
219
|
before do
|
208
220
|
day.add_task("mails")
|
209
|
-
day.add_task("mails")
|
221
|
+
day.add_task("mails")
|
210
222
|
end
|
211
223
|
|
212
224
|
it "should ignore it" do
|
data/spec/duration_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative '../lib/timert/duration'
|
2
2
|
|
3
3
|
describe Timert::Duration do
|
4
|
-
|
4
|
+
|
5
5
|
it 'should have a method that returns the number of hours' do
|
6
6
|
expect(Timert::Duration.new(3 * 60 * 60 + 2 * 60).hours).to eq(3)
|
7
7
|
end
|
@@ -21,8 +21,8 @@ describe Timert::Duration do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'should return formatted total elapsed time' do
|
24
|
-
expect(Timert::Duration.from(5, 45, 5).to_s).to eq("5h 45min 5sec")
|
25
|
-
expect(Timert::Duration.from(15, 0, 56).to_s).to eq("15h 0min 56sec")
|
24
|
+
expect(Timert::Duration.from(5, 45, 5).to_s).to eq("5h 45min 5sec")
|
25
|
+
expect(Timert::Duration.from(15, 0, 56).to_s).to eq("15h 0min 56sec")
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'should have a method that returns rounded duration when a full-hour duration is passed' do
|
data/spec/report_spec.rb
CHANGED
@@ -3,52 +3,74 @@ require 'timecop'
|
|
3
3
|
require_relative '../lib/timert/report'
|
4
4
|
|
5
5
|
describe Timert::Report do
|
6
|
-
let(:
|
7
|
-
let(:
|
6
|
+
let(:monday) { Date.new(2013, 2, 18) }
|
7
|
+
let(:tuesday) { Date.new(2013, 2, 19) }
|
8
|
+
let(:wednesday) { Date.new(2013, 2, 20) }
|
9
|
+
let(:sunday) { Date.new(2013, 2, 24) }
|
10
|
+
let(:last_monday) { Date.new(2013, 2, 11) }
|
11
|
+
let(:last_sunday) { Date.new(2013, 2, 17) }
|
12
|
+
let(:last_month) { Date.new(2013, 1, 10) }
|
8
13
|
let(:database) { double }
|
9
14
|
|
10
15
|
let(:first_day) do
|
11
|
-
double(total_elapsed_time: 3.5 * 3600,
|
12
|
-
date:
|
16
|
+
double(total_elapsed_time: 3.5 * 3600,
|
17
|
+
date: wednesday,
|
13
18
|
tasks: ["emails", "meeting"],
|
14
19
|
intervals: [
|
15
|
-
{"start" => time(
|
16
|
-
{"start" => time(
|
20
|
+
{"start" => time(wednesday, 16), "stop" => time(wednesday, 18, 30)},
|
21
|
+
{"start" => time(wednesday, 19), "stop" => time(wednesday, 20)}
|
17
22
|
])
|
18
23
|
end
|
19
24
|
|
20
25
|
let(:second_day) do
|
21
|
-
double(total_elapsed_time: 7 * 3600,
|
22
|
-
date:
|
26
|
+
double(total_elapsed_time: 7 * 3600,
|
27
|
+
date: tuesday,
|
23
28
|
tasks: ["reports", "bugs"],
|
24
29
|
intervals: [
|
25
|
-
{"start" => time(
|
26
|
-
{"start" => time(
|
30
|
+
{"start" => time(tuesday, 11, 30), "stop" => time(tuesday, 16)},
|
31
|
+
{"start" => time(tuesday, 16, 30), "stop" => time(tuesday, 19, 30)}
|
32
|
+
])
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:third_day) do
|
36
|
+
double(total_elapsed_time: 2 * 3600,
|
37
|
+
date: sunday,
|
38
|
+
tasks: ["code review"],
|
39
|
+
intervals: [
|
40
|
+
{"start" => time(sunday, 20, 15), "stop" => time(sunday, 22, 15)}
|
41
|
+
])
|
42
|
+
end
|
43
|
+
|
44
|
+
let(:last_month_day) do
|
45
|
+
double(total_elapsed_time: 4 * 3600,
|
46
|
+
date: last_month,
|
47
|
+
tasks: ["article"],
|
48
|
+
intervals: [
|
49
|
+
{"start" => time(last_month, 14, 15), "stop" => time(last_month, 18, 15)}
|
27
50
|
])
|
28
51
|
end
|
29
52
|
|
30
53
|
before(:each) do
|
31
|
-
Timecop.freeze(
|
54
|
+
Timecop.freeze(sunday)
|
32
55
|
end
|
33
56
|
|
34
57
|
after(:each) do
|
35
|
-
Timecop.return
|
58
|
+
Timecop.return
|
36
59
|
end
|
37
60
|
|
38
|
-
it 'should generate report for
|
39
|
-
database.should_receive(:day).with(
|
40
|
-
|
61
|
+
it 'should generate report for Sunday' do
|
62
|
+
database.should_receive(:day).with(sunday).and_return(third_day)
|
63
|
+
|
41
64
|
report = Timert::Report.generate(database)
|
42
|
-
expect(report.include?("2013-02-
|
43
|
-
expect(report.include?("
|
44
|
-
expect(report.include?("
|
45
|
-
expect(report.include?("3.5")).to eq(true)
|
65
|
+
expect(report.include?("2013-02-24")).to eq(true)
|
66
|
+
expect(report.include?("code review")).to eq(true)
|
67
|
+
expect(report.include?("2")).to eq(true)
|
46
68
|
end
|
47
69
|
|
48
|
-
it 'should generate report for any past day' do
|
49
|
-
database.should_receive(:day).with(
|
70
|
+
it 'should generate report for any past day' do
|
71
|
+
database.should_receive(:day).with(tuesday).and_return(second_day)
|
50
72
|
|
51
|
-
report = Timert::Report.generate(database, -
|
73
|
+
report = Timert::Report.generate(database, -5)
|
52
74
|
expect(report.include?("2013-02-19")).to eq(true)
|
53
75
|
expect(report.include?("reports")).to eq(true)
|
54
76
|
expect(report.include?("bugs")).to eq(true)
|
@@ -56,25 +78,49 @@ describe Timert::Report do
|
|
56
78
|
end
|
57
79
|
|
58
80
|
it 'should generate report for this week' do
|
59
|
-
database.should_receive(:days).and_return([first_day, second_day])
|
81
|
+
database.should_receive(:days).and_return([first_day, second_day, third_day])
|
82
|
+
Range.should_receive(:new).with(monday, sunday)
|
60
83
|
|
61
84
|
report = Timert::Report.generate(database, "week")
|
62
85
|
expect(report.include?("WEEK")).to eq(true)
|
63
86
|
expect(report.include?("2013-02-19")).to eq(true)
|
64
87
|
expect(report.include?("2013-02-20")).to eq(true)
|
88
|
+
expect(report.include?("2013-02-24")).to eq(true)
|
65
89
|
expect(report.include?("Total")).to eq(true)
|
90
|
+
expect(report.include?("12.5")).to eq(true)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should generate report for any past week' do
|
94
|
+
database.should_receive(:days).and_return([first_day, second_day])
|
95
|
+
Range.should_receive(:new).with(last_monday, last_sunday)
|
96
|
+
|
97
|
+
report = Timert::Report.generate(database, "week -1")
|
98
|
+
expect(report.include?("WEEK")).to eq(true)
|
99
|
+
expect(report.include?("2013-02-11")).to eq(true)
|
100
|
+
expect(report.include?("2013-02-17")).to eq(true)
|
66
101
|
expect(report.include?("10.5")).to eq(true)
|
67
102
|
end
|
68
103
|
|
69
104
|
it 'should generate report for this month' do
|
70
|
-
database.should_receive(:days).and_return([first_day, second_day])
|
105
|
+
database.should_receive(:days).and_return([first_day, second_day, third_day])
|
71
106
|
|
72
107
|
report = Timert::Report.generate(database, "month")
|
73
108
|
expect(report.include?("MONTH")).to eq(true)
|
74
109
|
expect(report.include?("2013-02-19")).to eq(true)
|
75
110
|
expect(report.include?("2013-02-20")).to eq(true)
|
111
|
+
expect(report.include?("2013-02-24")).to eq(true)
|
76
112
|
expect(report.include?("Total")).to eq(true)
|
77
|
-
expect(report.include?("
|
113
|
+
expect(report.include?("12.5")).to eq(true)
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should generate report for any past month' do
|
117
|
+
database.should_receive(:days).and_return([last_month_day])
|
118
|
+
|
119
|
+
report = Timert::Report.generate(database, "month -1")
|
120
|
+
expect(report.include?("MONTH 2013-01")).to eq(true)
|
121
|
+
expect(report.include?("2013-01-10")).to eq(true)
|
122
|
+
expect(report.include?("article")).to eq(true)
|
123
|
+
expect(report.include?("4")).to eq(true)
|
78
124
|
end
|
79
125
|
|
80
126
|
def time(day, hours, minutes = 0, seconds = 0)
|
data/spec/timer_spec.rb
CHANGED
@@ -7,9 +7,9 @@ describe Timert::Timer do
|
|
7
7
|
before(:each) do
|
8
8
|
@today = Timert::Day.new
|
9
9
|
@timer = Timert::Timer.new(@today)
|
10
|
-
end
|
10
|
+
end
|
11
11
|
|
12
|
-
it 'should return start time when started' do
|
12
|
+
it 'should return start time when started' do
|
13
13
|
Timecop.freeze(Time.new(2013, 2, 14, 22, 0)) do
|
14
14
|
expect(@timer.start[:time]).to eq(Time.now.to_i)
|
15
15
|
end
|
@@ -31,16 +31,16 @@ describe Timert::Timer do
|
|
31
31
|
expect(@timer.start(time + 10)[:started]).not_to eq(true)
|
32
32
|
@timer.stop
|
33
33
|
expect(@timer.start(time + 10)[:started]).to eq(true)
|
34
|
-
end
|
34
|
+
end
|
35
35
|
|
36
36
|
context 'and then stopped' do
|
37
|
-
it 'should return stop time' do
|
37
|
+
it 'should return stop time' do
|
38
38
|
Timecop.freeze(Time.new(2013, 2, 14, 23, 0)) do
|
39
|
-
expect(@timer.stop[:time]).to eq(Time.now.to_i)
|
39
|
+
expect(@timer.stop[:time]).to eq(Time.now.to_i)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
|
-
end
|
43
|
+
end
|
44
44
|
|
45
45
|
context 'while not running' do
|
46
46
|
it "should not stop until it's started" do
|
@@ -48,7 +48,7 @@ describe Timert::Timer do
|
|
48
48
|
@timer.start
|
49
49
|
expect(@timer.stop[:stopped]).to eq(true)
|
50
50
|
end
|
51
|
-
end
|
51
|
+
end
|
52
52
|
|
53
53
|
it 'should be able to start with given time' do
|
54
54
|
time = Time.now.to_i
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.1'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gosia Kwidzinska
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ! '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: guard-rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: timecop
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|