trello_lead_time 0.1.2 → 0.1.3
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +15 -5
- data/lib/trello_lead_time/board.rb +12 -0
- data/lib/trello_lead_time/card.rb +10 -5
- data/lib/trello_lead_time/config.rb +6 -1
- data/lib/trello_lead_time/list.rb +48 -0
- data/lib/trello_lead_time/version.rb +1 -1
- data/sample.rb +8 -1
- data/spec/fixtures/comments.json +1 -1
- data/spec/fixtures/labels.1111.json +1 -0
- data/spec/fixtures/labels.2222.json +1 -0
- data/spec/fixtures/labels.3333.json +1 -0
- data/spec/fixtures/labels.4444.json +1 -0
- data/spec/lib/trello_lead_time/board_spec.rb +53 -0
- data/spec/lib/trello_lead_time/card_spec.rb +9 -1
- data/spec/lib/trello_lead_time/config_spec.rb +17 -1
- data/spec/lib/trello_lead_time/list_spec.rb +67 -0
- data/spec/spec_helper.rb +1 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99edb0b33c6e54cfeaaf2b33a9f1a30a9207ef3c
|
4
|
+
data.tar.gz: 53abfe5d13488621fb6aa181bc824c9b8cb3b71b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ab0c95cb5dd91bb05b48f0e85bdb81a517b01c1032ee777ec35bd3f73962b159b75230931ec2aec5c8de8f65c7f04b831a8f3bb3c4cc62e46288575afa7b680
|
7
|
+
data.tar.gz: 6458a52dbc862e23a4dcd4ffe196259ada4f352acb791da5b33f7fd694cd88d92ba74d247daf4386e74247713e0767de076922d97f91e0a7b8cae8634adedca0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -50,6 +50,10 @@ Now, configure how you will calculate the metrics.
|
|
50
50
|
queue_time_lists = ['Next Up']
|
51
51
|
cycle_time_lists = ['In Progress', 'Testing']
|
52
52
|
|
53
|
+
Lead time analysis can be performed on a per-label basis. Create an array of labels and for which you want to get the total lead time of cards with those labels.
|
54
|
+
|
55
|
+
finance_type_labels = ['Feature', 'Bug']
|
56
|
+
|
53
57
|
When analyzing the timeline of each Trello card, the gem has to find out when it was moved into a "Done" state. This usually is the event when the card is placed in the one of the `source_lists`, e.g. "Live (4/8)".
|
54
58
|
|
55
59
|
You must provide a regular expression that will be compared to the names of lists a Trello card was in (at some point of its life) to identify when it was marked done.
|
@@ -59,11 +63,12 @@ You must provide a regular expression that will be compared to the names of list
|
|
59
63
|
Now that all those variables are set, you can configure the gem!
|
60
64
|
|
61
65
|
TrelloLeadTime.configure do |cfg|
|
62
|
-
cfg.organization_name
|
63
|
-
cfg.
|
64
|
-
cfg.
|
65
|
-
cfg.
|
66
|
+
cfg.organization_name = organization_name
|
67
|
+
cfg.queue_time_lists = queue_time_lists
|
68
|
+
cfg.cycle_time_lists = cycle_time_lists
|
69
|
+
cfg.finance_type_labels = finance_type_labels
|
66
70
|
cfg.list_name_matcher_for_done = /^Live/
|
71
|
+
cfg.set_trello_key_and_token(developer_public_key, member_token)
|
67
72
|
end
|
68
73
|
|
69
74
|
Easy right? Now let's put it to use!
|
@@ -78,7 +83,7 @@ Easy right? Now let's put it to use!
|
|
78
83
|
totals = board.totals(source_list)
|
79
84
|
averages = board.averages(source_list)
|
80
85
|
|
81
|
-
puts "
|
86
|
+
puts "Overall metrics for: #{source_list}"
|
82
87
|
puts "\tAverage Card Age: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(averages[:age][:overall])}"
|
83
88
|
puts "\tAverage Lead Time: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(averages[:lead_time][:overall])}"
|
84
89
|
puts "\tAverage Queue Time: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(averages[:queue_time][:overall])}"
|
@@ -89,6 +94,11 @@ Easy right? Now let's put it to use!
|
|
89
94
|
puts "\tTotal Queue Time: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(totals[:queue_time][:overall])}"
|
90
95
|
puts "\tTotal Cycle Time: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(totals[:lead_time][:overall])}"
|
91
96
|
puts ""
|
97
|
+
puts "\tFinance type breakdown (total lead time per label):"
|
98
|
+
totals[:lead_time][:finance_types].each do |label, value|
|
99
|
+
puts "\t\t#{label}: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(value)}"
|
100
|
+
end
|
101
|
+
puts ""
|
92
102
|
end
|
93
103
|
|
94
104
|
For each of the source lists, the cards are analyzed and aggregate (average and total) metrics are displayed. This takes some time because the Trello API must be hit for each card being analyzed. Therefore, the longer the lists in Trello, the longer it takes to process.
|
@@ -30,6 +30,12 @@ module TrelloLeadTime
|
|
30
30
|
response[:queue_time][:overall] = list.total_queue_time
|
31
31
|
response[:cycle_time][:overall] = list.total_cycle_time
|
32
32
|
response[:age][:overall] = list.total_age
|
33
|
+
|
34
|
+
breakdown_by_labels = list.breakdown_by_labels(Config.finance_type_labels)
|
35
|
+
response[:lead_time][:finance_types] = breakdown_by_labels[:total][:lead_time]
|
36
|
+
response[:queue_time][:finance_types] = breakdown_by_labels[:total][:queue_time]
|
37
|
+
response[:cycle_time][:finance_types] = breakdown_by_labels[:total][:cycle_time]
|
38
|
+
response[:age][:finance_types] = breakdown_by_labels[:total][:age]
|
33
39
|
response
|
34
40
|
end
|
35
41
|
|
@@ -42,6 +48,12 @@ module TrelloLeadTime
|
|
42
48
|
response[:queue_time][:overall] = list.average_queue_time
|
43
49
|
response[:cycle_time][:overall] = list.average_cycle_time
|
44
50
|
response[:age][:overall] = list.average_age
|
51
|
+
|
52
|
+
breakdown_by_labels = list.breakdown_by_labels(Config.finance_type_labels)
|
53
|
+
response[:lead_time][:finance_types] = breakdown_by_labels[:average][:lead_time]
|
54
|
+
response[:queue_time][:finance_types] = breakdown_by_labels[:average][:queue_time]
|
55
|
+
response[:cycle_time][:finance_types] = breakdown_by_labels[:average][:cycle_time]
|
56
|
+
response[:age][:finance_types] = breakdown_by_labels[:average][:age]
|
45
57
|
response
|
46
58
|
end
|
47
59
|
|
@@ -48,7 +48,16 @@ module TrelloLeadTime
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def hash_tags
|
51
|
-
comments.select { |comment| comment =~ /^#(.+)$/ } || []
|
51
|
+
comments_with_tags = comments.select { |comment| comment =~ /^#(.+)$/ } || []
|
52
|
+
tags = []
|
53
|
+
comments_with_tags.each do |comment|
|
54
|
+
tags.concat(comment.split.find_all { |word| /^#.+/.match(word) })
|
55
|
+
end
|
56
|
+
tags
|
57
|
+
end
|
58
|
+
|
59
|
+
def labels
|
60
|
+
@_labels ||= @trello_card.labels.map { |label| OpenStruct.new({name: label.name, color: label.color}) }
|
52
61
|
end
|
53
62
|
|
54
63
|
private
|
@@ -57,10 +66,6 @@ module TrelloLeadTime
|
|
57
66
|
lists.inject(0) { |sum, list_name| sum + @timeline.seconds_in_list(list_name) }
|
58
67
|
end
|
59
68
|
|
60
|
-
def labels
|
61
|
-
@_labels ||= @trello_card.labels
|
62
|
-
end
|
63
|
-
|
64
69
|
def comments
|
65
70
|
@_comments ||= @trello_card.actions(filter:"commentCard").map { |comment| comment.data['text'] }
|
66
71
|
end
|
@@ -5,7 +5,7 @@ module TrelloLeadTime
|
|
5
5
|
module Config
|
6
6
|
extend self
|
7
7
|
|
8
|
-
attr_accessor :organization_name, :queue_time_lists, :cycle_time_lists, :list_name_matcher_for_done
|
8
|
+
attr_accessor :organization_name, :queue_time_lists, :cycle_time_lists, :finance_type_labels, :list_name_matcher_for_done
|
9
9
|
|
10
10
|
def configure
|
11
11
|
reset!
|
@@ -29,6 +29,11 @@ module TrelloLeadTime
|
|
29
29
|
@cycle_time_lists
|
30
30
|
end
|
31
31
|
|
32
|
+
def finance_type_labels
|
33
|
+
@finance_type_labels = %w{CapEx OpEx} if !@finance_type_labels
|
34
|
+
@finance_type_labels
|
35
|
+
end
|
36
|
+
|
32
37
|
def list_name_matcher_for_done
|
33
38
|
@list_name_matcher_for_done = /^Done/i if !@list_name_matcher_for_done
|
34
39
|
@list_name_matcher_for_done
|
@@ -52,6 +52,34 @@ module TrelloLeadTime
|
|
52
52
|
average(times)
|
53
53
|
end
|
54
54
|
|
55
|
+
def breakdown_by_labels(labels)
|
56
|
+
times = default_breakdown_by_labels(labels)
|
57
|
+
|
58
|
+
done_or_closed_cards.each do |card|
|
59
|
+
matches = labels & card.labels.map(&:name)
|
60
|
+
matches.each do |label|
|
61
|
+
times[:total][:lead_time][label] += card.lead_time
|
62
|
+
times[:total][:queue_time][label] += card.queue_time
|
63
|
+
times[:total][:cycle_time][label] += card.cycle_time
|
64
|
+
times[:total][:age][label] += card.age_in_seconds
|
65
|
+
|
66
|
+
times[:average][:lead_time][label].push card.lead_time
|
67
|
+
times[:average][:queue_time][label].push card.queue_time
|
68
|
+
times[:average][:cycle_time][label].push card.cycle_time
|
69
|
+
times[:average][:age][label].push card.age_in_seconds
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
labels.each do |label|
|
74
|
+
times[:average][:lead_time][label] = average(times[:average][:lead_time][label])
|
75
|
+
times[:average][:queue_time][label] = average(times[:average][:queue_time][label])
|
76
|
+
times[:average][:cycle_time][label] = average(times[:average][:cycle_time][label])
|
77
|
+
times[:average][:age][label] = average(times[:average][:age][label])
|
78
|
+
end
|
79
|
+
|
80
|
+
times
|
81
|
+
end
|
82
|
+
|
55
83
|
private
|
56
84
|
|
57
85
|
def done_or_closed_cards
|
@@ -73,5 +101,25 @@ module TrelloLeadTime
|
|
73
101
|
end
|
74
102
|
avg
|
75
103
|
end
|
104
|
+
|
105
|
+
def default_breakdown_by_labels(labels)
|
106
|
+
times = {
|
107
|
+
total: { lead_time: {}, queue_time: {}, cycle_time: {}, age: {} },
|
108
|
+
average: { lead_time: {}, queue_time: {}, cycle_time: {}, age: {} }
|
109
|
+
}
|
110
|
+
labels.each do |label|
|
111
|
+
times[:total][:lead_time][label] = 0
|
112
|
+
times[:total][:queue_time][label] = 0
|
113
|
+
times[:total][:cycle_time][label] = 0
|
114
|
+
times[:total][:age][label] = 0
|
115
|
+
|
116
|
+
times[:average][:lead_time][label] = []
|
117
|
+
times[:average][:queue_time][label] = []
|
118
|
+
times[:average][:cycle_time][label] = []
|
119
|
+
times[:average][:age][label] = []
|
120
|
+
end
|
121
|
+
times
|
122
|
+
end
|
123
|
+
|
76
124
|
end
|
77
125
|
end
|
data/sample.rb
CHANGED
@@ -7,6 +7,7 @@ board_url = 'https://trello.com/b/nC8QJJoZ/trello-development'
|
|
7
7
|
source_lists = ['Live (4/8)', 'Live (3/17)', 'Live (3/3)', 'Live (2/11)', 'Live (1/14)']
|
8
8
|
queue_time_lists = ['Next Up']
|
9
9
|
cycle_time_lists = ['In Progress', 'Testing']
|
10
|
+
finance_type_labels = ['Feature', 'Bug']
|
10
11
|
list_name_matcher_for_done = /^Live/
|
11
12
|
|
12
13
|
TrelloLeadTime.configure do |cfg|
|
@@ -14,6 +15,7 @@ TrelloLeadTime.configure do |cfg|
|
|
14
15
|
cfg.set_trello_key_and_token(developer_public_key, member_token)
|
15
16
|
cfg.queue_time_lists = queue_time_lists
|
16
17
|
cfg.cycle_time_lists = cycle_time_lists
|
18
|
+
cfg.finance_type_labels = finance_type_labels
|
17
19
|
cfg.list_name_matcher_for_done = list_name_matcher_for_done
|
18
20
|
end
|
19
21
|
|
@@ -28,7 +30,7 @@ source_lists.each do |source_list|
|
|
28
30
|
totals = board.totals(source_list)
|
29
31
|
averages = board.averages(source_list)
|
30
32
|
|
31
|
-
puts "
|
33
|
+
puts "Overall metrics for: #{source_list}"
|
32
34
|
puts "\tAverage Card Age: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(averages[:age][:overall])}"
|
33
35
|
puts "\tAverage Lead Time: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(averages[:lead_time][:overall])}"
|
34
36
|
puts "\tAverage Queue Time: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(averages[:queue_time][:overall])}"
|
@@ -39,4 +41,9 @@ source_lists.each do |source_list|
|
|
39
41
|
puts "\tTotal Queue Time: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(totals[:queue_time][:overall])}"
|
40
42
|
puts "\tTotal Cycle Time: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(totals[:lead_time][:overall])}"
|
41
43
|
puts ""
|
44
|
+
puts "\tFinance type breakdown (total lead time per label):"
|
45
|
+
totals[:lead_time][:finance_types].each do |label, value|
|
46
|
+
puts "\t\t#{label}: #{TrelloLeadTime::TimeHumanizer.humanize_seconds(value)}"
|
47
|
+
end
|
48
|
+
puts ""
|
42
49
|
end
|
data/spec/fixtures/comments.json
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
[{"color":"green","name":"CapEx"}]
|
@@ -0,0 +1 @@
|
|
1
|
+
[{"color":"purple","name":"OpEx"}]
|
@@ -0,0 +1 @@
|
|
1
|
+
[{"color":"green","name":"CapEx"}]
|
@@ -0,0 +1 @@
|
|
1
|
+
[{"color":"orange","name":"iOS"},{"color":"yellow","name":"Needs definition"}]
|
@@ -39,6 +39,15 @@ describe TrelloLeadTime::Board do
|
|
39
39
|
}
|
40
40
|
}
|
41
41
|
|
42
|
+
let(:labels_json) {
|
43
|
+
{
|
44
|
+
"1111" => File.read(File.expand_path("../../../fixtures/labels.1111.json", __FILE__)),
|
45
|
+
"2222" => File.read(File.expand_path("../../../fixtures/labels.2222.json", __FILE__)),
|
46
|
+
"3333" => File.read(File.expand_path("../../../fixtures/labels.3333.json", __FILE__)),
|
47
|
+
"4444" => File.read(File.expand_path("../../../fixtures/labels.4444.json", __FILE__))
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
42
51
|
subject { TrelloLeadTime::Board.from_url(board_url) }
|
43
52
|
|
44
53
|
describe ".totals" do
|
@@ -63,6 +72,26 @@ describe TrelloLeadTime::Board do
|
|
63
72
|
stub_all_requests
|
64
73
|
totals[:age][:overall].should == 4512370
|
65
74
|
end
|
75
|
+
|
76
|
+
it "should have a lead time breakdown by finance type" do
|
77
|
+
stub_all_requests
|
78
|
+
totals[:lead_time][:finance_types].should == {"CapEx" => 1664755, "OpEx" => 474615}
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should have a queue time breakdown by finance type" do
|
82
|
+
stub_all_requests
|
83
|
+
totals[:queue_time][:finance_types].should == {"CapEx" => 864055, "OpEx" => 177300}
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should have a cycle time breakdown by finance type" do
|
87
|
+
stub_all_requests
|
88
|
+
totals[:cycle_time][:finance_types].should == {"CapEx" => 800700, "OpEx" => 297315}
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should have an age breakdown by finance type" do
|
92
|
+
stub_all_requests
|
93
|
+
totals[:age][:finance_types].should == {"CapEx" => 1664755, "OpEx" => 474615}
|
94
|
+
end
|
66
95
|
end
|
67
96
|
|
68
97
|
describe ".averages" do
|
@@ -87,6 +116,26 @@ describe TrelloLeadTime::Board do
|
|
87
116
|
stub_all_requests
|
88
117
|
averages[:age][:overall].should == 1128093
|
89
118
|
end
|
119
|
+
|
120
|
+
it "should have a lead time breakdown by finance type" do
|
121
|
+
stub_all_requests
|
122
|
+
averages[:lead_time][:finance_types].should == {"CapEx" => 832378, "OpEx" => 474615}
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should have a queue time breakdown by finance type" do
|
126
|
+
stub_all_requests
|
127
|
+
averages[:queue_time][:finance_types].should == {"CapEx" => 432028, "OpEx" => 177300}
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should have a cycle time breakdown by finance type" do
|
131
|
+
stub_all_requests
|
132
|
+
averages[:cycle_time][:finance_types].should == {"CapEx" => 400350, "OpEx" => 297315}
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should have an age breakdown by finance type" do
|
136
|
+
stub_all_requests
|
137
|
+
averages[:age][:finance_types].should == {"CapEx" => 832378, "OpEx" => 474615}
|
138
|
+
end
|
90
139
|
end
|
91
140
|
|
92
141
|
private
|
@@ -122,6 +171,10 @@ describe TrelloLeadTime::Board do
|
|
122
171
|
stub_request(:get, "https://api.trello.com/1/cards/#{card_id}/actions?filter=createCard,updateCard:idList,updateCard:closed&key=#{key}&token=#{token}").
|
123
172
|
with(headers).
|
124
173
|
to_return(stub_returns(actions_json[card_id]))
|
174
|
+
|
175
|
+
stub_request(:get, "https://api.trello.com/1/cards/#{card_id}/labels?key=#{key}&token=#{token}").
|
176
|
+
with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'User-Agent'=>'Ruby'}).
|
177
|
+
to_return(:status => 200, :body => labels_json[card_id], :headers => {})
|
125
178
|
end
|
126
179
|
end
|
127
180
|
|
@@ -42,7 +42,15 @@ describe TrelloLeadTime::Card do
|
|
42
42
|
describe ".hash_tags" do
|
43
43
|
it "should have a hash tag" do
|
44
44
|
do_stubs(key, token)
|
45
|
-
expect(subject.hash_tags).to eq(
|
45
|
+
expect(subject.hash_tags).to eq(%w{#tag1 #tag2 #tag3})
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe ".labels" do
|
50
|
+
it "should have labels" do
|
51
|
+
do_stubs(key, token)
|
52
|
+
expect(subject.labels.collect(&:name)).to eq(%w{iOS API})
|
53
|
+
|
46
54
|
end
|
47
55
|
end
|
48
56
|
|
@@ -7,15 +7,17 @@ describe TrelloLeadTime::Config do
|
|
7
7
|
organization_name: TrelloLeadTime::Config.organization_name,
|
8
8
|
queue_time_lists: TrelloLeadTime::Config.queue_time_lists,
|
9
9
|
cycle_time_lists: TrelloLeadTime::Config.cycle_time_lists,
|
10
|
+
finance_type_labels: TrelloLeadTime::Config.finance_type_labels,
|
10
11
|
list_name_matcher_for_done: TrelloLeadTime::Config.list_name_matcher_for_done
|
11
12
|
}
|
12
13
|
end
|
13
14
|
|
14
15
|
after(:all) do
|
15
16
|
TrelloLeadTime.configure do |cfg|
|
17
|
+
cfg.organization_name = @cfg[:organization_name]
|
16
18
|
cfg.queue_time_lists = @cfg[:queue_time_lists]
|
17
19
|
cfg.cycle_time_lists = @cfg[:cycle_time_lists]
|
18
|
-
cfg.
|
20
|
+
cfg.finance_type_labels = @cfg[:finance_type_labels]
|
19
21
|
cfg.list_name_matcher_for_done = @cfg[:list_name_matcher_for_done]
|
20
22
|
end
|
21
23
|
end
|
@@ -48,6 +50,20 @@ describe TrelloLeadTime::Config do
|
|
48
50
|
subject.cycle_time_lists.should include("my list")
|
49
51
|
end
|
50
52
|
|
53
|
+
it "should have default list for finance type labels" do
|
54
|
+
TrelloLeadTime.configure do |cfg|
|
55
|
+
cfg.finance_type_labels = nil
|
56
|
+
end
|
57
|
+
expect(subject.finance_type_labels).to eq(%w{CapEx OpEx})
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should set finance type labels" do
|
61
|
+
TrelloLeadTime.configure do |cfg|
|
62
|
+
cfg.finance_type_labels = ["my label"]
|
63
|
+
end
|
64
|
+
subject.finance_type_labels.should include("my label")
|
65
|
+
end
|
66
|
+
|
51
67
|
it "should have default done matcher" do
|
52
68
|
TrelloLeadTime.configure do |cfg|
|
53
69
|
cfg.list_name_matcher_for_done = nil
|
@@ -27,6 +27,19 @@ describe TrelloLeadTime::List do
|
|
27
27
|
}
|
28
28
|
}
|
29
29
|
|
30
|
+
let(:labels_json) {
|
31
|
+
{
|
32
|
+
"1111" => File.read(File.expand_path("../../../fixtures/labels.1111.json", __FILE__)),
|
33
|
+
"2222" => File.read(File.expand_path("../../../fixtures/labels.2222.json", __FILE__)),
|
34
|
+
"3333" => File.read(File.expand_path("../../../fixtures/labels.3333.json", __FILE__)),
|
35
|
+
"4444" => File.read(File.expand_path("../../../fixtures/labels.4444.json", __FILE__))
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
let(:labels) {
|
40
|
+
%w{CapEx OpEx}
|
41
|
+
}
|
42
|
+
|
30
43
|
subject { TrelloLeadTime::List.from_trello_list(list) }
|
31
44
|
|
32
45
|
it "should have an average age" do
|
@@ -69,6 +82,54 @@ describe TrelloLeadTime::List do
|
|
69
82
|
subject.total_cycle_time.should == 1815015
|
70
83
|
end
|
71
84
|
|
85
|
+
it "should have total lead times by label" do
|
86
|
+
stub_all_requests
|
87
|
+
times = subject.breakdown_by_labels(labels)
|
88
|
+
expect(times[:total][:lead_time]).to eq({"CapEx" => 1664755, "OpEx" => 474615})
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should have total queue times by label" do
|
92
|
+
stub_all_requests
|
93
|
+
times = subject.breakdown_by_labels(labels)
|
94
|
+
expect(times[:total][:queue_time]).to eq({"CapEx" => 864055, "OpEx" => 177300})
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should have total cycle times by label" do
|
98
|
+
stub_all_requests
|
99
|
+
times = subject.breakdown_by_labels(labels)
|
100
|
+
expect(times[:total][:cycle_time]).to eq({"CapEx" => 800700, "OpEx" => 297315})
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should have total ages by label" do
|
104
|
+
stub_all_requests
|
105
|
+
times = subject.breakdown_by_labels(labels)
|
106
|
+
expect(times[:total][:age]).to eq({"CapEx" => 1664755, "OpEx" => 474615})
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should have average lead times by label" do
|
110
|
+
stub_all_requests
|
111
|
+
times = subject.breakdown_by_labels(labels)
|
112
|
+
expect(times[:average][:lead_time]).to eq({"CapEx" => 832378, "OpEx" => 474615})
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should have average queue times by label" do
|
116
|
+
stub_all_requests
|
117
|
+
times = subject.breakdown_by_labels(labels)
|
118
|
+
expect(times[:average][:queue_time]).to eq({"CapEx" => 432028, "OpEx" => 177300})
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should have average cycle times by label" do
|
122
|
+
stub_all_requests
|
123
|
+
times = subject.breakdown_by_labels(labels)
|
124
|
+
expect(times[:average][:cycle_time]).to eq({"CapEx" => 400350, "OpEx" => 297315})
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should have average ages by label" do
|
128
|
+
stub_all_requests
|
129
|
+
times = subject.breakdown_by_labels(labels)
|
130
|
+
expect(times[:average][:age]).to eq({"CapEx" => 832378, "OpEx" => 474615})
|
131
|
+
end
|
132
|
+
|
72
133
|
private
|
73
134
|
|
74
135
|
def stub_all_requests
|
@@ -87,7 +148,13 @@ describe TrelloLeadTime::List do
|
|
87
148
|
stub_request(:get, "https://api.trello.com/1/cards/#{card_id}/actions?filter=createCard,updateCard:idList,updateCard:closed&key=#{key}&token=#{token}").
|
88
149
|
with(headers).
|
89
150
|
to_return(stub_returns(actions_json[card_id]))
|
151
|
+
|
152
|
+
stub_request(:get, "https://api.trello.com/1/cards/#{card_id}/labels?key=#{key}&token=#{token}").
|
153
|
+
with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'User-Agent'=>'Ruby'}).
|
154
|
+
to_return(:status => 200, :body => labels_json[card_id], :headers => {})
|
155
|
+
|
90
156
|
end
|
157
|
+
|
91
158
|
end
|
92
159
|
|
93
160
|
def headers
|
data/spec/spec_helper.rb
CHANGED
@@ -8,6 +8,7 @@ RSpec.configure do |config|
|
|
8
8
|
cfg.set_trello_key_and_token('key', 'token')
|
9
9
|
cfg.queue_time_lists = ['Product Backlog']
|
10
10
|
cfg.cycle_time_lists = ['Development', 'Acceptance']
|
11
|
+
cfg.finance_type_labels = ['CapEx', 'OpEx']
|
11
12
|
cfg.list_name_matcher_for_done = /^Done/i
|
12
13
|
end
|
13
14
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trello_lead_time
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Baldwin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -87,6 +87,10 @@ files:
|
|
87
87
|
- spec/fixtures/card.json
|
88
88
|
- spec/fixtures/cards.json
|
89
89
|
- spec/fixtures/comments.json
|
90
|
+
- spec/fixtures/labels.1111.json
|
91
|
+
- spec/fixtures/labels.2222.json
|
92
|
+
- spec/fixtures/labels.3333.json
|
93
|
+
- spec/fixtures/labels.4444.json
|
90
94
|
- spec/fixtures/labels.json
|
91
95
|
- spec/fixtures/lists.json
|
92
96
|
- spec/fixtures/organization.json
|
@@ -132,6 +136,10 @@ test_files:
|
|
132
136
|
- spec/fixtures/card.json
|
133
137
|
- spec/fixtures/cards.json
|
134
138
|
- spec/fixtures/comments.json
|
139
|
+
- spec/fixtures/labels.1111.json
|
140
|
+
- spec/fixtures/labels.2222.json
|
141
|
+
- spec/fixtures/labels.3333.json
|
142
|
+
- spec/fixtures/labels.4444.json
|
135
143
|
- spec/fixtures/labels.json
|
136
144
|
- spec/fixtures/lists.json
|
137
145
|
- spec/fixtures/organization.json
|