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