timert 1.0.1 → 1.1
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.
- 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
|