puppet-module 0.3.0

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 (159) hide show
  1. data/CHANGES.markdown +91 -0
  2. data/LICENSE +17 -0
  3. data/README.markdown +221 -0
  4. data/Rakefile +87 -0
  5. data/VERSION +1 -0
  6. data/bin/puppet-module +7 -0
  7. data/lib/puppet/module/tool.rb +124 -0
  8. data/lib/puppet/module/tool/applications.rb +18 -0
  9. data/lib/puppet/module/tool/applications/application.rb +83 -0
  10. data/lib/puppet/module/tool/applications/builder.rb +88 -0
  11. data/lib/puppet/module/tool/applications/checksummer.rb +38 -0
  12. data/lib/puppet/module/tool/applications/cleaner.rb +14 -0
  13. data/lib/puppet/module/tool/applications/freezer.rb +20 -0
  14. data/lib/puppet/module/tool/applications/generator.rb +117 -0
  15. data/lib/puppet/module/tool/applications/installer.rb +83 -0
  16. data/lib/puppet/module/tool/applications/registrar.rb +34 -0
  17. data/lib/puppet/module/tool/applications/releaser.rb +48 -0
  18. data/lib/puppet/module/tool/applications/searcher.rb +34 -0
  19. data/lib/puppet/module/tool/applications/unpacker.rb +69 -0
  20. data/lib/puppet/module/tool/applications/unreleaser.rb +42 -0
  21. data/lib/puppet/module/tool/cache.rb +56 -0
  22. data/lib/puppet/module/tool/checksums.rb +52 -0
  23. data/lib/puppet/module/tool/cli.rb +127 -0
  24. data/lib/puppet/module/tool/contents_description.rb +84 -0
  25. data/lib/puppet/module/tool/dependency.rb +26 -0
  26. data/lib/puppet/module/tool/metadata.rb +80 -0
  27. data/lib/puppet/module/tool/modulefile.rb +47 -0
  28. data/lib/puppet/module/tool/repository.rb +74 -0
  29. data/lib/puppet/module/tool/skeleton.rb +39 -0
  30. data/lib/puppet/module/tool/utils.rb +9 -0
  31. data/lib/puppet/module/tool/utils/interrogation.rb +39 -0
  32. data/lib/puppet/module/tool/utils/settings.rb +36 -0
  33. data/lib/puppet/module/tool/utils/uri.rb +16 -0
  34. data/spec/fixtures/releases/jamtur01-apache/Modulefile +2 -0
  35. data/spec/fixtures/releases/jamtur01-apache/files/httpd +24 -0
  36. data/spec/fixtures/releases/jamtur01-apache/files/test.vhost +18 -0
  37. data/spec/fixtures/releases/jamtur01-apache/lib/puppet/provider/a2mod/debian.rb +21 -0
  38. data/spec/fixtures/releases/jamtur01-apache/lib/puppet/type/a2mod.rb +12 -0
  39. data/spec/fixtures/releases/jamtur01-apache/manifests/dev.pp +5 -0
  40. data/spec/fixtures/releases/jamtur01-apache/manifests/init.pp +34 -0
  41. data/spec/fixtures/releases/jamtur01-apache/manifests/params.pp +17 -0
  42. data/spec/fixtures/releases/jamtur01-apache/manifests/php.pp +5 -0
  43. data/spec/fixtures/releases/jamtur01-apache/manifests/ssl.pp +15 -0
  44. data/spec/fixtures/releases/jamtur01-apache/manifests/vhost.pp +15 -0
  45. data/spec/fixtures/releases/jamtur01-apache/metadata.json +1 -0
  46. data/spec/fixtures/releases/jamtur01-apache/templates/vhost-default.conf.erb +20 -0
  47. data/spec/fixtures/releases/jamtur01-apache/tests/apache.pp +1 -0
  48. data/spec/fixtures/releases/jamtur01-apache/tests/dev.pp +1 -0
  49. data/spec/fixtures/releases/jamtur01-apache/tests/init.pp +1 -0
  50. data/spec/fixtures/releases/jamtur01-apache/tests/php.pp +1 -0
  51. data/spec/fixtures/releases/jamtur01-apache/tests/ssl.pp +1 -0
  52. data/spec/fixtures/releases/jamtur01-apache/tests/vhost.pp +2 -0
  53. data/spec/integration/cli_spec.rb +373 -0
  54. data/spec/spec.opts +1 -0
  55. data/spec/spec_helper.rb +15 -0
  56. data/spec/support/output_support.rb +19 -0
  57. data/spec/support/stub_http_support.rb +14 -0
  58. data/spec/support/testdir_support.rb +26 -0
  59. data/spec/unit/application_spec.rb +25 -0
  60. data/spec/unit/repository_spec.rb +51 -0
  61. data/templates/generator/Modulefile.erb +5 -0
  62. data/templates/generator/README.erb +3 -0
  63. data/templates/generator/files/README.markdown +22 -0
  64. data/templates/generator/lib/puppet/facter/README.markdown +22 -0
  65. data/templates/generator/lib/puppet/parser/functions/README.markdown +17 -0
  66. data/templates/generator/lib/puppet/provider/README.markdown +14 -0
  67. data/templates/generator/lib/puppet/type/README.markdown +14 -0
  68. data/templates/generator/manifests/README.markdown +28 -0
  69. data/templates/generator/manifests/init.pp.erb +17 -0
  70. data/templates/generator/metadata.json +12 -0
  71. data/templates/generator/spec/README.markdown +7 -0
  72. data/templates/generator/spec/spec.opts +6 -0
  73. data/templates/generator/spec/spec_helper.rb +18 -0
  74. data/templates/generator/spec/unit/puppet/provider/README.markdown +4 -0
  75. data/templates/generator/spec/unit/puppet/type/README.markdown +4 -0
  76. data/templates/generator/templates/README.markdown +23 -0
  77. data/templates/generator/tests/init.pp.erb +1 -0
  78. data/vendor/facets-2.8.2-partial/lib/facets/kernel/returning.rb +23 -0
  79. data/vendor/facets-2.8.2-partial/lib/facets/kernel/tap.rb +39 -0
  80. data/vendor/multipart-post-1.0/Manifest.txt +9 -0
  81. data/vendor/multipart-post-1.0/README.txt +61 -0
  82. data/vendor/multipart-post-1.0/Rakefile +21 -0
  83. data/vendor/multipart-post-1.0/lib/composite_io.rb +89 -0
  84. data/vendor/multipart-post-1.0/lib/multipartable.rb +13 -0
  85. data/vendor/multipart-post-1.0/lib/net/http/post/multipart.rb +27 -0
  86. data/vendor/multipart-post-1.0/lib/parts.rb +66 -0
  87. data/vendor/multipart-post-1.0/test/net/http/post/test_multipart.rb +55 -0
  88. data/vendor/multipart-post-1.0/test/test_composite_io.rb +50 -0
  89. data/vendor/thor-852190ae/CHANGELOG.rdoc +89 -0
  90. data/vendor/thor-852190ae/LICENSE +20 -0
  91. data/vendor/thor-852190ae/README.rdoc +297 -0
  92. data/vendor/thor-852190ae/REVISION +1 -0
  93. data/vendor/thor-852190ae/Thorfile +69 -0
  94. data/vendor/thor-852190ae/bin/rake2thor +86 -0
  95. data/vendor/thor-852190ae/bin/thor +6 -0
  96. data/vendor/thor-852190ae/lib/thor.rb +244 -0
  97. data/vendor/thor-852190ae/lib/thor/actions.rb +275 -0
  98. data/vendor/thor-852190ae/lib/thor/actions/create_file.rb +103 -0
  99. data/vendor/thor-852190ae/lib/thor/actions/directory.rb +91 -0
  100. data/vendor/thor-852190ae/lib/thor/actions/empty_directory.rb +134 -0
  101. data/vendor/thor-852190ae/lib/thor/actions/file_manipulation.rb +223 -0
  102. data/vendor/thor-852190ae/lib/thor/actions/inject_into_file.rb +104 -0
  103. data/vendor/thor-852190ae/lib/thor/base.rb +540 -0
  104. data/vendor/thor-852190ae/lib/thor/core_ext/file_binary_read.rb +9 -0
  105. data/vendor/thor-852190ae/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  106. data/vendor/thor-852190ae/lib/thor/core_ext/ordered_hash.rb +100 -0
  107. data/vendor/thor-852190ae/lib/thor/error.rb +30 -0
  108. data/vendor/thor-852190ae/lib/thor/group.rb +271 -0
  109. data/vendor/thor-852190ae/lib/thor/invocation.rb +180 -0
  110. data/vendor/thor-852190ae/lib/thor/parser.rb +4 -0
  111. data/vendor/thor-852190ae/lib/thor/parser/argument.rb +67 -0
  112. data/vendor/thor-852190ae/lib/thor/parser/arguments.rb +150 -0
  113. data/vendor/thor-852190ae/lib/thor/parser/option.rb +128 -0
  114. data/vendor/thor-852190ae/lib/thor/parser/options.rb +169 -0
  115. data/vendor/thor-852190ae/lib/thor/rake_compat.rb +66 -0
  116. data/vendor/thor-852190ae/lib/thor/runner.rb +314 -0
  117. data/vendor/thor-852190ae/lib/thor/shell.rb +83 -0
  118. data/vendor/thor-852190ae/lib/thor/shell/basic.rb +239 -0
  119. data/vendor/thor-852190ae/lib/thor/shell/color.rb +108 -0
  120. data/vendor/thor-852190ae/lib/thor/task.rb +102 -0
  121. data/vendor/thor-852190ae/lib/thor/util.rb +230 -0
  122. data/vendor/thor-852190ae/lib/thor/version.rb +3 -0
  123. data/vendor/thor-852190ae/spec/actions/create_file_spec.rb +170 -0
  124. data/vendor/thor-852190ae/spec/actions/directory_spec.rb +131 -0
  125. data/vendor/thor-852190ae/spec/actions/empty_directory_spec.rb +91 -0
  126. data/vendor/thor-852190ae/spec/actions/file_manipulation_spec.rb +271 -0
  127. data/vendor/thor-852190ae/spec/actions/inject_into_file_spec.rb +135 -0
  128. data/vendor/thor-852190ae/spec/actions_spec.rb +292 -0
  129. data/vendor/thor-852190ae/spec/base_spec.rb +263 -0
  130. data/vendor/thor-852190ae/spec/core_ext/hash_with_indifferent_access_spec.rb +43 -0
  131. data/vendor/thor-852190ae/spec/core_ext/ordered_hash_spec.rb +115 -0
  132. data/vendor/thor-852190ae/spec/fixtures/application.rb +2 -0
  133. data/vendor/thor-852190ae/spec/fixtures/bundle/execute.rb +6 -0
  134. data/vendor/thor-852190ae/spec/fixtures/bundle/main.thor +1 -0
  135. data/vendor/thor-852190ae/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  136. data/vendor/thor-852190ae/spec/fixtures/doc/README +3 -0
  137. data/vendor/thor-852190ae/spec/fixtures/doc/config.rb +1 -0
  138. data/vendor/thor-852190ae/spec/fixtures/group.thor +83 -0
  139. data/vendor/thor-852190ae/spec/fixtures/invoke.thor +112 -0
  140. data/vendor/thor-852190ae/spec/fixtures/script.thor +140 -0
  141. data/vendor/thor-852190ae/spec/fixtures/task.thor +10 -0
  142. data/vendor/thor-852190ae/spec/group_spec.rb +171 -0
  143. data/vendor/thor-852190ae/spec/invocation_spec.rb +107 -0
  144. data/vendor/thor-852190ae/spec/parser/argument_spec.rb +47 -0
  145. data/vendor/thor-852190ae/spec/parser/arguments_spec.rb +64 -0
  146. data/vendor/thor-852190ae/spec/parser/option_spec.rb +202 -0
  147. data/vendor/thor-852190ae/spec/parser/options_spec.rb +292 -0
  148. data/vendor/thor-852190ae/spec/rake_compat_spec.rb +68 -0
  149. data/vendor/thor-852190ae/spec/runner_spec.rb +202 -0
  150. data/vendor/thor-852190ae/spec/shell/basic_spec.rb +205 -0
  151. data/vendor/thor-852190ae/spec/shell/color_spec.rb +41 -0
  152. data/vendor/thor-852190ae/spec/shell_spec.rb +34 -0
  153. data/vendor/thor-852190ae/spec/spec.opts +1 -0
  154. data/vendor/thor-852190ae/spec/spec_helper.rb +54 -0
  155. data/vendor/thor-852190ae/spec/task_spec.rb +69 -0
  156. data/vendor/thor-852190ae/spec/thor_spec.rb +237 -0
  157. data/vendor/thor-852190ae/spec/util_spec.rb +167 -0
  158. data/vendor/thor-852190ae/thor.gemspec +120 -0
  159. metadata +229 -0
@@ -0,0 +1,292 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Thor::Actions do
4
+ def runner(options={})
5
+ @runner ||= MyCounter.new([1], options, { :destination_root => destination_root })
6
+ end
7
+
8
+ def action(*args, &block)
9
+ capture(:stdout){ runner.send(*args, &block) }
10
+ end
11
+
12
+ def file
13
+ File.join(destination_root, "foo")
14
+ end
15
+
16
+ describe "on include" do
17
+ it "adds runtime options to the base class" do
18
+ MyCounter.class_options.keys.must include(:pretend)
19
+ MyCounter.class_options.keys.must include(:force)
20
+ MyCounter.class_options.keys.must include(:quiet)
21
+ MyCounter.class_options.keys.must include(:skip)
22
+ end
23
+ end
24
+
25
+ describe "#initialize" do
26
+ it "has default behavior invoke" do
27
+ runner.behavior.must == :invoke
28
+ end
29
+
30
+ it "can have behavior revoke" do
31
+ MyCounter.new([1], {}, :behavior => :revoke).behavior.must == :revoke
32
+ end
33
+
34
+ it "when behavior is set to force, overwrite options" do
35
+ runner = MyCounter.new([1], { :force => false, :skip => true }, :behavior => :force)
36
+ runner.behavior.must == :invoke
37
+ runner.options.force.must be_true
38
+ runner.options.skip.must_not be_true
39
+ end
40
+
41
+ it "when behavior is set to skip, overwrite options" do
42
+ runner = MyCounter.new([1], ["--force"], :behavior => :skip)
43
+ runner.behavior.must == :invoke
44
+ runner.options.force.must_not be_true
45
+ runner.options.skip.must be_true
46
+ end
47
+ end
48
+
49
+ describe "accessors" do
50
+ describe "#destination_root=" do
51
+ it "gets the current directory and expands the path to set the root" do
52
+ base = MyCounter.new([1])
53
+ base.destination_root = "here"
54
+ base.destination_root.must == File.expand_path(File.join(File.dirname(__FILE__), "..", "here"))
55
+ end
56
+
57
+ it "does not use the current directory if one is given" do
58
+ root = File.expand_path("/")
59
+ base = MyCounter.new([1])
60
+ base.destination_root = root
61
+ base.destination_root.must == root
62
+ end
63
+
64
+ it "uses the current directory if none is given" do
65
+ base = MyCounter.new([1])
66
+ base.destination_root.must == File.expand_path(File.join(File.dirname(__FILE__), ".."))
67
+ end
68
+ end
69
+
70
+ describe "#relative_to_original_destination_root" do
71
+ it "returns the path relative to the absolute root" do
72
+ runner.relative_to_original_destination_root(file).must == "foo"
73
+ end
74
+
75
+ it "does not remove dot if required" do
76
+ runner.relative_to_original_destination_root(file, false).must == "./foo"
77
+ end
78
+
79
+ it "always use the absolute root" do
80
+ runner.inside("foo") do
81
+ runner.relative_to_original_destination_root(file).must == "foo"
82
+ end
83
+ end
84
+
85
+ describe "#source_paths_for_search" do
86
+ it "add source_root to source_paths_for_search" do
87
+ MyCounter.source_paths_for_search.must include(File.expand_path("fixtures", File.dirname(__FILE__)))
88
+ end
89
+
90
+ it "keeps only current source root in source paths" do
91
+ ClearCounter.source_paths_for_search.must include(File.expand_path("fixtures/bundle", File.dirname(__FILE__)))
92
+ ClearCounter.source_paths_for_search.must_not include(File.expand_path("fixtures", File.dirname(__FILE__)))
93
+ end
94
+
95
+ it "customized source paths should be before source roots" do
96
+ ClearCounter.source_paths_for_search[0].must == File.expand_path("fixtures/doc", File.dirname(__FILE__))
97
+ ClearCounter.source_paths_for_search[1].must == File.expand_path("fixtures/bundle", File.dirname(__FILE__))
98
+ end
99
+
100
+ it "keeps inherited source paths at the end" do
101
+ ClearCounter.source_paths_for_search.last.must == File.expand_path("fixtures/broken", File.dirname(__FILE__))
102
+ end
103
+ end
104
+ end
105
+
106
+ describe "#find_in_source_paths" do
107
+ it "raises an error if source path is empty" do
108
+ lambda {
109
+ A.new.find_in_source_paths("foo")
110
+ }.must raise_error(Thor::Error, /You don't have any source path defined for class A/)
111
+ end
112
+
113
+ it "finds a template inside the source path" do
114
+ runner.find_in_source_paths("doc").must == File.expand_path("doc", source_root)
115
+ lambda { runner.find_in_source_paths("README") }.must raise_error
116
+
117
+ new_path = File.join(source_root, "doc")
118
+ runner.instance_variable_set(:@source_paths, nil)
119
+ runner.source_paths.unshift(new_path)
120
+ runner.find_in_source_paths("README").must == File.expand_path("README", new_path)
121
+ end
122
+ end
123
+ end
124
+
125
+ describe "#inside" do
126
+ it "executes the block inside the given folder" do
127
+ runner.inside("foo") do
128
+ Dir.pwd.must == file
129
+ end
130
+ end
131
+
132
+ it "changes the base root" do
133
+ runner.inside("foo") do
134
+ runner.destination_root.must == file
135
+ end
136
+ end
137
+
138
+ it "creates the directory if it does not exist" do
139
+ runner.inside("foo") do
140
+ File.exists?(file).must be_true
141
+ end
142
+ end
143
+
144
+ describe "when verbose" do
145
+ it "logs status" do
146
+ capture(:stdout) do
147
+ runner.inside("foo", :verbose => true) {}
148
+ end.must =~ /inside foo/
149
+ end
150
+
151
+ it "uses padding in next status" do
152
+ capture(:stdout) do
153
+ runner.inside("foo", :verbose => true) do
154
+ runner.say_status :cool, :padding
155
+ end
156
+ end.must =~ /cool padding/
157
+ end
158
+
159
+ it "removes padding after block" do
160
+ capture(:stdout) do
161
+ runner.inside("foo", :verbose => true) {}
162
+ runner.say_status :no, :padding
163
+ end.must =~ /no padding/
164
+ end
165
+ end
166
+ end
167
+
168
+ describe "#in_root" do
169
+ it "executes the block in the root folder" do
170
+ runner.inside("foo") do
171
+ runner.in_root { Dir.pwd.must == destination_root }
172
+ end
173
+ end
174
+
175
+ it "changes the base root" do
176
+ runner.inside("foo") do
177
+ runner.in_root { runner.destination_root.must == destination_root }
178
+ end
179
+ end
180
+
181
+ it "returns to the previous state" do
182
+ runner.inside("foo") do
183
+ runner.in_root { }
184
+ runner.destination_root.must == file
185
+ end
186
+ end
187
+ end
188
+
189
+ describe "#apply" do
190
+ before(:each) do
191
+ @template = <<-TEMPLATE
192
+ @foo = "FOO"
193
+ say_status :cool, :padding
194
+ TEMPLATE
195
+ @template.instance_eval "def read; self; end" # Make the string respond to read
196
+
197
+ @file = "http://gist.github.com/103208.txt"
198
+ runner.should_receive(:open).and_return(@template)
199
+ end
200
+
201
+ it "opens a file and executes its content in the instance binding" do
202
+ action :apply, @file
203
+ runner.instance_variable_get("@foo").must == "FOO"
204
+ end
205
+
206
+ it "applies padding to the content inside the file" do
207
+ action(:apply, @file).must =~ /cool padding/
208
+ end
209
+
210
+ it "logs its status" do
211
+ action(:apply, @file).must =~ / apply #{@file}\n/
212
+ end
213
+
214
+ it "does not log status" do
215
+ content = action(:apply, @file, :verbose => false)
216
+ content.must =~ /cool padding/
217
+ content.must_not =~ /apply http/
218
+ end
219
+ end
220
+
221
+ describe "#run" do
222
+ before(:each) do
223
+ runner.should_receive(:`).with("ls")
224
+ end
225
+
226
+ it "executes the command given" do
227
+ action :run, "ls"
228
+ end
229
+
230
+ it "logs status" do
231
+ action(:run, "ls").must == " run ls from \".\"\n"
232
+ end
233
+
234
+ it "does not log status if required" do
235
+ action(:run, "ls", :verbose => false).must be_empty
236
+ end
237
+
238
+ it "accepts a color as status" do
239
+ runner.shell.should_receive(:say_status).with(:run, 'ls from "."', :yellow)
240
+ action :run, "ls", :verbose => :yellow
241
+ end
242
+ end
243
+
244
+ describe "#run_ruby_script" do
245
+ before(:each) do
246
+ Thor::Util.stub!(:ruby_command).and_return("/opt/jruby")
247
+ runner.should_receive(:`).with("/opt/jruby script.rb")
248
+ end
249
+
250
+ it "executes the ruby script" do
251
+ action :run_ruby_script, "script.rb"
252
+ end
253
+
254
+ it "logs status" do
255
+ action(:run_ruby_script, "script.rb").must == " run jruby script.rb from \".\"\n"
256
+ end
257
+
258
+ it "does not log status if required" do
259
+ action(:run_ruby_script, "script.rb", :verbose => false).must be_empty
260
+ end
261
+ end
262
+
263
+ describe "#thor" do
264
+ it "executes the thor command" do
265
+ runner.should_receive(:`).with("thor list")
266
+ action :thor, :list, :verbose => true
267
+ end
268
+
269
+ it "converts extra arguments to command arguments" do
270
+ runner.should_receive(:`).with("thor list foo bar")
271
+ action :thor, :list, "foo", "bar"
272
+ end
273
+
274
+ it "converts options hash to switches" do
275
+ runner.should_receive(:`).with("thor list foo bar --foo")
276
+ action :thor, :list, "foo", "bar", :foo => true
277
+
278
+ runner.should_receive(:`).with("thor list --foo 1 2 3")
279
+ action :thor, :list, :foo => [1,2,3]
280
+ end
281
+
282
+ it "logs status" do
283
+ runner.should_receive(:`).with("thor list")
284
+ action(:thor, :list).must == " run thor list from \".\"\n"
285
+ end
286
+
287
+ it "does not log status if required" do
288
+ runner.should_receive(:`).with("thor list --foo 1 2 3")
289
+ action(:thor, :list, :foo => [1,2,3], :verbose => false).must be_empty
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,263 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'thor/base'
3
+
4
+ class Amazing
5
+ desc "hello", "say hello"
6
+ def hello
7
+ puts "Hello"
8
+ end
9
+ end
10
+
11
+ describe Thor::Base do
12
+ describe "#initialize" do
13
+ it "sets arguments array" do
14
+ base = MyCounter.new [1, 2]
15
+ base.first.must == 1
16
+ base.second.must == 2
17
+ end
18
+
19
+ it "sets arguments default values" do
20
+ base = MyCounter.new [1]
21
+ base.second.must == 2
22
+ end
23
+
24
+ it "sets options default values" do
25
+ base = MyCounter.new [1, 2]
26
+ base.options[:third].must == 3
27
+ end
28
+
29
+ it "allows options to be given as symbols or strings" do
30
+ base = MyCounter.new [1, 2], :third => 4
31
+ base.options[:third].must == 4
32
+
33
+ base = MyCounter.new [1, 2], "third" => 4
34
+ base.options[:third].must == 4
35
+ end
36
+
37
+ it "creates options with indifferent access" do
38
+ base = MyCounter.new [1, 2], :third => 3
39
+ base.options['third'].must == 3
40
+ end
41
+
42
+ it "creates options with magic predicates" do
43
+ base = MyCounter.new [1, 2], :third => 3
44
+ base.options.third.must == 3
45
+ end
46
+ end
47
+
48
+ describe "#no_tasks" do
49
+ it "avoids methods being added as tasks" do
50
+ MyScript.tasks.keys.must include("animal")
51
+ MyScript.tasks.keys.must_not include("this_is_not_a_task")
52
+ end
53
+ end
54
+
55
+ describe "#argument" do
56
+ it "sets a value as required and creates an accessor for it" do
57
+ MyCounter.start(["1", "2", "--third", "3"])[0].must == 1
58
+ Scripts::MyScript.start(["zoo", "my_special_param", "--param=normal_param"]).must == "my_special_param"
59
+ end
60
+
61
+ it "does not set a value in the options hash" do
62
+ BrokenCounter.start(["1", "2", "--third", "3"])[0].must be_nil
63
+ end
64
+ end
65
+
66
+ describe "#arguments" do
67
+ it "returns the arguments for the class" do
68
+ MyCounter.arguments.must have(2).items
69
+ end
70
+ end
71
+
72
+ describe "#class_option" do
73
+ it "sets options class wise" do
74
+ MyCounter.start(["1", "2", "--third", "3"])[2].must == 3
75
+ end
76
+
77
+ it "does not create an acessor for it" do
78
+ BrokenCounter.start(["1", "2", "--third", "3"])[3].must be_false
79
+ end
80
+ end
81
+
82
+ describe "#class_options" do
83
+ it "sets default options overwriting superclass definitions" do
84
+ options = Scripts::MyScript.class_options
85
+ options[:force].must_not be_required
86
+ end
87
+ end
88
+
89
+ describe "#remove_argument" do
90
+ it "removes previous defined arguments from class" do
91
+ ClearCounter.arguments.must be_empty
92
+ end
93
+
94
+ it "undefine accessors if required" do
95
+ ClearCounter.new.must_not respond_to(:first)
96
+ ClearCounter.new.must_not respond_to(:second)
97
+ end
98
+ end
99
+
100
+ describe "#remove_class_option" do
101
+ it "removes previous defined class option" do
102
+ ClearCounter.class_options[:third].must be_nil
103
+ end
104
+ end
105
+
106
+ describe "#class_options_help" do
107
+ before(:each) do
108
+ @content = capture(:stdout) { MyCounter.help(Thor::Base.shell.new) }
109
+ end
110
+
111
+ it "shows options description" do
112
+ @content.must =~ /# The third argument/
113
+ end
114
+
115
+ it "shows usage with banner content" do
116
+ @content.must =~ /\[\-\-third=THREE\]/
117
+ end
118
+
119
+ it "shows default values below description" do
120
+ @content.must =~ /# Default: 3/
121
+ end
122
+
123
+ it "shows options in different groups" do
124
+ @content.must =~ /Options\:/
125
+ @content.must =~ /Runtime options\:/
126
+ @content.must =~ /\-p, \[\-\-pretend\]/
127
+ end
128
+
129
+ it "use padding in options that does not have aliases" do
130
+ @content.must =~ /^ -t, \[--third/
131
+ @content.must =~ /^ \[--fourth/
132
+ end
133
+
134
+ it "allows extra options to be given" do
135
+ hash = { "Foo" => B.class_options.values }
136
+
137
+ content = capture(:stdout) { MyCounter.send(:class_options_help, Thor::Base.shell.new, hash) }
138
+ content.must =~ /Foo options\:/
139
+ content.must =~ /--last-name=LAST_NAME/
140
+ end
141
+ end
142
+
143
+ describe "#namespace" do
144
+ it "returns the default class namespace" do
145
+ Scripts::MyScript.namespace.must == "scripts:my_script"
146
+ end
147
+
148
+ it "sets a namespace to the class" do
149
+ Scripts::MyDefaults.namespace.must == "default"
150
+ end
151
+ end
152
+
153
+ describe "#group" do
154
+ it "sets a group" do
155
+ MyScript.group.must == "script"
156
+ end
157
+
158
+ it "inherits the group from parent" do
159
+ MyChildScript.group.must == "script"
160
+ end
161
+
162
+ it "defaults to standard if no group is given" do
163
+ Amazing.group.must == "standard"
164
+ end
165
+ end
166
+
167
+ describe "#subclasses" do
168
+ it "tracks its subclasses in an Array" do
169
+ Thor::Base.subclasses.must include(MyScript)
170
+ Thor::Base.subclasses.must include(MyChildScript)
171
+ Thor::Base.subclasses.must include(Scripts::MyScript)
172
+ end
173
+ end
174
+
175
+ describe "#subclass_files" do
176
+ it "returns tracked subclasses, grouped by the files they come from" do
177
+ thorfile = File.join(File.dirname(__FILE__), "fixtures", "script.thor")
178
+ Thor::Base.subclass_files[File.expand_path(thorfile)].must == [
179
+ MyScript, MyScript::AnotherScript, MyChildScript, Scripts::MyScript,
180
+ Scripts::MyDefaults, Scripts::ChildDefault
181
+ ]
182
+ end
183
+
184
+ it "tracks a single subclass across multiple files" do
185
+ thorfile = File.join(File.dirname(__FILE__), "fixtures", "task.thor")
186
+ Thor::Base.subclass_files[File.expand_path(thorfile)].must include(Amazing)
187
+ Thor::Base.subclass_files[File.expand_path(__FILE__)].must include(Amazing)
188
+ end
189
+ end
190
+
191
+ describe "#tasks" do
192
+ it "returns a list with all tasks defined in this class" do
193
+ MyChildScript.new.must respond_to("animal")
194
+ MyChildScript.tasks.keys.must include("animal")
195
+ end
196
+
197
+ it "raises an error if a task with reserved word is defined" do
198
+ lambda {
199
+ klass = Class.new(Thor::Group)
200
+ klass.class_eval "def shell; end"
201
+ }.must raise_error(RuntimeError, /"shell" is a Thor reserved word and cannot be defined as task/)
202
+ end
203
+ end
204
+
205
+ describe "#all_tasks" do
206
+ it "returns a list with all tasks defined in this class plus superclasses" do
207
+ MyChildScript.new.must respond_to("foo")
208
+ MyChildScript.all_tasks.keys.must include("foo")
209
+ end
210
+ end
211
+
212
+ describe "#remove_task" do
213
+ it "removes the task from its tasks hash" do
214
+ MyChildScript.tasks.keys.must_not include("bar")
215
+ MyChildScript.tasks.keys.must_not include("boom")
216
+ end
217
+
218
+ it "undefines the method if desired" do
219
+ MyChildScript.new.must_not respond_to("boom")
220
+ end
221
+ end
222
+
223
+ describe "#from_superclass" do
224
+ it "does not send a method to the superclass if the superclass does not respond to it" do
225
+ MyCounter.get_from_super.must == 13
226
+ end
227
+ end
228
+
229
+ describe "#start" do
230
+ it "raises an error instead of rescueing if --debug is given" do
231
+ lambda {
232
+ MyScript.start ["what", "--debug"]
233
+ }.must raise_error(Thor::UndefinedTaskError, 'Could not find task "what" in "my_script" namespace.')
234
+ end
235
+
236
+ it "does not steal args" do
237
+ args = ["foo", "bar", "--force", "true"]
238
+ MyScript.start(args)
239
+ args.must == ["foo", "bar", "--force", "true"]
240
+ end
241
+
242
+ it "checks unknown options" do
243
+ capture(:stderr) {
244
+ MyScript.start(["foo", "bar", "--force", "true", "--unknown", "baz"])
245
+ }.strip.must == "Unknown switches '--unknown'"
246
+ end
247
+ end
248
+
249
+ describe "attr_*" do
250
+ it "should not add attr_reader as a task" do
251
+ capture(:stderr){ MyScript.start(["another_attribute"]) }.must =~ /Could not find/
252
+ end
253
+
254
+ it "should not add attr_writer as a task" do
255
+ capture(:stderr){ MyScript.start(["another_attribute=", "foo"]) }.must =~ /Could not find/
256
+ end
257
+
258
+ it "should not add attr_accessor as a task" do
259
+ capture(:stderr){ MyScript.start(["some_attribute"]) }.must =~ /Could not find/
260
+ capture(:stderr){ MyScript.start(["some_attribute=", "foo"]) }.must =~ /Could not find/
261
+ end
262
+ end
263
+ end