Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--color
--format documentation
25 changes: 13 additions & 12 deletions lib/punchcard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class PunchCard
HOURLY_RATE_PATTERN = /^\s*(\d+)([^\d]+)*\s*/i.freeze
TIME_POINT_PATTERN = /^((\d+|.+?\s[\+\-]\d{4}?\s*)(\-)*(\d+|\s.+\d?)*)$/.freeze
META_KEY_PATTERN = /^([a-zA-Z0-9]+)\:\s*(.*)$/.freeze
VERSION = '1.3.3'
VERSION = '1.4.0'

attr_accessor :title

Expand Down Expand Up @@ -149,7 +149,7 @@ def rename(new_project_name)
old_filename = project_filename
data = project_data
data[0] = new_project_name
write_string_to_project_file! data.join("\n")
write_string_to_project_file! data.join("\n").chomp
self.project = new_project_name
File.rename(old_filename, project_filename) && "#{old_filename} -> #{project_filename}"
end
Expand Down Expand Up @@ -272,7 +272,7 @@ def end_time
end

def time_points
line_to_time_points last_entry
line_to_time_points(last_entry) if last_entry
end

def line_to_time_points(line)
Expand All @@ -290,10 +290,7 @@ def string_to_timestamp(str)
return str if str.nil?

str.strip!
# here some legacy… previous versions stored timestamp,
# but now punched stores date-time strings for better readability.
# So we have to convert timestamp and date-time format into timestamp
str =~ /^\d+$/ ? str.to_i : (str =~ /^\d{4}\-\d/ ? Time.parse(str).to_i : nil)
str =~ /^\d{4}\-\d/ ? Time.parse(str).to_i : nil
end

def last_entry
Expand All @@ -316,7 +313,7 @@ def read_project_data
line.strip!
next if line.start_with?('#')

if i.zero? && !line.match(TIME_POINT_PATTERN)
if i.zero? && !line.empty? && !line.match(TIME_POINT_PATTERN)
title = line
elsif line.match(META_KEY_PATTERN)
set line.match(META_KEY_PATTERN)[1], line.match(META_KEY_PATTERN)[2]
Expand All @@ -339,17 +336,17 @@ def project_data_without_comments
end

def write_string_to_project_file!(string)
File.open(project_file, 'w') { |f| f.write(string) }
File.write(project_file, string ? string.chomp : '')
end

def write_to_project_file!
timestamps = project_data.select { |line| line.match(TIME_POINT_PATTERN) }
meta_data_lines = @meta_data.map { |key, value| "#{key}: #{value}" }
write_string_to_project_file! [@project, meta_data_lines.join("\n"), timestamps].reject(&:empty?).join("\n")
write_string_to_project_file! [project_name_if_differs_from_filename || '', meta_data_lines.join("\n"), timestamps].reject(&:empty?).join("\n")
end

def append_new_line(line)
open(project_file, 'a') { |f| f.puts("\n" + line.to_s.strip) }
File.open(project_file, 'a') { |f| f.puts("\n#{line.to_s.strip}") }
end

def replace_last_line(line)
Expand All @@ -371,10 +368,14 @@ def project_exist?
end

def find_or_make_file
write_string_to_project_file!(@project + "\n") unless project_exist?
write_string_to_project_file!(project_name_if_differs_from_filename) unless project_exist?
self.title ||= project_data.first
end

def project_name_if_differs_from_filename
@project != File.basename(project_file) ? @project : nil
end

def find_or_make_settings_dir
Dir.mkdir(SETTINGS_DIR) unless File.exist?(SETTINGS_DIR)
end
Expand Down
39 changes: 24 additions & 15 deletions spec/punchcard_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,25 @@ def two_seconds_tracking
example_project
end

it 'should create a new PunchCard object' do
it 'creates a new project / PunchCard object' do
expect(example_project).to be_a(PunchCard)
end

it 'should start a project' do
it 'starts a project' do
example_project.start
end

it 'should start and stop a project' do
it 'starts and stops a project' do
start_and_stop
end

it 'should track a project time' do
it 'tracks project time' do
start_and_stop
expect(my_project_file.lines.first.strip).to eq('My Project')
expect(my_project_file.lines.last.strip).to match(/^\d+-\d+-\d+ .+? - \d+-\d+-\d+ /)
end

it 'should calculate tracked total time' do
it 'calculates tracked total time' do
project = two_seconds_tracking
tracked_time = project.details.lines.last.match(/^\d{2}\:\d{2}\:(\d{2}).*total/)[1].to_i
expect(tracked_time).to be_between 1, 3
Expand All @@ -73,7 +73,7 @@ def two_seconds_tracking
expect(tracked_time).to be_between 3, 5
end

it 'should toggle' do
it 'toggles project status (start + stop)' do
project = start_and_stop
expect(project.status.lines.first).to match /stopped/
project.toggle
Expand All @@ -91,20 +91,20 @@ def two_seconds_tracking
expect(my_project_file).to match("\n# A comment line")
end

it 'should convert names to underscore with special characters' do
it 'converts names to underscore with special characters' do
PunchCard.new 'Playing Motörhead'
expect(my_project_file('playing_mot_rhead').strip).to eq('Playing Motörhead')
project = PunchCard.new 'Playing*'
expect(project.project).to eq('playing_mot_rhead')
end

it 'should set hourlyRate' do
it 'sets hourlyRate' do
project = start_and_stop
project.set 'hourlyRate', '1000 €'
expect(my_project_file.lines[1].strip).to eq('hourlyRate: 1000 €')
expect(my_project_file.lines.first.chomp).to eq('hourlyRate: 1000 €')
end

it 'should calculate earnings' do
it 'calculates earnings' do
project = start_and_stop
project.set 'hourlyRate', '1000EURO'
project.toggle
Expand All @@ -116,7 +116,7 @@ def two_seconds_tracking
expect(project.csv).to match /^"My Project \[my_project\]","stopped","[0-9\-\s\:]+?","[0-9\:]+?","1000.0 EURO","1\.\d+ EURO"$/
end

it 'should track different projects simultanously' do
it 'tracks different projects simultanously' do
project_a = random_project
project_b = random_project
expect(project_a.project).not_to eq(project_b.project)
Expand All @@ -129,7 +129,16 @@ def two_seconds_tracking
expect(project_b.total.to_i - project_a.total.to_i).to be_between(2, 4)
end

it 'should load latest project by wildcard' do
it 'stores title correctly if differs from filename' do
project = random_project
project.start
sleep 2
project.stop
project = random_project
expect(project.title).to start_with('My random Project ')
end

it 'loads latest project by wildcard' do
project_a = random_project
project = PunchCard.new 'My random*'
expect(project.project).to eq(project_a.project)
Expand All @@ -140,7 +149,7 @@ def two_seconds_tracking
expect(project.project).not_to eq(project_a.project)
end

it 'should rename' do
it 'renames project' do
project = example_project
content = my_project_file
project.rename 'Renamed Project'
Expand All @@ -156,14 +165,14 @@ def two_seconds_tracking
expect(File.exist?("#{example_settings_dir}/renamed_project")).to be_falsey
end

it 'should remove' do
it 'removes project' do
project = example_project
expect(File.exist?("#{example_settings_dir}/my_project")).to be_truthy
project.remove
expect(File.exist?("#{example_settings_dir}/my_project")).to be_falsey
end

it 'should call punched all' do
it 'show all projects' do
two_seconds_tracking
result = `#{punched_bin} all`
expect(result).to match('My Project')
Expand Down