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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MmI5ZjA5YWRlZjg1ZTIyODMwY2EyMzE4YWFmNjIyZmYxNTNkZjU0Ng==
4
+ NjE3MmI2YWFkMTgzYzgwMDE3Zjg3NDI3NjIzNDM3ZThkYWM5NWM3MQ==
5
5
  data.tar.gz: !binary |-
6
- OGNlMDgyNzY2MDU0ODIxMmQ2NzBhZWZlOTMzMjU5MTA3OWY3NGE1Nw==
6
+ ZTUyMzMzOWY4YmNhZjU2MjUwMDA4YmQ1MTk4ZWYxZTc0MjBlYmU2Zg==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- MzQ0NGU2ODI2YzYxNjNhMTNkNjExN2NjZTNkMjg0NWJlNTFkZjNlYTJlNzIw
10
- MWIwMTlmZWM3ZGFhNDM3MTc4ODhhZmU2NjdhMGQwYTY5NjQxMTJiMzY4YjVm
11
- OTc3NDVhZjAyZWRlMjhhYjRiOTE3YTE5YmY3NTE5MjE1YzE3YzM=
9
+ ZWE0NzQ4OGE1OWIxNTE3YWE3ZmEyZTlkMDMxYjYyNWIzZjM1ZjMxMzNkYjJl
10
+ ZTkzZTcxYjUwZWEwZWM5ZGM5Yjc3YzNmMTM3ZDMwOTk2MDFkODhmNzk5OTQ5
11
+ MDdkMWQ0NzQwYjAyYmJiZmQwNTU1MmU3MmY2ZDg3NDc2ZGU4ZWQ=
12
12
  data.tar.gz: !binary |-
13
- NjFmYTE0ZDNmNzcwNzRkMDNkMGFjNmYyNjg0OTJkN2ZkYTBlNTY1Njk5Yjk4
14
- MTNiNzhmZDI3MGJlOTNhZGUyMWQyNmRjNWIwOWRlNTIyZGI3NmQ0MzA1YTg3
15
- ODUyODQ0MTY0ZWRjMTBlOTY3YjhmY2FlMzgzZDc1NDYwZmE0MWE=
13
+ NDFiNmRmZThmNDVjYjFiNzc1N2M0YzlmMWQ2ZjNhYWRjODAwOWRjNDBkMjA4
14
+ MGFlOTI5ZTBkNjIzNzYxMTA5ZGI3NDZiNGIwNmIwYzBjZTBiNmNlZjU5Y2Iw
15
+ M2M5NjRmNDc2OGE5YzQ3NWM2N2YwZDU5NTMxOTZhOTgxNDliZDY=
@@ -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, arg)
25
+ def api_argument(action, *args)
26
26
  if is_time_method?(action)
27
- parse_time(arg)
27
+ parse_time(args[0])
28
28
  elsif is_report?(action)
29
- parse_report_arg(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?(arg)
42
- arg == "month" || arg == "week"
41
+ def is_month_or_week?(args)
42
+ args.include?("month") || args.include?("week")
43
43
  end
44
44
 
45
- def parse_report_arg(arg)
46
- is_month_or_week?(arg) ? arg : arg.to_i
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)
@@ -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
@@ -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(":")
@@ -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 + 1, 0)
106
+ Time.new(time.year, time.month, time.day, 23, 59, 60)
107
107
  end
108
108
  end
109
109
  end
@@ -2,7 +2,7 @@ module Timert
2
2
  class Duration
3
3
  attr_reader :hours, :minutes, :seconds, :value
4
4
 
5
- def initialize(duration)
5
+ def initialize(duration)
6
6
  @hours = duration / 3600
7
7
  @minutes = (duration % 3600) / 60
8
8
  @seconds = duration % 60
@@ -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
- if time_expression == "month"
11
- report_for_month(database)
12
- elsif time_expression == "week"
13
- report_for_week(database)
14
- else
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
- "REPORT FOR THIS WEEK\n".blue +
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
- "REPORT FOR THIS MONTH\n".blue +
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
@@ -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
@@ -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"])
@@ -10,7 +10,7 @@ describe Timert::DatabaseFile do
10
10
  after(:each) do
11
11
  File.delete(path)
12
12
  end
13
-
13
+
14
14
  it "should load data that's been saved" do
15
15
  data = {
16
16
  "example" => "This is a sample data."
@@ -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
@@ -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)
@@ -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
@@ -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
@@ -3,52 +3,74 @@ require 'timecop'
3
3
  require_relative '../lib/timert/report'
4
4
 
5
5
  describe Timert::Report do
6
- let(:today) { Date.new(2013, 2, 20) }
7
- let(:yesteday) { Date.new(2013, 2, 19) }
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: today,
16
+ double(total_elapsed_time: 3.5 * 3600,
17
+ date: wednesday,
13
18
  tasks: ["emails", "meeting"],
14
19
  intervals: [
15
- {"start" => time(today, 16), "stop" => time(today, 18, 30)},
16
- {"start" => time(today, 19), "stop" => time(today, 20)}
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: yesteday,
26
+ double(total_elapsed_time: 7 * 3600,
27
+ date: tuesday,
23
28
  tasks: ["reports", "bugs"],
24
29
  intervals: [
25
- {"start" => time(yesteday, 11, 30), "stop" => time(yesteday, 16)},
26
- {"start" => time(yesteday, 16, 30), "stop" => time(yesteday, 19, 30)}
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(today)
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 today' do
39
- database.should_receive(:day).with(today).and_return(first_day)
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-20")).to eq(true)
43
- expect(report.include?("emails")).to eq(true)
44
- expect(report.include?("meeting")).to eq(true)
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(yesteday).and_return(second_day)
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, -1)
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?("10.5")).to eq(true)
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)
@@ -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.0.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: 2013-07-30 00:00:00.000000000 Z
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