tracco 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG +16 -0
  2. data/Gemfile.lock +1 -1
  3. data/README.md +4 -4
  4. data/lib/patches/trello/card.rb +3 -2
  5. data/lib/patches/trello/member.rb +4 -2
  6. data/lib/tasks/tasks.rake +2 -2
  7. data/lib/tracco/google_docs_exporter.rb +50 -47
  8. data/lib/tracco/models/effort.rb +40 -0
  9. data/lib/tracco/models/estimate.rb +29 -0
  10. data/lib/tracco/models/member.rb +64 -0
  11. data/lib/tracco/models/tracked_card.rb +148 -0
  12. data/lib/tracco/tracking/base.rb +68 -65
  13. data/lib/tracco/tracking/card_done_tracking.rb +9 -6
  14. data/lib/tracco/tracking/effort_tracking.rb +32 -29
  15. data/lib/tracco/tracking/estimate_tracking.rb +16 -13
  16. data/lib/tracco/tracking/factory.rb +18 -16
  17. data/lib/tracco/tracking/invalid_tracking.rb +15 -13
  18. data/lib/tracco/trello_tracker.rb +34 -30
  19. data/lib/tracco/version.rb +2 -2
  20. data/lib/tracco.rb +4 -4
  21. data/spec/factories/effort_factory.rb +2 -2
  22. data/spec/factories/estimate_factory.rb +1 -1
  23. data/spec/factories/tracked_card_factory.rb +1 -1
  24. data/spec/integration/trello_tracker_spec.rb +49 -47
  25. data/spec/models/effort_spec.rb +61 -0
  26. data/spec/models/estimate_spec.rb +40 -0
  27. data/spec/models/member_spec.rb +83 -0
  28. data/spec/models/tracked_card_spec.rb +467 -0
  29. data/spec/support/spec_helper_methods.rb +7 -1
  30. data/spec/tracking/card_done_tracking_spec.rb +11 -9
  31. data/spec/tracking/effort_tracking_spec.rb +77 -75
  32. data/spec/tracking/estimate_tracking_spec.rb +30 -28
  33. data/spec/tracking/factory_spec.rb +39 -0
  34. data/spec/trello_tracker_spec.rb +20 -18
  35. data/tracco.gemspec +1 -1
  36. metadata +12 -12
  37. data/lib/tracco/effort.rb +0 -37
  38. data/lib/tracco/estimate.rb +0 -26
  39. data/lib/tracco/member.rb +0 -61
  40. data/lib/tracco/tracked_card.rb +0 -145
  41. data/spec/effort_spec.rb +0 -59
  42. data/spec/estimate_spec.rb +0 -38
  43. data/spec/member_spec.rb +0 -81
  44. data/spec/tracked_card_spec.rb +0 -465
  45. data/spec/tracking_factory_spec.rb +0 -42
@@ -1,42 +1,45 @@
1
- module Tracking
2
- class EffortTracking
3
- include Base
1
+ module Tracco
2
+ module Tracking
3
+ class EffortTracking
4
+ include Base
4
5
 
5
- def add_to(card)
6
- card.efforts << effort unless card.contains_effort?(effort)
7
- end
6
+ def add_to(card)
7
+ card.efforts << effort unless card.contains_effort?(effort)
8
+ end
8
9
 
9
- def effort
10
- @effort ||= Effort.new(amount: total_effort_from(raw_effort), date: date, members: effort_members, tracking_notification_id: tracking_notification.id)
11
- end
10
+ def effort
11
+ @effort ||= Effort.new(amount: total_effort_from(raw_effort), date: date, members: effort_members, tracking_notification_id: tracking_notification.id)
12
+ end
12
13
 
13
- private
14
+ private
14
15
 
15
- def total_effort_from(raw_effort)
16
- effort_amount = convert_to_hours(raw_effort)
17
- total_effort = effort_amount * effort_members.size
18
- end
16
+ def total_effort_from(raw_effort)
17
+ effort_amount = convert_to_hours(raw_effort)
18
+ total_effort = effort_amount * effort_members.size
19
+ end
19
20
 
20
- def raw_effort
21
- extract_match_from_raw_tracking(/\+#{DURATION_REGEXP}/)
22
- end
21
+ def raw_effort
22
+ extract_match_from_raw_tracking(/\+#{DURATION_REGEXP}/)
23
+ end
23
24
 
24
- def effort_members
25
- @effort_members ||= members_involved_in_the_effort.map do |username|
26
- Member.build_from(Trello::Member.find(username))
25
+ def effort_members
26
+ @effort_members ||= members_involved_in_the_effort.map do |username|
27
+ Member.build_from(Trello::Member.find(username))
28
+ end
27
29
  end
28
- end
29
30
 
30
- def members_involved_in_the_effort
31
- members_involved_in_the_effort = raw_tracking.scan(/@(\w+)/).flatten
32
- members_involved_in_the_effort << notifier.username unless should_count_only_listed_members?
31
+ def members_involved_in_the_effort
32
+ members_involved_in_the_effort = raw_tracking.scan(/@(\w+)/).flatten
33
+ members_involved_in_the_effort << notifier.username unless should_count_only_listed_members?
33
34
 
34
- members_involved_in_the_effort
35
- end
35
+ members_involved_in_the_effort
36
+ end
36
37
 
37
- def should_count_only_listed_members?
38
- raw_tracking =~ /\((@\w+\W*\s*)+\)/
39
- end
38
+ def should_count_only_listed_members?
39
+ raw_tracking =~ /\((@\w+\W*\s*)+\)/
40
+ end
40
41
 
42
+ end
41
43
  end
44
+
42
45
  end
@@ -1,20 +1,23 @@
1
- module Tracking
2
- class EstimateTracking
3
- include Base
1
+ module Tracco
2
+ module Tracking
3
+ class EstimateTracking
4
+ include Base
4
5
 
5
- def estimate
6
- @estimate ||= Estimate.new(amount: convert_to_hours(raw_estimate), date: date, tracking_notification_id: tracking_notification.id)
7
- end
6
+ def estimate
7
+ @estimate ||= Estimate.new(amount: convert_to_hours(raw_estimate), date: date, tracking_notification_id: tracking_notification.id)
8
+ end
8
9
 
9
- def add_to(card)
10
- card.estimates << estimate unless card.contains_estimate?(estimate)
11
- end
10
+ def add_to(card)
11
+ card.estimates << estimate unless card.contains_estimate?(estimate)
12
+ end
12
13
 
13
- private
14
+ private
14
15
 
15
- def raw_estimate
16
- extract_match_from_raw_tracking(/\[#{DURATION_REGEXP}\]/)
17
- end
16
+ def raw_estimate
17
+ extract_match_from_raw_tracking(/\[#{DURATION_REGEXP}\]/)
18
+ end
18
19
 
20
+ end
19
21
  end
22
+
20
23
  end
@@ -1,26 +1,28 @@
1
- module Tracking
2
- class Factory
1
+ module Tracco
2
+ module Tracking
3
+ class Factory
3
4
 
4
- DURATION_REGEXP = '(\d+\.?\d*[phdg])'
5
+ DURATION_REGEXP = '(\d+\.?\d*[phdg])'
5
6
 
6
- @match_pairs = {}
7
+ @match_pairs = {}
7
8
 
8
- def self.build_from(tracking_notification)
9
- matching_pair = @match_pairs.find { |regexp, tracking_class| tracking_notification.data['text'] =~ regexp }
9
+ def self.build_from(tracking_notification)
10
+ matching_pair = @match_pairs.find { |regexp, tracking_class| tracking_notification.data['text'] =~ regexp }
10
11
 
11
- tracking_class = matching_pair ? matching_pair.last : Tracking::InvalidTracking
12
- tracking_class.new(tracking_notification)
13
- end
12
+ tracking_class = matching_pair ? matching_pair.last : Tracking::InvalidTracking
13
+ tracking_class.new(tracking_notification)
14
+ end
14
15
 
15
- private
16
+ private
16
17
 
17
- def self.match(match_pair)
18
- @match_pairs.merge!(match_pair)
19
- end
18
+ def self.match(match_pair)
19
+ @match_pairs.merge!(match_pair)
20
+ end
20
21
 
21
- match /\[#{DURATION_REGEXP}\]/ => Tracking::EstimateTracking
22
- match /\+#{DURATION_REGEXP}/ => Tracking::EffortTracking
23
- match /DONE/ => Tracking::CardDoneTracking
22
+ match /\[#{DURATION_REGEXP}\]/ => Tracking::EstimateTracking
23
+ match /\+#{DURATION_REGEXP}/ => Tracking::EffortTracking
24
+ match /DONE/ => Tracking::CardDoneTracking
24
25
 
26
+ end
25
27
  end
26
28
  end
@@ -1,19 +1,21 @@
1
- module Tracking
2
- class InvalidTracking
3
- include Base
1
+ module Tracco
2
+ module Tracking
3
+ class InvalidTracking
4
+ include Base
4
5
 
5
- def add_to(card)
6
- # do nothing
7
- Trello.logger.warn "Ignoring tracking notification: '#{raw_text}'"
8
- end
6
+ def add_to(card)
7
+ # do nothing
8
+ Trello.logger.warn "Ignoring tracking notification: '#{raw_text}'"
9
+ end
9
10
 
10
- def estimate
11
- nil
12
- end
11
+ def estimate
12
+ nil
13
+ end
13
14
 
14
- def effort
15
- nil
16
- end
15
+ def effort
16
+ nil
17
+ end
17
18
 
19
+ end
18
20
  end
19
21
  end
@@ -1,44 +1,48 @@
1
- class TrelloTracker
2
- include TrelloAuthorize
3
- include Trello
1
+ module Tracco
4
2
 
5
- trap("SIGINT") { exit! }
3
+ class TrelloTracker
4
+ include TrelloAuthorize
5
+ include Trello
6
6
 
7
- def initialize(custom_config_params = {})
8
- authorize_on_trello(custom_config_params)
9
- tracker_username(custom_config_params[:tracker_username])
10
- end
7
+ trap("SIGINT") { exit! }
8
+
9
+ def initialize(custom_config_params = {})
10
+ authorize_on_trello(custom_config_params)
11
+ tracker_username(custom_config_params[:tracker_username])
12
+ end
11
13
 
12
- def track(starting_date=Date.today)
13
- notifications = tracker.notifications_since(starting_date)
14
+ def track(starting_date=Date.today)
15
+ tracking_notifications = tracker.tracking_notifications_since(starting_date)
14
16
 
15
- oldest, latest = boundary_dates_in(notifications)
16
- Trello.logger.info "Processing #{notifications.size} tracking notifications (from #{oldest} to #{latest}) starting from #{starting_date}..."
17
+ oldest, latest = boundary_dates_in(tracking_notifications)
18
+ Trello.logger.info "Processing #{tracking_notifications.size} tracking events (from #{oldest} to #{latest}) starting from #{starting_date}..."
17
19
 
18
- notifications.each do |notification|
19
- tracking = Tracking::Factory.build_from(notification)
20
- begin
21
- tracked_card = TrackedCard.update_or_create_with(notification.card)
22
- tracked_card.add!(tracking)
23
- Trello.logger.info tracking
20
+ tracking_notifications.each do |tracking_notification|
21
+ tracking = Tracking::Factory.build_from(tracking_notification)
22
+ begin
23
+ tracked_card = TrackedCard.update_or_create_with(tracking_notification.card)
24
+ tracked_card.add!(tracking)
25
+ Trello.logger.info tracking
24
26
 
25
- rescue StandardError => e
26
- Trello.logger.warn "skipping tracking: #{e.message}".color(:magenta)
27
- Trello.logger.debug "#{e.backtrace}"
27
+ rescue StandardError => e
28
+ Trello.logger.warn "skipping tracking: #{e.message}".color(:magenta)
29
+ Trello.logger.debug "#{e.backtrace}"
30
+ end
28
31
  end
32
+ Trello.logger.info "Done tracking cards!".color(:green)
29
33
  end
30
- Trello.logger.info "Done tracking cards!".color(:green)
31
- end
32
34
 
33
- private
35
+ private
34
36
 
35
- def tracker
36
- @tracker ||= Member.find(tracker_username)
37
- end
37
+ def tracker
38
+ @tracker ||= Trello::Member.find(tracker_username)
39
+ end
40
+
41
+ def boundary_dates_in(tracking_notifications)
42
+ dates = tracking_notifications.map { |each_tracking_notification| Chronic.parse(each_tracking_notification.date) }
43
+ [dates.min, dates.max]
44
+ end
38
45
 
39
- def boundary_dates_in(notifications)
40
- dates = notifications.map { |each_notification| Chronic.parse(each_notification.date) }
41
- [dates.min, dates.max]
42
46
  end
43
47
 
44
48
  end
@@ -1,3 +1,3 @@
1
- class TrelloEffortTracker
2
- VERSION = '0.0.14'
1
+ module Tracco
2
+ VERSION = '0.0.15'
3
3
  end
data/lib/tracco.rb CHANGED
@@ -9,10 +9,10 @@ require 'forwardable'
9
9
  require 'tracco/mongoid_helper'
10
10
  require 'tracco/trello_configuration'
11
11
  require 'tracco/trello_authorize'
12
- require 'tracco/tracked_card'
13
- require 'tracco/member'
14
- require 'tracco/estimate'
15
- require 'tracco/effort'
12
+ require 'tracco/models/tracked_card'
13
+ require 'tracco/models/member'
14
+ require 'tracco/models/estimate'
15
+ require 'tracco/models/effort'
16
16
  require 'tracco/tracking/base'
17
17
  require 'tracco/tracking/estimate_tracking'
18
18
  require 'tracco/tracking/effort_tracking'
@@ -1,9 +1,9 @@
1
1
  FactoryGirl.define do
2
2
 
3
- factory :effort do
3
+ factory :effort, :class => Tracco::Effort do
4
4
  amount 4
5
5
  date Date.today
6
- members [Member.new(username: "any_name")]
6
+ members [Tracco::Member.new(username: "any_name")]
7
7
  sequence(:tracking_notification_id, 1000)
8
8
  muted false
9
9
  end
@@ -1,6 +1,6 @@
1
1
  FactoryGirl.define do
2
2
 
3
- factory :estimate do
3
+ factory :estimate, :class => Tracco::Estimate do
4
4
  amount 42
5
5
  date Date.today
6
6
  sequence(:tracking_notification_id, 1000)
@@ -1,6 +1,6 @@
1
1
  FactoryGirl.define do
2
2
 
3
- factory :tracked_card do
3
+ factory :tracked_card, :class => Tracco::TrackedCard do
4
4
  sequence(:short_id, 1000)
5
5
  sequence(:trello_id, 100000) { |n| "xyz#{n}" }
6
6
  sequence(:name) { |n| "any_card_#{n}" }
@@ -1,66 +1,68 @@
1
1
  require 'spec_helper'
2
2
  require 'ostruct'
3
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
4
+ module Tracco
5
+ describe TrelloTracker do
6
+ # This integration test works on a real Trello board created just for this purpose
7
+ # (see https://trello.com/board/testingboard/50ff225c7162123e3600074f)
8
+ # The board has some cards in todo, one card in progress and one done
8
9
 
9
- TODO_CARD_ID = "51062b71df2bfec47b0039fb"
10
- IN_PROGRESS_CARD_ID = "51062b99d81a343121004046"
11
- DONE_CARD_ID = "51062b936d2deed22100157e"
12
- ANOTHER_DONE_CARD_ID = "510c46d7c7bc9ac6020007ab"
10
+ TODO_CARD_ID = "51062b71df2bfec47b0039fb"
11
+ IN_PROGRESS_CARD_ID = "51062b99d81a343121004046"
12
+ DONE_CARD_ID = "51062b936d2deed22100157e"
13
+ ANOTHER_DONE_CARD_ID = "510c46d7c7bc9ac6020007ab"
13
14
 
14
- let(:config) {
15
- # auth params for trackinguser_for_test/testinguser!
16
- OpenStruct.new(tracker: "trackinguser_for_test",
17
- dev_key: "ef7c400e711057d7ba5e00be20139a33",
18
- token: "9047d8fdbfdc960d41910673e300516cc8630dd4967e9b418fc27e410516362e")
19
- }
15
+ let(:config) {
16
+ # auth params for trackinguser_for_test/testinguser!
17
+ OpenStruct.new(tracker: "trackinguser_for_test",
18
+ dev_key: "ef7c400e711057d7ba5e00be20139a33",
19
+ token: "9047d8fdbfdc960d41910673e300516cc8630dd4967e9b418fc27e410516362e")
20
+ }
20
21
 
21
- it "tracks some estimates and efforts", :needs_valid_configuration => true do
22
- without_logging do
23
- tracker = TrelloTracker.new(tracker_username: config.tracker, developer_public_key: config.dev_key, access_token_key: config.token)
24
- tracker.track(DateTime.parse("2013-01-28"))
25
- end
22
+ it "tracks some estimates and efforts", :needs_valid_configuration => true do
23
+ without_logging do
24
+ tracker = TrelloTracker.new(tracker_username: config.tracker, developer_public_key: config.dev_key, access_token_key: config.token)
25
+ tracker.track(DateTime.parse("2013-01-28"))
26
+ end
26
27
 
27
- # a card to do
28
- todo_card = TrackedCard.find_by_trello_id(TODO_CARD_ID)
28
+ # a card to do
29
+ todo_card = TrackedCard.find_by_trello_id(TODO_CARD_ID)
29
30
 
30
- todo_card.estimates.should have(1).estimate
31
- todo_card.estimates.first.amount.should == 4
32
- todo_card.should_not be_done
31
+ todo_card.estimates.should have(1).estimate
32
+ todo_card.estimates.first.amount.should == 4
33
+ todo_card.should_not be_done
33
34
 
34
- # a card in progress
35
- in_progress_card = TrackedCard.find_by_trello_id(IN_PROGRESS_CARD_ID)
35
+ # a card in progress
36
+ in_progress_card = TrackedCard.find_by_trello_id(IN_PROGRESS_CARD_ID)
36
37
 
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
38
+ in_progress_card.estimates.should have(1).estimate
39
+ in_progress_card.estimates.should have(1).effort
40
+ in_progress_card.estimates.first.amount.should == 5
41
+ in_progress_card.efforts.first.amount.should == 1
42
+ in_progress_card.should_not be_done
42
43
 
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
44
+ # a done card
45
+ done_card = TrackedCard.find_by_trello_id(DONE_CARD_ID)
46
+ done_card.total_effort.should == 2
47
+ done_card.should be_done
47
48
 
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
49
+ # another done card (this time for the DONE column)
50
+ another_done_card = TrackedCard.find_by_trello_id(ANOTHER_DONE_CARD_ID)
51
+ another_done_card.should be_done
52
+ end
52
53
 
53
54
 
54
- private
55
+ private
55
56
 
56
- def without_logging(&block)
57
- original_error_level = Trello.logger.level
57
+ def without_logging(&block)
58
+ original_error_level = Trello.logger.level
58
59
 
59
- begin
60
- Trello.logger.level = Logger::WARN
61
- block.call unless block.nil?
62
- ensure
63
- Trello.logger.level = original_error_level
60
+ begin
61
+ Trello.logger.level = Logger::WARN
62
+ block.call unless block.nil?
63
+ ensure
64
+ Trello.logger.level = original_error_level
65
+ end
64
66
  end
65
67
  end
66
68
  end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'mongoid-rspec'
3
+
4
+ module Tracco
5
+ describe Effort do
6
+
7
+ it { should have_fields(:amount, :date, :muted, :tracking_notification_id) }
8
+ it { should be_embedded_in(:tracked_card) }
9
+ it { should embed_many(:members) }
10
+
11
+ describe "validation" do
12
+ it { should validate_presence_of(:amount) }
13
+ it { should validate_presence_of(:date) }
14
+ it { should validate_presence_of(:members) }
15
+ end
16
+
17
+ %w{piero tommaso tom ugo}.each do |username|
18
+ let(username.to_sym) { Member.new(username: username) }
19
+ end
20
+
21
+ describe "#amount_per_member" do
22
+ it "counts the amount spent per single member" do
23
+ effort = Effort.new(amount: 6, members: [piero, tommaso], date: Date.parse("2012-11-09"), )
24
+ effort.amount_per_member.should == 3
25
+ end
26
+ end
27
+
28
+ describe "equality" do
29
+ it "is equal to another effort with same amount, date and members" do
30
+ effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [piero, tommaso])
31
+ same_effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [piero, tommaso])
32
+ yet_same_effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [tommaso, piero])
33
+
34
+ effort.should == same_effort
35
+ effort.should == yet_same_effort
36
+ end
37
+
38
+ it "is not equal when amount differs" do
39
+ effort = Effort.new(amount: 3, date: Date.today, members: [tom, ugo])
40
+ another_effort = Effort.new(amount: 1, date: Date.today, members: [tom, ugo])
41
+
42
+ effort.should_not == another_effort
43
+ end
44
+
45
+ it "is not equal when date differs" do
46
+ effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [tom, ugo])
47
+ another_effort = Effort.new(amount: 3, date: Date.parse("2011-10-08"), members: [tom, ugo])
48
+
49
+ effort.should_not == another_effort
50
+ end
51
+
52
+ it "is not equal when members differ" do
53
+ effort = Effort.new(amount: 3, date: Date.today, members: [tom, ugo])
54
+ another_effort = Effort.new(amount: 3, date: Date.today, members: [piero, ugo])
55
+
56
+ effort.should_not == another_effort
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ require 'mongoid-rspec'
3
+
4
+ module Tracco
5
+ describe Estimate do
6
+
7
+ it { should have_fields(:amount, :date) }
8
+ it { should be_embedded_in(:tracked_card) }
9
+
10
+ describe "validation" do
11
+ it { should validate_presence_of(:amount) }
12
+ it { should validate_presence_of(:date) }
13
+ end
14
+
15
+ describe "equality" do
16
+
17
+ it "is equal to another estimate with same amount and date" do
18
+ estimate = Estimate.new(amount: 3, date: Date.parse("2012-11-09"))
19
+ same_estimate = Estimate.new(amount: 3, date: Date.parse("2012-11-09"))
20
+
21
+ estimate.should == same_estimate
22
+ end
23
+
24
+ it "is not equal when amount differs" do
25
+ estimate = Estimate.new(amount: 3, date: Date.today)
26
+ another_estimate = Estimate.new(amount: 1, date: Date.today)
27
+
28
+ estimate.should_not == another_estimate
29
+ end
30
+
31
+ it "is not equal when date differs" do
32
+ estimate = Estimate.new(amount: 3, date: Date.parse("2012-11-09"))
33
+ another_estimate = Estimate.new(amount: 3, date: Date.parse("2011-10-08"))
34
+
35
+ estimate.should_not == another_estimate
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ require 'mongoid-rspec'
3
+
4
+ module Tracco
5
+ describe Member do
6
+
7
+ it { should have_fields(:trello_id, :username, :full_name, :avatar_id, :bio, :url) }
8
+ it { should be_embedded_in(:effort) }
9
+
10
+ describe "validation" do
11
+ it { should validate_presence_of(:username) }
12
+ end
13
+
14
+ describe "equality" do
15
+ it "is equal to another member with the same username" do
16
+ member = Member.new(username: "piero")
17
+ same_member = Member.new(username: "piero")
18
+ different_member = Member.new(username: "tommaso")
19
+
20
+ member.should == same_member
21
+ member.should_not == different_member
22
+ end
23
+ end
24
+
25
+ describe ".build_from" do
26
+ it "builds a Member from a Trello Member" do
27
+ member = Member.build_from(Trello::Member.new("username" => "piero"))
28
+
29
+ member.username.should == "piero"
30
+ end
31
+
32
+ it "takes the Trello Member id and set it as trello_id" do
33
+ member = Member.build_from(Trello::Member.new("username" => "piero", "id" => "1234567abc"))
34
+
35
+ member.id.should_not == "1234567abc"
36
+ member.trello_id.should == "1234567abc"
37
+ end
38
+ end
39
+
40
+ describe "#effort_spent" do
41
+ %w{piero tommaso}.each do |username|
42
+ let(username.to_sym) { Member.new(username: username) }
43
+ end
44
+
45
+ let(:card) { TrackedCard.create(name: "any", short_id: 1234, trello_id: "123123") }
46
+ let(:another_card) { TrackedCard.create(name: "any_other", short_id: 1235, trello_id: "123125") }
47
+
48
+ it "is zero when the member did not spent effort at all" do
49
+ piero.effort_spent.should == 0
50
+ end
51
+
52
+ it "counts the effort spent on a card" do
53
+ card.efforts << Effort.new(amount: 4, date: Date.today, members: [piero, tommaso])
54
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
55
+
56
+ piero.effort_spent.should == 4 / 2
57
+ end
58
+
59
+ it "counts the effort spent on several cards" do
60
+ card.efforts << Effort.new(amount: 4, date: Date.today, members: [piero, tommaso])
61
+ another_card.efforts << Effort.new(amount: 5, date: Date.today, members: [piero])
62
+
63
+ piero.effort_spent.should == 2 + 5
64
+ end
65
+
66
+ it "counts the effort spent on a card from a given date" do
67
+ card.efforts << Effort.new(amount: 4, date: Date.yesterday, members: [piero])
68
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [piero])
69
+
70
+ piero.effort_spent(Date.today).should == 5
71
+ piero.effort_spent_since(Date.today).should == 5
72
+ end
73
+
74
+ end
75
+
76
+ describe "#avatar_url" do
77
+ it "points to the avatar thumbnail image" do
78
+ member = Member.new(avatar_id: "123xyz")
79
+ member.avatar_url.should == "https://trello-avatars.s3.amazonaws.com/123xyz/30.png"
80
+ end
81
+ end
82
+ end
83
+ end