minglr 1.3.11

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.
Files changed (45) hide show
  1. data/.document +5 -0
  2. data/.gitignore +3 -0
  3. data/LICENSE +20 -0
  4. data/PostInstall.txt +1 -0
  5. data/README.rdoc +87 -0
  6. data/Rakefile +90 -0
  7. data/VERSION.yml +4 -0
  8. data/bin/minglr +29 -0
  9. data/bin/mtx +14 -0
  10. data/cucumber.yml +2 -0
  11. data/features/cards.feature +27 -0
  12. data/features/step_definitions/minglr_steps.rb +34 -0
  13. data/features/step_definitions/shared_steps.rb +69 -0
  14. data/features/users.feature +6 -0
  15. data/lib/minglr.rb +34 -0
  16. data/lib/minglr/action.rb +85 -0
  17. data/lib/minglr/config_parser.rb +51 -0
  18. data/lib/minglr/extensions/array.rb +23 -0
  19. data/lib/minglr/mtx/input_cache.rb +24 -0
  20. data/lib/minglr/mtx/options_parser.rb +58 -0
  21. data/lib/minglr/options_parser.rb +82 -0
  22. data/lib/minglr/resources/attachment.rb +51 -0
  23. data/lib/minglr/resources/base.rb +42 -0
  24. data/lib/minglr/resources/card.rb +117 -0
  25. data/lib/minglr/resources/project.rb +25 -0
  26. data/lib/minglr/resources/property_definition.rb +12 -0
  27. data/lib/minglr/resources/transition_execution.rb +6 -0
  28. data/lib/minglr/resources/user.rb +19 -0
  29. data/minglr.gemspec +120 -0
  30. data/minglrconfig.sample +37 -0
  31. data/tasks/commit.sample.rake +86 -0
  32. data/tasks/svn.sample.rake +27 -0
  33. data/test/action_test.rb +75 -0
  34. data/test/commands_test.rb +111 -0
  35. data/test/config_parser_test.rb +116 -0
  36. data/test/extensions/array_test.rb +41 -0
  37. data/test/options_parser_test.rb +74 -0
  38. data/test/resources/attachment_test.rb +90 -0
  39. data/test/resources/base_test.rb +58 -0
  40. data/test/resources/card_test.rb +199 -0
  41. data/test/resources/project_test.rb +44 -0
  42. data/test/resources/property_definition_test.rb +25 -0
  43. data/test/resources/user_test.rb +32 -0
  44. data/test/test_helper.rb +31 -0
  45. metadata +219 -0
@@ -0,0 +1,116 @@
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")).returns(true)
11
+ #File.expects(:exist?).with(File.expand_path(File.join(ENV["PWD"], ".minglrconfig"))).returns(false)
12
+ config_file_contents = ""
13
+ File.expects(:read).with(File.join(ENV["HOME"], ".minglrconfig")).returns(config_file_contents)
14
+
15
+ ConfigParser.parse
16
+ end
17
+
18
+ should "return the parsed configuration as a hash" do
19
+ configuration_content = <<-EOS
20
+ [foo]
21
+ myfoo = myvalue
22
+ [bar]
23
+ mybar = yourvalue
24
+ EOS
25
+
26
+ File.stubs(:exist?).returns(true)
27
+ File.expects(:read).returns(configuration_content)
28
+ parsed_configuration = ConfigParser.parse
29
+
30
+ assert_equal Hash, parsed_configuration.class
31
+ end
32
+
33
+ should "print a message if the config file cannot be found" do
34
+ File.expects(:exist?).times(2).returns(false)
35
+ ConfigParser.expects(:class_eval).with("send :exit, 1")
36
+ ConfigParser.expects(:puts)
37
+ ConfigParser.parse
38
+ end
39
+
40
+ end
41
+
42
+ context "initialize" do
43
+
44
+ should "parse the configuration file into sections and variables" do
45
+ configuration_content = <<-EOS
46
+ [foo]
47
+ myfoo = myvalue
48
+ [bar]
49
+ mybar = yourvalue
50
+ EOS
51
+
52
+ parsed_configuration = ConfigParser.new(configuration_content)
53
+ assert_equal true, parsed_configuration.config.has_key?(:foo)
54
+ assert_equal true, parsed_configuration.config.has_key?(:bar)
55
+ assert_equal true, parsed_configuration.config[:foo].has_key?(:myfoo)
56
+ assert_equal true, parsed_configuration.config[:bar].has_key?(:mybar)
57
+ assert_equal "myvalue", parsed_configuration.config[:foo][:myfoo]
58
+ assert_equal "yourvalue", parsed_configuration.config[:bar][:mybar]
59
+ end
60
+
61
+ should "skip comment lines" do
62
+ configuration_content = <<-EOS
63
+ # [foo]
64
+ # bar = bad
65
+ [foo]
66
+ bar = baz
67
+ EOS
68
+
69
+ parsed_configuration = ConfigParser.new(configuration_content)
70
+ assert_equal "baz", parsed_configuration.config[:foo][:bar]
71
+ end
72
+
73
+ should "skip blank lines" do
74
+ configuration_content = <<-EOS
75
+
76
+ [foo]
77
+
78
+ [babble]
79
+ bar = baz
80
+ EOS
81
+
82
+ parsed_configuration = ConfigParser.new(configuration_content)
83
+ assert_equal "baz", parsed_configuration.config[:babble][:bar]
84
+ end
85
+
86
+ should "not redefine a section if it has already been defined" do
87
+ configuration_content = <<-EOS
88
+ [foo]
89
+ bar = baz
90
+ should = bekept
91
+
92
+ [foo]
93
+ bar = somethingelse
94
+ EOS
95
+
96
+ parsed_configuration = ConfigParser.new(configuration_content)
97
+ assert_equal "somethingelse", parsed_configuration.config[:foo][:bar]
98
+ assert_equal "bekept", parsed_configuration.config[:foo][:should]
99
+ end
100
+
101
+ should "set a section variable to the latest value allowing it to be redefined" do
102
+ configuration_content = <<-EOS
103
+ [foo]
104
+ bar = baz
105
+ bar = somethingelse
106
+ EOS
107
+
108
+ parsed_configuration = ConfigParser.new(configuration_content)
109
+ assert_equal "somethingelse", parsed_configuration.config[:foo][:bar]
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,41 @@
1
+ require 'test_helper'
2
+
3
+ module Minglr
4
+ module Extensions
5
+
6
+ class ArrayTest < Test::Unit::TestCase
7
+
8
+ context Array do
9
+
10
+ context "filter" do
11
+
12
+ setup do
13
+ class TestObject
14
+ attr_accessor :name
15
+ end
16
+ @test1 = TestObject.new
17
+ @test2 = TestObject.new
18
+ @test1.name = "test1"
19
+ @test2.name = "test2"
20
+ @collection = [@test1, @test2]
21
+ @collection.send(:extend, Minglr::Extensions::Array)
22
+ end
23
+
24
+ should "include elements matching words in attributes" do
25
+ assert_equal [@test1], @collection.filter([:name], ["1"])
26
+ assert_equal [@test1, @test2], @collection.filter([:name], ["test"])
27
+ end
28
+
29
+ should "deal with empty words and attributes" do
30
+ assert_equal [@test1, @test2], @collection.filter([], [])
31
+ assert_equal [@test1, @test2], @collection.filter([:name], [])
32
+ assert_equal [], @collection.filter([], ["1"])
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
41
+ 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
@@ -0,0 +1,90 @@
1
+ require 'test_helper'
2
+
3
+ module Resources
4
+
5
+ class AttachmentTest < Test::Unit::TestCase
6
+
7
+ context Attachment do
8
+
9
+ context "configure" do
10
+
11
+ should "append to the site url" do
12
+ options = { :username => "user",
13
+ :password => "pass",
14
+ :url => "proto://somehost.com:1234/projects/my_project" }
15
+ Base.configure(options)
16
+ Attachment.configure
17
+ assert_equal "/projects/my_project/cards/1/", Attachment.prefix(:card_number => 1)
18
+ end
19
+
20
+ end
21
+
22
+ context "fetch" do
23
+
24
+ should "download all found attachments for a given card number" do
25
+ card = Card.new
26
+ card.stubs(:number).returns(1)
27
+
28
+ attachment1 = Attachment.new
29
+ attachment1.stubs(:url).returns("http://attachment1.url")
30
+ attachment1.stubs(:file_name).returns("attachment1.txt")
31
+ attachment2 = Attachment.new
32
+ attachment2.stubs(:url).returns("http://attachment2.url")
33
+ attachment2.stubs(:file_name).returns("attachment2.txt")
34
+
35
+ Attachment.stubs(:puts)
36
+ Card.expects(:find).with(1).returns(card)
37
+ Attachment.expects(:find).with(:all, :params => { :card_number => 1 }).returns([attachment1, attachment2])
38
+ Attachment.expects(:curl).with("curl --insecure --progress-bar --output attachment1.txt --user username:password http://attachment1.url")
39
+ Attachment.expects(:curl).with("curl --insecure --progress-bar --output attachment2.txt --user username:password http://attachment2.url")
40
+
41
+ Attachment.fetch(1, "username", "password")
42
+ end
43
+
44
+ end
45
+
46
+ context "attach" do
47
+
48
+ setup do
49
+ options = { :username => "user",
50
+ :password => "pass",
51
+ :url => "proto://somehost.com:1234/projects/my_project" }
52
+ Base.configure(options)
53
+ end
54
+
55
+ should "upload file for a given card number" do
56
+ file_name = File.join(File.dirname(__FILE__), "..", "..", "Rakefile")
57
+
58
+ card = Card.new
59
+ card.stubs(:number).returns(1)
60
+
61
+ fake_response = stub("Response", :status_code => 201)
62
+ fake_client = mock("HTTPClient")
63
+ fake_client.expects(:post).returns(fake_response)
64
+ fake_client.expects(:set_auth).with(nil, "username", "password")
65
+
66
+ Card.expects(:find).with(1).returns(card)
67
+ HTTPClient.expects(:new).returns(fake_client)
68
+ Attachment.expects(:puts).with("File '#{file_name}' attached to card 1")
69
+
70
+ Attachment.attach(1, file_name, "username", "password")
71
+ end
72
+
73
+ should "warn for invalid file" do
74
+ card = Card.new
75
+ card.stubs(:number).returns(1)
76
+
77
+ Card.expects(:find).with(1).returns(card)
78
+ File.expects(:exist?).with("myfile.txt").returns(false)
79
+ Attachment.expects(:warn).with("Unable to open file 'myfile.txt'")
80
+
81
+ Attachment.attach(1, "myfile.txt", "username", "password")
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+
3
+ module Resources
4
+
5
+ class BaseTest < Test::Unit::TestCase
6
+
7
+ context Base do
8
+
9
+ context "configure" do
10
+
11
+ should "combine options to build url" do
12
+ options = { :username => "user",
13
+ :password => "pass",
14
+ :url => "proto://somehost.com:1234/projects/my_project" }
15
+ Base.configure(options)
16
+ assert_equal "proto://user:pass@somehost.com:1234/projects/my_project",
17
+ Base.site.to_s
18
+ end
19
+
20
+ end
21
+
22
+ context "warn" do
23
+
24
+ should "prepend message with warning" do
25
+ Base.expects(:puts).with("Warning: test")
26
+ Base.warn("test")
27
+ end
28
+
29
+ end
30
+
31
+ context "print_collection" do
32
+
33
+ setup do
34
+ @object1 = stub("Object", :name => "Foo", :description => "Bar")
35
+ @object2 = stub("Object", :name => "Bar", :description => "Frobble")
36
+ @collection = [@object1, @object2]
37
+ @attributes = [:name, :description]
38
+ end
39
+
40
+ should "print values of attributes of objects separated by dashes and aligning columns of values" do
41
+ Base.expects(:puts).with("Foo - Bar ")
42
+ Base.expects(:puts).with("Bar - Frobble")
43
+ Base.print_collection(@collection, @attributes)
44
+ end
45
+
46
+ should "allow for right adjusted values" do
47
+ Base.expects(:puts).with("Foo - Bar")
48
+ Base.expects(:puts).with("Bar - Frobble")
49
+ Base.print_collection(@collection, @attributes, :right)
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -0,0 +1,199 @@
1
+ require 'test_helper'
2
+
3
+ module Resources
4
+
5
+ class CardTest < Test::Unit::TestCase
6
+
7
+ context Card do
8
+
9
+ context "create" do
10
+
11
+ should "create a card with options passed in" do
12
+ card = Card.new
13
+ card.stubs(:number).returns(1)
14
+ Card.expects(:new).with(:name => "Name").returns(card)
15
+ Card.any_instance.expects(:save).returns(true)
16
+ Card.any_instance.expects(:reload)
17
+ Card.expects(:puts).with("Card #1 created")
18
+ Card.create({:name => "Name"})
19
+ end
20
+
21
+ should "create a card with the status of new if status property is available" do
22
+ card = Card.new
23
+ card.stubs(:number).returns(1)
24
+ Card.expects(:new).with(:some_option => "value", :cp_status => "New").returns(card)
25
+ Card.any_instance.expects(:save).returns(true)
26
+ Card.any_instance.expects(:reload)
27
+ Card.expects(:puts).with("Card #1 created")
28
+ Card.create({:some_option => "value"}, "cp_status")
29
+ end
30
+
31
+ should "warn if it is unable to create the card" do
32
+ Card.any_instance.expects(:save).returns(false)
33
+ Card.expects(:warn).with("Unable to create card")
34
+ Card.create
35
+ end
36
+
37
+ end
38
+
39
+ context "move" do
40
+
41
+ should "move card from one state to the next as defined" do
42
+ card = Card.new
43
+ card.stubs(:card_type_name).returns("story")
44
+ card.stubs(:status).returns("New")
45
+ config = { :story_state_1 => "New > Dev", :status_property => "status"}
46
+ response = stub("Response", :attributes => { "status" => "completed" })
47
+
48
+ Card.expects(:find).with(1).returns(card)
49
+ TransitionExecution.expects(:create).with(:transition => 'Dev', :card => 1).returns(response)
50
+ Card.expects(:puts).with("Moved card from New to Dev")
51
+ Card.move(1, {}, config)
52
+ end
53
+
54
+ should "warn if no matching card type is found" do
55
+ card = Card.new
56
+ card.stubs(:card_type_name).returns("someothertype")
57
+ card.stubs(:status).returns("New")
58
+ config = { :story_state_1 => "New > Dev", :status_property => "status"}
59
+
60
+ Card.expects(:find).with(1).returns(card)
61
+ Card.expects(:warn).with("No transitions defined for card of type someothertype")
62
+ Card.move(1, {}, config)
63
+ end
64
+
65
+ should "warn if card has no status property" do
66
+ card = Card.new
67
+ card.stubs(:card_type_name).returns("story")
68
+ card.stubs(:current_status).returns("New")
69
+ config = { :story_state_1 => "New > Dev"}
70
+
71
+ Card.expects(:find).with(1).returns(card)
72
+ Card.expects(:warn).with("No known status of card #1, cannot move!")
73
+ Card.move(1, {}, config)
74
+ end
75
+
76
+ should "warn if card cannot be found" do
77
+ Card.expects(:find).with(0).returns(nil)
78
+ Card.expects(:warn).with("No card #0 found to move")
79
+ Card.move(0)
80
+ end
81
+
82
+ end
83
+
84
+ context "print_all" do
85
+
86
+ should "warn if there are no cards" do
87
+ Card.expects(:find).with(:all).returns([])
88
+ Card.expects(:warn).with("No cards found")
89
+ Card.print_all
90
+ end
91
+
92
+ should "print the cards found with format" do
93
+ card1 = stub("Card", :number => 1, :card_type_name => "Story", :name => "Some Story")
94
+ card2 = stub("Card", :number => 2, :card_type_name => "Task", :name => "Some Task")
95
+ Card.expects(:find).with(:all).returns([card1, card2])
96
+ Card.expects(:puts).with("1 - Story - Some Story")
97
+ Card.expects(:puts).with("2 - Task - Some Task ")
98
+ Card.print_all
99
+ end
100
+
101
+ should "print cards with status property if available" do
102
+ card1 = stub("Card", :number => 1, :card_type_name => "Story", :name => "Some Story", :cp_status => "Ready")
103
+ Card.expects(:find).with(:all).returns([card1])
104
+ Card.expects(:puts).with("1 - Story - Ready - Some Story")
105
+ Card.print_all([], "cp_status")
106
+ end
107
+
108
+ end
109
+
110
+ context "print_card" do
111
+
112
+ should "print the details for a given card" do
113
+ status_property = "cp_status"
114
+ card = Card.new
115
+ card.expects(:to_s).with(status_property)
116
+ Card.expects(:find).with(1).returns(card)
117
+ Card.stubs(:puts)
118
+ Card.print_card(1, status_property)
119
+ end
120
+
121
+ should "warn if it is not able to find the card" do
122
+ Card.expects(:find).with(0).returns(nil)
123
+ Card.expects(:warn).with("No card #0 found")
124
+ Card.print_card(0)
125
+ end
126
+
127
+ end
128
+
129
+ context "update" do
130
+
131
+ should "update a card with the options passed in" do
132
+ card = mock("Card")
133
+ card.stubs(:number).returns(1)
134
+ card.expects(:foo=).with("bar")
135
+ card.expects(:baz=).with("frobble")
136
+ card.expects(:save)
137
+ Card.stubs(:puts)
138
+ Card.expects(:find).with(1).returns(card)
139
+
140
+ Card.update(1, {:foo => "bar", :baz => "frobble"})
141
+ end
142
+
143
+ should "print out the details of the card after updating" do
144
+ card = mock("Card")
145
+ card.stubs(:number).returns(1)
146
+ card.stubs(:foo=)
147
+ card.stubs(:baz=)
148
+ card.stubs(:save)
149
+ Card.stubs(:find).with(1).returns(card)
150
+
151
+ Card.expects(:puts).with("Card #1 updated\n\n")
152
+ Card.expects(:puts).with(card.to_s)
153
+ Card.update(1, {:foo => "bar", :baz => "frobble"})
154
+ end
155
+
156
+ should "warn if it is not able to find the card" do
157
+ Card.expects(:find).with(0).returns(nil)
158
+ Card.expects(:warn).with("Unable to update card #0")
159
+ Card.update(0)
160
+ end
161
+
162
+ end
163
+
164
+ context "to_s" do
165
+
166
+ should "format the details of a given card including attachments" do
167
+ Resources::Base.site = "http://foo.bar"
168
+
169
+ attachment = Attachment.new
170
+ attachment.stubs(:file_name).returns("My File Name")
171
+ attachment.stubs(:url).returns("http://some.url")
172
+ Attachment.expects(:find).with(:all, :params => { :card_number => 1 }).returns([attachment])
173
+
174
+ card = Card.new
175
+ card.stubs(:number).returns(1)
176
+ card.stubs(:name).returns("My Name")
177
+ card.stubs(:card_type_name).returns("My Type")
178
+ card.stubs(:description).returns("My Description")
179
+
180
+ expected_output = <<-EOS
181
+ Number: 1
182
+ Name: My Name
183
+ Type: My Type
184
+ Status:
185
+ Description: My Description
186
+
187
+ Attachments:
188
+ * My File Name: http://some.url
189
+ EOS
190
+ assert_equal expected_output, card.to_s
191
+ end
192
+
193
+ end
194
+
195
+ end
196
+
197
+ end
198
+
199
+ end