trollolo 0.1.1 → 0.2.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +21 -2
- data/.rubocop_todo.yml +105 -270
- data/CHANGELOG.md +10 -0
- data/CONTRIBUTING.md +6 -4
- data/Gemfile +1 -1
- data/README.md +10 -1
- data/Rakefile +4 -4
- data/bin/trollolo +2 -2
- data/lib/backup.rb +21 -23
- data/lib/burndown_chart.rb +46 -49
- data/lib/burndown_data.rb +21 -21
- data/lib/card.rb +23 -32
- data/lib/checklist.rb +13 -1
- data/lib/cli.rb +105 -110
- data/lib/column.rb +11 -10
- data/lib/empty_column.rb +2 -2
- data/lib/scrum/backlog_mover.rb +3 -3
- data/lib/scrum/card_type_detection.rb +1 -1
- data/lib/scrum/creator.rb +7 -7
- data/lib/scrum/prioritizer.rb +1 -1
- data/lib/scrum/sprint_board.rb +4 -4
- data/lib/scrum/sprint_cleaner.rb +3 -3
- data/lib/scrum/sprint_planning_board.rb +2 -4
- data/lib/scrum_board.rb +3 -3
- data/lib/settings.rb +29 -27
- data/lib/trello_service.rb +1 -1
- data/lib/trello_wrapper.rb +9 -9
- data/lib/version.rb +1 -1
- data/spec/data/card.json +19 -0
- data/spec/data/trollolorc +3 -0
- data/spec/integration/command_line_spec.rb +14 -14
- data/spec/integration/create_burndown_spec.rb +25 -25
- data/spec/integration/integration_spec_helper.rb +1 -1
- data/spec/integration/wrapper/credentials_input_wrapper +7 -11
- data/spec/integration/wrapper/empty_config_trollolo_wrapper +2 -2
- data/spec/integration/wrapper/trollolo_wrapper +2 -2
- data/spec/unit/backup_spec.rb +14 -14
- data/spec/unit/burndown_chart_spec.rb +176 -184
- data/spec/unit/burndown_data_spec.rb +21 -23
- data/spec/unit/card_spec.rb +38 -24
- data/spec/unit/cli_spec.rb +57 -57
- data/spec/unit/empty_column_spec.rb +1 -1
- data/spec/unit/retrieve_data_spec.rb +13 -13
- data/spec/unit/scrum/backlog_mover_spec.rb +8 -8
- data/spec/unit/scrum/card_type_detection_spec.rb +12 -12
- data/spec/unit/scrum/creator_spec.rb +8 -8
- data/spec/unit/scrum/prioritizer_spec.rb +19 -19
- data/spec/unit/scrum/priority_name_spec.rb +16 -16
- data/spec/unit/scrum/sprint_board_spec.rb +3 -3
- data/spec/unit/scrum/sprint_cleaner_spec.rb +15 -15
- data/spec/unit/scrum/sprint_planning_board_spec.rb +2 -2
- data/spec/unit/scrum_board_spec.rb +56 -56
- data/spec/unit/settings_spec.rb +23 -23
- data/spec/unit/spec_helper.rb +3 -3
- data/spec/unit/support/test_data_operations.rb +4 -0
- data/spec/unit/support/update_webmock_data +9 -11
- data/spec/unit/support/vcr.rb +3 -3
- data/spec/unit/support/webmocks.rb +21 -12
- data/spec/unit/trello_wrapper_spec.rb +40 -29
- data/trollolo.gemspec +3 -3
- metadata +8 -5
@@ -5,12 +5,12 @@ include GivenFilesystemSpecHelpers
|
|
5
5
|
describe BurndownData do
|
6
6
|
before(:each) do
|
7
7
|
@burndown = BurndownData.new(dummy_settings)
|
8
|
-
@burndown.board_id =
|
8
|
+
@burndown.board_id = '53186e8391ef8671265eba9d'
|
9
9
|
full_board_mock
|
10
10
|
end
|
11
11
|
|
12
12
|
describe BurndownData::Result do
|
13
|
-
it
|
13
|
+
it 'calculates total' do
|
14
14
|
r = described_class.new
|
15
15
|
r.open = 7
|
16
16
|
r.done = 4
|
@@ -19,83 +19,81 @@ describe BurndownData do
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
describe
|
23
|
-
it
|
22
|
+
describe 'setters' do
|
23
|
+
it 'sets open story points' do
|
24
24
|
@burndown.story_points.open = 13
|
25
25
|
expect(@burndown.story_points.open).to eq 13
|
26
26
|
end
|
27
27
|
|
28
|
-
it
|
28
|
+
it 'sets open tasks' do
|
29
29
|
@burndown.tasks.open = 42
|
30
30
|
expect(@burndown.tasks.open).to eq 42
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
describe
|
35
|
-
context
|
34
|
+
describe '#fetch' do
|
35
|
+
context 'with meta data on sprint card' do
|
36
36
|
before do
|
37
37
|
@burndown.fetch
|
38
38
|
end
|
39
39
|
|
40
|
-
it
|
40
|
+
it 'returns story points' do
|
41
41
|
expect( @burndown.story_points.total ).to eq 16
|
42
42
|
expect( @burndown.story_points.open ).to eq 13
|
43
43
|
expect( @burndown.story_points.done ).to eq 3
|
44
44
|
end
|
45
45
|
|
46
|
-
it
|
46
|
+
it 'returns extra story points' do
|
47
47
|
expect( @burndown.extra_story_points.total ).to eq 8
|
48
48
|
expect( @burndown.extra_story_points.open ).to eq 8
|
49
49
|
expect( @burndown.extra_story_points.done ).to eq 0
|
50
50
|
end
|
51
51
|
|
52
|
-
it
|
52
|
+
it 'returns unplanned story points' do
|
53
53
|
expect( @burndown.unplanned_story_points.total ).to eq 3
|
54
54
|
expect( @burndown.unplanned_story_points.open ).to eq 1
|
55
55
|
expect( @burndown.unplanned_story_points.done ).to eq 2
|
56
56
|
end
|
57
57
|
|
58
|
-
it
|
58
|
+
it 'returns tasks' do
|
59
59
|
expect( @burndown.tasks.total ).to eq 13
|
60
60
|
expect( @burndown.tasks.open ).to eq 9
|
61
61
|
expect( @burndown.tasks.done ).to eq 4
|
62
62
|
end
|
63
63
|
|
64
|
-
it
|
64
|
+
it 'returns extra tasks' do
|
65
65
|
expect( @burndown.extra_tasks.total ).to eq 1
|
66
66
|
expect( @burndown.extra_tasks.open ).to eq 1
|
67
67
|
expect( @burndown.extra_tasks.done ).to eq 0
|
68
68
|
end
|
69
69
|
|
70
|
-
it
|
70
|
+
it 'returns unplanned tasks' do
|
71
71
|
expect( @burndown.unplanned_tasks.total ).to eq 2
|
72
72
|
expect( @burndown.unplanned_tasks.open ).to eq 1
|
73
73
|
expect( @burndown.unplanned_tasks.done ).to eq 1
|
74
74
|
end
|
75
75
|
|
76
|
-
it
|
77
|
-
expect( @burndown.meta ).to eq(
|
78
|
-
|
79
|
-
|
80
|
-
"weekend_lines" => [1.5, 6.5, 11.5, 16.5]
|
81
|
-
})
|
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])
|
82
80
|
end
|
83
81
|
|
84
|
-
it
|
85
|
-
expected_date_time = DateTime.parse(
|
82
|
+
it 'saves date and time' do
|
83
|
+
expected_date_time = DateTime.parse('2015-01-12T13:57:16+01:00')
|
86
84
|
allow(DateTime).to receive(:now).and_return(expected_date_time)
|
87
85
|
@burndown.fetch
|
88
86
|
expect(@burndown.date_time).to eq(expected_date_time)
|
89
87
|
end
|
90
88
|
end
|
91
89
|
|
92
|
-
context
|
90
|
+
context 'without meta data on sprint card' do
|
93
91
|
before do
|
94
92
|
allow(Card).to receive(:parse_yaml_from_description).and_return(nil)
|
95
93
|
@burndown.fetch
|
96
94
|
end
|
97
95
|
|
98
|
-
it
|
96
|
+
it 'does not fail' do
|
99
97
|
expect(@burndown.meta).to be(nil)
|
100
98
|
end
|
101
99
|
end
|
data/spec/unit/card_spec.rb
CHANGED
@@ -1,36 +1,50 @@
|
|
1
|
-
require_relative
|
1
|
+
require_relative 'spec_helper'
|
2
2
|
|
3
3
|
describe Card do
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe 'parses name' do
|
6
6
|
before(:each) do
|
7
7
|
allow_any_instance_of(Card).to receive(:init_data)
|
8
|
-
@card = Card.new(double, double)
|
8
|
+
@card = Card.new(double, double, dummy_settings)
|
9
9
|
end
|
10
10
|
|
11
|
-
it
|
12
|
-
allow(@card).to receive(:name).and_return(
|
11
|
+
it 'extracts single digit story point value from card name' do
|
12
|
+
allow(@card).to receive(:name).and_return('(3) P1: Refactor cards')
|
13
13
|
expect(@card.story_points).to eq(3)
|
14
14
|
end
|
15
15
|
|
16
|
-
it
|
17
|
-
allow(@card).to receive(:name).and_return
|
16
|
+
it 'extracts double digit story point value from card name' do
|
17
|
+
allow(@card).to receive(:name).and_return '(13) P1: Refactor cards'
|
18
18
|
expect(@card.story_points).to eq(13)
|
19
19
|
end
|
20
20
|
|
21
|
-
it
|
22
|
-
allow(@card).to receive(:name).and_return
|
21
|
+
it 'extracts fractional story point value from card name' do
|
22
|
+
allow(@card).to receive(:name).and_return '(0.5) P1: Refactor cards'
|
23
23
|
expect(@card.story_points).to eq(0.5)
|
24
24
|
end
|
25
25
|
|
26
|
-
it
|
27
|
-
allow(@card).to receive(:name).and_return
|
26
|
+
it 'extracts story points when value is not at beginning of card name' do
|
27
|
+
allow(@card).to receive(:name).and_return 'P01: (3) Refactor cards'
|
28
28
|
expect(@card.story_points).to eq(3)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
describe
|
33
|
-
|
32
|
+
describe 'counts checklists' do
|
33
|
+
before(:each) do
|
34
|
+
@card = Card.new({ 'cards' => [dummy_card_json] }, '5319c0409a567dc62b68aa6b', dummy_settings)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'counts all checklist items that are marked as no_task_checklists' do
|
38
|
+
expect(@card.tasks).to eq(3)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'counts all closed checklist items that are marked as no_task_checklists' do
|
42
|
+
expect(@card.done_tasks).to eq(1)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#parse_yaml_from_description' do
|
47
|
+
it 'parses description only having YAML' do
|
34
48
|
description = <<EOT
|
35
49
|
```yaml
|
36
50
|
total_days: 18
|
@@ -40,11 +54,11 @@ weekend_lines:
|
|
40
54
|
```
|
41
55
|
EOT
|
42
56
|
meta = Card.parse_yaml_from_description(description)
|
43
|
-
expect(meta[
|
44
|
-
expect(meta[
|
57
|
+
expect(meta['total_days']).to eq(18)
|
58
|
+
expect(meta['weekend_lines']).to eq([1.5, 6.5])
|
45
59
|
end
|
46
60
|
|
47
|
-
it
|
61
|
+
it 'parses description only having unmarked YAML' do
|
48
62
|
description = <<EOT
|
49
63
|
```
|
50
64
|
total_days: 18
|
@@ -54,11 +68,11 @@ weekend_lines:
|
|
54
68
|
```
|
55
69
|
EOT
|
56
70
|
meta = Card.parse_yaml_from_description(description)
|
57
|
-
expect(meta[
|
58
|
-
expect(meta[
|
71
|
+
expect(meta['total_days']).to eq(18)
|
72
|
+
expect(meta['weekend_lines']).to eq([1.5, 6.5])
|
59
73
|
end
|
60
74
|
|
61
|
-
it
|
75
|
+
it 'parses description having YAML and text' do
|
62
76
|
description = <<EOT
|
63
77
|
This is some text
|
64
78
|
|
@@ -72,18 +86,18 @@ weekend_lines:
|
|
72
86
|
And more text.
|
73
87
|
EOT
|
74
88
|
meta = Card.parse_yaml_from_description(description)
|
75
|
-
expect(meta[
|
76
|
-
expect(meta[
|
89
|
+
expect(meta['total_days']).to eq(18)
|
90
|
+
expect(meta['weekend_lines']).to eq([1.5, 6.5])
|
77
91
|
end
|
78
92
|
end
|
79
93
|
|
80
|
-
describe
|
81
|
-
it
|
94
|
+
describe 'gets raw JSON' do
|
95
|
+
it 'for cards' do
|
82
96
|
@settings = dummy_settings
|
83
97
|
full_board_mock
|
84
98
|
|
85
99
|
trello = TrelloWrapper.new(@settings)
|
86
|
-
board = trello.board(
|
100
|
+
board = trello.board('53186e8391ef8671265eba9d')
|
87
101
|
|
88
102
|
expected_json = <<EOT
|
89
103
|
{
|
data/spec/unit/cli_spec.rb
CHANGED
@@ -11,31 +11,31 @@ describe Cli do
|
|
11
11
|
@cli = Cli.new
|
12
12
|
end
|
13
13
|
|
14
|
-
it
|
14
|
+
it 'fetches burndown data from board-list' do
|
15
15
|
full_board_mock
|
16
16
|
dir = given_directory
|
17
|
-
@cli.options = {
|
18
|
-
|
17
|
+
@cli.options = {'board-list' => 'spec/data/board-list.yaml',
|
18
|
+
'output' => dir}
|
19
19
|
@cli.burndowns
|
20
|
-
expect(File.exist?(File.join(dir,
|
21
|
-
expect(File.exist?(File.join(dir,
|
20
|
+
expect(File.exist?(File.join(dir, 'orange/burndown-data-01.yaml')))
|
21
|
+
expect(File.exist?(File.join(dir, 'blue/burndown-data-01.yaml')))
|
22
22
|
end
|
23
23
|
|
24
|
-
it
|
24
|
+
it 'backups board' do
|
25
25
|
expect_any_instance_of(Backup).to receive(:backup)
|
26
|
-
@cli.options = {
|
26
|
+
@cli.options = {'board-id' => '1234'}
|
27
27
|
@cli.backup
|
28
28
|
end
|
29
29
|
|
30
|
-
it
|
30
|
+
it 'backups board using an alias' do
|
31
31
|
expect_any_instance_of(Backup).to receive(:backup)
|
32
|
-
@cli.options = {
|
32
|
+
@cli.options = {'board-id' => 'MyTrelloBoard'}
|
33
33
|
@cli.backup
|
34
34
|
end
|
35
35
|
|
36
|
-
it
|
36
|
+
it 'gets lists' do
|
37
37
|
full_board_mock
|
38
|
-
@cli.options = {
|
38
|
+
@cli.options = {'board-id' => '53186e8391ef8671265eba9d'}
|
39
39
|
expected_output = <<EOT
|
40
40
|
Sprint Backlog
|
41
41
|
Doing
|
@@ -44,21 +44,21 @@ Done Sprint 9
|
|
44
44
|
Done Sprint 8
|
45
45
|
Legend
|
46
46
|
EOT
|
47
|
-
expect
|
47
|
+
expect do
|
48
48
|
@cli.get_lists
|
49
|
-
|
49
|
+
end.to output(expected_output).to_stdout
|
50
50
|
|
51
51
|
|
52
52
|
# Using an alias
|
53
|
-
@cli.options = {
|
54
|
-
expect
|
53
|
+
@cli.options = {'board-id' => 'MyTrelloBoard'}
|
54
|
+
expect do
|
55
55
|
@cli.get_lists
|
56
|
-
|
56
|
+
end.to output(expected_output).to_stdout
|
57
57
|
end
|
58
58
|
|
59
|
-
it
|
59
|
+
it 'gets cards' do
|
60
60
|
full_board_mock
|
61
|
-
@cli.options = {
|
61
|
+
@cli.options = {'board-id' => '53186e8391ef8671265eba9d'}
|
62
62
|
expected_output = <<EOT
|
63
63
|
Sprint 3
|
64
64
|
(3) P1: Fill Backlog column
|
@@ -84,20 +84,20 @@ Sprint 8
|
|
84
84
|
Purpose
|
85
85
|
Background image
|
86
86
|
EOT
|
87
|
-
expect
|
87
|
+
expect do
|
88
88
|
@cli.get_cards
|
89
|
-
|
89
|
+
end.to output(expected_output).to_stdout
|
90
90
|
|
91
91
|
# Using an alias
|
92
|
-
@cli.options = {
|
93
|
-
expect
|
92
|
+
@cli.options = {'board-id' => 'MyTrelloBoard'}
|
93
|
+
expect do
|
94
94
|
@cli.get_cards
|
95
|
-
|
95
|
+
end.to output(expected_output).to_stdout
|
96
96
|
end
|
97
97
|
|
98
|
-
it
|
98
|
+
it 'gets checklists' do
|
99
99
|
full_board_mock
|
100
|
-
@cli.options = {
|
100
|
+
@cli.options = {'board-id' => '53186e8391ef8671265eba9d'}
|
101
101
|
expected_output = <<EOT
|
102
102
|
Tasks
|
103
103
|
Tasks
|
@@ -112,18 +112,18 @@ Tasks
|
|
112
112
|
Tasks
|
113
113
|
Tasks
|
114
114
|
EOT
|
115
|
-
expect
|
115
|
+
expect do
|
116
116
|
@cli.get_checklists
|
117
|
-
|
117
|
+
end.to output(expected_output).to_stdout
|
118
118
|
|
119
119
|
# Using an alias
|
120
|
-
@cli.options = {
|
121
|
-
expect
|
120
|
+
@cli.options = {'board-id' => 'MyTrelloBoard'}
|
121
|
+
expect do
|
122
122
|
@cli.get_checklists
|
123
|
-
|
123
|
+
end.to output(expected_output).to_stdout
|
124
124
|
end
|
125
125
|
|
126
|
-
it
|
126
|
+
it 'gets description' do
|
127
127
|
body = <<-EOT
|
128
128
|
{
|
129
129
|
"id": "54ae8485221b1cc5b173e713",
|
@@ -131,41 +131,41 @@ EOT
|
|
131
131
|
}
|
132
132
|
EOT
|
133
133
|
stub_request(
|
134
|
-
:get,
|
134
|
+
:get, 'https://api.trello.com/1/cards/54ae8485221b1cc5b173e713?key=mykey&token=mytoken'
|
135
135
|
).with(
|
136
|
-
:
|
136
|
+
headers: {
|
137
137
|
'Accept' => '*/*; q=0.5, application/xml',
|
138
138
|
'Accept-Encoding' => 'gzip, deflate',
|
139
139
|
'User-Agent' => 'Ruby'
|
140
140
|
}
|
141
|
-
).to_return(:
|
142
|
-
@cli.options = {
|
141
|
+
).to_return(status: 200, body: body, headers: {})
|
142
|
+
@cli.options = {'card-id' => '54ae8485221b1cc5b173e713'}
|
143
143
|
expected_output = "haml\n"
|
144
|
-
expect
|
144
|
+
expect do
|
145
145
|
@cli.get_description
|
146
|
-
|
146
|
+
end.to output(expected_output).to_stdout
|
147
147
|
end
|
148
148
|
|
149
|
-
it
|
150
|
-
expect(STDIN).to receive(:read).and_return(
|
149
|
+
it 'sets description' do
|
150
|
+
expect(STDIN).to receive(:read).and_return('My description')
|
151
151
|
stub_request(
|
152
|
-
:put,
|
152
|
+
:put, 'https://api.trello.com/1/cards/54ae8485221b1cc5b173e713/desc?key=mykey&token=mytoken&value=My%20description'
|
153
153
|
).with(
|
154
|
-
:
|
154
|
+
headers: {
|
155
155
|
'Accept' => '*/*; q=0.5, application/xml',
|
156
156
|
'Accept-Encoding' => 'gzip, deflate',
|
157
157
|
'Content-Length' => '0',
|
158
158
|
'Content-Type' => 'application/x-www-form-urlencoded',
|
159
159
|
'User-Agent' => 'Ruby'
|
160
160
|
}
|
161
|
-
).to_return(:
|
162
|
-
@cli.options = {
|
161
|
+
).to_return(status: 200, body: '', headers: {})
|
162
|
+
@cli.options = {'card-id' => '54ae8485221b1cc5b173e713'}
|
163
163
|
@cli.set_description
|
164
|
-
expect(WebMock).to have_requested(:put,
|
164
|
+
expect(WebMock).to have_requested(:put, 'https://api.trello.com/1/cards/54ae8485221b1cc5b173e713/desc?key=mykey&token=mytoken&value=My%20description')
|
165
165
|
end
|
166
166
|
|
167
|
-
it
|
168
|
-
@cli.options = {
|
167
|
+
it 'sets priorities for default planning list', vcr: 'prioritize_backlog_list', vcr_record: false do
|
168
|
+
@cli.options = {'board-id' => 'neUHHzDo'}
|
169
169
|
|
170
170
|
expected_output = <<-EOT
|
171
171
|
set priority to 1 for "P1: (2) Document how to run cf-openstack-validator on SUSE"
|
@@ -182,32 +182,32 @@ set priority to 11 for "P11: (3) Set up Concourse pipeline for BATs"
|
|
182
182
|
set priority to 12 for "P12: Bike Shedding Feature"
|
183
183
|
set priority to 13 for "P13: (3) Set up Concourse pipeline for os image building"
|
184
184
|
EOT
|
185
|
-
expect
|
185
|
+
expect do
|
186
186
|
@cli.set_priorities
|
187
|
-
|
187
|
+
end.to output(expected_output).to_stdout
|
188
188
|
end
|
189
189
|
|
190
|
-
it
|
191
|
-
@cli.options = {
|
190
|
+
it 'sets priorities for specified planning list', vcr: 'prioritize_backlog_list', vcr_record: false do
|
191
|
+
@cli.options = {'board-id' => 'neUHHzDo', 'backlog-list-name' => 'Nonexisting List'}
|
192
192
|
|
193
|
-
expect
|
193
|
+
expect do
|
194
194
|
@cli.set_priorities
|
195
|
-
|
195
|
+
end.to raise_error /'Nonexisting List' not found/
|
196
196
|
end
|
197
197
|
|
198
|
-
context
|
198
|
+
context '#board_id' do
|
199
199
|
before do
|
200
200
|
Cli.settings = Settings.new(
|
201
201
|
File.expand_path('../../data/trollolorc_with_board_aliases', __FILE__))
|
202
202
|
@cli = Cli.new
|
203
203
|
end
|
204
204
|
|
205
|
-
it
|
206
|
-
expect(@cli.send(:board_id,
|
205
|
+
it 'returns the id when no alias exists' do
|
206
|
+
expect(@cli.send(:board_id, '1234')).to eq('1234')
|
207
207
|
end
|
208
208
|
|
209
|
-
it
|
210
|
-
expect(@cli.send(:board_id,
|
209
|
+
it 'return the id when an alias exists' do
|
210
|
+
expect(@cli.send(:board_id, 'MyTrelloBoard')).to eq('53186e8391ef8671265eba9d')
|
211
211
|
end
|
212
212
|
end
|
213
213
|
end
|