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 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