trollolo 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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +5 -1
- data/CHANGELOG.md +29 -0
- data/Gemfile +7 -2
- data/README.md +19 -0
- data/bin/trollolo +1 -1
- data/lib/array.rb +6 -0
- data/lib/backup.rb +67 -0
- data/lib/burndown_chart.rb +96 -67
- data/lib/burndown_data.rb +62 -123
- data/lib/card.rb +74 -30
- data/lib/cli.rb +131 -9
- data/lib/column.rb +61 -0
- data/lib/result.rb +0 -0
- data/lib/scrum_board.rb +104 -0
- data/lib/settings.rb +9 -4
- data/lib/trello_wrapper.rb +62 -0
- data/lib/trollolo.rb +10 -7
- data/lib/version.rb +1 -1
- data/scripts/.gitignore +1 -0
- data/scripts/burndowndata.py +113 -0
- data/scripts/create_burndown.py +111 -146
- data/scripts/graph.py +116 -0
- data/scripts/plot.py +131 -0
- data/spec/data/board.json +63 -0
- data/spec/data/burndown-data.yaml +3 -0
- data/spec/data/burndown_dir/burndown-data-01.yaml +1 -1
- data/spec/data/burndown_dir/burndown-data-02.yaml +1 -1
- data/spec/data/card.json +61 -0
- data/spec/data/full-board.json +1626 -0
- data/spec/data/lists.json +25 -25
- data/spec/data/trollolorc +5 -0
- data/spec/{command_line_spec.rb → integration/command_line_spec.rb} +1 -4
- data/spec/integration/create_burndown_spec.rb +57 -0
- data/spec/integration/integration_spec_helper.rb +10 -0
- data/spec/integration/support/aruba_hook.rb +11 -0
- data/spec/integration/support/custom_matchers.rb +13 -0
- data/spec/{wrapper → integration/wrapper}/credentials_input_wrapper +2 -2
- data/spec/{wrapper → integration/wrapper}/empty_config_trollolo_wrapper +2 -2
- data/spec/integration/wrapper/trollolo_wrapper +10 -0
- data/spec/unit/backup_spec.rb +107 -0
- data/spec/unit/burndown_chart_spec.rb +396 -0
- data/spec/unit/burndown_data_spec.rb +118 -0
- data/spec/unit/card_spec.rb +79 -0
- data/spec/unit/cli_spec.rb +38 -0
- data/spec/unit/retrieve_data_spec.rb +54 -0
- data/spec/unit/scrum_board_spec.rb +18 -0
- data/spec/{settings_spec.rb → unit/settings_spec.rb} +1 -1
- data/spec/{spec_helper.rb → unit/spec_helper.rb} +4 -12
- data/spec/unit/support/test_data_operations.rb +7 -0
- data/spec/unit/support/update_webmock_data +17 -0
- data/spec/unit/support/webmocks.rb +52 -0
- data/spec/unit/trello_wrapper_spec.rb +47 -0
- data/trollolo.gemspec +10 -11
- metadata +54 -37
- data/lib/trello.rb +0 -66
- data/spec/burndown_chart_spec.rb +0 -307
- data/spec/burndown_data_spec.rb +0 -125
- data/spec/card_spec.rb +0 -15
- data/spec/cli_spec.rb +0 -18
- data/spec/data/cards.json +0 -1002
- data/spec/trello_spec.rb +0 -32
- data/spec/wrapper/trollolo_wrapper +0 -11
data/spec/data/lists.json
CHANGED
@@ -1,50 +1,50 @@
|
|
1
1
|
[
|
2
2
|
{
|
3
|
-
"
|
4
|
-
"subscribed": false,
|
3
|
+
"id": "53186e8391ef8671265eba9e",
|
5
4
|
"name": "Sprint Backlog",
|
6
5
|
"closed": false,
|
7
|
-
"
|
8
|
-
"
|
6
|
+
"idBoard": "53186e8391ef8671265eba9d",
|
7
|
+
"pos": 16384,
|
8
|
+
"subscribed": false
|
9
9
|
},
|
10
10
|
{
|
11
|
-
"
|
12
|
-
"subscribed": false,
|
11
|
+
"id": "53186e8391ef8671265eba9f",
|
13
12
|
"name": "Doing",
|
14
13
|
"closed": false,
|
15
|
-
"
|
16
|
-
"
|
14
|
+
"idBoard": "53186e8391ef8671265eba9d",
|
15
|
+
"pos": 32768,
|
16
|
+
"subscribed": false
|
17
17
|
},
|
18
18
|
{
|
19
|
-
"
|
20
|
-
"subscribed": false,
|
19
|
+
"id": "5319bf088cdf9cd82be336b0",
|
21
20
|
"name": "Done Sprint 10",
|
22
21
|
"closed": false,
|
23
|
-
"
|
24
|
-
"
|
22
|
+
"idBoard": "53186e8391ef8671265eba9d",
|
23
|
+
"pos": 36864,
|
24
|
+
"subscribed": false
|
25
25
|
},
|
26
26
|
{
|
27
|
-
"
|
28
|
-
"subscribed": false,
|
27
|
+
"id": "5319bf045c6ef0092c55331e",
|
29
28
|
"name": "Done Sprint 9",
|
30
29
|
"closed": false,
|
31
|
-
"
|
32
|
-
"
|
30
|
+
"idBoard": "53186e8391ef8671265eba9d",
|
31
|
+
"pos": 40960,
|
32
|
+
"subscribed": false
|
33
33
|
},
|
34
34
|
{
|
35
|
-
"
|
36
|
-
"subscribed": false,
|
35
|
+
"id": "53186e8391ef8671265ebaa0",
|
37
36
|
"name": "Done Sprint 8",
|
38
37
|
"closed": false,
|
39
|
-
"
|
40
|
-
"
|
38
|
+
"idBoard": "53186e8391ef8671265eba9d",
|
39
|
+
"pos": 49152,
|
40
|
+
"subscribed": false
|
41
41
|
},
|
42
42
|
{
|
43
|
-
"
|
44
|
-
"subscribed": false,
|
43
|
+
"id": "5319bc0aa338308d42f108d6",
|
45
44
|
"name": "Legend",
|
46
45
|
"closed": false,
|
47
|
-
"
|
48
|
-
"
|
46
|
+
"idBoard": "53186e8391ef8671265eba9d",
|
47
|
+
"pos": 114688,
|
48
|
+
"subscribed": false
|
49
49
|
}
|
50
|
-
]
|
50
|
+
]
|
data/spec/data/trollolorc
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative "integration_spec_helper"
|
2
|
+
|
3
|
+
include GivenFilesystemSpecHelpers
|
4
|
+
|
5
|
+
HELPER_SCRIPT = File.expand_path("../../../scripts/create_burndown.py", __FILE__)
|
6
|
+
|
7
|
+
describe "create_burndown.py" do
|
8
|
+
use_given_filesystem(keep_files: true)
|
9
|
+
|
10
|
+
it "creates burndown chart for sprint 23" do
|
11
|
+
@working_dir = given_directory do
|
12
|
+
given_file("burndown-data-23.yaml", from: "create_burndown_helper/burndown-data-23.yaml")
|
13
|
+
end
|
14
|
+
|
15
|
+
cmd = "#{HELPER_SCRIPT} 23 --output=#{@working_dir} --no-head"
|
16
|
+
run(cmd)
|
17
|
+
assert_exit_status(0)
|
18
|
+
expect(File.join(@working_dir, "burndown-23.png")).
|
19
|
+
to be_same_image_as("create_burndown_helper/burndown-23.png")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "creates burndown chart for sprint 31" do
|
23
|
+
@working_dir = given_directory do
|
24
|
+
given_file("burndown-data-31.yaml", from: "create_burndown_helper/burndown-data-31.yaml")
|
25
|
+
end
|
26
|
+
|
27
|
+
cmd = "#{HELPER_SCRIPT} 31 --output=#{@working_dir} --no-head"
|
28
|
+
run(cmd)
|
29
|
+
assert_exit_status(0)
|
30
|
+
expect(File.join(@working_dir, "burndown-31.png")).
|
31
|
+
to be_same_image_as("create_burndown_helper/burndown-31.png")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "creates burndown chart for sprint 35" do
|
35
|
+
@working_dir = given_directory do
|
36
|
+
given_file("burndown-data-35.yaml", from: "create_burndown_helper/burndown-data-35.yaml")
|
37
|
+
end
|
38
|
+
|
39
|
+
cmd = "#{HELPER_SCRIPT} 35 --output=#{@working_dir} --no-head"
|
40
|
+
run(cmd)
|
41
|
+
assert_exit_status(0)
|
42
|
+
expect(File.join(@working_dir, "burndown-35.png")).
|
43
|
+
to be_same_image_as("create_burndown_helper/burndown-35.png")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "creates burndown chart for sprint 8" do
|
47
|
+
@working_dir = given_directory do
|
48
|
+
given_file("burndown-data-08.yaml", from: "create_burndown_helper/burndown-data-08.yaml")
|
49
|
+
end
|
50
|
+
|
51
|
+
cmd = "#{HELPER_SCRIPT} 08 --output=#{@working_dir} --no-tasks --with-fast-lane --no-head"
|
52
|
+
run(cmd)
|
53
|
+
assert_exit_status(0)
|
54
|
+
expect(File.join(@working_dir, "burndown-08.png")).
|
55
|
+
to be_same_image_as("create_burndown_helper/burndown-08.png")
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative '../../lib/trollolo'
|
2
|
+
require 'given_filesystem/spec_helpers'
|
3
|
+
|
4
|
+
bin_path = File.expand_path( "../../../bin/", __FILE__ )
|
5
|
+
|
6
|
+
if ENV['PATH'] !~ /#{bin_path}/
|
7
|
+
ENV['PATH'] = bin_path + File::PATH_SEPARATOR + ENV['PATH']
|
8
|
+
end
|
9
|
+
|
10
|
+
Dir.glob(::File.expand_path('../support/*.rb', __FILE__)).each { |f| require_relative f }
|
@@ -0,0 +1,13 @@
|
|
1
|
+
RSpec::Matchers.define :be_same_image_as do |expected|
|
2
|
+
match do |actual|
|
3
|
+
expected_path = File.expand_path('../../../data/' + expected, __FILE__)
|
4
|
+
expected_file = File.binread(expected_path)
|
5
|
+
actual_file = File.binread(actual)
|
6
|
+
|
7
|
+
expected_file == actual_file
|
8
|
+
end
|
9
|
+
|
10
|
+
description do
|
11
|
+
"be the same image as \"#{expected}\""
|
12
|
+
end
|
13
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
#!/usr/bin/ruby
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "expect"
|
4
4
|
require "pty"
|
5
5
|
|
6
6
|
config_path = "/tmp/test-trollolorc-#{rand(100000)}"
|
7
|
-
bin_path = File.expand_path('
|
7
|
+
bin_path = File.expand_path('../../../../bin/trollolo',__FILE__)
|
8
8
|
|
9
9
|
ENV["TROLLOLO_CONFIG_PATH"] = config_path
|
10
10
|
|
@@ -1,7 +1,7 @@
|
|
1
|
-
#!/usr/bin/ruby
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
config_path = "/tmp/test-trollolorc-#{rand(100000)}"
|
4
|
-
bin_path = File.expand_path('
|
4
|
+
bin_path = File.expand_path('../../../../bin/trollolo',__FILE__)
|
5
5
|
|
6
6
|
ENV["TROLLOLO_CONFIG_PATH"] = config_path
|
7
7
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
test_config_path = File.expand_path('../../../data/trollolorc',__FILE__)
|
4
|
+
bin_path = File.expand_path('../../../../bin/trollolo',__FILE__)
|
5
|
+
|
6
|
+
ENV["TROLLOLO_CONFIG_PATH"] = test_config_path
|
7
|
+
|
8
|
+
cmd = "#{bin_path} #{ARGV.join(" ")}"
|
9
|
+
|
10
|
+
exec(cmd)
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
include GivenFilesystemSpecHelpers
|
4
|
+
|
5
|
+
describe Backup do
|
6
|
+
it "sets backup directory" do
|
7
|
+
backup = Backup.new(dummy_settings)
|
8
|
+
expect(backup.directory).to match File.expand_path("~/.trollolo/backup")
|
9
|
+
end
|
10
|
+
|
11
|
+
context "custom backup directory" do
|
12
|
+
use_given_filesystem(keep_files: true)
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
full_board_mock
|
16
|
+
@backup = Backup.new(dummy_settings)
|
17
|
+
@directory = given_directory
|
18
|
+
@backup.directory = @directory
|
19
|
+
end
|
20
|
+
|
21
|
+
it "backups board" do
|
22
|
+
@backup.backup("53186e8391ef8671265eba9d")
|
23
|
+
backup_file = File.join(@directory, "53186e8391ef8671265eba9d", "board.json")
|
24
|
+
expect(File.exist?(backup_file)).to be true
|
25
|
+
expect(File.read(backup_file)).to eq load_test_file("full-board.json").chomp
|
26
|
+
end
|
27
|
+
|
28
|
+
it "lists backups" do
|
29
|
+
@backup.backup("53186e8391ef8671265eba9d")
|
30
|
+
expect(@backup.list).to eq ["53186e8391ef8671265eba9d"]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "shows backup" do
|
34
|
+
output_capturer = StringIO.new
|
35
|
+
@backup.backup("53186e8391ef8671265eba9d")
|
36
|
+
@backup.show("53186e8391ef8671265eba9d", output: output_capturer )
|
37
|
+
expect(output_capturer.string).to eq(<<EOT
|
38
|
+
Trollolo Testing Board
|
39
|
+
Sprint Backlog
|
40
|
+
Sprint 3
|
41
|
+
(3) P1: Fill Backlog column
|
42
|
+
Tasks
|
43
|
+
Add card to fill Backlog column (incomplete)
|
44
|
+
Add card to read data from Trollolo (incomplete)
|
45
|
+
Add card to save read data as reference data (incomplete)
|
46
|
+
Add card under the waterline (incomplete)
|
47
|
+
(5) P4: Read data from Trollolo
|
48
|
+
Tasks
|
49
|
+
Add option to Trollolo to provide the board id (incomplete)
|
50
|
+
Call command (incomplete)
|
51
|
+
(3) P5: Save read data as reference data
|
52
|
+
Tasks
|
53
|
+
Save test data (incomplete)
|
54
|
+
Make tests work (incomplete)
|
55
|
+
Waterline
|
56
|
+
(8) P6: Celebrate testing board
|
57
|
+
Tasks
|
58
|
+
Party (incomplete)
|
59
|
+
Doing
|
60
|
+
(2) P2: Fill Doing column
|
61
|
+
Tasks
|
62
|
+
Add task to add task to Fill Doing column card (incomplete)
|
63
|
+
Create card to Fill Doing column (complete)
|
64
|
+
Feedback
|
65
|
+
Ask user who requested the feature (complete)
|
66
|
+
Ask product manager (incomplete)
|
67
|
+
Done Sprint 10
|
68
|
+
Burndown chart
|
69
|
+
Sprint 10
|
70
|
+
(3) P3: Fill Done columns
|
71
|
+
Tasks
|
72
|
+
Fill Done Sprint 1 (complete)
|
73
|
+
Fill Done Sprint 2 (complete)
|
74
|
+
Fill Done Sprint 3 (complete)
|
75
|
+
Done Sprint 9
|
76
|
+
Burndown chart
|
77
|
+
Sprint 9
|
78
|
+
(2) P1: Explain purpose
|
79
|
+
(2) P2: Create Scrum columns
|
80
|
+
Tasks
|
81
|
+
Backlog (complete)
|
82
|
+
Doing (complete)
|
83
|
+
Multiple Done Columns (complete)
|
84
|
+
Done Sprint 8
|
85
|
+
Burndown chart
|
86
|
+
Sprint 8
|
87
|
+
(1) P1: Create Trello Testing Board
|
88
|
+
Tasks
|
89
|
+
Create board (complete)
|
90
|
+
Name board (complete)
|
91
|
+
(5) P2: Add fancy background
|
92
|
+
Tasks
|
93
|
+
Find image (complete)
|
94
|
+
Download image (complete)
|
95
|
+
Set image (complete)
|
96
|
+
Add attribution (complete)
|
97
|
+
(1) P4: Add legend
|
98
|
+
Tasks
|
99
|
+
Create Legend column (complete)
|
100
|
+
Legend
|
101
|
+
Purpose
|
102
|
+
Background image
|
103
|
+
EOT
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,396 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
include GivenFilesystemSpecHelpers
|
4
|
+
|
5
|
+
describe BurndownChart do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@settings = dummy_settings
|
9
|
+
@burndown_data = BurndownData.new(@settings)
|
10
|
+
@chart = BurndownChart.new(@settings)
|
11
|
+
full_board_mock
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "initializer" do
|
15
|
+
it "sets initial meta data" do
|
16
|
+
expect(@chart.data["meta"]["sprint"]).to eq 1
|
17
|
+
expect(@chart.data["meta"]["total_days"]).to eq 10
|
18
|
+
expect(@chart.data["meta"]["weekend_lines"]).to eq [3.5, 8.5]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "data" do
|
23
|
+
use_given_filesystem
|
24
|
+
|
25
|
+
before(:each) do
|
26
|
+
@raw_data = [
|
27
|
+
{
|
28
|
+
"date" => '2014-04-23',
|
29
|
+
"updated_at" => '2014-04-23T10:00:00+01:00',
|
30
|
+
"story_points" =>
|
31
|
+
{
|
32
|
+
"total" => 30,
|
33
|
+
"open" => 23
|
34
|
+
},
|
35
|
+
"tasks" =>
|
36
|
+
{
|
37
|
+
"total" => 25,
|
38
|
+
"open" => 21
|
39
|
+
}
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"date" => '2014-04-24',
|
43
|
+
"updated_at" => '2014-04-24T19:00:00+01:00',
|
44
|
+
"story_points" =>
|
45
|
+
{
|
46
|
+
"total" => 30,
|
47
|
+
"open" => 21
|
48
|
+
},
|
49
|
+
"tasks" =>
|
50
|
+
{
|
51
|
+
"total" => 26,
|
52
|
+
"open" => 19
|
53
|
+
},
|
54
|
+
"story_points_extra" =>
|
55
|
+
{
|
56
|
+
"done" => 3
|
57
|
+
},
|
58
|
+
"tasks_extra" =>
|
59
|
+
{
|
60
|
+
"done" => 2
|
61
|
+
}
|
62
|
+
}
|
63
|
+
]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "creates first data entry" do
|
67
|
+
@burndown_data.story_points.open = 16
|
68
|
+
@burndown_data.story_points.done = 7
|
69
|
+
@burndown_data.tasks.open = 10
|
70
|
+
@burndown_data.tasks.done = 11
|
71
|
+
@burndown_data.date_time = DateTime.parse("2014-05-30")
|
72
|
+
|
73
|
+
@chart.add_data(@burndown_data)
|
74
|
+
|
75
|
+
expect( @chart.data["days"].first["story_points"] ).to eq(
|
76
|
+
{
|
77
|
+
"total" => 23,
|
78
|
+
"open" => 16
|
79
|
+
} )
|
80
|
+
expect( @chart.data["days"].first["tasks"] ).to eq(
|
81
|
+
{
|
82
|
+
"total" => 21,
|
83
|
+
"open" => 10
|
84
|
+
} )
|
85
|
+
end
|
86
|
+
|
87
|
+
it "returns sprint number" do
|
88
|
+
expect(@chart.sprint).to eq 1
|
89
|
+
end
|
90
|
+
|
91
|
+
it "adds data" do
|
92
|
+
@chart.data["days"] = @raw_data
|
93
|
+
|
94
|
+
@burndown_data.story_points.open = 16
|
95
|
+
@burndown_data.story_points.done = 7
|
96
|
+
@burndown_data.tasks.open = 10
|
97
|
+
@burndown_data.tasks.done = 11
|
98
|
+
@burndown_data.extra_story_points.open = 2
|
99
|
+
@burndown_data.extra_story_points.done = 3
|
100
|
+
@burndown_data.extra_tasks.open = 5
|
101
|
+
@burndown_data.extra_tasks.done = 2
|
102
|
+
@burndown_data.date_time = DateTime.parse("2014-05-30")
|
103
|
+
|
104
|
+
@chart.add_data(@burndown_data)
|
105
|
+
|
106
|
+
expect( @chart.data["days"].count ).to eq 3
|
107
|
+
expect( @chart.data["days"].last["date"] ).to eq ( "2014-05-30" )
|
108
|
+
expect( @chart.data["days"].last["story_points"] ).to eq ( {
|
109
|
+
"total" => 23,
|
110
|
+
"open" => 16
|
111
|
+
} )
|
112
|
+
expect( @chart.data["days"].last["tasks"] ).to eq ( {
|
113
|
+
"total" => 21,
|
114
|
+
"open" => 10
|
115
|
+
} )
|
116
|
+
expect( @chart.data["days"].last["story_points_extra"] ).to eq ( {
|
117
|
+
"done" => 3
|
118
|
+
} )
|
119
|
+
expect( @chart.data["days"].last["tasks_extra"] ).to eq ( {
|
120
|
+
"done" => 2
|
121
|
+
} )
|
122
|
+
end
|
123
|
+
|
124
|
+
it "replaces data of same day" do
|
125
|
+
@chart.data["days"] = @raw_data
|
126
|
+
|
127
|
+
@burndown_data.story_points.open = 16
|
128
|
+
@burndown_data.story_points.done = 7
|
129
|
+
@burndown_data.tasks.open = 10
|
130
|
+
@burndown_data.tasks.done = 11
|
131
|
+
@burndown_data.date_time = DateTime.parse("2014-05-30")
|
132
|
+
|
133
|
+
@chart.add_data(@burndown_data)
|
134
|
+
|
135
|
+
expect( @chart.data["days"].count ).to eq 3
|
136
|
+
expect( @chart.data["days"].last["story_points"] ).to eq ( {
|
137
|
+
"total" => 23,
|
138
|
+
"open" => 16
|
139
|
+
} )
|
140
|
+
|
141
|
+
@burndown_data.story_points.done = 8
|
142
|
+
@chart.add_data(@burndown_data)
|
143
|
+
|
144
|
+
expect( @chart.data["days"].count ).to eq 3
|
145
|
+
expect( @chart.data["days"].last["story_points"] ).to eq ( {
|
146
|
+
"total" => 24,
|
147
|
+
"open" => 16
|
148
|
+
} )
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "#read_data" do
|
152
|
+
it "reads data" do
|
153
|
+
@chart.read_data given_file('burndown-data.yaml')
|
154
|
+
|
155
|
+
expect(@chart.data["days"]).to eq @raw_data
|
156
|
+
end
|
157
|
+
|
158
|
+
it "reads not done columns" do
|
159
|
+
@chart.read_data given_file('burndown-data.yaml', from: 'burndown-data-with-config.yaml')
|
160
|
+
expect(@settings.not_done_columns).to eq ["Sprint Backlog", "Doing", "QA"]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "#write_data" do
|
165
|
+
it "writes object to disk" do
|
166
|
+
@chart.sprint = 2
|
167
|
+
@chart.data["meta"]["total_days"] = 9
|
168
|
+
@chart.data["meta"]["weekend_lines"] = [3.5, 7.5]
|
169
|
+
@chart.data["meta"]["board_id"] = "myboardid"
|
170
|
+
@chart.data["days"] = @raw_data
|
171
|
+
|
172
|
+
write_path = given_dummy_file
|
173
|
+
@chart.write_data(write_path)
|
174
|
+
expect(File.read(write_path)). to eq load_test_file('burndown-data.yaml')
|
175
|
+
end
|
176
|
+
|
177
|
+
it "writes all data which was read" do
|
178
|
+
read_path = given_file('burndown-data.yaml')
|
179
|
+
@chart.read_data(read_path)
|
180
|
+
|
181
|
+
write_path = given_dummy_file
|
182
|
+
@chart.write_data(write_path)
|
183
|
+
|
184
|
+
expect(File.read(write_path)).to eq File.read(read_path)
|
185
|
+
end
|
186
|
+
|
187
|
+
it "doesn't write extra entries with 0 values" do
|
188
|
+
raw_data = [
|
189
|
+
{
|
190
|
+
"date" => '2014-04-24',
|
191
|
+
"story_points" =>
|
192
|
+
{
|
193
|
+
"total" => 30,
|
194
|
+
"open" => 21
|
195
|
+
},
|
196
|
+
"tasks" =>
|
197
|
+
{
|
198
|
+
"total" => 26,
|
199
|
+
"open" => 19
|
200
|
+
},
|
201
|
+
"story_points_extra" =>
|
202
|
+
{
|
203
|
+
"done" => 0
|
204
|
+
},
|
205
|
+
"tasks_extra" =>
|
206
|
+
{
|
207
|
+
"done" => 0
|
208
|
+
}
|
209
|
+
}
|
210
|
+
]
|
211
|
+
@chart.data["days"] = raw_data
|
212
|
+
@chart.data["meta"]["board_id"] = "1234"
|
213
|
+
|
214
|
+
write_path = given_dummy_file
|
215
|
+
@chart.write_data(write_path)
|
216
|
+
|
217
|
+
expected_file_content = <<EOT
|
218
|
+
---
|
219
|
+
meta:
|
220
|
+
board_id: '1234'
|
221
|
+
sprint: 1
|
222
|
+
total_days: 10
|
223
|
+
weekend_lines:
|
224
|
+
- 3.5
|
225
|
+
- 8.5
|
226
|
+
days:
|
227
|
+
- date: '2014-04-24'
|
228
|
+
story_points:
|
229
|
+
total: 30
|
230
|
+
open: 21
|
231
|
+
tasks:
|
232
|
+
total: 26
|
233
|
+
open: 19
|
234
|
+
EOT
|
235
|
+
expect(File.read(write_path)).to eq expected_file_content
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
describe "commands" do
|
242
|
+
use_given_filesystem(keep_files: true)
|
243
|
+
|
244
|
+
describe "setup" do
|
245
|
+
it "initializes new chart" do
|
246
|
+
path = given_directory
|
247
|
+
@chart.setup(path,"53186e8391ef8671265eba9d")
|
248
|
+
|
249
|
+
expect(File.exist?(File.join(path,"burndown-data-01.yaml"))).to be true
|
250
|
+
|
251
|
+
chart = BurndownChart.new(@settings)
|
252
|
+
chart.read_data(File.join(path,"burndown-data-01.yaml"))
|
253
|
+
|
254
|
+
expect(chart.board_id).to eq "53186e8391ef8671265eba9d"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe "last_sprint" do
|
259
|
+
it "gets the last sprint based on the burndown files" do
|
260
|
+
path = given_directory_from_data("burndown_dir")
|
261
|
+
expect(@chart.last_sprint(path)).to eq(2)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe "load_last_sprint" do
|
266
|
+
let(:path) { given_directory_from_data("burndown_dir") }
|
267
|
+
it "loads the burndown form the 2nd sprint into data" do
|
268
|
+
@chart.load_last_sprint(path)
|
269
|
+
expect(@chart.data).to eq({"meta"=>
|
270
|
+
{"board_id"=>"53186e8391ef8671265eba9d",
|
271
|
+
"sprint"=>2,
|
272
|
+
"total_days"=>9,
|
273
|
+
"weekend_lines"=>[3.5, 7.5]},
|
274
|
+
"days"=>[]})
|
275
|
+
end
|
276
|
+
|
277
|
+
it "returns the path of the last sprint" do
|
278
|
+
expect(@chart.load_last_sprint(path)).to eq(File.join(path,"burndown-data-02.yaml"))
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "update" do
|
283
|
+
let(:path) { given_directory_from_data("burndown_dir") }
|
284
|
+
let(:options) { {'output' => path} }
|
285
|
+
let(:before) { BurndownChart.new(@settings) }
|
286
|
+
let(:after) { BurndownChart.new(@settings) }
|
287
|
+
|
288
|
+
it "updates chart with latest data" do
|
289
|
+
updated_at = "2015-01-12T13:57:16+01:00"
|
290
|
+
expected_date_time = DateTime.parse(updated_at)
|
291
|
+
allow(DateTime).to receive(:now).and_return(expected_date_time)
|
292
|
+
|
293
|
+
before.read_data(File.join(path,'burndown-data-02.yaml'))
|
294
|
+
@chart.update(options)
|
295
|
+
after.read_data(File.join(path,'burndown-data-02.yaml'))
|
296
|
+
expect(after.days.size).to eq before.days.size + 1
|
297
|
+
|
298
|
+
expect(after.days.last["date"]).to eq "2015-01-12"
|
299
|
+
expect(after.days.last["updated_at"]).to eq updated_at
|
300
|
+
end
|
301
|
+
|
302
|
+
it "overwrites data on same date" do
|
303
|
+
before.read_data(File.join(path,'burndown-data-02.yaml'))
|
304
|
+
@chart.update(options)
|
305
|
+
@chart.update(options)
|
306
|
+
after.read_data(File.join(path,'burndown-data-02.yaml'))
|
307
|
+
expect(after.days.size).to eq before.days.size + 1
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
describe "create_next_sprint" do
|
312
|
+
it "create new sprint file" do
|
313
|
+
path = given_directory_from_data("burndown_dir")
|
314
|
+
chart = BurndownChart.new(@settings)
|
315
|
+
chart.create_next_sprint(path)
|
316
|
+
|
317
|
+
next_sprint_file = File.join(path, "burndown-data-03.yaml")
|
318
|
+
expect(File.exist?(next_sprint_file)).to be true
|
319
|
+
|
320
|
+
expected_file_content = <<EOT
|
321
|
+
---
|
322
|
+
meta:
|
323
|
+
board_id: 53186e8391ef8671265eba9d
|
324
|
+
sprint: 3
|
325
|
+
total_days: 9
|
326
|
+
weekend_lines:
|
327
|
+
- 3.5
|
328
|
+
- 7.5
|
329
|
+
days: []
|
330
|
+
EOT
|
331
|
+
expect(File.read(next_sprint_file)).to eq expected_file_content
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
describe "reads meta data from the board" do
|
337
|
+
|
338
|
+
use_given_filesystem
|
339
|
+
|
340
|
+
it "merges meta data from board if present" do
|
341
|
+
chart = BurndownChart.new(@settings)
|
342
|
+
chart.read_data(given_file("burndown-data-10.yaml"))
|
343
|
+
|
344
|
+
expect(chart.data["meta"]["weekend_lines"]).to eq([3.5, 8.5])
|
345
|
+
|
346
|
+
burndown = BurndownData.new(@settings)
|
347
|
+
burndown.board_id = "53186e8391ef8671265eba9d"
|
348
|
+
burndown.fetch
|
349
|
+
|
350
|
+
chart.merge_meta_data_from_board(burndown)
|
351
|
+
|
352
|
+
expect(chart.data["meta"]["weekend_lines"]).to eq([1.5, 6.5, 11.5, 16.5])
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
describe '.plot' do
|
357
|
+
|
358
|
+
it 'sends joined parsed options to python script' do
|
359
|
+
allow(described_class).to receive(:process_options).and_return(%w{ --test 1 --no-blah })
|
360
|
+
allow(described_class).to receive(:plot_helper).and_return('mescript')
|
361
|
+
expect(described_class).to receive(:system).with('python mescript 42 --test 1 --no-blah')
|
362
|
+
described_class.plot(42, {foo: 1, bar: 2})
|
363
|
+
end
|
364
|
+
|
365
|
+
end
|
366
|
+
|
367
|
+
describe '.plot_helper' do
|
368
|
+
|
369
|
+
it 'expands path to burndown generator' do
|
370
|
+
expect(described_class.plot_helper).to include('scripts/create_burndown.py')
|
371
|
+
end
|
372
|
+
|
373
|
+
end
|
374
|
+
|
375
|
+
describe '.process_options' do
|
376
|
+
|
377
|
+
it 'builds an array of switches for burndown chart based on input hash' do
|
378
|
+
test_hash = { 'no-tasks' => true }
|
379
|
+
expect(described_class.send(:process_options, test_hash)).to eq %w{ --no-tasks }
|
380
|
+
test_hash = { 'with-fast-lane' => true }
|
381
|
+
expect(described_class.send(:process_options, test_hash)).to eq %w{ --with-fast-lane }
|
382
|
+
test_hash = { 'output' => 'fanagoro' }
|
383
|
+
expect(described_class.send(:process_options, test_hash)).to eq [ '--output fanagoro' ]
|
384
|
+
test_hash = {}
|
385
|
+
expect(described_class.send(:process_options, test_hash)).to eq [ ]
|
386
|
+
test_hash = {
|
387
|
+
'no-tasks' => true,
|
388
|
+
'with-fast-lane' => true,
|
389
|
+
'output' => 'fanagoro',
|
390
|
+
'verbose' => true
|
391
|
+
}
|
392
|
+
expect(described_class.send(:process_options, test_hash)).to eq ['--no-tasks', '--with-fast-lane', '--output fanagoro', '--verbose']
|
393
|
+
end
|
394
|
+
|
395
|
+
end
|
396
|
+
end
|