cp 0.0.1.pre1 → 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.
@@ -1,3 +1,3 @@
1
1
  module CP
2
- VERSION = "0.0.1.pre1"
2
+ VERSION = "0.0.1"
3
3
  end
@@ -8,43 +8,56 @@ describe CP::App do
8
8
  it_should_behave_like "it accepts commands"
9
9
  it_should_behave_like "it accepts options"
10
10
 
11
- describe "#instance" do
12
- it "should always return the same object" do
13
- @target.should == CP::App.instance
11
+ describe "#error" do
12
+ it "should take one argument" do
13
+ CP::App.instance.method( :error ).arity.should === 1
14
+ end
15
+
16
+ it "should print the message" do
17
+ errors, output = trap_output do
18
+ CP::App.instance.error( "test error" )
19
+ end
20
+
21
+ errors.should match( /test error/ )
14
22
  end
15
23
  end
16
24
 
17
- describe "#parser" do
18
- it "should default to CmdParser" do
19
- @target.parser.should == CP::Parsers::CmdParse
25
+ describe "#instance" do
26
+ it "should always return the same object" do
27
+ @target.should == CP::App.instance
20
28
  end
21
29
  end
22
30
 
23
31
  describe "#run" do
24
32
  it "should exist" do
25
- @target.methods.include?( :run ).should be_true
33
+ CP::App.methods.include?( :run ).should be_true
26
34
  end
27
35
 
28
- it "should not take any parameters" do
29
- @target.method( :run ).arity.should === 0
36
+ it "should take an number of arguments" do
37
+ CP::App.method( :run ).arity.should === -1
30
38
  end
31
39
  end
32
40
 
33
41
  describe "properties" do
34
- [:name, :version].each do |prop_name|
35
- it "should accept a #{prop_name} property" do
36
- prop_val = "0.1.1"
37
-
42
+ [:name, :version].each do |prop|
43
+ it "should accept a #{prop} property" do
44
+ value = "0.1.1"
38
45
  lambda {
39
- @target.app prop_name, prop_val
40
- }.should change( @target, prop_name ).from( nil ).to( prop_val )
46
+ @target.app prop, value
47
+ }.should change( @target, prop ).from( @target.send( prop ) ).to( value )
41
48
  end
42
49
  end
43
50
 
44
51
  it "should raise a ArgumentError when setting other properties" do
45
52
  lambda {
46
- test_app.app :foo, "bar"
53
+ @target.app :foo, "bar"
47
54
  }.should raise_error( ArgumentError, /no such property/ )
48
55
  end
56
+
57
+ describe "#name" do
58
+ it "should default to the name of the script" do
59
+ @target.name.should === File.basename( $0 )
60
+ end
61
+ end
49
62
  end
50
63
  end
@@ -2,7 +2,7 @@ require File.join( File.dirname( __FILE__ ), "support", "spec_helper" )
2
2
 
3
3
  describe CP::Command do
4
4
  before( :each ) do
5
- @target = test_command
5
+ @target = CP::Command.new( :test )
6
6
  end
7
7
 
8
8
  it_should_behave_like "it accepts commands"
@@ -12,7 +12,6 @@ describe CP::Command do
12
12
  [
13
13
  [:description, "description"],
14
14
  [:summary, "summary"],
15
- [:execute, lambda {}],
16
15
  ].each { |(attr, val)|
17
16
  it "defines a ##{attr} accessor" do
18
17
  lambda {
@@ -23,8 +22,8 @@ describe CP::Command do
23
22
  end
24
23
 
25
24
  describe "#new" do
26
- it "takes one parameter" do
27
- CP::Command.instance_method( :initialize ).arity.should === 1
25
+ it "takes 1 or 2 parameters" do
26
+ @target.method( :initialize ).arity.should === -2
28
27
  end
29
28
 
30
29
  it "takes a symbol" do
@@ -37,6 +36,13 @@ describe CP::Command do
37
36
  CP::Command.new( :test ).name.should === :test
38
37
  end
39
38
 
39
+ it "saves the block as #block" do
40
+ block_ran = false
41
+ @target.execute { block_ran = true }
42
+ @target.block.call( nil )
43
+ block_ran.should be_true
44
+ end
45
+
40
46
  it "yields itself" do
41
47
  yielded = nil
42
48
  c = CP::Command.new( :test ) do |cmd|
@@ -4,7 +4,7 @@ describe CP do
4
4
  describe "methods" do
5
5
  def assert_method_added( method )
6
6
  Object.new.methods.include?( method ).should be_false
7
- App.new.methods.include?( method ).should be_true
7
+ TestApp.new.methods.include?( method ).should be_true
8
8
  end
9
9
 
10
10
  it "should define a app method" do
@@ -0,0 +1,10 @@
1
+ require File.join( File.dirname( __FILE__ ), "..", "support", "spec_helper" )
2
+
3
+ describe CP::Has::Commands do
4
+ before( :each ) do
5
+ class Target; include CP::Has::Commands; end
6
+ @target = Target.new
7
+ end
8
+
9
+ it_should_behave_like "it accepts commands"
10
+ end
@@ -0,0 +1,10 @@
1
+ require File.join( File.dirname( __FILE__ ), "..", "support", "spec_helper" )
2
+
3
+ describe CP::Has::Options do
4
+ before( :each ) do
5
+ class Target; include CP::Has::Options; end
6
+ @target = Target.new
7
+ end
8
+
9
+ it_should_behave_like "it accepts options"
10
+ end
@@ -9,10 +9,8 @@ describe CP::Option do
9
9
  describe "attributes" do
10
10
  [
11
11
  [:allowed, ["foo", "bar"]],
12
- [:block, lambda{}],
13
12
  [:description, "description"],
14
13
  [:long, "--short"],
15
- [:required, true],
16
14
  [:short, "-s"],
17
15
  [:type, String]
18
16
  ].each { |(attr, val)|
@@ -39,6 +37,29 @@ describe CP::Option do
39
37
  end
40
38
  end
41
39
 
40
+ describe "#block" do
41
+ it "should save the value" do
42
+ block = lambda {}
43
+ @target.block.call( "foo" )
44
+ @target.value.should === "foo"
45
+ end
46
+
47
+ it "should call the use's block" do
48
+ called = false
49
+ @target.block = lambda { |val| called = true }
50
+ @target.block.call( "value" )
51
+ called.should be_true
52
+ end
53
+ end
54
+
55
+ describe "#default" do
56
+ it "should be returned as the value when no value is set" do
57
+ @target.short = "-s VAL"
58
+ @target.default = "foo"
59
+ @target.value.should === "foo"
60
+ end
61
+ end
62
+
42
63
  describe "#name" do
43
64
  it "returns a symbol" do
44
65
  @target.name.is_a?( Symbol )
@@ -107,7 +128,7 @@ describe CP::Option do
107
128
  end
108
129
  it "sets the block from arguments" do
109
130
  ran = false
110
- CP::Option.new( "-s", lambda{ ran = true } ).block.call
131
+ CP::Option.new( "-s", lambda{ ran = true } ).block.call( nil )
111
132
  ran.should be_true
112
133
  end
113
134
 
@@ -136,23 +157,30 @@ describe CP::Option do
136
157
  end
137
158
  end
138
159
 
139
- describe "#long=" do
160
+ describe "#long" do
140
161
  it "parses the option, separating the option argument" do
141
- o = CP::Option.new do |opt|
142
- opt.long = "--switch VALUE"
143
- end
144
- o.arg.should == " VALUE"
145
- o.long.should == "--switch"
162
+ @target.long = "--switch VALUE"
163
+ @target.arg.should == " VALUE"
164
+ @target.long.should == "--switch"
146
165
  end
147
166
  end
148
167
 
149
- describe "#short=" do
168
+ describe "#required" do
169
+ it "defaults to false" do
170
+ @target.required?.should be_false
171
+ end
172
+
173
+ it "is converted to a boolean" do
174
+ @target.required = "not a boolean"
175
+ @target.required?.should be_true
176
+ end
177
+ end
178
+
179
+ describe "#short" do
150
180
  it "parses the option, separating the option argument" do
151
- o = CP::Option.new do |opt|
152
- opt.short = "-s VALUE"
153
- end
154
- o.arg.should == " VALUE"
155
- o.short.should == "-s"
181
+ @target.short = "-s VALUE"
182
+ @target.arg.should == " VALUE"
183
+ @target.short.should == "-s"
156
184
  end
157
185
  end
158
186
 
@@ -0,0 +1,7 @@
1
+ require File.join( File.dirname( __FILE__ ), "support", "spec_helper" )
2
+
3
+ describe CP::OptionsStruct do
4
+ it "is a proper Struct" do
5
+ CP::OptionsStruct.new( :test ).should be_a( Struct )
6
+ end
7
+ end
@@ -1,47 +1,15 @@
1
- require File.join( File.dirname( __FILE__ ), "support", "spec_helper" )
1
+ require File.join( File.dirname( __FILE__ ), "..", "support", "spec_helper" )
2
2
 
3
3
  describe CP::Runners::CmdParse do
4
4
  before( :each ) do
5
- @target = test_app.parser
5
+ @target = CP::Runners::CmdParse.new( create_test_app )
6
6
  end
7
7
 
8
- describe "#instance" do
9
- it "should always return the same object" do
10
- @target.should == CP::App.instance
11
- end
12
- end
13
-
14
- describe "#parser" do
15
- it "should default to CmdParser" do
16
- @target.parser.should == CP::Parsers::CmdParse
17
- end
18
- end
19
-
20
- describe "#run" do
21
- it "should exist" do
22
- @target.methods.include?( :run ).should be_true
23
- end
24
-
25
- it "should not take any parameters" do
26
- @target.method( :run ).arity.should === 0
27
- end
28
- end
29
-
30
- describe "properties" do
31
- [:name, :version].each do |prop_name|
32
- it "should accept a #{prop_name} property" do
33
- prop_val = "0.1.1"
34
-
35
- lambda {
36
- @target.app prop_name, prop_val
37
- }.should change( @target, prop_name ).from( nil ).to( prop_val )
38
- end
39
- end
8
+ it_should_behave_like "it is a runner"
40
9
 
41
- it "should raise a ArgumentError when setting other properties" do
42
- lambda {
43
- test_app.app :foo, "bar"
44
- }.should raise_error( ArgumentError, /no such property/ )
10
+ describe "#runner" do
11
+ it "return a CmdParse::CommandParser" do
12
+ @target.runner.should be_a( CmdParse::CommandParser )
45
13
  end
46
14
  end
47
15
  end
@@ -0,0 +1,16 @@
1
+ class TestAppRunner
2
+ attr_reader :errors, :exit_status, :output
3
+
4
+ def run( *args )
5
+ @errors, @output = trap_output do
6
+ app = create_test_app
7
+ yield app if block_given?
8
+
9
+ begin
10
+ app.run *args
11
+ rescue SystemExit => e
12
+ @exit_status = e.status
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,52 @@
1
+ shared_examples_for "it accepts commands" do
2
+ describe "#command" do
3
+ it "should return a Command" do
4
+ @target.command( :test ).should be_an_instance_of( CP::Command )
5
+ end
6
+
7
+ it "should return the existing Command" do
8
+ @target.command( :test ).should === @target.command( :test )
9
+ end
10
+
11
+ describe "automatic subcommand creation" do
12
+ it "should define the parent command" do
13
+ @target.command( "test foo" )
14
+ @target.command( :test ).commands.size.should === 1
15
+ end
16
+
17
+ it "should define subcommands when the name includes spaces" do
18
+ @target.command( :test )
19
+ lambda {
20
+ @target.command( "test foo" )
21
+ }.should_not change(){ @target.commands.size }.by( 1 )
22
+ end
23
+
24
+ it "should return the subcommand" do
25
+ @target.command( "test foo" ).name.should === :foo
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "#commands" do
31
+ it "should return an array" do
32
+ @target.commands.should be_an_instance_of( Array )
33
+ end
34
+
35
+ it "should increase with each defined command" do
36
+ lambda {
37
+ @target.command( :test )
38
+ }.should change(){ @target.commands.size }.by( 1 )
39
+ end
40
+
41
+ it "should include each defined command" do
42
+ @target.commands.include?( @target.command( :test ) ).should be_true
43
+ end
44
+
45
+ it "should only allow one default command" do
46
+ lambda {
47
+ @target.command( :test ) { |c| c.default = true }
48
+ @target.command( :test2 ) { |c| c.default = true }
49
+ }.should raise_error( CP::CommandError, /only one/ )
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,23 @@
1
+ shared_examples_for "it accepts options" do
2
+ describe "#option" do
3
+ it "should return an Option" do
4
+ @target.option( "-s" ).should be_an_instance_of( CP::Option )
5
+ end
6
+ end
7
+
8
+ describe "#options" do
9
+ it "should return an array" do
10
+ @target.options.should be_an_instance_of( Array )
11
+ end
12
+
13
+ it "should increase with each defined option" do
14
+ lambda {
15
+ @target.option( "-s" )
16
+ }.should change(){ @target.options.length}.by( 1 )
17
+ end
18
+
19
+ it "should include each defined option" do
20
+ @target.options.include?( @target.option( "-s" ) ).should be_true
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,173 @@
1
+ shared_examples_for "it is a runner" do
2
+ describe "#new" do
3
+ it "should take one parameter" do
4
+ @target.method( :initialize ).arity.should === 1
5
+ end
6
+ end
7
+
8
+ describe "arguments" do
9
+ it "should be passed to the command block" do
10
+ passed_args = nil
11
+
12
+ run( "test", "foo", "bar" ) do |app|
13
+ app.command( :test ) { |c|
14
+ c.execute { |args, opts| passed_args = args }
15
+ }
16
+ end
17
+
18
+ passed_args.should == ["foo", "bar"]
19
+ end
20
+ end
21
+
22
+ describe "commands" do
23
+ describe "invalid commands" do
24
+ it "should explain that it's not valid" do
25
+ run( "invalid" ).errors.should match( /'invalid' is not a (\w+ )+command/i )
26
+ end
27
+
28
+ it "should exit with a nonzero status" do
29
+ run( "invalid" ).exit_status.should_not === 0
30
+ end
31
+ end
32
+
33
+ describe "the help command" do
34
+ it "should exist" do
35
+ run( "help" ).exit_status.should === 0
36
+ end
37
+
38
+ it "should not overwrite a custom help command" do
39
+ custom_help_ran = false
40
+
41
+ run( "help" ) do |app|
42
+ app.command( :help ) do |c|
43
+ c.execute { custom_help_ran = true }
44
+ end
45
+ end
46
+
47
+ custom_help_ran .should be_true
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "options" do
53
+ describe "boolean options" do
54
+ describe "defaults" do
55
+ it "should allow a `true` default" do
56
+ passed_value = nil
57
+
58
+ run( "test" ) do |app|
59
+ app.command( :test ) { |c|
60
+ c.option( "--[no-]option" ) { |o| o.default = true }
61
+ c.execute { |args, opts| passed_value = opts.option }
62
+ }
63
+ end
64
+
65
+ passed_value.should be_true
66
+ end
67
+
68
+ it "should allow overriding of the `true` default" do
69
+ passed_value = nil
70
+
71
+ run( "test", "--no-option" ) do |app|
72
+ app.command( :test ) { |c|
73
+ c.option( "--[no-]option" ) { |o| o.default = true }
74
+ c.execute { |args, opts| passed_value = opts.option }
75
+ }
76
+ end
77
+
78
+ passed_value.should be_false
79
+ end
80
+ end
81
+ end
82
+
83
+ describe "default values" do
84
+ it "should pass them to the command block" do
85
+ passed_value = nil
86
+
87
+ run( "test" ) do |app|
88
+ app.command( :test ) { |c|
89
+ c.option( "--option VAL" ) { |o| o.default = "foo" }
90
+ c.execute { |args, opts| passed_value = opts.option }
91
+ }
92
+ end
93
+
94
+ passed_value.should === "foo"
95
+ end
96
+ end
97
+
98
+ describe "invalid options" do
99
+ it "should explain that it's not valid" do
100
+ run( "--invalid" ).errors.should match( /'--invalid' is not a valid option/i )
101
+ end
102
+
103
+ it "should exit with a nonzero status" do
104
+ run( "--invalid" ).exit_status.should_not === 0
105
+ end
106
+ end
107
+
108
+ describe "required options" do
109
+ describe "missing" do
110
+ before( :each ) do
111
+ @result = run( "test" ) do |app|
112
+ app.command( :test ) { |c|
113
+ c.option( "--option" ) { |o| o.required = true }
114
+ c.execute { |args, opts| }
115
+ }
116
+ end
117
+ end
118
+
119
+ it "should explain that the option is required" do
120
+ @result.errors.should match( /'--option' is required/i )
121
+ end
122
+
123
+ it "should exit with a nonzero status" do
124
+ @result.exit_status.should_not === 0
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "the options struct" do
130
+ it "should be passed to the command block" do
131
+ opts_struct = nil
132
+
133
+ run( "test", "foo", "bar" ) do |app|
134
+ app.command( :test ) { |c|
135
+ c.execute { |args, opts| opts_struct = opts }
136
+ }
137
+ end
138
+
139
+ opts_struct.should be_a( Struct::Options )
140
+ end
141
+
142
+ it "should provide access to passed option values" do
143
+ passed_value = nil
144
+
145
+ run( "test", "--option", "foo" ) do |app|
146
+ app.command( :test ) { |c|
147
+ c.option( "--option FOO" )
148
+ c.execute { |args, opts| passed_value = opts.option }
149
+ }
150
+ end
151
+
152
+ passed_value.should === "foo"
153
+ end
154
+
155
+ it "should include parent options" do
156
+ passed_value = nil
157
+
158
+ run( "cmd", "sub1", "--option", "foo", "sub2" ) do |app|
159
+ app.command( :cmd ) { |cmd|
160
+ cmd.command( :sub1 ) { |sub1|
161
+ sub1.option( "--option FOO" )
162
+ sub1.command( :sub2 ) { |sub2|
163
+ sub2.execute { |args, opts| passed_value = opts.option }
164
+ }
165
+ }
166
+ }
167
+ end
168
+
169
+ passed_value.should === "foo"
170
+ end
171
+ end
172
+ end
173
+ end