schubert-minglr 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Rakefile +16 -3
- data/VERSION.yml +2 -2
- data/bin/mtx +3 -3
- data/cucumber.yml +2 -0
- data/features/cards.feature +27 -0
- data/features/step_definitions/minglr_steps.rb +34 -0
- data/features/step_definitions/shared_steps.rb +69 -0
- data/features/users.feature +6 -0
- data/lib/minglr.rb +6 -2
- data/lib/minglr/action.rb +2 -2
- data/lib/minglr/mtx/input_cache.rb +24 -0
- data/lib/minglr/mtx/options_parser.rb +58 -0
- data/lib/minglr/options_parser.rb +13 -10
- data/lib/minglr/resources/attachment.rb +6 -1
- data/lib/minglr/resources/card.rb +26 -16
- data/lib/minglr/resources/user.rb +0 -6
- data/minglr.gemspec +31 -9
- data/tasks/commit.sample.rake +3 -3
- data/test/action_test.rb +75 -0
- data/test/commands_test.rb +111 -0
- data/test/config_parser_test.rb +113 -0
- data/test/options_parser_test.rb +74 -0
- data/test/resources/attachment_test.rb +53 -3
- data/test/resources/base_test.rb +15 -2
- data/test/resources/card_test.rb +119 -9
- data/test/resources/project_test.rb +18 -0
- data/test/resources/user_test.rb +0 -7
- data/test/test_helper.rb +2 -0
- metadata +21 -7
- data/lib/minglr/input_cache.rb +0 -22
- data/lib/minglr/mtx_options_parser.rb +0 -53
data/minglr.gemspec
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
1
3
|
Gem::Specification.new do |s|
|
2
4
|
s.name = %q{minglr}
|
3
|
-
s.version = "1.
|
4
|
-
|
5
|
-
s.specification_version = 2 if s.respond_to? :specification_version=
|
5
|
+
s.version = "1.3.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Michael Schubert", "Stephen Chu", "Chris O'Meara"]
|
9
|
-
s.date = %q{2009-07-
|
9
|
+
s.date = %q{2009-07-27}
|
10
10
|
s.description = %q{* This gem provides two executable binaries to interact with Mingle (http://mingle.thoughtworks.com/mingle-agile-project-management) through its API. It also has sample interactive Rake task on how to facilitate easy card movements when a card enters/exits the development queue. * mtx is a binary that facilities transition changes for use on rake tasks * minglr is a more interactive tool that provides a quick interface for many common uses}
|
11
11
|
s.email = %q{michael@schubert.cx}
|
12
12
|
s.executables = ["mtx", "minglr"]
|
@@ -24,12 +24,17 @@ Gem::Specification.new do |s|
|
|
24
24
|
"VERSION.yml",
|
25
25
|
"bin/minglr",
|
26
26
|
"bin/mtx",
|
27
|
+
"cucumber.yml",
|
28
|
+
"features/cards.feature",
|
29
|
+
"features/step_definitions/minglr_steps.rb",
|
30
|
+
"features/step_definitions/shared_steps.rb",
|
31
|
+
"features/users.feature",
|
27
32
|
"lib/minglr.rb",
|
28
33
|
"lib/minglr/action.rb",
|
29
34
|
"lib/minglr/config_parser.rb",
|
30
35
|
"lib/minglr/extensions/array.rb",
|
31
|
-
"lib/minglr/input_cache.rb",
|
32
|
-
"lib/minglr/
|
36
|
+
"lib/minglr/mtx/input_cache.rb",
|
37
|
+
"lib/minglr/mtx/options_parser.rb",
|
33
38
|
"lib/minglr/options_parser.rb",
|
34
39
|
"lib/minglr/resources/attachment.rb",
|
35
40
|
"lib/minglr/resources/base.rb",
|
@@ -42,7 +47,11 @@ Gem::Specification.new do |s|
|
|
42
47
|
"minglrconfig.sample",
|
43
48
|
"tasks/commit.sample.rake",
|
44
49
|
"tasks/svn.sample.rake",
|
50
|
+
"test/action_test.rb",
|
51
|
+
"test/commands_test.rb",
|
52
|
+
"test/config_parser_test.rb",
|
45
53
|
"test/extensions/array_test.rb",
|
54
|
+
"test/options_parser_test.rb",
|
46
55
|
"test/resources/attachment_test.rb",
|
47
56
|
"test/resources/base_test.rb",
|
48
57
|
"test/resources/card_test.rb",
|
@@ -51,15 +60,18 @@ Gem::Specification.new do |s|
|
|
51
60
|
"test/resources/user_test.rb",
|
52
61
|
"test/test_helper.rb"
|
53
62
|
]
|
54
|
-
s.has_rdoc = true
|
55
63
|
s.homepage = %q{http://github.com/schubert/minglr}
|
56
64
|
s.post_install_message = %q{PostInstall.txt}
|
57
65
|
s.rdoc_options = ["--charset=UTF-8"]
|
58
66
|
s.require_paths = ["lib"]
|
59
|
-
s.rubygems_version = %q{1.
|
67
|
+
s.rubygems_version = %q{1.3.5}
|
60
68
|
s.summary = %q{command line user tool for Mingle (http://mingle.thoughtworks.com/mingle-agile-project-management)}
|
61
69
|
s.test_files = [
|
62
|
-
"test/
|
70
|
+
"test/action_test.rb",
|
71
|
+
"test/commands_test.rb",
|
72
|
+
"test/config_parser_test.rb",
|
73
|
+
"test/extensions/array_test.rb",
|
74
|
+
"test/options_parser_test.rb",
|
63
75
|
"test/resources/attachment_test.rb",
|
64
76
|
"test/resources/base_test.rb",
|
65
77
|
"test/resources/card_test.rb",
|
@@ -68,4 +80,14 @@ Gem::Specification.new do |s|
|
|
68
80
|
"test/resources/user_test.rb",
|
69
81
|
"test/test_helper.rb"
|
70
82
|
]
|
83
|
+
|
84
|
+
if s.respond_to? :specification_version then
|
85
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
86
|
+
s.specification_version = 3
|
87
|
+
|
88
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
89
|
+
else
|
90
|
+
end
|
91
|
+
else
|
92
|
+
end
|
71
93
|
end
|
data/tasks/commit.sample.rake
CHANGED
@@ -64,7 +64,7 @@ namespace :minglr do
|
|
64
64
|
end
|
65
65
|
else
|
66
66
|
print "#{message}"
|
67
|
-
if cache = InputCache.get(options[:cache_key])
|
67
|
+
if cache = MTX::InputCache.get(options[:cache_key])
|
68
68
|
print " [#{cache}]"
|
69
69
|
end
|
70
70
|
print ": "
|
@@ -72,8 +72,8 @@ namespace :minglr do
|
|
72
72
|
end
|
73
73
|
|
74
74
|
if !options[:secure] && cache_key = options.delete(:cache_key)
|
75
|
-
user_input = InputCache.get(cache_key) if user_input.blank?
|
76
|
-
InputCache.put(cache_key, user_input)
|
75
|
+
user_input = MTX::InputCache.get(cache_key) if user_input.blank?
|
76
|
+
MTX::InputCache.put(cache_key, user_input)
|
77
77
|
end
|
78
78
|
|
79
79
|
user_input = escape(user_input)
|
data/test/action_test.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Minglr
|
4
|
+
|
5
|
+
class ActionTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context Action do
|
8
|
+
|
9
|
+
context "valid_actions" do
|
10
|
+
|
11
|
+
should "return an array of valid actions" do
|
12
|
+
valid_actions = ["users", "cards", "card", "move", "update", "attach", "projects", "create", "fetch"].sort
|
13
|
+
assert_equal [], (valid_actions - Action.valid_actions)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
context "valid_action?" do
|
19
|
+
|
20
|
+
should "return true if action is a valid action" do
|
21
|
+
assert_equal true, Action.valid_action?("move")
|
22
|
+
end
|
23
|
+
|
24
|
+
should "return false if action is not a valid action" do
|
25
|
+
assert_equal false, Action.valid_action?("frobble")
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
context "execute" do
|
31
|
+
|
32
|
+
should "ignore the first option if no project is specified" do
|
33
|
+
action = :someaction
|
34
|
+
options = ["someaction", "option2"]
|
35
|
+
flag_options = { :foo => "bar" }
|
36
|
+
config = { :foo => "bar" }
|
37
|
+
|
38
|
+
Minglr::Action::Commands.expects(:send).with(action, ["option2"], flag_options, config)
|
39
|
+
Action.execute(action, options, flag_options, config)
|
40
|
+
end
|
41
|
+
|
42
|
+
should "ignore the first two options if project is specified" do
|
43
|
+
action = :someaction
|
44
|
+
options = ["someproject", "someaction", "option2"]
|
45
|
+
flag_options = { :foo => "bar" }
|
46
|
+
config = { :foo => "bar" }
|
47
|
+
|
48
|
+
Minglr::Action::Commands.expects(:send).with(action, ["option2"], flag_options, config)
|
49
|
+
Action.execute(action, options, flag_options, config)
|
50
|
+
end
|
51
|
+
|
52
|
+
should "send the action to commands" do
|
53
|
+
action = "someaction"
|
54
|
+
options = ["option1", "option2"]
|
55
|
+
flag_options = { :foo => "bar" }
|
56
|
+
config = { :foo => "bar" }
|
57
|
+
|
58
|
+
Minglr::Action::Commands.expects(:send).with(action, options, flag_options, config)
|
59
|
+
Action.execute(action, options, flag_options, config)
|
60
|
+
end
|
61
|
+
|
62
|
+
should "rescue and print an error if the resource can't be found" do
|
63
|
+
Action.expects(:puts).with("Failed with MyError for URL '#{Resources::Base.site}' ...")
|
64
|
+
Minglr::Action::Commands.expects(:send).raises(ActiveResource::ResourceNotFound, stub("Response", :code => "MyError"))
|
65
|
+
|
66
|
+
Action.execute("someaction", ["someaction"])
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Minglr
|
4
|
+
|
5
|
+
class CommandsTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context Action::Commands do
|
8
|
+
|
9
|
+
setup do
|
10
|
+
@options = []
|
11
|
+
@flag_options = {}
|
12
|
+
@config = { :status_property => "cp_status", :username => "user", :password => "password" }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "attach" do
|
16
|
+
|
17
|
+
should "parse card number and file number as options and call resource" do
|
18
|
+
@options << "1"
|
19
|
+
@flag_options[:file_attachment] = "file"
|
20
|
+
|
21
|
+
Resources::Attachment.expects(:attach).with("1", "file", "user", "password")
|
22
|
+
Action::Commands.attach(@options, @flag_options, @config)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
context "card" do
|
28
|
+
|
29
|
+
should "parse card number and call resource" do
|
30
|
+
@options << "1"
|
31
|
+
|
32
|
+
Resources::Card.expects(:print_card).with("1", "cp_status")
|
33
|
+
Action::Commands.card(@options, @flag_options, @config)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
context "cards" do
|
39
|
+
|
40
|
+
should "call resource" do
|
41
|
+
Resources::Card.expects(:print_all).with(@options, "cp_status")
|
42
|
+
Action::Commands.cards(@options, @flag_options, @config)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
context "create" do
|
48
|
+
|
49
|
+
should "call resource" do
|
50
|
+
Resources::Card.expects(:create).with(@flag_options, "cp_status")
|
51
|
+
Action::Commands.create(@options, @flag_options, @config)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
context "fetch" do
|
57
|
+
|
58
|
+
should "parse card number and call resource" do
|
59
|
+
@options << "1"
|
60
|
+
|
61
|
+
Resources::Attachment.expects(:fetch).with("1", "user", "password")
|
62
|
+
Action::Commands.fetch(@options, @flag_options, @config)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
context "move" do
|
68
|
+
|
69
|
+
should "parse card number and call resource" do
|
70
|
+
@options << "1"
|
71
|
+
|
72
|
+
Resources::Card.expects(:move).with("1", @flag_options, @config)
|
73
|
+
Action::Commands.move(@options, @flag_options, @config)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
context "projects" do
|
79
|
+
|
80
|
+
should "call resource" do
|
81
|
+
Resources::Project.expects(:print_all).with(@options, "cp_status")
|
82
|
+
Action::Commands.projects(@options, @flag_options, @config)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
context "update" do
|
88
|
+
|
89
|
+
should "parse card number and call resource" do
|
90
|
+
@options << "1"
|
91
|
+
|
92
|
+
Resources::Card.expects(:update).with("1", @flag_options)
|
93
|
+
Action::Commands.update(@options, @flag_options, @config)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
context "users" do
|
99
|
+
|
100
|
+
should "call resource" do
|
101
|
+
Resources::User.expects(:print_all).with(@options)
|
102
|
+
Action::Commands.users(@options, @flag_options, @config)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Minglr
|
4
|
+
|
5
|
+
class ConfigParserTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context "parse" do
|
8
|
+
|
9
|
+
should "look for a config file in the user home directory or the current working directory" do
|
10
|
+
File.expects(:exist?).with(File.join(ENV["HOME"], ".minglrconfig"))
|
11
|
+
File.expects(:exist?).with(File.expand_path(File.join(ENV["PWD"], ".minglrconfig")))
|
12
|
+
ConfigParser.stubs(:puts)
|
13
|
+
ConfigParser.parse
|
14
|
+
end
|
15
|
+
|
16
|
+
should "return the parsed configuration as a hash" do
|
17
|
+
configuration_content = <<-EOS
|
18
|
+
[foo]
|
19
|
+
myfoo = myvalue
|
20
|
+
[bar]
|
21
|
+
mybar = yourvalue
|
22
|
+
EOS
|
23
|
+
|
24
|
+
File.stubs(:exist?).returns(true)
|
25
|
+
File.expects(:read).returns(configuration_content)
|
26
|
+
parsed_configuration = ConfigParser.parse
|
27
|
+
|
28
|
+
assert_equal Hash, parsed_configuration.class
|
29
|
+
end
|
30
|
+
|
31
|
+
should "print a message if the config file cannot be found" do
|
32
|
+
File.expects(:exist?).times(2).returns(false)
|
33
|
+
ConfigParser.expects(:puts)
|
34
|
+
ConfigParser.parse
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
context "initialize" do
|
40
|
+
|
41
|
+
should "parse the configuration file into sections and variables" do
|
42
|
+
configuration_content = <<-EOS
|
43
|
+
[foo]
|
44
|
+
myfoo = myvalue
|
45
|
+
[bar]
|
46
|
+
mybar = yourvalue
|
47
|
+
EOS
|
48
|
+
|
49
|
+
parsed_configuration = ConfigParser.new(configuration_content)
|
50
|
+
assert_equal true, parsed_configuration.config.has_key?(:foo)
|
51
|
+
assert_equal true, parsed_configuration.config.has_key?(:bar)
|
52
|
+
assert_equal true, parsed_configuration.config[:foo].has_key?(:myfoo)
|
53
|
+
assert_equal true, parsed_configuration.config[:bar].has_key?(:mybar)
|
54
|
+
assert_equal "myvalue", parsed_configuration.config[:foo][:myfoo]
|
55
|
+
assert_equal "yourvalue", parsed_configuration.config[:bar][:mybar]
|
56
|
+
end
|
57
|
+
|
58
|
+
should "skip comment lines" do
|
59
|
+
configuration_content = <<-EOS
|
60
|
+
# [foo]
|
61
|
+
# bar = bad
|
62
|
+
[foo]
|
63
|
+
bar = baz
|
64
|
+
EOS
|
65
|
+
|
66
|
+
parsed_configuration = ConfigParser.new(configuration_content)
|
67
|
+
assert_equal "baz", parsed_configuration.config[:foo][:bar]
|
68
|
+
end
|
69
|
+
|
70
|
+
should "skip blank lines" do
|
71
|
+
configuration_content = <<-EOS
|
72
|
+
|
73
|
+
[foo]
|
74
|
+
|
75
|
+
[babble]
|
76
|
+
bar = baz
|
77
|
+
EOS
|
78
|
+
|
79
|
+
parsed_configuration = ConfigParser.new(configuration_content)
|
80
|
+
assert_equal "baz", parsed_configuration.config[:babble][:bar]
|
81
|
+
end
|
82
|
+
|
83
|
+
should "not redefine a section if it has already been defined" do
|
84
|
+
configuration_content = <<-EOS
|
85
|
+
[foo]
|
86
|
+
bar = baz
|
87
|
+
should = bekept
|
88
|
+
|
89
|
+
[foo]
|
90
|
+
bar = somethingelse
|
91
|
+
EOS
|
92
|
+
|
93
|
+
parsed_configuration = ConfigParser.new(configuration_content)
|
94
|
+
assert_equal "somethingelse", parsed_configuration.config[:foo][:bar]
|
95
|
+
assert_equal "bekept", parsed_configuration.config[:foo][:should]
|
96
|
+
end
|
97
|
+
|
98
|
+
should "set a section variable to the latest value allowing it to be redefined" do
|
99
|
+
configuration_content = <<-EOS
|
100
|
+
[foo]
|
101
|
+
bar = baz
|
102
|
+
bar = somethingelse
|
103
|
+
EOS
|
104
|
+
|
105
|
+
parsed_configuration = ConfigParser.new(configuration_content)
|
106
|
+
assert_equal "somethingelse", parsed_configuration.config[:foo][:bar]
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Minglr
|
4
|
+
|
5
|
+
class OptionsParserTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context "parse" do
|
8
|
+
|
9
|
+
should "gather all property definitions for a given project" do
|
10
|
+
Resources::Base.site = "http://foo.bar"
|
11
|
+
Resources::PropertyDefinition.expects(:project_options).returns([[:column_name, "Some Column Name"]])
|
12
|
+
OptionsParser.expects(:puts)
|
13
|
+
OptionsParser.parse(["--version"])
|
14
|
+
end
|
15
|
+
|
16
|
+
should "warn about authentication if property definition gathering fails" do
|
17
|
+
Resources::Base.site = "http://foo.bar"
|
18
|
+
Resources::PropertyDefinition.expects(:project_options).raises(ActiveResource::UnauthorizedAccess, stub(:code => "BadAccess"))
|
19
|
+
OptionsParser.expects(:puts).at_least(1)
|
20
|
+
OptionsParser.expects(:puts).with("Connection Failed with BadAccess to http://foo.bar")
|
21
|
+
OptionsParser.expects(:puts).with("Did you set 'basic_authentication_enabled: true' in your auth_config.yml file?")
|
22
|
+
OptionsParser.parse(["--version"])
|
23
|
+
end
|
24
|
+
|
25
|
+
should "parse name option" do
|
26
|
+
Resources::Base.site = "http://foo.bar"
|
27
|
+
Resources::PropertyDefinition.stubs(:project_options).returns([])
|
28
|
+
options = OptionsParser.parse(["-n", "MyName"])
|
29
|
+
|
30
|
+
assert_equal true, options.has_key?(:name)
|
31
|
+
assert_equal "MyName", options[:name]
|
32
|
+
end
|
33
|
+
|
34
|
+
should "parse description option" do
|
35
|
+
Resources::Base.site = "http://foo.bar"
|
36
|
+
Resources::PropertyDefinition.stubs(:project_options).returns([])
|
37
|
+
options = OptionsParser.parse(["-d", "MyDescription"])
|
38
|
+
|
39
|
+
assert_equal true, options.has_key?(:description)
|
40
|
+
assert_equal "MyDescription", options[:description]
|
41
|
+
end
|
42
|
+
|
43
|
+
should "parse type option" do
|
44
|
+
Resources::Base.site = "http://foo.bar"
|
45
|
+
Resources::PropertyDefinition.stubs(:project_options).returns([])
|
46
|
+
options = OptionsParser.parse(["-t MyType"])
|
47
|
+
|
48
|
+
assert_equal true, options.has_key?(:card_type_name)
|
49
|
+
assert_equal "MyType", options[:card_type_name]
|
50
|
+
end
|
51
|
+
|
52
|
+
should "parse comment option" do
|
53
|
+
Resources::Base.site = "http://foo.bar"
|
54
|
+
Resources::PropertyDefinition.stubs(:project_options).returns([])
|
55
|
+
options = OptionsParser.parse(["-c MyComment"])
|
56
|
+
|
57
|
+
assert_equal true, options.has_key?(:comment)
|
58
|
+
assert_equal "MyComment", options[:comment]
|
59
|
+
end
|
60
|
+
|
61
|
+
should "parse file option" do
|
62
|
+
Resources::Base.site = "http://foo.bar"
|
63
|
+
Resources::PropertyDefinition.stubs(:project_options).returns([])
|
64
|
+
options = OptionsParser.parse(["-f MyFile"])
|
65
|
+
|
66
|
+
assert_equal true, options.has_key?(:file_attachment)
|
67
|
+
assert_equal "MyFile", options[:file_attachment]
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|