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.
- data/.gitignore +2 -1
- data/.travis.yml +0 -1
- data/CHANGELOG +17 -0
- data/Gemfile +7 -4
- data/Gemfile.lock +27 -13
- data/README.md +106 -36
- data/Rakefile +1 -1
- data/config/config.template.yml +0 -1
- data/config/config.yml.trackinguser_for_test +7 -0
- data/lib/patches/trello/card.rb +19 -0
- data/lib/patches/trello/member.rb +5 -5
- data/lib/trello_effort_tracker/tracked_card.rb +17 -10
- data/lib/trello_effort_tracker/tracking/base.rb +82 -0
- data/lib/trello_effort_tracker/tracking/card_done_tracking.rb +10 -0
- data/lib/trello_effort_tracker/tracking/effort_tracking.rb +45 -0
- data/lib/trello_effort_tracker/tracking/estimate_tracking.rb +23 -0
- data/lib/trello_effort_tracker/tracking/invalid_tracking.rb +19 -0
- data/lib/trello_effort_tracker/tracking_factory.rb +22 -0
- data/lib/trello_effort_tracker/trello_authorize.rb +4 -20
- data/lib/trello_effort_tracker/trello_tracker.rb +5 -10
- data/lib/trello_effort_tracker/version.rb +1 -1
- data/lib/trello_effort_tracker.rb +7 -1
- data/spec/integration/trello_tracker_spec.rb +69 -0
- data/spec/patches/trello/card_spec.rb +25 -0
- data/spec/spec_helper.rb +46 -1
- data/spec/support/database_cleaner.rb +12 -0
- data/spec/tracked_card_spec.rb +56 -5
- data/spec/tracking/card_done_tracking_spec.rb +18 -0
- data/spec/tracking/effort_tracking_spec.rb +114 -0
- data/spec/tracking/estimate_tracking_spec.rb +44 -0
- data/spec/tracking_factory_spec.rb +42 -0
- data/spec/trello_authorize_spec.rb +10 -16
- data/spec/trello_configuration_spec.rb +2 -2
- data/trello_effort_tracker.gemspec +12 -0
- metadata +131 -5
- data/lib/trello_effort_tracker/tracking.rb +0 -130
- data/spec/tracking_spec.rb +0 -236
@@ -16,41 +16,37 @@ describe TrelloAuthorize do
|
|
16
16
|
describe "#authorize_on_trello" do
|
17
17
|
|
18
18
|
it "creates oath credentials using auth params given as params when present as arguments, ignoring env vars or config YML vars" do
|
19
|
-
ENV["developer_public_key"] = ENV["access_token_key"] =
|
19
|
+
ENV["developer_public_key"] = ENV["access_token_key"] = "anything"
|
20
20
|
YAML.should_receive(:load_file).never
|
21
21
|
|
22
|
-
authorize_on_trello("developer_public_key" => "custom_dpk", "access_token_key" => "custom_atk"
|
22
|
+
authorize_on_trello("developer_public_key" => "custom_dpk", "access_token_key" => "custom_atk")
|
23
23
|
|
24
|
-
Trello
|
25
|
-
Trello
|
26
|
-
Trello::Authorization::OAuthPolicy.token.key.should == "custom_atk"
|
24
|
+
Trello.client.auth_policy.developer_public_key.should == "custom_dpk"
|
25
|
+
Trello.client.auth_policy.member_token.should == "custom_atk"
|
27
26
|
end
|
28
27
|
|
29
28
|
it "creates oath credentials using auth params taken from env variables when auth params are not given as arguments" do
|
30
29
|
ENV["developer_public_key"] = "my_dpk"
|
31
30
|
ENV["access_token_key"] = "my_atk"
|
32
|
-
ENV["developer_secret"] = "my_ds"
|
33
31
|
|
34
32
|
YAML.should_receive(:load_file).never
|
35
33
|
|
36
34
|
authorize_on_trello("any" => "thing")
|
37
35
|
|
38
|
-
Trello
|
39
|
-
Trello
|
40
|
-
Trello::Authorization::OAuthPolicy.token.key.should == "my_atk"
|
36
|
+
Trello.client.auth_policy.developer_public_key.should == "my_dpk"
|
37
|
+
Trello.client.auth_policy.member_token.should == "my_atk"
|
41
38
|
end
|
42
39
|
|
43
40
|
it "creates oath credentials using auth params from config file when auth env variables are not set" do
|
44
|
-
ENV["developer_public_key"] = ENV["access_token_key"] =
|
41
|
+
ENV["developer_public_key"] = ENV["access_token_key"] = nil
|
45
42
|
|
46
|
-
config_hash = {"trello" => { "developer_public_key" => "any_dpk", "access_token_key" => "any_atk"
|
43
|
+
config_hash = {"trello" => { "developer_public_key" => "any_dpk", "access_token_key" => "any_atk"}}
|
47
44
|
YAML.should_receive(:load_file).with("config/config.yml").and_return(config_hash)
|
48
45
|
|
49
46
|
authorize_on_trello("any" => "thing")
|
50
47
|
|
51
|
-
Trello
|
52
|
-
Trello
|
53
|
-
Trello::Authorization::OAuthPolicy.token.key.should == "any_atk"
|
48
|
+
Trello.client.auth_policy.developer_public_key.should == "any_dpk"
|
49
|
+
Trello.client.auth_policy.member_token.should == "any_atk"
|
54
50
|
end
|
55
51
|
|
56
52
|
end
|
@@ -60,12 +56,10 @@ describe TrelloAuthorize do
|
|
60
56
|
def keep_original_auth_envs
|
61
57
|
@original_developer_public_key = ENV["developer_public_key"]
|
62
58
|
@original_access_token_key = ENV["access_token_key"]
|
63
|
-
@original_developer_secret = ENV["developer_secret"]
|
64
59
|
end
|
65
60
|
|
66
61
|
def reset_original_auth_envs
|
67
62
|
ENV["developer_public_key"] = @original_developer_public_key
|
68
63
|
ENV["access_token_key"] = @original_access_token_key
|
69
|
-
ENV["developer_secret"] = @original_developer_secre
|
70
64
|
end
|
71
65
|
end
|
@@ -6,12 +6,11 @@ describe TrelloConfiguration do
|
|
6
6
|
|
7
7
|
describe "#authorization_params_from_config_file" do
|
8
8
|
it "loads the default trello auth params from config yml" do
|
9
|
-
config_hash = {"trello" => { "developer_public_key" => "any_dpk", "access_token_key" => "any_atk"
|
9
|
+
config_hash = { "trello" => { "developer_public_key" => "any_dpk", "access_token_key" => "any_atk" } }
|
10
10
|
YAML.should_receive(:load_file).with("config/config.yml").and_return(config_hash)
|
11
11
|
|
12
12
|
authorization_params_from_config_file["developer_public_key"].should == "any_dpk"
|
13
13
|
authorization_params_from_config_file["access_token_key"].should == "any_atk"
|
14
|
-
authorization_params_from_config_file["developer_secret"].should == "any_ds"
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
@@ -30,6 +29,7 @@ describe TrelloConfiguration do
|
|
30
29
|
|
31
30
|
tracker_username.should == "my_tracker"
|
32
31
|
end
|
32
|
+
|
33
33
|
it "searches for the trello tracker username in the config yml file if the env var is not set" do
|
34
34
|
ENV["tracker_username"] = nil
|
35
35
|
config_hash = {"tracker_username" => "my_trello_tracker" }
|
@@ -4,16 +4,28 @@ require File.expand_path('../lib/trello_effort_tracker/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.name = "trello_effort_tracker"
|
6
6
|
gem.version = TrelloEffortTracker::VERSION
|
7
|
+
gem.platform = Gem::Platform::RUBY
|
8
|
+
|
7
9
|
gem.description = "A tool to extract estimates and efforts from Trello"
|
8
10
|
gem.summary = "You notify all the estimates and efforts of your Trello cards. This tool will extract and store these estimates and actual efforts to let you extract useful key metrics (e.g. estimate errors)"
|
9
11
|
gem.authors = ['Pietro Di Bello']
|
10
12
|
gem.email = 'pierodibello@gmail.com'
|
11
13
|
gem.homepage = 'http://xplayer.wordpress.com'
|
12
14
|
gem.date = Time.now.strftime "%Y-%m-%d"
|
15
|
+
|
13
16
|
gem.require_paths = ["lib"]
|
14
17
|
gem.files = `git ls-files`.split("\n")
|
15
18
|
gem.test_files = `git ls-files -- {spec}/*`.split("\n")
|
16
19
|
gem.extra_rdoc_files = ["README.md"]
|
20
|
+
|
17
21
|
gem.rubygems_version = %q{1.8.24}
|
18
22
|
gem.required_rubygems_version = ">= 1.3.6"
|
23
|
+
|
24
|
+
gem.add_dependency 'ruby-trello'
|
25
|
+
gem.add_dependency 'mongoid'
|
26
|
+
gem.add_dependency 'bson_ext'
|
27
|
+
gem.add_dependency 'google_drive'
|
28
|
+
gem.add_dependency 'rainbow'
|
29
|
+
gem.add_dependency 'chronic'
|
30
|
+
gem.add_dependency 'highline'
|
19
31
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trello_effort_tracker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,120 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
13
|
-
dependencies:
|
12
|
+
date: 2013-02-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ruby-trello
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: mongoid
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bson_ext
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: google_drive
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rainbow
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: chronic
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: highline
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
14
126
|
description: A tool to extract estimates and efforts from Trello
|
15
127
|
email: pierodibello@gmail.com
|
16
128
|
executables: []
|
@@ -22,13 +134,16 @@ files:
|
|
22
134
|
- .rspec
|
23
135
|
- .rvmrc.template
|
24
136
|
- .travis.yml
|
137
|
+
- CHANGELOG
|
25
138
|
- Gemfile
|
26
139
|
- Gemfile.lock
|
27
140
|
- LICENSE.txt
|
28
141
|
- README.md
|
29
142
|
- Rakefile
|
30
143
|
- config/config.template.yml
|
144
|
+
- config/config.yml.trackinguser_for_test
|
31
145
|
- config/mongoid.template.yml
|
146
|
+
- lib/patches/trello/card.rb
|
32
147
|
- lib/patches/trello/member.rb
|
33
148
|
- lib/startup_trello.rb
|
34
149
|
- lib/trello_effort_tracker.rb
|
@@ -38,7 +153,12 @@ files:
|
|
38
153
|
- lib/trello_effort_tracker/member.rb
|
39
154
|
- lib/trello_effort_tracker/mongoid_helper.rb
|
40
155
|
- lib/trello_effort_tracker/tracked_card.rb
|
41
|
-
- lib/trello_effort_tracker/tracking.rb
|
156
|
+
- lib/trello_effort_tracker/tracking/base.rb
|
157
|
+
- lib/trello_effort_tracker/tracking/card_done_tracking.rb
|
158
|
+
- lib/trello_effort_tracker/tracking/effort_tracking.rb
|
159
|
+
- lib/trello_effort_tracker/tracking/estimate_tracking.rb
|
160
|
+
- lib/trello_effort_tracker/tracking/invalid_tracking.rb
|
161
|
+
- lib/trello_effort_tracker/tracking_factory.rb
|
42
162
|
- lib/trello_effort_tracker/trello_authorize.rb
|
43
163
|
- lib/trello_effort_tracker/trello_configuration.rb
|
44
164
|
- lib/trello_effort_tracker/trello_tracker.rb
|
@@ -50,10 +170,16 @@ files:
|
|
50
170
|
- spec/effort_spec.rb
|
51
171
|
- spec/estimate_spec.rb
|
52
172
|
- spec/integration/trello_authorization_spec.rb
|
173
|
+
- spec/integration/trello_tracker_spec.rb
|
53
174
|
- spec/member_spec.rb
|
175
|
+
- spec/patches/trello/card_spec.rb
|
54
176
|
- spec/spec_helper.rb
|
177
|
+
- spec/support/database_cleaner.rb
|
55
178
|
- spec/tracked_card_spec.rb
|
56
|
-
- spec/
|
179
|
+
- spec/tracking/card_done_tracking_spec.rb
|
180
|
+
- spec/tracking/effort_tracking_spec.rb
|
181
|
+
- spec/tracking/estimate_tracking_spec.rb
|
182
|
+
- spec/tracking_factory_spec.rb
|
57
183
|
- spec/trello_authorize_spec.rb
|
58
184
|
- spec/trello_configuration_spec.rb
|
59
185
|
- trello_effort_tracker.gemspec
|
@@ -1,130 +0,0 @@
|
|
1
|
-
class Tracking
|
2
|
-
extend Forwardable
|
3
|
-
include TrelloConfiguration
|
4
|
-
|
5
|
-
TIME_CONVERTERS = {
|
6
|
-
'h' => lambda { |estimate| estimate },
|
7
|
-
'd' => lambda { |estimate| estimate * 8 },
|
8
|
-
'g' => lambda { |estimate| estimate * 8 },
|
9
|
-
'p' => lambda { |estimate| estimate / 2 }
|
10
|
-
}
|
11
|
-
|
12
|
-
DURATION_REGEXP = '(\d+\.?\d*[phdg])'
|
13
|
-
DATE_REGEXP = /(\d{2})\.(\d{2})\.(\d{4})/
|
14
|
-
|
15
|
-
# delegate to the trello notification the member_creator method aliased as 'notifier'
|
16
|
-
def_delegator :@tracking_notification, :member_creator, :notifier
|
17
|
-
|
18
|
-
def initialize(tracking_notification)
|
19
|
-
@tracking_notification = tracking_notification
|
20
|
-
end
|
21
|
-
|
22
|
-
def date
|
23
|
-
Chronic.parse(date_as_string).to_date
|
24
|
-
end
|
25
|
-
|
26
|
-
def estimate?
|
27
|
-
!raw_estimate.nil?
|
28
|
-
end
|
29
|
-
|
30
|
-
def estimate
|
31
|
-
estimate = convert_to_hours(raw_estimate)
|
32
|
-
Estimate.new(amount: estimate, date: date, tracking_notification_id: @tracking_notification.id) if estimate
|
33
|
-
end
|
34
|
-
|
35
|
-
def effort?
|
36
|
-
!raw_effort.nil?
|
37
|
-
end
|
38
|
-
|
39
|
-
def effort
|
40
|
-
effort_amount = convert_to_hours(raw_effort)
|
41
|
-
if effort_amount
|
42
|
-
total_effort = effort_amount * effort_members.size
|
43
|
-
Effort.new(amount: total_effort, date: date, members: effort_members, tracking_notification_id: @tracking_notification.id)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def unknown_format?
|
48
|
-
!estimate? && !effort?
|
49
|
-
end
|
50
|
-
|
51
|
-
def to_s
|
52
|
-
"[#{date}] From #{notifier.username.color(:green)}\t on card '#{trello_card.name.color(:yellow)}': #{raw_text}"
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def effort_members
|
58
|
-
@effort_members ||= users_involved_in_the_effort.map do |username|
|
59
|
-
Member.build_from(Trello::Member.find(username))
|
60
|
-
end
|
61
|
-
|
62
|
-
@effort_members
|
63
|
-
end
|
64
|
-
|
65
|
-
def users_involved_in_the_effort
|
66
|
-
users_involved_in_the_effort = raw_tracking.scan(/@(\w+)/).flatten
|
67
|
-
users_involved_in_the_effort << notifier.username unless should_count_only_listed_members?
|
68
|
-
|
69
|
-
users_involved_in_the_effort
|
70
|
-
end
|
71
|
-
|
72
|
-
def should_count_only_listed_members?
|
73
|
-
raw_tracking =~ /\((@\w+\W*\s*)+\)/
|
74
|
-
end
|
75
|
-
|
76
|
-
def raw_tracking
|
77
|
-
raw_text.gsub("@#{tracker_username}", "")
|
78
|
-
end
|
79
|
-
|
80
|
-
def raw_text
|
81
|
-
@tracking_notification.data['text']
|
82
|
-
end
|
83
|
-
|
84
|
-
def raw_estimate
|
85
|
-
extract_match_from_raw_tracking(/\[#{DURATION_REGEXP}\]/)
|
86
|
-
end
|
87
|
-
|
88
|
-
def raw_effort
|
89
|
-
extract_match_from_raw_tracking(/\+#{DURATION_REGEXP}/)
|
90
|
-
end
|
91
|
-
|
92
|
-
def convert_to_hours(duration_as_string)
|
93
|
-
return if duration_as_string.nil?
|
94
|
-
|
95
|
-
time_scale = duration_as_string.slice!(-1)
|
96
|
-
converter = TIME_CONVERTERS[time_scale]
|
97
|
-
converter.call(Float(duration_as_string))
|
98
|
-
end
|
99
|
-
|
100
|
-
def date_as_string
|
101
|
-
case raw_tracking
|
102
|
-
when DATE_REGEXP
|
103
|
-
day, month, year = raw_tracking.scan(DATE_REGEXP).flatten
|
104
|
-
"#{year}-#{month}-#{day}"
|
105
|
-
when /yesterday\s+\+#{DURATION_REGEXP}/, /\+#{DURATION_REGEXP}\s+yesterday/
|
106
|
-
(notification_date - 1).to_s
|
107
|
-
else
|
108
|
-
@tracking_notification.date
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def extract_match_from_raw_tracking(regexp)
|
113
|
-
extracted = nil
|
114
|
-
raw_tracking.scan(regexp) do |match|
|
115
|
-
extracted = match.first
|
116
|
-
end
|
117
|
-
|
118
|
-
extracted
|
119
|
-
end
|
120
|
-
|
121
|
-
def trello_card
|
122
|
-
@trello_card ||= @tracking_notification.card
|
123
|
-
end
|
124
|
-
|
125
|
-
def notification_date
|
126
|
-
Chronic.parse(@tracking_notification.date).to_date
|
127
|
-
end
|
128
|
-
|
129
|
-
end
|
130
|
-
|
data/spec/tracking_spec.rb
DELETED
@@ -1,236 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Tracking do
|
4
|
-
|
5
|
-
TIME_MEASUREMENTS = {
|
6
|
-
hours: 'h',
|
7
|
-
days: 'd',
|
8
|
-
giorni: 'g',
|
9
|
-
pomodori: 'p'
|
10
|
-
}
|
11
|
-
|
12
|
-
let(:unrecognized_notification) { create_notification(data: { 'text' => '@trackinguser hi there!' }) }
|
13
|
-
|
14
|
-
describe "#unknown_format?" do
|
15
|
-
it "tells when a notification cannot be interpreted as a tracking info" do
|
16
|
-
Tracking.new(unrecognized_notification).unknown_format?.should be_true
|
17
|
-
|
18
|
-
with_message("@trackinguser +30m") { |tracking| tracking.unknown_format?.should be_true }
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
describe "#estimate?" do
|
24
|
-
it "is false when the notification does not contain an estimate" do
|
25
|
-
Tracking.new(unrecognized_notification).estimate?.should be_false
|
26
|
-
end
|
27
|
-
|
28
|
-
TIME_MEASUREMENTS.each_key do |time_measurement|
|
29
|
-
it "is true when the notification contains an estimate in #{time_measurement}" do
|
30
|
-
tracking_estimate = Tracking.new(create_estimate(time_measurement))
|
31
|
-
|
32
|
-
tracking_estimate.estimate?.should be_true
|
33
|
-
tracking_estimate.effort?.should be_false
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
describe "#estimate" do
|
40
|
-
|
41
|
-
it "is nil when the notification does not contain an estimate" do
|
42
|
-
Tracking.new(unrecognized_notification).estimate.should be_nil
|
43
|
-
end
|
44
|
-
|
45
|
-
it "is the hour-based estimate when the notification contains an estimate in hours" do
|
46
|
-
raw_data = create_notification(data: { 'text' => "@trackinguser [2h]" }, date: "2012-10-28T21:06:14.801Z")
|
47
|
-
|
48
|
-
Tracking.new(raw_data).estimate.should == Estimate.new(amount: 2.0, date: Date.parse('2012-10-28'))
|
49
|
-
end
|
50
|
-
|
51
|
-
it "converts the estimate in hours when the notification contains an estimate in days" do
|
52
|
-
Tracking.new(create_notification(data: { 'text' => "@trackinguser [1.5d]" })).estimate.amount.should == 8+4
|
53
|
-
Tracking.new(create_notification(data: { 'text' => "@trackinguser [1.5g]" })).estimate.amount.should == 8+4
|
54
|
-
end
|
55
|
-
|
56
|
-
it "converts the estimate in hours when the notification contains an estimate in pomodori" do
|
57
|
-
raw_data = create_notification(data: { 'text' => "@trackinguser [10p]" })
|
58
|
-
Tracking.new(raw_data).estimate.amount.should == 5
|
59
|
-
end
|
60
|
-
|
61
|
-
it "fetch the estimate from a complex estimate message" do
|
62
|
-
raw_data = create_notification(data: { 'text' => "@maxmazza Dobbiamo ancora lavorarci.\n@trackinguser ristimo ancora [3h] per il fix" })
|
63
|
-
Tracking.new(raw_data).estimate.amount.should == 3.0
|
64
|
-
end
|
65
|
-
|
66
|
-
it "tracks the effort with the date given in the notification text, not the actual notification date" do
|
67
|
-
raw_data = create_notification( data: { 'text' => "@trackinguser 22.11.2012 [6p]" }, date: "2012-09-19T12:46:13.713Z")
|
68
|
-
|
69
|
-
tracking = Tracking.new(raw_data)
|
70
|
-
|
71
|
-
tracking.estimate.date.should == Date.parse('2012-11-22')
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
describe "#effort?" do
|
77
|
-
it "is false when the notification does not contain an estimate" do
|
78
|
-
Tracking.new(unrecognized_notification).effort?.should be_false
|
79
|
-
end
|
80
|
-
|
81
|
-
TIME_MEASUREMENTS.each_key do |time_measurement|
|
82
|
-
it "is true when the notification contains an estimate in #{time_measurement}" do
|
83
|
-
tracking_effort = Tracking.new(create_effort(time_measurement))
|
84
|
-
|
85
|
-
tracking_effort.effort?.should be_true
|
86
|
-
tracking_effort.estimate?.should be_false
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
describe "#effort" do
|
92
|
-
|
93
|
-
%w{pietrodibello michelepangrazzi alessandrodescovi michelevincenzi}.each do |username|
|
94
|
-
let(username.to_sym) { Member.new(username: username) }
|
95
|
-
end
|
96
|
-
|
97
|
-
before(:each) do
|
98
|
-
Trello::Member.stub(:find).and_return(Member.new(username: "any"))
|
99
|
-
end
|
100
|
-
|
101
|
-
it "is nil when the notification does not contain an estimate" do
|
102
|
-
with(unrecognized_notification) { |tracking| tracking.effort.should be_nil }
|
103
|
-
end
|
104
|
-
|
105
|
-
it "does not parse effort in minutes (e.g. +30m)" do
|
106
|
-
with_message("@trackinguser +30m") { |tracking| tracking.effort.should be_nil }
|
107
|
-
end
|
108
|
-
|
109
|
-
it "is the hour-based effort when the notification contains an effort in hours" do
|
110
|
-
Trello::Member.should_receive(:find).with("michelepangrazzi").and_return(michelepangrazzi)
|
111
|
-
|
112
|
-
raw_data = create_notification(data: { 'text' => "@trackinguser +2h" },
|
113
|
-
date: "2012-10-28T21:06:14.801Z",
|
114
|
-
member_creator: stub(username: "michelepangrazzi"))
|
115
|
-
|
116
|
-
Tracking.new(raw_data).effort.should == Effort.new(amount: 2.0, date: Date.parse('2012-10-28'), members: [michelepangrazzi])
|
117
|
-
end
|
118
|
-
|
119
|
-
it "converts the effort in hours when the notification contains an effort in days" do
|
120
|
-
with_message("@trackinguser +1.5d") { |t| t.effort.amount.should == 8+4 }
|
121
|
-
with_message("@trackinguser +1.5g") { |t| t.effort.amount.should == 8+4 }
|
122
|
-
end
|
123
|
-
|
124
|
-
it "converts the effort in hours when the notification contains an effort in pomodori" do
|
125
|
-
with_message("@trackinguser +10p") { |t| t.effort.amount.should == 5}
|
126
|
-
end
|
127
|
-
|
128
|
-
it "fetch the effort from a complex effort message" do
|
129
|
-
with_message "@trackinguser ho speso +2h e spero che stavolta possiamo rilasciarla" do |tracking|
|
130
|
-
tracking.effort.amount.should == 2.0
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
it "fetch the effort even when beween square brackets" do
|
135
|
-
with_message "@trackinguser [+0.5h]" do |tracking|
|
136
|
-
tracking.effort.amount.should == 0.5
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
it "computes the effort considering all the mentioned team mates in the message" do
|
141
|
-
with_message "@trackinguser +2h assieme a @michelepangrazzi e @alessandrodescovi" do |tracking|
|
142
|
-
tracking.effort.amount.should == 2.0 * 3
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
it "tracks all the team mates which spent that effort on the card" do
|
147
|
-
%w{pietrodibello michelepangrazzi alessandrodescovi}.each do |username|
|
148
|
-
Trello::Member.should_receive(:find).with(username).and_return(self.send(username))
|
149
|
-
end
|
150
|
-
|
151
|
-
notification = create_notification(data: { 'text' => "@trackinguser +2h assieme a @michelepangrazzi e @alessandrodescovi" },
|
152
|
-
member_creator: stub(username: "pietrodibello"))
|
153
|
-
with notification do |tracking|
|
154
|
-
tracking.effort.members.should == [michelepangrazzi, alessandrodescovi, pietrodibello]
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
it "tracks the effort only on the team members listed between round brackets" do
|
159
|
-
%w{michelevincenzi alessandrodescovi}.each do |username|
|
160
|
-
Trello::Member.should_receive(:find).with(username).and_return(self.send(username))
|
161
|
-
end
|
162
|
-
|
163
|
-
notification = create_notification(data: { 'text' => "@trackinguser +3p (@alessandrodescovi @michelevincenzi)" },
|
164
|
-
member_creator: stub(username: "pietrodibello"))
|
165
|
-
|
166
|
-
with notification do |tracking|
|
167
|
-
tracking.effort.members.should == [alessandrodescovi, michelevincenzi]
|
168
|
-
tracking.effort.amount.should == 1.5 * 2
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
it "does not have an effort when is an estimate" do
|
173
|
-
raw_data = create_notification(data: { 'text' => "@trackinguser stimata [6h]" })
|
174
|
-
|
175
|
-
tracking = Tracking.new(raw_data)
|
176
|
-
|
177
|
-
tracking.effort.should be_nil
|
178
|
-
end
|
179
|
-
|
180
|
-
it "tracks the effort with the date given in the notification text, not the actual notification date" do
|
181
|
-
raw_data = create_notification(data: { 'text' => "@trackinguser 22.11.2012 +6p" }, date: "2012-09-19T12:46:13.713Z")
|
182
|
-
|
183
|
-
tracking = Tracking.new(raw_data)
|
184
|
-
|
185
|
-
tracking.effort.date.should == Date.parse('2012-11-22')
|
186
|
-
end
|
187
|
-
|
188
|
-
it "tracks the effort to yesterday when the keyword 'yesterday' is present before the effort amount" do
|
189
|
-
raw_data = create_notification(data: { 'text' => "@trackinguser yesterday +6p" }, date: "2012-09-19T12:46:13.713Z")
|
190
|
-
|
191
|
-
tracking = Tracking.new(raw_data)
|
192
|
-
|
193
|
-
tracking.effort.date.should == Date.parse('2012-09-18')
|
194
|
-
end
|
195
|
-
|
196
|
-
it "tracks the effort to yesterday when the keyword 'yesterday' is present before the effort amount" do
|
197
|
-
raw_data = create_notification(data: { 'text' => "@trackinguser +6p yesterday" }, date: "2012-09-19T12:46:13.713Z")
|
198
|
-
|
199
|
-
tracking = Tracking.new(raw_data)
|
200
|
-
|
201
|
-
tracking.effort.date.should == Date.parse('2012-09-18')
|
202
|
-
end
|
203
|
-
|
204
|
-
end
|
205
|
-
|
206
|
-
private
|
207
|
-
|
208
|
-
def notification_with_message(message)
|
209
|
-
create_notification(data: { 'text' => message })
|
210
|
-
end
|
211
|
-
|
212
|
-
def create_notification(custom_params)
|
213
|
-
params = { data: { 'text' => "@trackinguser +2h" }, date: "2012-10-28T21:06:14.801Z", member_creator: stub(username: "pietrodibello") }
|
214
|
-
params.merge!(custom_params)
|
215
|
-
|
216
|
-
stub(data: params[:data], date: params[:date], member_creator: params[:member_creator]).as_null_object
|
217
|
-
end
|
218
|
-
|
219
|
-
def create_estimate(time_measurement)
|
220
|
-
create_notification(data: { 'text' => "@trackinguser [1.5#{TIME_MEASUREMENTS[time_measurement]}]" })
|
221
|
-
end
|
222
|
-
|
223
|
-
def create_effort(time_measurement)
|
224
|
-
create_notification(data: { 'text' => "@trackinguser +4.5#{TIME_MEASUREMENTS[time_measurement]}]" })
|
225
|
-
end
|
226
|
-
|
227
|
-
def with(notification)
|
228
|
-
tracking = Tracking.new(notification)
|
229
|
-
yield(tracking)
|
230
|
-
end
|
231
|
-
|
232
|
-
def with_message(notification_message, &block)
|
233
|
-
with(notification_with_message(notification_message), &block)
|
234
|
-
end
|
235
|
-
|
236
|
-
end
|