amp-front 0.1.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 (78) hide show
  1. data/.document +5 -0
  2. data/.gitignore +24 -0
  3. data/Ampfile +3 -0
  4. data/Gemfile +10 -0
  5. data/Gemfile.lock +36 -0
  6. data/LICENSE +20 -0
  7. data/README.md +50 -0
  8. data/Rakefile +64 -0
  9. data/VERSION +1 -0
  10. data/design_docs/commands.md +91 -0
  11. data/design_docs/dependencies.md +35 -0
  12. data/design_docs/plugins.md +47 -0
  13. data/features/amp.feature +8 -0
  14. data/features/amp_help.feature +36 -0
  15. data/features/amp_plugin_list.feature +10 -0
  16. data/features/step_definitions/amp-front_steps.rb +23 -0
  17. data/features/support/env.rb +4 -0
  18. data/lib/amp-front.rb +30 -0
  19. data/lib/amp-front/dispatch/commands/base.rb +158 -0
  20. data/lib/amp-front/dispatch/commands/builtin/help.rb +23 -0
  21. data/lib/amp-front/dispatch/commands/builtin/plugin.rb +24 -0
  22. data/lib/amp-front/dispatch/commands/validations.rb +171 -0
  23. data/lib/amp-front/dispatch/runner.rb +86 -0
  24. data/lib/amp-front/help/entries/__default__.erb +31 -0
  25. data/lib/amp-front/help/entries/ampfiles.md +42 -0
  26. data/lib/amp-front/help/entries/commands.erb +6 -0
  27. data/lib/amp-front/help/entries/new-commands.md +81 -0
  28. data/lib/amp-front/help/help.rb +312 -0
  29. data/lib/amp-front/plugins/base.rb +87 -0
  30. data/lib/amp-front/support/module_extensions.rb +92 -0
  31. data/lib/amp-front/third_party/maruku.rb +136 -0
  32. data/lib/amp-front/third_party/maruku/attributes.rb +227 -0
  33. data/lib/amp-front/third_party/maruku/defaults.rb +71 -0
  34. data/lib/amp-front/third_party/maruku/errors_management.rb +92 -0
  35. data/lib/amp-front/third_party/maruku/helpers.rb +260 -0
  36. data/lib/amp-front/third_party/maruku/input/charsource.rb +326 -0
  37. data/lib/amp-front/third_party/maruku/input/extensions.rb +69 -0
  38. data/lib/amp-front/third_party/maruku/input/html_helper.rb +189 -0
  39. data/lib/amp-front/third_party/maruku/input/linesource.rb +111 -0
  40. data/lib/amp-front/third_party/maruku/input/parse_block.rb +615 -0
  41. data/lib/amp-front/third_party/maruku/input/parse_doc.rb +234 -0
  42. data/lib/amp-front/third_party/maruku/input/parse_span_better.rb +746 -0
  43. data/lib/amp-front/third_party/maruku/input/rubypants.rb +225 -0
  44. data/lib/amp-front/third_party/maruku/input/type_detection.rb +147 -0
  45. data/lib/amp-front/third_party/maruku/input_textile2/t2_parser.rb +163 -0
  46. data/lib/amp-front/third_party/maruku/maruku.rb +33 -0
  47. data/lib/amp-front/third_party/maruku/output/to_ansi.rb +223 -0
  48. data/lib/amp-front/third_party/maruku/output/to_html.rb +991 -0
  49. data/lib/amp-front/third_party/maruku/output/to_markdown.rb +164 -0
  50. data/lib/amp-front/third_party/maruku/output/to_s.rb +56 -0
  51. data/lib/amp-front/third_party/maruku/string_utils.rb +191 -0
  52. data/lib/amp-front/third_party/maruku/structures.rb +167 -0
  53. data/lib/amp-front/third_party/maruku/structures_inspect.rb +87 -0
  54. data/lib/amp-front/third_party/maruku/structures_iterators.rb +61 -0
  55. data/lib/amp-front/third_party/maruku/textile2.rb +1 -0
  56. data/lib/amp-front/third_party/maruku/toc.rb +199 -0
  57. data/lib/amp-front/third_party/maruku/usage/example1.rb +33 -0
  58. data/lib/amp-front/third_party/maruku/version.rb +40 -0
  59. data/lib/amp-front/third_party/trollop.rb +766 -0
  60. data/spec/amp-front_spec.rb +25 -0
  61. data/spec/command_specs/base_spec.rb +123 -0
  62. data/spec/command_specs/command_spec.rb +97 -0
  63. data/spec/command_specs/help_spec.rb +33 -0
  64. data/spec/command_specs/spec_helper.rb +37 -0
  65. data/spec/command_specs/validations_spec.rb +267 -0
  66. data/spec/dispatch_specs/runner_spec.rb +116 -0
  67. data/spec/dispatch_specs/spec_helper.rb +15 -0
  68. data/spec/help_specs/help_entry_spec.rb +78 -0
  69. data/spec/help_specs/help_registry_spec.rb +77 -0
  70. data/spec/help_specs/spec_helper.rb +15 -0
  71. data/spec/plugin_specs/base_spec.rb +36 -0
  72. data/spec/plugin_specs/spec_helper.rb +15 -0
  73. data/spec/spec.opts +1 -0
  74. data/spec/spec_helper.rb +33 -0
  75. data/spec/support_specs/module_extensions_spec.rb +104 -0
  76. data/spec/support_specs/spec_helper.rb +15 -0
  77. data/test/third_party_tests/test_trollop.rb +1181 -0
  78. metadata +192 -0
@@ -0,0 +1,25 @@
1
+ ##################################################################
2
+ # Licensing Information #
3
+ # #
4
+ # The following code is licensed, as standalone code, under #
5
+ # the Ruby License, unless otherwise directed within the code. #
6
+ # #
7
+ # For information on the license of this code when distributed #
8
+ # with and used in conjunction with the other modules in the #
9
+ # Amp project, please see the root-level LICENSE file. #
10
+ # #
11
+ # © Michael J. Edgar and Ari Brown, 2009-2010 #
12
+ # #
13
+ ##################################################################
14
+
15
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
16
+
17
+ describe Amp do
18
+ it "has a version" do
19
+ Amp::VERSION.should_not be_nil
20
+ end
21
+
22
+ it "has a version title" do
23
+ Amp::VERSION_TITLE.should_not be_nil
24
+ end
25
+ end
@@ -0,0 +1,123 @@
1
+ ##################################################################
2
+ # Licensing Information #
3
+ # #
4
+ # The following code is licensed, as standalone code, under #
5
+ # the Ruby License, unless otherwise directed within the code. #
6
+ # #
7
+ # For information on the license of this code when distributed #
8
+ # with and used in conjunction with the other modules in the #
9
+ # Amp project, please see the root-level LICENSE file. #
10
+ # #
11
+ # © Michael J. Edgar and Ari Brown, 2009-2010 #
12
+ # #
13
+ ##################################################################
14
+
15
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
16
+ require 'amp-front/dispatch/commands/base'
17
+
18
+ describe Amp::Command::Base do
19
+ before do
20
+ @klass = Class.new(Amp::Command::Base)
21
+ end
22
+
23
+ describe '#call' do
24
+ it "sets the instance's options before running on_call" do
25
+ input_opts = {:a => :b}
26
+ received_opts = nil
27
+ @klass.on_call { received_opts = options }
28
+ @klass.new.call(input_opts, nil)
29
+ received_opts.should == input_opts
30
+ end
31
+
32
+ it "sets the instance's arguments before running on_call" do
33
+ input_args = [1, 2, 3]
34
+ received_args = nil
35
+ @klass.on_call { received_args = arguments }
36
+ @klass.new.call(nil, input_args)
37
+ received_args.should == input_args
38
+ end
39
+ end
40
+
41
+ describe '#on_call' do
42
+ it "sets the class's on_call handler when a block is given" do
43
+ flag = false
44
+ @klass.on_call { flag = true }
45
+ @klass.new.call(nil, nil)
46
+ flag.should be_true
47
+ end
48
+
49
+ it 'returns the current handler if no block is given' do
50
+ @klass.on_call.should == nil
51
+ @klass.on_call { puts 'hello' }
52
+ @klass.on_call.should_not == nil
53
+ @klass.on_call.should respond_to(:call)
54
+ end
55
+ end
56
+
57
+ describe '#opt' do
58
+ it 'adds an option to the command class' do
59
+ @klass.options.should == []
60
+ @klass.opt :verbose, 'Provide verbose output', :type => :boolean
61
+ @klass.options.should == [[:verbose, 'Provide verbose output',
62
+ {:type => :boolean}]
63
+ ]
64
+ end
65
+ end
66
+
67
+ describe '#collect_options' do
68
+ context 'with no options specified' do
69
+ it 'returns a nearly empty hash' do
70
+ @klass.new.collect_options([]).first.should == {:help => false}
71
+ end
72
+ end
73
+
74
+ context 'with --verbose specified' do
75
+ before do
76
+ @klass.opt :verbose, 'Text', :type => :boolean
77
+ end
78
+
79
+ context 'with --verbose not provided' do
80
+ it 'returns :verbose_given => false' do
81
+ opts,args = @klass.new.collect_options([])
82
+ opts[:verbose_given].should be_false
83
+ end
84
+ end
85
+
86
+ context 'with --verbose provided' do
87
+ it 'returns :verbose_given => true, :verbose => true' do
88
+ opts,args = @klass.new.collect_options(['--verbose'])
89
+ opts[:verbose_given].should be_true
90
+ opts[:verbose].should be_true
91
+ end
92
+
93
+ it 'leaves ARGV alone' do
94
+ swizzling_argv(['--verbose']) do
95
+ @klass.new.collect_options([])
96
+ ARGV.should == ['--verbose']
97
+ end
98
+ end
99
+
100
+ it 'returns modified arguments' do
101
+ arguments = ['--verbose']
102
+ opts,args = @klass.new.collect_options(arguments)
103
+ arguments.should == ['--verbose']
104
+ args.should == []
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ it 'should have a name' do
111
+ @klass.name.should_not be_nil
112
+ end
113
+
114
+ describe '#all_commands' do
115
+ it 'should not include nil' do
116
+ @klass.all_commands.should_not include(nil)
117
+ end
118
+
119
+ it 'should have itself' do
120
+ @klass.all_commands.should include(@klass)
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,97 @@
1
+ ##################################################################
2
+ # Licensing Information #
3
+ # #
4
+ # The following code is licensed, as standalone code, under #
5
+ # the Ruby License, unless otherwise directed within the code. #
6
+ # #
7
+ # For information on the license of this code when distributed #
8
+ # with and used in conjunction with the other modules in the #
9
+ # Amp project, please see the root-level LICENSE file. #
10
+ # #
11
+ # © Michael J. Edgar and Ari Brown, 2009-2010 #
12
+ # #
13
+ ##################################################################
14
+
15
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
16
+ require 'amp-front/dispatch/commands/base.rb'
17
+
18
+ describe Amp::Command do
19
+ it 'should fail to look up a nonexistent command' do
20
+ Amp::Command.for_name('sillyzargbyl --verbose').should be_nil
21
+ end
22
+
23
+ context 'when created with a specific name' do
24
+ before do
25
+ @name = next_name
26
+ @command_name = @name.capitalize
27
+ @class = Amp::Command.create(@command_name) do |c|
28
+ c.desc 'Hello'
29
+ c.opt :verbose, "Verbose output", :type => :boolean
30
+ end
31
+ end
32
+
33
+ it 'creates the named class as a submodule of Amp::Command' do
34
+ Amp::Command.const_get(@command_name).should == @class
35
+ end
36
+
37
+ it 'uppercases the first letter of the name' do
38
+ klass = Amp::Command.create('search0') {|c| }
39
+ Amp::Command.const_get('Search0').should == klass
40
+ end
41
+
42
+ it 'stores the new subclass in the all_commands list' do
43
+ Amp::Command::Base.all_commands.should include(@class)
44
+ end
45
+
46
+ it 'can be looked up by for_name' do
47
+ Amp::Command.for_name(@command_name).should == @class
48
+ end
49
+
50
+ it "doesn't crash if you have an odd argument" do
51
+ # The hyphen cause const_defined? to bail at one point since it's
52
+ # not allowed in module names
53
+ Amp::Command.for_name("#{@command_name} new-commands").should == @class
54
+ end
55
+
56
+ it 'can be looked up by a set of command line arguments' do
57
+ Amp::Command.for_name("#{@command_name} show --verbose").should == @class
58
+ end
59
+
60
+ it 'has a description' do
61
+ @class.desc.should == 'Hello'
62
+ end
63
+
64
+ it 'has a name' do
65
+ @class.name.should == @command_name
66
+ end
67
+ end
68
+
69
+ context 'when created within a namespace' do
70
+ before do
71
+ @name = next_name
72
+ Amp::Command.namespace 'TempNamespace' do
73
+ @class = Amp::Command.create(@name) do |c|
74
+ c.opt :verbose, "Verbose output", :type => :boolean
75
+ end
76
+ end
77
+ end
78
+
79
+ it 'should create the requested namespace as a module' do
80
+ Amp::Command::Tempnamespace.should_not be_nil
81
+ end
82
+
83
+ it "should create the command in the namespace's module" do
84
+ Amp::Command::Tempnamespace.const_get(@name.capitalize).should == @class
85
+ end
86
+
87
+ it 'can be looked up by for_name with the nested command syntax' do
88
+ Amp::Command.for_name("tempnamespace #{@name.downcase}").should == @class
89
+ end
90
+ end
91
+
92
+ context 'when no name given' do
93
+ it 'should return nil' do
94
+ Amp::Command.for_name('').should == nil
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,33 @@
1
+ ##################################################################
2
+ # Licensing Information #
3
+ # #
4
+ # The following code is licensed, as standalone code, under #
5
+ # the Ruby License, unless otherwise directed within the code. #
6
+ # #
7
+ # For information on the license of this code when distributed #
8
+ # with and used in conjunction with the other modules in the #
9
+ # Amp project, please see the root-level LICENSE file. #
10
+ # #
11
+ # © Michael J. Edgar and Ari Brown, 2009-2010 #
12
+ # #
13
+ ##################################################################
14
+
15
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
16
+
17
+ describe Amp::Command::Help do
18
+ it 'creates the help command' do
19
+ Amp::Command::Help.should_not be_nil
20
+ end
21
+
22
+ it 'stores the help command in the all_commands list' do
23
+ Amp::Command::Base.all_commands.should include(Amp::Command::Help)
24
+ end
25
+
26
+ it 'can be looked up as base help' do
27
+ Amp::Command.for_name('help').should == Amp::Command::Help
28
+ end
29
+
30
+ it 'prints the help text of all commands' do
31
+ run_command('help').should include('Thanks for using Amp!')
32
+ end
33
+ end
@@ -0,0 +1,37 @@
1
+ ##################################################################
2
+ # Licensing Information #
3
+ # #
4
+ # The following code is licensed, as standalone code, under #
5
+ # the Ruby License, unless otherwise directed within the code. #
6
+ # #
7
+ # For information on the license of this code when distributed #
8
+ # with and used in conjunction with the other modules in the #
9
+ # Amp project, please see the root-level LICENSE file. #
10
+ # #
11
+ # © Michael J. Edgar and Ari Brown, 2009-2010 #
12
+ # #
13
+ ##################################################################
14
+
15
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
16
+
17
+ def run_command(command, opts={}, args=[])
18
+ swizzling_stdout do
19
+ Amp::Command.for_name(command).new.call(opts, args)
20
+ end
21
+ end
22
+
23
+
24
+ def next_name
25
+ # Shared by all subclasses.
26
+ @@__next_name_counter ||= 0
27
+ @@__next_name_counter += 1
28
+ "TempClass#{@@__next_name_counter}"
29
+ end
30
+
31
+ def swizzling_argv(argv)
32
+ old_argv = ARGV.dup
33
+ ARGV.replace(argv)
34
+ yield
35
+ ensure
36
+ ARGV.replace(old_argv)
37
+ end
@@ -0,0 +1,267 @@
1
+ ##################################################################
2
+ # Licensing Information #
3
+ # #
4
+ # The following code is licensed, as standalone code, under #
5
+ # the Ruby License, unless otherwise directed within the code. #
6
+ # #
7
+ # For information on the license of this code when distributed #
8
+ # with and used in conjunction with the other modules in the #
9
+ # Amp project, please see the root-level LICENSE file. #
10
+ # #
11
+ # © Michael J. Edgar and Ari Brown, 2009-2010 #
12
+ # #
13
+ ##################################################################
14
+
15
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
16
+ require 'amp-front/dispatch/commands/base'
17
+
18
+ describe Amp::Command::Validations do
19
+ before do
20
+ @klass = Amp::Command.create(next_name) do |command|
21
+ command.before do |opts,args|
22
+ opts[:hello] && args.size >= 1
23
+ end
24
+ command.after do |opts,args|
25
+ !opts[:world]
26
+ end
27
+ end
28
+ end
29
+
30
+ context '#valid?' do
31
+ it 'runs before blocks to check validity' do
32
+ instance = @klass.new
33
+ instance.should be_valid({:hello => true}, ['stuff'])
34
+ instance.should_not be_valid({:hello => false}, ['stuff'])
35
+ instance.should_not be_valid({:hello => true}, [])
36
+ end
37
+ end
38
+
39
+ context '#run_after' do
40
+ it 'runs the after blocks' do
41
+ instance = @klass.new
42
+ instance.run_after({:world => false}, []).should be_true
43
+ instance.run_after({:world => true}, []).should be_false
44
+ end
45
+ end
46
+
47
+ context '#validates_each' do
48
+ before do
49
+ @class = Amp::Command.create(next_name) do |c|
50
+ c.validates_each(:hello, :world) do |opts, key, value|
51
+ value > 0
52
+ end
53
+ end
54
+ end
55
+
56
+ it 'runs the validation block on the named options' do
57
+ instance = @class.new
58
+ instance.should be_valid({:hello => 3, :world => 5},[])
59
+ instance.should_not be_valid({:hello => -3, :world => 5},[])
60
+ instance.should_not be_valid({:hello => 3, :world => -5},[])
61
+ end
62
+ end
63
+
64
+ context '#validates_block' do
65
+ before do
66
+ @class = Amp::Command.create(next_name) do |c|
67
+ c.validates_block(:unless => :some_method) do |opts, args|
68
+ args.size == 0
69
+ end
70
+ end
71
+
72
+ @class.send(:define_method, :some_method) do |opts, args|
73
+ opts[:skip_validation]
74
+ end
75
+ end
76
+
77
+ it 'only runs the validation when some_method returns true' do
78
+ instance = @class.new
79
+ instance.should be_valid({:skip_validation => false}, [])
80
+ instance.should be_valid({:skip_validation => true}, [])
81
+ instance.should be_invalid({:skip_validation => false}, [5])
82
+ instance.should be_valid({:skip_validation => true}, [5])
83
+ end
84
+ end
85
+
86
+ context '#validates_presence_of' do
87
+ before do
88
+ @class = Amp::Command.create(next_name) do |c|
89
+ c.validates_presence_of :hello
90
+ end
91
+ end
92
+
93
+ it 'runs the validation block on the named options' do
94
+ instance = @class.new
95
+ instance.should be_valid({:hello => 3, :hello_given => true},[])
96
+ instance.should be_invalid({:hello => 3, :hello_given => false},[])
97
+ instance.should be_valid({:hello => nil, :hello_given => true},[])
98
+ instance.should be_invalid({:hello => nil, :hello_given => false},[])
99
+ end
100
+ end
101
+
102
+ context '#validates_inclusion_of' do
103
+ before do
104
+ @class = Amp::Command.create(next_name) do |c|
105
+ c.validates_inclusion_of(:hello, :in => 3..15)
106
+ c.validates_inclusion_of(:world, :in => %w[mike ari])
107
+ end
108
+ end
109
+
110
+ it 'runs the validation block on the named options' do
111
+ instance = @class.new
112
+ instance.should be_valid({:hello => 3, :world => 'mike'},[])
113
+ instance.should be_invalid({:hello => -1, :world => 'ari'},[])
114
+ instance.should be_invalid({:hello => 5, :world => 'steve'},[])
115
+ end
116
+
117
+ it 'fails when no options hash is provided' do
118
+ proc {
119
+ Amp::Command.create(next_name) do |c|
120
+ c.validates_inclusion_of(:temp)
121
+ end
122
+ }.should raise_error(ArgumentError)
123
+ end
124
+
125
+ it 'handles being parameterized by :if' do
126
+ klass = Amp::Command.create(next_name) do |c|
127
+ c.validates_inclusion_of(:temp, :in => 3..15, :if => proc {|opts,args| args.size >= 1})
128
+ end
129
+
130
+ instance = klass.new
131
+ instance.should be_valid({:temp => 5}, ['hello'])
132
+ instance.should be_valid({:temp => 1}, [])
133
+ instance.should be_invalid({:temp => 1}, ['hello'])
134
+ end
135
+ end
136
+
137
+ context '#validates_length_of' do
138
+ it 'runs the validation block handling :in and :within' do
139
+ klass = Amp::Command.create(next_name) do |c|
140
+ c.validates_length_of(:hello, :in => 3..15)
141
+ c.validates_length_of(:world, :within => 13..25)
142
+ end
143
+ instance = klass.new
144
+ instance.should be_valid({:hello => 'a' * 3, :world => 'a' * 24},[])
145
+ instance.should be_invalid({:hello => 'a' * 1, :world => 'a' * 19},[])
146
+ instance.should be_invalid({:hello => 'a' * 5, :world => 'a' * 3},[])
147
+ end
148
+
149
+ it 'runs the validation block handling :maximum' do
150
+ klass = Amp::Command.create(next_name) do |c|
151
+ c.validates_length_of(:hello, :maximum => 10)
152
+ end
153
+ instance = klass.new
154
+ instance.should be_valid({:hello => 'a' * 8},[])
155
+ instance.should be_valid({:hello => 'a' * 10},[])
156
+ instance.should be_invalid({:hello => 'a' * 11},[])
157
+ instance.should be_valid({:hello => ''},[])
158
+ end
159
+
160
+ it 'runs the validation block handling :minimum' do
161
+ klass = Amp::Command.create(next_name) do |c|
162
+ c.validates_length_of(:hello, :minimum => 10)
163
+ end
164
+ instance = klass.new
165
+ instance.should be_valid({:hello => 'a' * 12},[])
166
+ instance.should be_valid({:hello => 'a' * 10},[])
167
+ instance.should be_invalid({:hello => 'a' * 9},[])
168
+ instance.should be_invalid({:hello => ''},[])
169
+ end
170
+
171
+ it 'runs the validation block handling :is' do
172
+ klass = Amp::Command.create(next_name) do |c|
173
+ c.validates_length_of(:hello, :is => 4)
174
+ end
175
+ instance = klass.new
176
+ instance.should be_valid({:hello => 'a' * 4},[])
177
+ instance.should be_invalid({:hello => 'a' * 5},[])
178
+ instance.should be_invalid({:hello => 'a' * 3},[])
179
+ instance.should be_invalid({:hello => ''},[])
180
+ end
181
+
182
+ it 'fails when no length keys are provided' do
183
+ proc {
184
+ Amp::Command.create(next_name) do |c|
185
+ c.validates_length_of(:temp, {})
186
+ end
187
+ }.should raise_error(ArgumentError)
188
+ end
189
+
190
+ it 'handles being parameterized by :if' do
191
+ klass = Amp::Command.create(next_name) do |c|
192
+ c.validates_length_of(:temp, :in => 3..15, :if => proc {|opts,args| args.size >= 1})
193
+ end
194
+
195
+ instance = klass.new
196
+ instance.should be_valid({:temp => 'a' * 5}, ['hello'])
197
+ instance.should be_valid({:temp => 'a' * 1}, [])
198
+ instance.should be_invalid({:temp => 'a' * 1}, ['hello'])
199
+ end
200
+ end
201
+
202
+
203
+ context '#validates_argument_count' do
204
+ it 'runs the validation block handling :in and :within' do
205
+ klass = Amp::Command.create(next_name) do |c|
206
+ c.validates_argument_count(:in => 1..2)
207
+ end
208
+ instance = klass.new
209
+ instance.should be_valid({}, [3] * 1)
210
+ instance.should be_invalid({}, [3] * 3)
211
+ instance.should be_invalid({}, [])
212
+ end
213
+
214
+ it 'runs the validation block handling :maximum' do
215
+ klass = Amp::Command.create(next_name) do |c|
216
+ c.validates_argument_count(:maximum => 10)
217
+ end
218
+ instance = klass.new
219
+ instance.should be_valid({},[3] * 8)
220
+ instance.should be_valid({},[3] * 10)
221
+ instance.should be_invalid({},[3] * 11)
222
+ instance.should be_valid({},[])
223
+ end
224
+
225
+ it 'runs the validation block handling :minimum' do
226
+ klass = Amp::Command.create(next_name) do |c|
227
+ c.validates_argument_count(:minimum => 10)
228
+ end
229
+ instance = klass.new
230
+ instance.should be_valid({},[3] * 12)
231
+ instance.should be_valid({},[3] * 10)
232
+ instance.should be_invalid({},[3] * 9)
233
+ instance.should be_invalid({},[])
234
+ end
235
+
236
+ it 'runs the validation block handling :is' do
237
+ klass = Amp::Command.create(next_name) do |c|
238
+ c.validates_argument_count(:is => 4)
239
+ end
240
+ instance = klass.new
241
+ instance.should be_valid({},[3] * 4)
242
+ instance.should be_invalid({},[3] * 3)
243
+ instance.should be_invalid({},[3] * 5)
244
+ instance.should be_invalid({},[])
245
+ end
246
+
247
+ it 'fails when no length keys are provided' do
248
+ proc {
249
+ Amp::Command.create(next_name) do |c|
250
+ c.validates_argument_count
251
+ end
252
+ }.should raise_error(ArgumentError)
253
+ end
254
+
255
+ it 'handles being parameterized by :if' do
256
+ klass = Amp::Command.create(next_name) do |c|
257
+ c.validates_argument_count(:in => 2..3, :unless => proc {|opts,args| args[0] == 'off'})
258
+ end
259
+
260
+ instance = klass.new
261
+ instance.should be_valid({}, ['hello', 'world'])
262
+ instance.should be_valid({}, ['off'])
263
+ instance.should be_invalid({}, ['hello'])
264
+ end
265
+ end
266
+ end
267
+