trello_effort_tracker 0.0.3 → 0.0.4

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.
Files changed (37) hide show
  1. data/.gitignore +2 -1
  2. data/.travis.yml +0 -1
  3. data/CHANGELOG +17 -0
  4. data/Gemfile +7 -4
  5. data/Gemfile.lock +27 -13
  6. data/README.md +106 -36
  7. data/Rakefile +1 -1
  8. data/config/config.template.yml +0 -1
  9. data/config/config.yml.trackinguser_for_test +7 -0
  10. data/lib/patches/trello/card.rb +19 -0
  11. data/lib/patches/trello/member.rb +5 -5
  12. data/lib/trello_effort_tracker/tracked_card.rb +17 -10
  13. data/lib/trello_effort_tracker/tracking/base.rb +82 -0
  14. data/lib/trello_effort_tracker/tracking/card_done_tracking.rb +10 -0
  15. data/lib/trello_effort_tracker/tracking/effort_tracking.rb +45 -0
  16. data/lib/trello_effort_tracker/tracking/estimate_tracking.rb +23 -0
  17. data/lib/trello_effort_tracker/tracking/invalid_tracking.rb +19 -0
  18. data/lib/trello_effort_tracker/tracking_factory.rb +22 -0
  19. data/lib/trello_effort_tracker/trello_authorize.rb +4 -20
  20. data/lib/trello_effort_tracker/trello_tracker.rb +5 -10
  21. data/lib/trello_effort_tracker/version.rb +1 -1
  22. data/lib/trello_effort_tracker.rb +7 -1
  23. data/spec/integration/trello_tracker_spec.rb +69 -0
  24. data/spec/patches/trello/card_spec.rb +25 -0
  25. data/spec/spec_helper.rb +46 -1
  26. data/spec/support/database_cleaner.rb +12 -0
  27. data/spec/tracked_card_spec.rb +56 -5
  28. data/spec/tracking/card_done_tracking_spec.rb +18 -0
  29. data/spec/tracking/effort_tracking_spec.rb +114 -0
  30. data/spec/tracking/estimate_tracking_spec.rb +44 -0
  31. data/spec/tracking_factory_spec.rb +42 -0
  32. data/spec/trello_authorize_spec.rb +10 -16
  33. data/spec/trello_configuration_spec.rb +2 -2
  34. data/trello_effort_tracker.gemspec +12 -0
  35. metadata +131 -5
  36. data/lib/trello_effort_tracker/tracking.rb +0 -130
  37. data/spec/tracking_spec.rb +0 -236
@@ -0,0 +1,23 @@
1
+ module Tracking
2
+ class EstimateTracking
3
+ include Base
4
+
5
+ #TODO: rename to 'amount' ?
6
+ #TODO: avoid recomputing estimate every time using a lazy instance variable
7
+ def estimate
8
+ estimate = convert_to_hours(raw_estimate)
9
+ Estimate.new(amount: estimate, date: date, tracking_notification_id: tracking_notification.id)
10
+ end
11
+
12
+ def add_to(card)
13
+ card.estimates << estimate unless card.contains_estimate?(estimate)
14
+ end
15
+
16
+ private
17
+
18
+ def raw_estimate
19
+ extract_match_from_raw_tracking(/\[#{DURATION_REGEXP}\]/)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ module Tracking
2
+ class InvalidTracking
3
+ include Base
4
+
5
+ def add_to(card)
6
+ # do nothing
7
+ Trello.logger.warn "Ignoring tracking notification: '#{raw_text}'"
8
+ end
9
+
10
+ def estimate
11
+ nil
12
+ end
13
+
14
+ def effort
15
+ nil
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ class TrackingFactory
2
+
3
+ DURATION_REGEXP = '(\d+\.?\d*[phdg])'
4
+
5
+ @match_pairs = {}
6
+
7
+ def self.match(match_pair)
8
+ @match_pairs.merge!(match_pair)
9
+ end
10
+
11
+ def self.build_from(tracking_notification)
12
+ matching_pair = @match_pairs.find { |regexp, tracking_class| tracking_notification.data['text'] =~ regexp }
13
+
14
+ tracking_class = matching_pair ? matching_pair.last : Tracking::InvalidTracking
15
+ tracking_class.new(tracking_notification)
16
+ end
17
+
18
+ match /\[#{DURATION_REGEXP}\]/ => Tracking::EstimateTracking
19
+ match /\+#{DURATION_REGEXP}/ => Tracking::EffortTracking
20
+ match /DONE/ => Tracking::CardDoneTracking
21
+
22
+ end
@@ -3,30 +3,14 @@ module TrelloAuthorize
3
3
  include Trello::Authorization
4
4
 
5
5
  def authorize_on_trello(auth_params={})
6
- %w{developer_public_key access_token_key developer_secret}.each do |key|
6
+ %w{developer_public_key access_token_key}.each do |key|
7
7
  auth_params[key] ||= ENV[key] || authorization_params_from_config_file[key]
8
8
  end
9
9
 
10
- init_trello(auth_params)
11
- end
12
-
13
- private
14
-
15
- def init_trello(auth_params)
16
- ignoring_warnings do
17
- Trello::Authorization.const_set(:AuthPolicy, OAuthPolicy)
10
+ Trello.configure do |config|
11
+ config.developer_public_key = auth_params["developer_public_key"]
12
+ config.member_token = auth_params["access_token_key"]
18
13
  end
19
-
20
- OAuthPolicy.consumer_credential = OAuthCredential.new(auth_params["developer_public_key"], auth_params["developer_secret"])
21
- OAuthPolicy.token = OAuthCredential.new(auth_params["access_token_key"], nil)
22
14
  end
23
15
 
24
- def ignoring_warnings(&block)
25
- begin
26
- v, $VERBOSE = $VERBOSE, nil
27
- block.call if block
28
- ensure
29
- $VERBOSE = v
30
- end
31
- end
32
16
  end
@@ -15,19 +15,18 @@ class TrelloTracker
15
15
  Trello.logger.info "Processing #{notifications.size} tracking notifications (from #{oldest} to #{latest}) starting from #{starting_date}..."
16
16
 
17
17
  notifications.each do |notification|
18
- tracking = Tracking.new(notification)
18
+ tracking = TrackingFactory.build_from(notification)
19
19
  begin
20
- card = TrackedCard.update_or_create_with(notification.card)
21
- card.add(tracking)
20
+ tracked_card = TrackedCard.update_or_create_with(notification.card)
21
+ tracked_card.add!(tracking)
22
22
  Trello.logger.info tracking
23
23
 
24
24
  rescue StandardError => e
25
- Trello.logger.error "skipping tracking: #{e.message}".color(:magenta)
26
- Trello.logger.error "#{e.backtrace}"
25
+ Trello.logger.warn "skipping tracking: #{e.message}".color(:magenta)
26
+ Trello.logger.debug "#{e.backtrace}"
27
27
  end
28
28
  end
29
29
  Trello.logger.info "Done tracking cards!".color(:green)
30
- print_all_cards
31
30
  end
32
31
 
33
32
  private
@@ -41,8 +40,4 @@ class TrelloTracker
41
40
  [dates.min, dates.max]
42
41
  end
43
42
 
44
- def print_all_cards
45
- TrackedCard.all.each { |tracked_card| Trello.logger.info(tracked_card.to_s.color(:yellow)) }
46
- end
47
-
48
43
  end
@@ -1,3 +1,3 @@
1
1
  class TrelloEffortTracker
2
- VERSION = '0.0.3'
2
+ VERSION = '0.0.4'
3
3
  end
@@ -12,11 +12,17 @@ require 'trello_effort_tracker/tracked_card'
12
12
  require 'trello_effort_tracker/member'
13
13
  require 'trello_effort_tracker/estimate'
14
14
  require 'trello_effort_tracker/effort'
15
- require 'trello_effort_tracker/tracking'
15
+ require 'trello_effort_tracker/tracking/base'
16
+ require 'trello_effort_tracker/tracking/estimate_tracking'
17
+ require 'trello_effort_tracker/tracking/effort_tracking'
18
+ require 'trello_effort_tracker/tracking/card_done_tracking'
19
+ require 'trello_effort_tracker/tracking/invalid_tracking'
20
+ require 'trello_effort_tracker/tracking_factory'
16
21
  require 'trello_effort_tracker/trello_tracker'
17
22
  require 'trello_effort_tracker/google_docs_exporter'
18
23
 
19
24
  require 'patches/trello/member'
25
+ require 'patches/trello/card'
20
26
 
21
27
  TrelloConfiguration::Database.load_env(ENV['MONGOID_ENV'] || "development")
22
28
 
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+
4
+ describe TrelloTracker do
5
+ # This integration test works on a real Trello board created just for this purpose
6
+ # (see https://trello.com/board/testingboard/50ff225c7162123e3600074f)
7
+ # The board has some cards in todo, one card in progress and one done
8
+
9
+ TODO_CARD_ID = "51062b71df2bfec47b0039fb"
10
+ IN_PROGRESS_CARD_ID = "51062b99d81a343121004046"
11
+ DONE_CARD_ID = "51062b936d2deed22100157e"
12
+ ANOTHER_DONE_CARD_ID = "510c46d7c7bc9ac6020007ab"
13
+
14
+ let(:config) {
15
+ # auth params for trackinguser_for_test/testinguser!
16
+ OpenStruct.new(tracker_username: "trackinguser_for_test",
17
+ developer_key: "ef7c400e711057d7ba5e00be20139a33",
18
+ access_token: "9047d8fdbfdc960d41910673e300516cc8630dd4967e9b418fc27e410516362e")
19
+ }
20
+
21
+ it "tracks some estimates and efforts", :needs_valid_configuration => true do
22
+ with_trackinguser(config.tracker_username) do
23
+ tracker = TrelloTracker.new("developer_public_key" => config.developer_key, "access_token_key" => config.access_token)
24
+ tracker.track(DateTime.parse("2013-01-28"))
25
+ end
26
+
27
+ # a card to do
28
+ todo_card = TrackedCard.find_by_trello_id(TODO_CARD_ID)
29
+
30
+ todo_card.estimates.should have(1).estimate
31
+ todo_card.estimates.first.amount.should == 4
32
+ todo_card.should_not be_done
33
+
34
+ # a card in progress
35
+ in_progress_card = TrackedCard.find_by_trello_id(IN_PROGRESS_CARD_ID)
36
+
37
+ in_progress_card.estimates.should have(1).estimate
38
+ in_progress_card.estimates.should have(1).effort
39
+ in_progress_card.estimates.first.amount.should == 5
40
+ in_progress_card.efforts.first.amount.should == 1
41
+ in_progress_card.should_not be_done
42
+
43
+ # a done card
44
+ done_card = TrackedCard.find_by_trello_id(DONE_CARD_ID)
45
+ done_card.total_effort.should == 2
46
+ done_card.should be_done
47
+
48
+ # another done card (this time for the DONE column)
49
+ another_done_card = TrackedCard.find_by_trello_id(ANOTHER_DONE_CARD_ID)
50
+ another_done_card.should be_done
51
+ end
52
+
53
+
54
+ private
55
+
56
+ def with_trackinguser(tracking_user, &block)
57
+ original_tracker = ENV["tracker_username"]
58
+ original_error_level = Trello.logger.level
59
+
60
+ begin
61
+ ENV["tracker_username"] = tracking_user
62
+ Trello.logger.level = Logger::WARN
63
+ block.call unless block.nil?
64
+ ensure
65
+ ENV["tracker_username"] = original_tracker
66
+ Trello.logger.level = original_error_level
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Trello::Card do
4
+
5
+ describe "#in_done_column?" do
6
+
7
+ let(:trello_card) { Trello::Card.new("name" => "a name", "desc" => "any description") }
8
+
9
+ let(:todo_column) { Trello::List.new("name" => "ToDo") }
10
+ let(:done_column) { Trello::List.new("name" => "Done yesterday") }
11
+
12
+ it "is done when is in a DONE column" do
13
+ trello_card.stub(:list).and_return(done_column)
14
+
15
+ trello_card.in_done_column?.should be_true
16
+ end
17
+
18
+ it "is still not done when is not in DONE column" do
19
+ trello_card.stub(:list).and_return(todo_column)
20
+
21
+ trello_card.in_done_column?.should be_false
22
+ end
23
+
24
+ end
25
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  require 'rubygems'
2
2
 
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+
3
6
  # Set up gems listed in the Gemfile.
4
7
  begin
5
8
  ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__))
@@ -11,7 +14,13 @@ rescue Bundler::GemNotFound => e
11
14
  exit!
12
15
  end
13
16
 
14
- Bundler.require
17
+ Bundler.require(:spec)
18
+
19
+ require 'trello_effort_tracker'
20
+
21
+ # Requires supporting ruby files with custom matchers and macros, etc,
22
+ # in spec/support/ and its subdirectories.
23
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
15
24
 
16
25
  RSpec.configure do |configuration|
17
26
  configuration.include Mongoid::Matchers
@@ -19,3 +28,39 @@ end
19
28
 
20
29
  # force test env for the mongodb configuration
21
30
  TrelloConfiguration::Database.load_env("test")
31
+
32
+
33
+ ## Spec Helper Methods (TODO: should we move them in a separate file?)
34
+
35
+ def unrecognized_notification
36
+ create_notification(data: { 'text' => '@trackinguser hi there!' })
37
+ end
38
+
39
+ def notification_with_message(message)
40
+ create_notification(data: { 'text' => message })
41
+ end
42
+
43
+ def create_estimate(time_measurement)
44
+ create_notification(data: { 'text' => "@trackinguser [1.5#{TIME_MEASUREMENTS[time_measurement]}]" })
45
+ end
46
+
47
+ def create_effort(time_measurement)
48
+ create_notification(data: { 'text' => "@trackinguser +4.5#{TIME_MEASUREMENTS[time_measurement]}]" })
49
+ end
50
+
51
+ def with(notification)
52
+ tracking = TrackingFactory.build_from(notification)
53
+ yield(tracking)
54
+ end
55
+
56
+ def with_message(notification_message, &block)
57
+ with(notification_with_message(notification_message), &block)
58
+ end
59
+
60
+ def create_notification(custom_params)
61
+ params = { data: { 'text' => "@trackinguser +2h" }, date: "2012-10-28T21:06:14.801Z", member_creator: stub(username: "pietrodibello") }
62
+ params.merge!(custom_params)
63
+
64
+ stub(data: params[:data], date: params[:date], member_creator: params[:member_creator]).as_null_object
65
+ end
66
+
@@ -0,0 +1,12 @@
1
+ require 'database_cleaner'
2
+
3
+ RSpec.configure do |config|
4
+ config.before(:suite) do
5
+ DatabaseCleaner.orm = 'mongoid'
6
+ DatabaseCleaner.strategy = :truncation
7
+ end
8
+
9
+ config.before(:each) do
10
+ DatabaseCleaner.clean
11
+ end
12
+ end
@@ -4,11 +4,6 @@ describe TrackedCard do
4
4
 
5
5
  before(:each) do
6
6
  Date.stub(:today).and_return(Date.parse("2012-11-05"))
7
- TrackedCard.delete_all
8
- end
9
-
10
- after(:each) do
11
- TrackedCard.delete_all
12
7
  end
13
8
 
14
9
  subject(:card) { TrackedCard.new(name: "any", short_id: 1234, trello_id: "123123") }
@@ -48,6 +43,10 @@ describe TrackedCard do
48
43
  describe ".update_or_create_with" do
49
44
  let(:trello_card) { Trello::Card.new("id" => "ABC123", "name" => "a name", "idShort" => 1, "desc" => "any description") }
50
45
 
46
+ before(:each) do
47
+ Trello::Card.any_instance.stub(:in_done_column?)
48
+ end
49
+
51
50
  it "creates a tracked card on a given trello card" do
52
51
  tracked_card = TrackedCard.update_or_create_with(trello_card)
53
52
 
@@ -72,6 +71,22 @@ describe TrackedCard do
72
71
  TrackedCard.all.should be_empty
73
72
  end
74
73
 
74
+ it "tracks the card as done when the original trello card is moved in a DONE column" do
75
+ trello_card.stub(:in_done_column?).and_return(true)
76
+
77
+ tracked_card = TrackedCard.update_or_create_with(trello_card)
78
+
79
+ tracked_card.should be_done
80
+ end
81
+
82
+ it "tracks the card as NOT done when the original trello card is moved in a column different from DONE" do
83
+ trello_card.stub(:in_done_column?).and_return(false)
84
+
85
+ tracked_card = TrackedCard.update_or_create_with(trello_card)
86
+
87
+ tracked_card.should_not be_done
88
+ end
89
+
75
90
  end
76
91
 
77
92
  describe ".build_from" do
@@ -121,6 +136,42 @@ describe TrackedCard do
121
136
  end
122
137
  end
123
138
 
139
+ describe "#add" do
140
+ let(:card) { TrackedCard.new(name: "a name", trello_id: "123456789") }
141
+ let(:estimate_tracking) { Tracking::EstimateTracking.new(create_notification(data: { 'text' => "@trackinguser [1h]" })) }
142
+
143
+ it "adds an estimate from a tracking estimate notification" do
144
+ card.add(estimate_tracking)
145
+ card.estimates.should have(1).estimate
146
+ end
147
+
148
+ it "adds an estimate only once" do
149
+ card.add(estimate_tracking)
150
+ card.add(estimate_tracking)
151
+
152
+ card.estimates.should have(1).estimate
153
+ end
154
+
155
+ it "is done when has a DONE notification" do
156
+ card.should_not be_done
157
+
158
+ card.add(Tracking::CardDoneTracking.new(stub(:notification)))
159
+ card.should be_done
160
+ end
161
+
162
+ end
163
+
164
+ describe "#add!" do
165
+ let(:card) { TrackedCard.new(name: "a name", trello_id: "123456789", short_id: "123") }
166
+
167
+ it "saves the tracked card after adding the tracking" do
168
+ any_tracking = Tracking::EstimateTracking.new(create_notification(data: { 'text' => "@trackinguser [1h]" }))
169
+
170
+ card.add!(any_tracking)
171
+ card.reload.should_not be_nil
172
+ end
173
+ end
174
+
124
175
  describe "#total_effort" do
125
176
  it "is zero when there's no effort" do
126
177
  card.total_effort.should == 0
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ module Tracking
4
+ describe CardDoneTracking do
5
+
6
+ describe "#add_to" do
7
+ it "marks the card as done" do
8
+ card = TrackedCard.new
9
+
10
+ done_tracking = TrackingFactory.build_from(notification_with_message("DONE"))
11
+ done_tracking.add_to(card)
12
+
13
+ card.done?.should be_true
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ module Tracking
4
+ describe EffortTracking do
5
+
6
+ describe "#effort" do
7
+
8
+ %w{pietrodibello michelepangrazzi alessandrodescovi michelevincenzi}.each do |username|
9
+ let(username.to_sym) { Member.new(username: username) }
10
+ end
11
+
12
+ before(:each) do
13
+ Trello::Member.stub(:find).and_return(Member.new(username: "any"))
14
+ end
15
+
16
+ it "is nil when the notification does not contain an estimate" do
17
+ with(unrecognized_notification) { |tracking| tracking.effort.should be_nil }
18
+ end
19
+
20
+ it "does not parse effort in minutes (e.g. +30m)" do
21
+ with_message("@trackinguser +30m") { |tracking| tracking.effort.should be_nil }
22
+ end
23
+
24
+ it "is the hour-based effort when the notification contains an effort in hours" do
25
+ Trello::Member.should_receive(:find).with("michelepangrazzi").and_return(michelepangrazzi)
26
+
27
+ raw_data = create_notification(data: { 'text' => "@trackinguser +2h" },
28
+ date: "2012-10-28T21:06:14.801Z",
29
+ member_creator: stub(username: "michelepangrazzi"))
30
+
31
+ TrackingFactory.build_from(raw_data).effort.should == Effort.new(amount: 2.0, date: Date.parse('2012-10-28'), members: [michelepangrazzi])
32
+ end
33
+
34
+ it "converts the effort in hours when the notification contains an effort in days" do
35
+ with_message("@trackinguser +1.5d") { |t| t.effort.amount.should == 8+4 }
36
+ with_message("@trackinguser +1.5g") { |t| t.effort.amount.should == 8+4 }
37
+ end
38
+
39
+ it "converts the effort in hours when the notification contains an effort in pomodori" do
40
+ with_message("@trackinguser +10p") { |t| t.effort.amount.should == 5}
41
+ end
42
+
43
+ it "fetch the effort from a complex effort message" do
44
+ with_message "@trackinguser ho speso +2h e spero che stavolta possiamo rilasciarla" do |tracking|
45
+ tracking.effort.amount.should == 2.0
46
+ end
47
+ end
48
+
49
+ it "fetch the effort even when beween square brackets" do
50
+ with_message "@trackinguser [+0.5h]" do |tracking|
51
+ tracking.effort.amount.should == 0.5
52
+ end
53
+ end
54
+
55
+ it "computes the effort considering all the mentioned team mates in the message" do
56
+ with_message "@trackinguser +2h assieme a @michelepangrazzi e @alessandrodescovi" do |tracking|
57
+ tracking.effort.amount.should == 2.0 * 3
58
+ end
59
+ end
60
+
61
+ it "tracks all the team mates which spent that effort on the card" do
62
+ %w{pietrodibello michelepangrazzi alessandrodescovi}.each do |username|
63
+ Trello::Member.should_receive(:find).with(username).and_return(self.send(username))
64
+ end
65
+
66
+ notification = create_notification(data: { 'text' => "@trackinguser +2h assieme a @michelepangrazzi e @alessandrodescovi" },
67
+ member_creator: stub(username: "pietrodibello"))
68
+ with notification do |tracking|
69
+ tracking.effort.members.should == [michelepangrazzi, alessandrodescovi, pietrodibello]
70
+ end
71
+ end
72
+
73
+ it "tracks the effort only on the team members listed between round brackets" do
74
+ %w{michelevincenzi alessandrodescovi}.each do |username|
75
+ Trello::Member.should_receive(:find).with(username).and_return(self.send(username))
76
+ end
77
+
78
+ notification = create_notification(data: { 'text' => "@trackinguser +3p (@alessandrodescovi @michelevincenzi)" },
79
+ member_creator: stub(username: "pietrodibello"))
80
+
81
+ with notification do |tracking|
82
+ tracking.effort.members.should == [alessandrodescovi, michelevincenzi]
83
+ tracking.effort.amount.should == 1.5 * 2
84
+ end
85
+ end
86
+
87
+ it "tracks the effort with the date given in the notification text, not the actual notification date" do
88
+ raw_data = create_notification(data: { 'text' => "@trackinguser 22.11.2012 +6p" }, date: "2012-09-19T12:46:13.713Z")
89
+
90
+ tracking = TrackingFactory.build_from(raw_data)
91
+
92
+ tracking.effort.date.should == Date.parse('2012-11-22')
93
+ end
94
+
95
+ it "tracks the effort to yesterday when the keyword 'yesterday' is present before the effort amount" do
96
+ raw_data = create_notification(data: { 'text' => "@trackinguser yesterday +6p" }, date: "2012-09-19T12:46:13.713Z")
97
+
98
+ tracking = TrackingFactory.build_from(raw_data)
99
+
100
+ tracking.effort.date.should == Date.parse('2012-09-18')
101
+ end
102
+
103
+ it "tracks the effort to yesterday when the keyword 'yesterday' is present before the effort amount" do
104
+ raw_data = create_notification(data: { 'text' => "@trackinguser +6p yesterday" }, date: "2012-09-19T12:46:13.713Z")
105
+
106
+ tracking = TrackingFactory.build_from(raw_data)
107
+
108
+ tracking.effort.date.should == Date.parse('2012-09-18')
109
+ end
110
+
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ module Tracking
4
+ describe EstimateTracking do
5
+
6
+ describe "#estimate" do
7
+
8
+ it "is nil when the notification does not contain an estimate" do
9
+ TrackingFactory.build_from(unrecognized_notification).estimate.should be_nil
10
+ end
11
+
12
+ it "is the hour-based estimate when the notification contains an estimate in hours" do
13
+ raw_data = create_notification(data: { 'text' => "@trackinguser [2h]" }, date: "2012-10-28T21:06:14.801Z")
14
+
15
+ TrackingFactory.build_from(raw_data).estimate.should == Estimate.new(amount: 2.0, date: Date.parse('2012-10-28'))
16
+ end
17
+
18
+ it "converts the estimate in hours when the notification contains an estimate in days" do
19
+ TrackingFactory.build_from(create_notification(data: { 'text' => "@trackinguser [1.5d]" })).estimate.amount.should == 8+4
20
+ TrackingFactory.build_from(create_notification(data: { 'text' => "@trackinguser [1.5g]" })).estimate.amount.should == 8+4
21
+ end
22
+
23
+ it "converts the estimate in hours when the notification contains an estimate in pomodori" do
24
+ raw_data = create_notification(data: { 'text' => "@trackinguser [10p]" })
25
+ TrackingFactory.build_from(raw_data).estimate.amount.should == 5
26
+ end
27
+
28
+ it "fetch the estimate from a complex estimate message" do
29
+ raw_data = create_notification(data: { 'text' => "@maxmazza Dobbiamo ancora lavorarci.\n@trackinguser ristimo ancora [3h] per il fix" })
30
+ TrackingFactory.build_from(raw_data).estimate.amount.should == 3.0
31
+ end
32
+
33
+ it "tracks the effort with the date given in the notification text, not the actual notification date" do
34
+ raw_data = create_notification( data: { 'text' => "@trackinguser 22.11.2012 [6p]" }, date: "2012-09-19T12:46:13.713Z")
35
+
36
+ tracking = TrackingFactory.build_from(raw_data)
37
+
38
+ tracking.estimate.date.should == Date.parse('2012-11-22')
39
+ end
40
+
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe TrackingFactory do
4
+
5
+ TIME_MEASUREMENTS = {
6
+ hours: 'h',
7
+ days: 'd',
8
+ giorni: 'g',
9
+ pomodori: 'p'
10
+ }
11
+
12
+ context "unknown tracking format" do
13
+ it "builds an invalid tracking instance" do
14
+ TrackingFactory.build_from(unrecognized_notification).class.should == Tracking::InvalidTracking
15
+
16
+ with_message("@trackinguser +30m") { |tracking| tracking.class.should == Tracking::InvalidTracking }
17
+ end
18
+ end
19
+
20
+ TIME_MEASUREMENTS.each_key do |time_measurement|
21
+
22
+ context "estimate tracking notification in #{time_measurement}" do
23
+ it "builds an estimate tracking instance" do
24
+ TrackingFactory.build_from(create_estimate(time_measurement)).class.should == Tracking::EstimateTracking
25
+ end
26
+ end
27
+
28
+ context "effort tracking notification in #{time_measurement}" do
29
+ it "builds an effort tracking instance" do
30
+ TrackingFactory.build_from(create_effort(time_measurement)).class.should == Tracking::EffortTracking
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ context "card done tracking notification" do
37
+ it "builds a card done tracking instance" do
38
+ with_message("@trackinguser DONE") { |tracking| tracking.class.should == Tracking::CardDoneTracking }
39
+ end
40
+ end
41
+
42
+ end