minestrone 0.0.1

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 (96) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +32 -0
  3. data/.gitignore +5 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +35 -0
  7. data/Rakefile +10 -0
  8. data/bin/capify +89 -0
  9. data/bin/min +5 -0
  10. data/docs/lib-codebase-map.md +162 -0
  11. data/docs/lib-dependency-graph.svg +129 -0
  12. data/lib/minestrone/callback.rb +45 -0
  13. data/lib/minestrone/cli/help.rb +131 -0
  14. data/lib/minestrone/cli/help.txt +72 -0
  15. data/lib/minestrone/cli/options.rb +232 -0
  16. data/lib/minestrone/cli.rb +159 -0
  17. data/lib/minestrone/command.rb +177 -0
  18. data/lib/minestrone/configuration/actions/file_transfer.rb +53 -0
  19. data/lib/minestrone/configuration/actions/inspect.rb +46 -0
  20. data/lib/minestrone/configuration/actions/invocation.rb +202 -0
  21. data/lib/minestrone/configuration/alias_task.rb +29 -0
  22. data/lib/minestrone/configuration/callbacks.rb +129 -0
  23. data/lib/minestrone/configuration/connections.rb +66 -0
  24. data/lib/minestrone/configuration/execution.rb +139 -0
  25. data/lib/minestrone/configuration/loading.rb +207 -0
  26. data/lib/minestrone/configuration/log_formatters.rb +75 -0
  27. data/lib/minestrone/configuration/namespaces.rb +225 -0
  28. data/lib/minestrone/configuration/servers.rb +70 -0
  29. data/lib/minestrone/configuration/variables.rb +115 -0
  30. data/lib/minestrone/configuration.rb +69 -0
  31. data/lib/minestrone/errors.rb +17 -0
  32. data/lib/minestrone/ext/string.rb +7 -0
  33. data/lib/minestrone/extensions.rb +56 -0
  34. data/lib/minestrone/logger.rb +171 -0
  35. data/lib/minestrone/processable.rb +50 -0
  36. data/lib/minestrone/recipes/deploy/assets.rb +194 -0
  37. data/lib/minestrone/recipes/deploy/bundler.rb +81 -0
  38. data/lib/minestrone/recipes/deploy/dependencies.rb +44 -0
  39. data/lib/minestrone/recipes/deploy/local_dependency.rb +45 -0
  40. data/lib/minestrone/recipes/deploy/remote_dependency.rb +119 -0
  41. data/lib/minestrone/recipes/deploy/scm/base.rb +204 -0
  42. data/lib/minestrone/recipes/deploy/scm/git.rb +284 -0
  43. data/lib/minestrone/recipes/deploy/scm/none.rb +54 -0
  44. data/lib/minestrone/recipes/deploy/scm.rb +22 -0
  45. data/lib/minestrone/recipes/deploy/strategy/base.rb +87 -0
  46. data/lib/minestrone/recipes/deploy/strategy/copy.rb +353 -0
  47. data/lib/minestrone/recipes/deploy/strategy/remote_cache.rb +80 -0
  48. data/lib/minestrone/recipes/deploy/strategy.rb +22 -0
  49. data/lib/minestrone/recipes/deploy.rb +639 -0
  50. data/lib/minestrone/recipes/standard.rb +23 -0
  51. data/lib/minestrone/recipes/templates/maintenance.rhtml +53 -0
  52. data/lib/minestrone/server_definition.rb +56 -0
  53. data/lib/minestrone/ssh.rb +81 -0
  54. data/lib/minestrone/task_definition.rb +82 -0
  55. data/lib/minestrone/transfer.rb +205 -0
  56. data/lib/minestrone/version.rb +11 -0
  57. data/lib/minestrone.rb +3 -0
  58. data/minestrone.gemspec +32 -0
  59. data/test/cli/execute_test.rb +130 -0
  60. data/test/cli/help_test.rb +178 -0
  61. data/test/cli/options_test.rb +315 -0
  62. data/test/cli/ui_test.rb +26 -0
  63. data/test/cli_test.rb +17 -0
  64. data/test/command_test.rb +305 -0
  65. data/test/configuration/actions/file_transfer_test.rb +61 -0
  66. data/test/configuration/actions/inspect_test.rb +76 -0
  67. data/test/configuration/actions/invocation_test.rb +258 -0
  68. data/test/configuration/alias_task_test.rb +110 -0
  69. data/test/configuration/callbacks_test.rb +201 -0
  70. data/test/configuration/connections_test.rb +192 -0
  71. data/test/configuration/execution_test.rb +176 -0
  72. data/test/configuration/loading_test.rb +149 -0
  73. data/test/configuration/namespace_dsl_test.rb +325 -0
  74. data/test/configuration/servers_test.rb +100 -0
  75. data/test/configuration/variables_test.rb +191 -0
  76. data/test/configuration_test.rb +77 -0
  77. data/test/deploy/local_dependency_test.rb +61 -0
  78. data/test/deploy/remote_dependency_test.rb +146 -0
  79. data/test/deploy/scm/base_test.rb +55 -0
  80. data/test/deploy/scm/git_test.rb +260 -0
  81. data/test/deploy/scm/none_test.rb +26 -0
  82. data/test/deploy/strategy/copy_test.rb +360 -0
  83. data/test/extensions_test.rb +69 -0
  84. data/test/fixtures/cli_integration.rb +5 -0
  85. data/test/fixtures/config.rb +4 -0
  86. data/test/fixtures/custom.rb +3 -0
  87. data/test/logger_formatting_test.rb +149 -0
  88. data/test/logger_test.rb +134 -0
  89. data/test/recipes_test.rb +26 -0
  90. data/test/server_definition_test.rb +121 -0
  91. data/test/ssh_test.rb +99 -0
  92. data/test/task_definition_test.rb +117 -0
  93. data/test/transfer_test.rb +172 -0
  94. data/test/utils.rb +28 -0
  95. data/test/version_test.rb +11 -0
  96. metadata +258 -0
@@ -0,0 +1,178 @@
1
+ require "utils"
2
+ require 'minestrone/cli/help'
3
+
4
+ class CLIHelpTest < Test::Unit::TestCase
5
+ class MockCLI
6
+ attr_reader :options, :called_original
7
+
8
+ def initialize
9
+ @options = {}
10
+ @called_original = false
11
+ end
12
+
13
+ def execute_requested_actions(config)
14
+ @called_original = config
15
+ end
16
+
17
+ include Minestrone::CLI::Help
18
+ end
19
+
20
+ def setup
21
+ @cli = MockCLI.new
22
+ @cli.options[:verbose] = 0
23
+ @ui = stub("ui", :output_cols => 80, :output_rows => 20, :page_at= => nil)
24
+ MockCLI.stubs(:ui).returns(@ui)
25
+ end
26
+
27
+ def test_execute_requested_actions_without_tasks_or_explain_should_call_original
28
+ @cli.execute_requested_actions(:config)
29
+ @cli.expects(:task_list).never
30
+ @cli.expects(:explain_task).never
31
+ assert_equal :config, @cli.called_original
32
+ end
33
+
34
+ def test_execute_requested_actions_with_tasks_should_call_task_list
35
+ @cli.options[:tasks] = true
36
+ @cli.expects(:task_list).with(:config, true)
37
+ @cli.expects(:explain_task).never
38
+ @cli.execute_requested_actions(:config)
39
+ assert !@cli.called_original
40
+ end
41
+
42
+ def test_execute_requested_actions_with_explain_should_call_explain_task
43
+ @cli.options[:explain] = "deploy_with_niftiness"
44
+ @cli.expects(:task_list).never
45
+ @cli.expects(:explain_task).with(:config, "deploy_with_niftiness")
46
+ @cli.execute_requested_actions(:config)
47
+ assert !@cli.called_original
48
+ end
49
+
50
+ def test_task_list_with_no_tasks_should_emit_warning
51
+ config = mock("config", :task_list => [])
52
+ @cli.expects(:warn)
53
+ @cli.task_list(config)
54
+ end
55
+
56
+ def test_task_list_should_query_all_tasks_in_all_namespaces
57
+ expected_max_len = 80 - 3 - MockCLI::LINE_PADDING
58
+ task_list = [task("c"), task("g", "c:g"), task("b", "c:b"), task("a")]
59
+ task_list.each { |t| t.expects(:brief_description).with(expected_max_len).returns(t.fully_qualified_name) }
60
+
61
+ config = mock("config")
62
+ config.expects(:task_list).with(:all).returns(task_list)
63
+ @cli.stubs(:puts)
64
+ @cli.task_list(config)
65
+ end
66
+
67
+ def test_task_list_should_query_tasks_with_pattern
68
+ expected_max_len = 80 - 3 - MockCLI::LINE_PADDING
69
+ task_list = [task("g", "c:g"), task("b", "c:b")]
70
+ task_list.each { |t| t.expects(:brief_description).with(expected_max_len).returns(t.fully_qualified_name)}
71
+
72
+ config = mock("config")
73
+ config.expects(:task_list).with(:all).once.returns(task_list)
74
+
75
+ @cli.stubs(:puts)
76
+ @cli.task_list(config, "c")
77
+ end
78
+
79
+ def test_task_list_should_query_for_all_tasks_when_pattern_doesnt_match
80
+ expected_max_len = 80 - 3 - MockCLI::LINE_PADDING
81
+ task_list = [task("g", "c:g"), task("b", "c:b")]
82
+ task_list.each { |t| t.expects(:brief_description).with(expected_max_len).returns(t.fully_qualified_name) }
83
+
84
+ config = mock("config")
85
+ config.expects(:task_list).with(:all).times(2).returns(task_list)
86
+
87
+ @cli.stubs(:warn)
88
+ @cli.stubs(:puts)
89
+ @cli.task_list(config, "z")
90
+ end
91
+
92
+ def test_task_list_should_never_use_less_than_MIN_MAX_LEN_chars_for_descriptions
93
+ @ui.stubs(:output_cols).returns(20)
94
+ t = task("c")
95
+ t.expects(:brief_description).with(30).returns("hello")
96
+ config = mock("config", :task_list => [t])
97
+ @cli.stubs(:puts)
98
+ @cli.task_list(config)
99
+ end
100
+
101
+ def test_task_list_should_not_include_tasks_with_blank_description_or_internal_by_default
102
+ t1 = task("c")
103
+ t1.expects(:brief_description).returns("hello")
104
+ t2 = task("d", "d", "[internal] howdy")
105
+ t2.expects(:brief_description).never
106
+ t3 = task("e", "e", "")
107
+ t3.expects(:brief_description).never
108
+
109
+ config = mock("config", :task_list => [t1, t2, t3])
110
+ @cli.stubs(:puts)
111
+ @cli.expects(:puts).never.with { |s,| (s || "").include?("[internal]") || s =~ /#\s*$/ }
112
+ @cli.task_list(config)
113
+ end
114
+
115
+ def test_task_list_should_include_tasks_with_blank_descriptions_and_internal_when_verbose
116
+ t1 = task("c")
117
+ t1.expects(:brief_description).returns("hello")
118
+ t2 = task("d", "d", "[internal] howdy")
119
+ t2.expects(:brief_description).returns("[internal] howdy")
120
+ t3 = task("e", "e", "")
121
+ t3.expects(:brief_description).returns("")
122
+
123
+ config = mock("config", :task_list => [t1, t2, t3])
124
+ @cli.options[:verbose] = 1
125
+ @cli.stubs(:puts)
126
+ @cli.expects(:puts).with { |s,| (s || "").include?("[internal]") || s =~ /#\s*$/ }.at_least_once
127
+ @cli.task_list(config)
128
+ end
129
+
130
+ def test_explain_task_should_warn_if_task_does_not_exist
131
+ config = mock("config", :find_task => nil)
132
+ @cli.expects(:warn).with { |s,| s =~ /`deploy_with_niftiness'/ }
133
+ @cli.explain_task(config, "deploy_with_niftiness")
134
+ end
135
+
136
+ def test_explain_task_with_task_that_has_no_description_should_emit_stub
137
+ t = mock("task", :description => "")
138
+ config = mock("config")
139
+ config.expects(:find_task).with("deploy_with_niftiness").returns(t)
140
+ @cli.stubs(:puts)
141
+ @cli.expects(:puts).with("There is no description for this task.")
142
+ @cli.explain_task(config, "deploy_with_niftiness")
143
+ end
144
+
145
+ def test_explain_task_with_task_should_format_description
146
+ t = stub("task", :description => "line1\nline2\n\nline3")
147
+ config = mock("config", :find_task => t)
148
+ @cli.stubs(:puts)
149
+ @cli.explain_task(config, "deploy_with_niftiness")
150
+ end
151
+
152
+ def test_format_text_should_wrap_lines_and_preserve_indentation
153
+ @ui.stubs(:output_cols).returns(45)
154
+ text = " alpha beta gamma delta epsilon zeta eta theta\n\n" \
155
+ "\talpha beta gamma delta epsilon zeta eta theta\n"
156
+
157
+ assert_equal \
158
+ " alpha beta gamma delta epsilon zeta eta\n" \
159
+ " theta\n" \
160
+ "\n" \
161
+ "\talpha beta gamma delta epsilon zeta\n" \
162
+ "\teta theta\n",
163
+ @cli.format_text(text)
164
+ end
165
+
166
+ def test_long_help_should_load_and_format_help_txt_file
167
+ help_file = File.expand_path("../../lib/minestrone/cli/help.txt", __dir__)
168
+ File.expects(:read).with(help_file).returns("text")
169
+ @ui.expects(:say).with("text\n")
170
+ @cli.long_help
171
+ end
172
+
173
+ private
174
+
175
+ def task(name, fqn = name, desc = "a description")
176
+ stub("task", :name => name, :fully_qualified_name => fqn, :description => desc)
177
+ end
178
+ end
@@ -0,0 +1,315 @@
1
+ require "utils"
2
+ require 'minestrone/cli'
3
+
4
+ class CLIOptionsTest < Test::Unit::TestCase
5
+ class ExitException < Exception; end
6
+
7
+ class MockCLI < Minestrone::CLI
8
+ def initialize(args = [])
9
+ @args = args
10
+ end
11
+
12
+ attr_reader :args
13
+ end
14
+
15
+ def setup
16
+ @cli = MockCLI.new
17
+ end
18
+
19
+ def test_parse_options_should_require_non_empty_args_list
20
+ @cli.stubs(:warn)
21
+ @cli.expects(:exit).raises(ExitException)
22
+ assert_raises(ExitException) { @cli.parse_options! }
23
+ end
24
+
25
+ def test_parse_options_with_d_should_set_debug_option
26
+ @cli.args << "-d"
27
+ @cli.parse_options!
28
+ assert @cli.options[:debug]
29
+ end
30
+
31
+ def test_parse_options_with_n_should_set_dry_run_option
32
+ @cli.args << "-n"
33
+ @cli.parse_options!
34
+ assert @cli.options[:dry_run]
35
+ end
36
+
37
+ def test_parse_options_with_dry_run_should_set_dry_run_option
38
+ @cli.args << "--dry-run"
39
+ @cli.parse_options!
40
+ assert @cli.options[:dry_run]
41
+ end
42
+
43
+ def test_parse_options_with_e_should_set_explain_option
44
+ @cli.args << "-e" << "sample"
45
+ @cli.parse_options!
46
+ assert_equal "sample", @cli.options[:explain]
47
+ end
48
+
49
+ def test_parse_options_with_f_should_add_recipe_file
50
+ @cli.args << "-f" << "deploy"
51
+ @cli.parse_options!
52
+ assert_equal %w(deploy), @cli.options[:recipes]
53
+ end
54
+
55
+ def test_parse_options_with_multiple_f_should_add_each_as_recipe_file
56
+ @cli.args << "-f" << "deploy" << "-f" << "monitor"
57
+ @cli.parse_options!
58
+ assert_equal %w(deploy monitor), @cli.options[:recipes]
59
+ end
60
+
61
+ def test_parse_options_with_H_should_show_verbose_help_and_exit
62
+ @cli.expects(:exit).raises(ExitException)
63
+ @cli.expects(:long_help)
64
+ @cli.args << "-H"
65
+ assert_raises(ExitException) { @cli.parse_options! }
66
+ end
67
+
68
+ def test_parse_options_with_h_should_show_options_and_exit
69
+ @cli.expects(:puts).with(@cli.option_parser)
70
+ @cli.expects(:exit).raises(ExitException)
71
+ @cli.args << "-h"
72
+ assert_raises(ExitException) { @cli.parse_options! }
73
+ end
74
+
75
+ def test_parse_options_with_p_should_prompt_for_password
76
+ MockCLI.expects(:password_prompt).returns(:the_password)
77
+ @cli.args << "-p"
78
+ @cli.parse_options!
79
+ assert_equal :the_password, @cli.options[:password]
80
+ end
81
+
82
+ def test_parse_options_without_p_should_set_proc_for_password
83
+ @cli.args << "-e" << "sample"
84
+ @cli.parse_options!
85
+ assert_instance_of Proc, @cli.options[:password]
86
+ end
87
+
88
+ def test_parse_options_with_q_should_set_verbose_to_0
89
+ @cli.args << "-q"
90
+ @cli.parse_options!
91
+ assert_equal 0, @cli.options[:verbose]
92
+ end
93
+
94
+ def test_parse_options_with_S_should_set_pre_vars
95
+ @cli.args << "-S" << "foo=bar"
96
+ @cli.parse_options!
97
+ assert_equal "bar", @cli.options[:pre_vars][:foo]
98
+ end
99
+
100
+ def test_S_should_coerce_digits_to_integers
101
+ @cli.args << "-S" << "foo=1234"
102
+ @cli.parse_options!
103
+ assert_equal 1234, @cli.options[:pre_vars][:foo]
104
+ end
105
+
106
+ def test_S_should_treat_quoted_integers_as_string
107
+ @cli.args << "-S" << "foo=\"1234\""
108
+ @cli.parse_options!
109
+ assert_equal "1234", @cli.options[:pre_vars][:foo]
110
+ end
111
+
112
+ def test_S_should_treat_digits_with_dot_as_floating_point
113
+ @cli.args << "-S" << "foo=3.1415"
114
+ @cli.parse_options!
115
+ assert_equal 3.1415, @cli.options[:pre_vars][:foo]
116
+ end
117
+
118
+ def test_S_should_treat_true_as_boolean_true
119
+ @cli.args << "-S" << "foo=true"
120
+ @cli.parse_options!
121
+ assert_equal true, @cli.options[:pre_vars][:foo]
122
+ end
123
+
124
+ def test_S_should_treat_false_as_boolean_false
125
+ @cli.args << "-S" << "foo=false"
126
+ @cli.parse_options!
127
+ assert_equal false, @cli.options[:pre_vars][:foo]
128
+ end
129
+
130
+ def test_S_should_treat_nil_as_nil
131
+ @cli.args << "-S" << "foo=nil"
132
+ @cli.parse_options!
133
+ assert_equal nil, @cli.options[:pre_vars][:foo]
134
+ end
135
+
136
+ def test_parse_options_with_s_should_set_vars
137
+ @cli.args << "-s" << "foo=bar"
138
+ @cli.parse_options!
139
+ assert_equal "bar", @cli.options[:vars][:foo]
140
+ end
141
+
142
+ def test_s_should_coerce_digits_to_integers
143
+ @cli.args << "-s" << "foo=1234"
144
+ @cli.parse_options!
145
+ assert_equal 1234, @cli.options[:vars][:foo]
146
+ end
147
+
148
+ def test_s_should_treat_quoted_integers_as_string
149
+ @cli.args << "-s" << "foo=\"1234\""
150
+ @cli.parse_options!
151
+ assert_equal "1234", @cli.options[:vars][:foo]
152
+ end
153
+
154
+ def test_s_should_treat_digits_with_dot_as_floating_point
155
+ @cli.args << "-s" << "foo=3.1415"
156
+ @cli.parse_options!
157
+ assert_equal 3.1415, @cli.options[:vars][:foo]
158
+ end
159
+
160
+ def test_s_should_treat_true_as_boolean_true
161
+ @cli.args << "-s" << "foo=true"
162
+ @cli.parse_options!
163
+ assert_equal true, @cli.options[:vars][:foo]
164
+ end
165
+
166
+ def test_s_should_treat_false_as_boolean_false
167
+ @cli.args << "-s" << "foo=false"
168
+ @cli.parse_options!
169
+ assert_equal false, @cli.options[:vars][:foo]
170
+ end
171
+
172
+ def test_s_should_treat_nil_as_nil
173
+ @cli.args << "-s" << "foo=nil"
174
+ @cli.parse_options!
175
+ assert_equal nil, @cli.options[:vars][:foo]
176
+ end
177
+
178
+ def test_parse_options_with_T_should_set_tasks_option_and_set_verbose_off
179
+ @cli.args << "-T"
180
+ @cli.parse_options!
181
+ assert @cli.options[:tasks]
182
+ assert_equal 0, @cli.options[:verbose]
183
+ end
184
+
185
+ def test_parse_options_with_V_should_show_version_and_exit
186
+ @cli.args << "-V"
187
+ @cli.expects(:puts).with { |s| s.include?(Minestrone::Version.to_s) }
188
+ @cli.expects(:exit).raises(ExitException)
189
+ assert_raises(ExitException) { @cli.parse_options! }
190
+ end
191
+
192
+ def test_parse_options_with_v_should_set_verbose_to_1
193
+ @cli.args << "-v"
194
+ @cli.parse_options!
195
+ assert_equal 1, @cli.options[:verbose]
196
+ end
197
+
198
+ def test_parse_options_with_multiple_v_should_set_verbose_accordingly
199
+ @cli.args << "-vvvvvvv"
200
+ @cli.parse_options!
201
+ assert_equal 7, @cli.options[:verbose]
202
+ end
203
+
204
+ def test_parse_options_without_X_should_set_sysconf
205
+ @cli.args << "-v"
206
+ @cli.parse_options!
207
+ assert @cli.options.key?(:sysconf)
208
+ end
209
+
210
+ def test_parse_options_with_X_should_unset_sysconf
211
+ @cli.args << "-X"
212
+ @cli.parse_options!
213
+ assert !@cli.options.key?(:sysconf)
214
+ end
215
+
216
+ def test_parse_options_without_x_should_set_dotfile
217
+ @cli.args << "-v"
218
+ @cli.parse_options!
219
+ assert @cli.options.key?(:dotfile)
220
+ end
221
+
222
+ def test_parse_options_with_x_should_unset_dotfile
223
+ @cli.args << "-x"
224
+ @cli.parse_options!
225
+ assert !@cli.options.key?(:dotfile)
226
+ end
227
+
228
+ def test_parse_options_without_q_or_v_should_set_verbose_to_3
229
+ @cli.args << "-x"
230
+ @cli.parse_options!
231
+ assert_equal 3, @cli.options[:verbose]
232
+ end
233
+
234
+ def test_should_search_for_default_recipes_if_f_not_given
235
+ @cli.expects(:look_for_default_recipe_file!)
236
+ @cli.args << "-v"
237
+ @cli.parse_options!
238
+ end
239
+
240
+ def test_should_not_search_for_default_recipes_if_f_given
241
+ @cli.expects(:look_for_default_recipe_file!).never
242
+ @cli.args << "-f" << "hello"
243
+ @cli.parse_options!
244
+ end
245
+
246
+ def test_F_should_search_for_default_recipes_even_if_f_is_given
247
+ @cli.expects(:look_for_default_recipe_file!)
248
+ @cli.args << "-Ff" << "hello"
249
+ @cli.parse_options!
250
+ end
251
+
252
+ def test_should_extract_env_vars_from_command_line
253
+ assert_nil ENV["HELLO"]
254
+ assert_nil ENV["ANOTHER"]
255
+
256
+ @cli.args << "HELLO=world" << "hello" << "ANOTHER=value"
257
+ @cli.parse_options!
258
+
259
+ assert_equal "world", ENV["HELLO"]
260
+ assert_equal "value", ENV["ANOTHER"]
261
+ ensure
262
+ ENV.delete("HELLO")
263
+ ENV.delete("ANOTHER")
264
+ end
265
+
266
+ def test_remaining_args_should_be_added_to_actions_list
267
+ @cli.args << "-v" << "HELLO=world" << "-f" << "foo" << "something" << "else"
268
+ @cli.parse_options!
269
+ assert_equal %w(something else), @cli.args
270
+ ensure
271
+ ENV.delete("HELLO")
272
+ end
273
+
274
+ def test_search_for_default_recipe_file_should_look_for_Capfile
275
+ File.stubs(:file?).returns(false)
276
+ File.expects(:file?).with("Capfile").returns(true)
277
+ @cli.args << "-v"
278
+ @cli.parse_options!
279
+ assert_equal %w(Capfile), @cli.options[:recipes]
280
+ end
281
+
282
+ def test_search_for_default_recipe_file_should_look_for_capfile
283
+ File.stubs(:file?).returns(false)
284
+ File.expects(:file?).with("capfile").returns(true)
285
+ @cli.args << "-v"
286
+ @cli.parse_options!
287
+ assert_equal %w(capfile), @cli.options[:recipes]
288
+ end
289
+
290
+ def test_search_for_default_recipe_should_hike_up_the_directory_tree_until_it_finds_default_recipe
291
+ File.stubs(:file?).returns(false)
292
+ File.expects(:file?).with("capfile").times(2).returns(false,true)
293
+ Dir.expects(:pwd).times(3).returns(*%w(/bar/baz /bar/baz /bar))
294
+ Dir.expects(:chdir).with("..")
295
+ @cli.args << "-v"
296
+ @cli.parse_options!
297
+ assert_equal %w(capfile), @cli.options[:recipes]
298
+ end
299
+
300
+ def test_search_for_default_recipe_should_halt_at_root_directory
301
+ File.stubs(:file?).returns(false)
302
+ Dir.expects(:pwd).times(7).returns(*%w(/bar/baz /bar/baz /bar /bar / / /))
303
+ Dir.expects(:chdir).with("..").times(3)
304
+ Dir.expects(:chdir).with("/bar/baz")
305
+ @cli.args << "-v"
306
+ @cli.parse_options!
307
+ assert @cli.options[:recipes].empty?
308
+ end
309
+
310
+ def test_parse_should_instantiate_new_cli_and_call_parse_options
311
+ cli = mock("cli", :parse_options! => nil)
312
+ MockCLI.expects(:new).with(%w(a b c)).returns(cli)
313
+ assert_equal cli, MockCLI.parse(%w(a b c))
314
+ end
315
+ end
@@ -0,0 +1,26 @@
1
+ require "utils"
2
+ require 'minestrone/cli'
3
+
4
+ class CLIUITest < Test::Unit::TestCase
5
+ class MockCLI < Minestrone::CLI; end
6
+
7
+ def test_ui_should_return_highline_instance
8
+ assert_instance_of HighLine, MockCLI.ui
9
+ end
10
+
11
+ def test_password_prompt_should_have_default_prompt_and_set_echo_false
12
+ q = mock("question")
13
+ q.expects(:echo=).with(false)
14
+ ui = mock("ui")
15
+ ui.expects(:ask).with("Password: ").yields(q).returns("sayuncle")
16
+ MockCLI.expects(:ui).returns(ui)
17
+ assert_equal "sayuncle", MockCLI.password_prompt
18
+ end
19
+
20
+ def test_password_prompt_with_custom_prompt_should_use_custom_prompt
21
+ ui = mock("ui")
22
+ ui.expects(:ask).with("Give the passphrase: ").returns("sayuncle")
23
+ MockCLI.expects(:ui).returns(ui)
24
+ assert_equal "sayuncle", MockCLI.password_prompt("Give the passphrase: ")
25
+ end
26
+ end
data/test/cli_test.rb ADDED
@@ -0,0 +1,17 @@
1
+ require "utils"
2
+ require 'minestrone/cli'
3
+
4
+ class CLI_Test < Test::Unit::TestCase
5
+ def test_options_ui_and_help_modules_should_integrate_successfully_with_configuration
6
+ cli = Minestrone::CLI.parse(%w(-T -x -X))
7
+ cli.expects(:puts).at_least_once
8
+ cli.execute!
9
+ end
10
+
11
+ def test_options_and_execute_modules_should_integrate_successfully_with_configuration
12
+ path = "#{File.dirname(__FILE__)}/fixtures/cli_integration.rb"
13
+ cli = Minestrone::CLI.parse(%W(-x -X -q -f #{path} testing))
14
+ config = cli.execute!
15
+ assert config[:testing_occurred]
16
+ end
17
+ end