trollolo 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|