trollolo 0.2.0 → 0.3.0

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/lib/scrum/creator.rb CHANGED
@@ -9,7 +9,7 @@ module Scrum
9
9
  private
10
10
 
11
11
  def create_labels(board_id)
12
- @scrum.label_names.each { |_, name| Trello::Label.create(name: name, board_id: board_id) }
12
+ @scrum.label_names.each_value { |name| Trello::Label.create(name: name, board_id: board_id) }
13
13
  end
14
14
 
15
15
  def create_sprint_board
data/lib/scrum_board.rb CHANGED
@@ -12,6 +12,14 @@ class ScrumBoard
12
12
  @columns ||= @board_data['lists'].map{|x| Column.new(@board_data, x['id'], @settings)}
13
13
  end
14
14
 
15
+ def todo_columns
16
+ columns.select{|c| @settings.todo_columns.include?(c.name)}
17
+ end
18
+
19
+ def doing_columns
20
+ columns.select{|c| @settings.doing_columns.include?(c.name) }
21
+ end
22
+
15
23
  def done_column
16
24
  done_columns = columns.select{|c| c.name =~ @settings.done_column_name_regex }
17
25
  if done_columns.empty?
@@ -21,8 +29,11 @@ class ScrumBoard
21
29
  end
22
30
  end
23
31
 
32
+ def accepted_columns
33
+ columns.select{|c| c.name =~ @settings.accepted_column_name_regex }
34
+ end
35
+
24
36
  def accepted_column
25
- accepted_columns = columns.select{|c| c.name =~ @settings.accepted_column_name_regex }
26
37
  if accepted_columns.empty?
27
38
  EmptyColumn.new
28
39
  else
data/lib/settings.rb CHANGED
@@ -18,9 +18,9 @@
18
18
  class Settings
19
19
 
20
20
  attr_accessor :developer_public_key, :member_token, :board_aliases, :verbose,
21
- :raw, :not_done_columns, :todo_column, :accepted_column_name_regex,
21
+ :raw, :not_done_columns, :todo_columns, :doing_columns, :accepted_column_name_regex,
22
22
  :done_column_name_regex, :todo_column_name_regex, :scrum,
23
- :no_task_checklists
23
+ :no_task_checklists, :swimlanes
24
24
 
25
25
  def initialize(config_file_path)
26
26
  @config_file_path = config_file_path
@@ -34,10 +34,12 @@ class Settings
34
34
  @scrum = OpenStruct.new(@config['scrum'] || scrum_defaults)
35
35
  @not_done_columns = @config['not_done_columns'].freeze || ['Sprint Backlog', 'Doing']
36
36
  @no_task_checklists = @config['no_task_checklists'].freeze || ['Feedback']
37
- @todo_column = @config['todo_column'].freeze
37
+ @todo_columns = @config['todo_columns'].freeze || ['Sprint Backlog']
38
+ @doing_columns = @config['doing_columns'].freeze || ['Doing']
38
39
  @done_column_name_regex = @config['done_column_name_regex'].freeze || /\ADone/
39
40
  @accepted_column_name_regex = @config['accepted_column_name_regex'].freeze || /\AAccepted/
40
41
  @todo_column_name_regex = @config['todo_column_name_regex'].freeze || /\ATo Do\Z/
42
+ @swimlanes = @config['swimlanes'].freeze || []
41
43
  else
42
44
  raise "Couldn't read config data from '#{config_file_path}'"
43
45
  end
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Trollolo
2
2
 
3
- VERSION = '0.2.0'.freeze
3
+ VERSION = '0.3.0'.freeze
4
4
 
5
5
  end
@@ -0,0 +1,32 @@
1
+ ---
2
+ meta:
3
+ board_id: myboardid
4
+ doing_columns:
5
+ - Doing
6
+ - QA
7
+ sprint: 2
8
+ total_days: 9
9
+ weekend_lines:
10
+ - 3.5
11
+ - 7.5
12
+ days:
13
+ - date: '2014-04-23'
14
+ updated_at: '2014-04-23T10:00:00+01:00'
15
+ story_points:
16
+ total: 30
17
+ open: 23
18
+ tasks:
19
+ total: 25
20
+ open: 21
21
+ - date: '2014-04-24'
22
+ updated_at: '2014-04-24T19:00:00+01:00'
23
+ story_points:
24
+ total: 30
25
+ open: 21
26
+ tasks:
27
+ total: 26
28
+ open: 19
29
+ story_points_extra:
30
+ done: 3
31
+ tasks_extra:
32
+ done: 2
@@ -0,0 +1,32 @@
1
+ ---
2
+ meta:
3
+ board_id: myboardid
4
+ swimlanes:
5
+ - Swimlane One
6
+ - swimlanetwo
7
+ sprint: 2
8
+ total_days: 9
9
+ weekend_lines:
10
+ - 3.5
11
+ - 7.5
12
+ days:
13
+ - date: '2014-04-23'
14
+ updated_at: '2014-04-23T10:00:00+01:00'
15
+ story_points:
16
+ total: 30
17
+ open: 23
18
+ tasks:
19
+ total: 25
20
+ open: 21
21
+ - date: '2014-04-24'
22
+ updated_at: '2014-04-24T19:00:00+01:00'
23
+ story_points:
24
+ total: 30
25
+ open: 21
26
+ tasks:
27
+ total: 26
28
+ open: 19
29
+ story_points_extra:
30
+ done: 3
31
+ tasks_extra:
32
+ done: 2
@@ -0,0 +1,35 @@
1
+ ---
2
+ meta:
3
+ board_id: myboardid
4
+ todo_columns:
5
+ - Swimlane Backlog
6
+ - Sprint Backlog
7
+ swimlanes:
8
+ - Swimlane One
9
+ - swimlanetwo
10
+ sprint: 2
11
+ total_days: 9
12
+ weekend_lines:
13
+ - 3.5
14
+ - 7.5
15
+ days:
16
+ - date: '2014-04-23'
17
+ updated_at: '2014-04-23T10:00:00+01:00'
18
+ story_points:
19
+ total: 30
20
+ open: 23
21
+ tasks:
22
+ total: 25
23
+ open: 21
24
+ - date: '2014-04-24'
25
+ updated_at: '2014-04-24T19:00:00+01:00'
26
+ story_points:
27
+ total: 30
28
+ open: 21
29
+ tasks:
30
+ total: 26
31
+ open: 19
32
+ story_points_extra:
33
+ done: 3
34
+ tasks_extra:
35
+ done: 2
@@ -22,8 +22,8 @@ def compare_images_for_sprint(sprint_number, extra_args = [])
22
22
 
23
23
  result = run_helper(@working_dir, sprint_number, extra_args)
24
24
  expect(result).to exit_with_success('')
25
- expect(File.join(@working_dir, "burndown-#{sprint_number}.png")).
26
- to be_same_image_as("create_burndown_helper/burndown-#{sprint_number}.png")
25
+ expect(File.join(@working_dir, "burndown-#{sprint_number}.png"))
26
+ .to be_same_image_as("create_burndown_helper/burndown-#{sprint_number}.png")
27
27
  end
28
28
 
29
29
  describe 'create_burndown.py' do
@@ -0,0 +1,96 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe BoardMock do
4
+ context 'one column' do
5
+ let :subject do
6
+ BoardMock.new
7
+ .list('One')
8
+ end
9
+
10
+ it 'has one column' do
11
+ expect(subject.columns.count).to eq(1)
12
+ end
13
+
14
+ it 'has no cards' do
15
+ expect(subject.cards.count).to eq(0)
16
+ end
17
+ end
18
+
19
+ context 'two columns' do
20
+ let :subject do
21
+ board = BoardMock.new
22
+ board.list('One')
23
+ board.list('Two')
24
+ board
25
+ end
26
+
27
+ it 'has two columns' do
28
+ expect(subject.columns.count).to eq(2)
29
+ end
30
+
31
+ it 'has no cards' do
32
+ expect(subject.cards.count).to eq(0)
33
+ end
34
+ end
35
+
36
+ context 'one column and two cards' do
37
+ let :subject do
38
+ board = BoardMock.new
39
+ list = board.list('One')
40
+ list.card('Red')
41
+ list.card('Green')
42
+ board
43
+ end
44
+
45
+ it 'has one column' do
46
+ expect(subject.columns.count).to eq(1)
47
+ end
48
+
49
+ it 'has two cards' do
50
+ expect(subject.cards.count).to eq(2)
51
+ end
52
+ end
53
+
54
+ context 'two columns and two cards each' do
55
+ let :subject do
56
+ BoardMock.new
57
+ .list('One')
58
+ .card('Red')
59
+ .card('Green')
60
+ .list('Two')
61
+ .card('Blue')
62
+ .card('Yellow')
63
+ end
64
+
65
+ it 'has two columns' do
66
+ expect(subject.columns.count).to eq(2)
67
+ end
68
+
69
+ it 'has four cards' do
70
+ expect(subject.cards.count).to eq(4)
71
+ end
72
+
73
+ it 'has two cards in each list' do
74
+ subject.columns.each do |column|
75
+ expect(column.cards.count).to eq(2)
76
+ end
77
+ end
78
+ end
79
+
80
+ context 'one card with one label' do
81
+ let :subject do
82
+ BoardMock.new
83
+ .list('One')
84
+ .card('Red')
85
+ .label('Cold')
86
+ end
87
+
88
+ it 'has one card' do
89
+ expect(subject.cards.count).to eq(1)
90
+ end
91
+
92
+ it 'card has one label' do
93
+ expect(subject.cards.first.label?('Cold'))
94
+ end
95
+ end
96
+ end
@@ -234,10 +234,25 @@ describe BurndownChart do
234
234
  expect(@chart.data['days']).to eq @raw_data
235
235
  end
236
236
 
237
+ it 'reads todo columns' do
238
+ @chart.read_data given_file('burndown-data.yaml', from: 'burndown-data-with-todo-columns.yaml')
239
+ expect(@settings.todo_columns).to eq ['Swimlane Backlog', 'Sprint Backlog']
240
+ end
241
+
242
+ it 'reads doing columns' do
243
+ @chart.read_data given_file('burndown-data.yaml', from: 'burndown-data-with-doing-columns.yaml')
244
+ expect(@settings.doing_columns).to eq ['Doing', 'QA']
245
+ end
246
+
237
247
  it 'reads not done columns' do
238
248
  @chart.read_data given_file('burndown-data.yaml', from: 'burndown-data-with-config.yaml')
239
249
  expect(@settings.not_done_columns).to eq ['Sprint Backlog', 'Doing', 'QA']
240
250
  end
251
+
252
+ it 'reads swimlanes' do
253
+ @chart.read_data given_file('burndown-data.yaml', from: 'burndown-data-with-swimlanes.yaml')
254
+ expect(@settings.swimlanes).to eq ['Swimlane One', 'swimlanetwo']
255
+ end
241
256
  end
242
257
 
243
258
  describe '#write_data' do
@@ -3,146 +3,205 @@ require_relative 'spec_helper'
3
3
  include GivenFilesystemSpecHelpers
4
4
 
5
5
  describe BurndownData do
6
- before(:each) do
7
- @burndown = BurndownData.new(dummy_settings)
8
- @burndown.board_id = '53186e8391ef8671265eba9d'
9
- full_board_mock
10
- end
11
-
12
- describe BurndownData::Result do
13
- it 'calculates total' do
14
- r = described_class.new
15
- r.open = 7
16
- r.done = 4
17
-
18
- expect(r.total).to eq 11
19
- end
20
- end
21
-
22
- describe 'setters' do
23
- it 'sets open story points' do
24
- @burndown.story_points.open = 13
25
- expect(@burndown.story_points.open).to eq 13
6
+ context 'with full board mock' do
7
+ before(:each) do
8
+ @burndown = BurndownData.new(dummy_settings)
9
+ @burndown.board_id = '53186e8391ef8671265eba9d'
10
+ full_board_mock
26
11
  end
27
12
 
28
- it 'sets open tasks' do
29
- @burndown.tasks.open = 42
30
- expect(@burndown.tasks.open).to eq 42
31
- end
32
- end
13
+ describe BurndownData::Result do
14
+ it 'calculates total' do
15
+ r = described_class.new
16
+ r.open = 7
17
+ r.done = 4
33
18
 
34
- describe '#fetch' do
35
- context 'with meta data on sprint card' do
36
- before do
37
- @burndown.fetch
19
+ expect(r.total).to eq 11
38
20
  end
21
+ end
39
22
 
40
- it 'returns story points' do
41
- expect( @burndown.story_points.total ).to eq 16
42
- expect( @burndown.story_points.open ).to eq 13
43
- expect( @burndown.story_points.done ).to eq 3
23
+ describe 'setters' do
24
+ it 'sets open story points' do
25
+ @burndown.story_points.open = 13
26
+ expect(@burndown.story_points.open).to eq 13
44
27
  end
45
28
 
46
- it 'returns extra story points' do
47
- expect( @burndown.extra_story_points.total ).to eq 8
48
- expect( @burndown.extra_story_points.open ).to eq 8
49
- expect( @burndown.extra_story_points.done ).to eq 0
29
+ it 'sets open tasks' do
30
+ @burndown.tasks.open = 42
31
+ expect(@burndown.tasks.open).to eq 42
50
32
  end
33
+ end
51
34
 
52
- it 'returns unplanned story points' do
53
- expect( @burndown.unplanned_story_points.total ).to eq 3
54
- expect( @burndown.unplanned_story_points.open ).to eq 1
55
- expect( @burndown.unplanned_story_points.done ).to eq 2
35
+ describe '#fetch' do
36
+ context 'with meta data on sprint card' do
37
+ before do
38
+ @burndown.fetch
39
+ end
40
+
41
+ it 'returns story points' do
42
+ expect( @burndown.story_points.total ).to eq 16
43
+ expect( @burndown.story_points.open ).to eq 13
44
+ expect( @burndown.story_points.done ).to eq 3
45
+ end
46
+
47
+ it 'returns extra story points' do
48
+ expect( @burndown.extra_story_points.total ).to eq 8
49
+ expect( @burndown.extra_story_points.open ).to eq 8
50
+ expect( @burndown.extra_story_points.done ).to eq 0
51
+ end
52
+
53
+ it 'returns unplanned story points' do
54
+ expect( @burndown.unplanned_story_points.total ).to eq 3
55
+ expect( @burndown.unplanned_story_points.open ).to eq 1
56
+ expect( @burndown.unplanned_story_points.done ).to eq 2
57
+ end
58
+
59
+ it 'returns tasks' do
60
+ expect( @burndown.tasks.total ).to eq 13
61
+ expect( @burndown.tasks.open ).to eq 9
62
+ expect( @burndown.tasks.done ).to eq 4
63
+ end
64
+
65
+ it 'returns extra tasks' do
66
+ expect( @burndown.extra_tasks.total ).to eq 1
67
+ expect( @burndown.extra_tasks.open ).to eq 1
68
+ expect( @burndown.extra_tasks.done ).to eq 0
69
+ end
70
+
71
+ it 'returns unplanned tasks' do
72
+ expect( @burndown.unplanned_tasks.total ).to eq 2
73
+ expect( @burndown.unplanned_tasks.open ).to eq 1
74
+ expect( @burndown.unplanned_tasks.done ).to eq 1
75
+ end
76
+
77
+ it 'returns meta data' do
78
+ expect( @burndown.meta ).to eq( 'sprint' => 10,
79
+ 'total_days' => 18,
80
+ 'weekend_lines' => [1.5, 6.5, 11.5, 16.5])
81
+ end
82
+
83
+ it 'saves date and time' do
84
+ expected_date_time = DateTime.parse('2015-01-12T13:57:16+01:00')
85
+ allow(DateTime).to receive(:now).and_return(expected_date_time)
86
+ @burndown.fetch
87
+ expect(@burndown.date_time).to eq(expected_date_time)
88
+ end
56
89
  end
57
90
 
58
- it 'returns tasks' do
59
- expect( @burndown.tasks.total ).to eq 13
60
- expect( @burndown.tasks.open ).to eq 9
61
- expect( @burndown.tasks.done ).to eq 4
62
- end
91
+ context 'without meta data on sprint card' do
92
+ before do
93
+ allow(Card).to receive(:parse_yaml_from_description).and_return(nil)
94
+ @burndown.fetch
95
+ end
63
96
 
64
- it 'returns extra tasks' do
65
- expect( @burndown.extra_tasks.total ).to eq 1
66
- expect( @burndown.extra_tasks.open ).to eq 1
67
- expect( @burndown.extra_tasks.done ).to eq 0
68
- end
69
-
70
- it 'returns unplanned tasks' do
71
- expect( @burndown.unplanned_tasks.total ).to eq 2
72
- expect( @burndown.unplanned_tasks.open ).to eq 1
73
- expect( @burndown.unplanned_tasks.done ).to eq 1
97
+ it 'does not fail' do
98
+ expect(@burndown.meta).to be(nil)
99
+ end
74
100
  end
101
+ end
75
102
 
76
- it 'returns meta data' do
77
- expect( @burndown.meta ).to eq( 'sprint' => 10,
78
- 'total_days' => 18,
79
- 'weekend_lines' => [1.5, 6.5, 11.5, 16.5])
80
- end
103
+ describe '#to_hash' do
104
+ it 'converts to hash' do
105
+ @burndown.story_points.open = 1
106
+ @burndown.story_points.done = 2
107
+ @burndown.tasks.open = 3
108
+ @burndown.tasks.done = 4
109
+ @burndown.extra_story_points.open = 5
110
+ @burndown.extra_story_points.done = 6
111
+ @burndown.extra_tasks.open = 7
112
+ @burndown.extra_tasks.done = 8
113
+ @burndown.unplanned_story_points.open = 1
114
+ @burndown.unplanned_story_points.done = 2
115
+ @burndown.unplanned_tasks.open = 1
116
+ @burndown.unplanned_tasks.done = 1
117
+ @burndown.date_time = DateTime.parse('20150115')
118
+
119
+ expected_hash = {
120
+ 'date' => '2015-01-15',
121
+ 'updated_at' => '2015-01-15T00:00:00+00:00',
122
+ 'story_points' => {
123
+ 'total' => 3,
124
+ 'open' => 1
125
+ },
126
+ 'tasks' => {
127
+ 'total' => 7,
128
+ 'open' => 3
129
+ },
130
+ 'story_points_extra' => {
131
+ 'done' => 6
132
+ },
133
+ 'tasks_extra' => {
134
+ 'done' => 8
135
+ },
136
+ 'unplanned_story_points' => {
137
+ 'total' => 3,
138
+ 'open' => 1
139
+ },
140
+ 'unplanned_tasks' => {
141
+ 'total' => 2,
142
+ 'open' => 1
143
+ }
144
+ }
81
145
 
82
- it 'saves date and time' do
83
- expected_date_time = DateTime.parse('2015-01-12T13:57:16+01:00')
84
- allow(DateTime).to receive(:now).and_return(expected_date_time)
85
- @burndown.fetch
86
- expect(@burndown.date_time).to eq(expected_date_time)
146
+ expect(@burndown.to_hash).to eq(expected_hash)
87
147
  end
88
148
  end
149
+ end
89
150
 
90
- context 'without meta data on sprint card' do
91
- before do
92
- allow(Card).to receive(:parse_yaml_from_description).and_return(nil)
93
- @burndown.fetch
94
- end
151
+ context 'board with swimlanes' do
152
+ let :subject do
153
+ settings = dummy_settings
154
+ settings.todo_columns = ['Swimlane Backlog', 'Sprint Backlog']
155
+ settings.swimlanes = ['myswimlane']
156
+
157
+ mock_board = BoardMock.new(settings)
158
+ .list('Swimlane Backlog')
159
+ .card('(2) Three')
160
+ .label('myswimlane')
161
+ .list('Sprint Backlog')
162
+ .card('(3) One')
163
+ .card('(5) Two')
164
+ .list('Doing')
165
+ .card('(7) Two')
166
+ .label('myswimlane')
167
+ .list('Done')
168
+ .card('(11) Four')
169
+ .card('(13) Five')
170
+ .label('myswimlane')
171
+ .list('Accepted Sprint 2')
172
+ .card('(17) Six')
173
+ .label('myswimlane')
174
+ .list('Accepted Sprint 1')
175
+ .card('(21) Seven')
176
+ .label('myswimlane')
177
+
178
+ burndown = BurndownData.new(settings)
179
+ allow(burndown).to receive(:board).and_return mock_board
180
+ burndown.fetch
181
+ burndown
182
+ end
95
183
 
96
- it 'does not fail' do
97
- expect(@burndown.meta).to be(nil)
98
- end
184
+ it 'ignores swimlane story points' do
185
+ expect(subject.story_points.open).to eq(8)
186
+ expect(subject.story_points.done).to eq(11)
99
187
  end
100
- end
101
188
 
102
- describe '#to_hash' do
103
- it 'converts to hash' do
104
- @burndown.story_points.open = 1
105
- @burndown.story_points.done = 2
106
- @burndown.tasks.open = 3
107
- @burndown.tasks.done = 4
108
- @burndown.extra_story_points.open = 5
109
- @burndown.extra_story_points.done = 6
110
- @burndown.extra_tasks.open = 7
111
- @burndown.extra_tasks.done = 8
112
- @burndown.unplanned_story_points.open = 1
113
- @burndown.unplanned_story_points.done = 2
114
- @burndown.unplanned_tasks.open = 1
115
- @burndown.unplanned_tasks.done = 1
116
- @burndown.date_time = DateTime.parse('20150115')
189
+ it 'records swimlane story points' do
190
+ expect(subject.swimlanes['myswimlane'].todo).to eq(2)
191
+ expect(subject.swimlanes['myswimlane'].doing).to eq(7)
192
+ expect(subject.swimlanes['myswimlane'].done).to eq(51)
193
+ end
117
194
 
195
+ it 'includes swimlane story points in hash' do
118
196
  expected_hash = {
119
- 'date' => '2015-01-15',
120
- 'updated_at' => '2015-01-15T00:00:00+00:00',
121
- 'story_points' => {
122
- 'total' => 3,
123
- 'open' => 1
124
- },
125
- 'tasks' => {
126
- 'total' => 7,
127
- 'open' => 3
128
- },
129
- 'story_points_extra' => {
130
- 'done' => 6
131
- },
132
- 'tasks_extra' => {
133
- 'done' => 8
134
- },
135
- 'unplanned_story_points' => {
136
- 'total' => 3,
137
- 'open' => 1
138
- },
139
- 'unplanned_tasks' => {
140
- 'total' => 2,
141
- 'open' => 1
197
+ 'myswimlane' => {
198
+ 'todo' => 2,
199
+ 'doing' => 7,
200
+ 'done' => 51
142
201
  }
143
202
  }
144
-
145
- expect(@burndown.to_hash).to eq(expected_hash)
203
+ expect(subject.to_hash.key?('swimlanes')).to be true
204
+ expect(subject.to_hash['swimlanes']).to eq(expected_hash)
146
205
  end
147
206
  end
148
207
  end