thor 0.12.0 → 0.13.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.
- data/CHANGELOG.rdoc +5 -5
- data/README.rdoc +65 -2
- data/Thorfile +15 -9
- data/bin/thor +1 -0
- data/lib/thor/actions/create_file.rb +2 -2
- data/lib/thor/actions/directory.rb +2 -4
- data/lib/thor/actions/file_manipulation.rb +10 -6
- data/lib/thor/actions/inject_into_file.rb +10 -7
- data/lib/thor/actions.rb +6 -5
- data/lib/thor/base.rb +45 -32
- data/lib/thor/core_ext/file_binary_read.rb +9 -0
- data/lib/thor/group.rb +46 -37
- data/lib/thor/runner.rb +49 -42
- data/lib/thor/shell/basic.rb +49 -29
- data/lib/thor/shell/color.rb +1 -1
- data/lib/thor/shell.rb +1 -1
- data/lib/thor/task.rb +27 -38
- data/lib/thor/util.rb +4 -22
- data/lib/thor/version.rb +1 -1
- data/lib/thor.rb +43 -45
- data/spec/actions/create_file_spec.rb +7 -7
- data/spec/actions/directory_spec.rb +5 -4
- data/spec/actions/file_manipulation_spec.rb +29 -16
- data/spec/actions/inject_into_file_spec.rb +29 -0
- data/spec/actions_spec.rb +14 -13
- data/spec/base_spec.rb +16 -1
- data/spec/fixtures/bundle/main.thor +1 -0
- data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
- data/spec/fixtures/doc/README +3 -0
- data/spec/fixtures/group.thor +83 -0
- data/spec/fixtures/invoke.thor +112 -0
- data/spec/fixtures/script.thor +134 -0
- data/spec/fixtures/task.thor +10 -0
- data/spec/group_spec.rb +1 -7
- data/spec/runner_spec.rb +35 -39
- data/spec/shell/basic_spec.rb +56 -62
- data/spec/shell/color_spec.rb +6 -6
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +5 -4
- data/spec/task_spec.rb +14 -32
- data/spec/thor_spec.rb +21 -22
- data/spec/util_spec.rb +7 -31
- metadata +28 -19
data/spec/runner_spec.rb
CHANGED
|
@@ -26,11 +26,11 @@ describe Thor::Runner do
|
|
|
26
26
|
|
|
27
27
|
it "shows information about a specific Thor group class" do
|
|
28
28
|
content = capture(:stdout){ Thor::Runner.start(["help", "my_counter"]) }
|
|
29
|
-
content.must =~ /my_counter N
|
|
29
|
+
content.must =~ /my_counter N/
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it "raises error if a class/task cannot be found" do
|
|
33
|
-
|
|
33
|
+
Thor::Runner.should_receive(:exit).with(1)
|
|
34
34
|
content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
|
|
35
35
|
content.must =~ /could not find Thor class or task 'unknown'/
|
|
36
36
|
end
|
|
@@ -39,7 +39,7 @@ describe Thor::Runner do
|
|
|
39
39
|
describe "#start" do
|
|
40
40
|
it "invokes a task from Thor::Runner" do
|
|
41
41
|
ARGV.replace ["list"]
|
|
42
|
-
capture(:stdout){ Thor::Runner.start }.must =~ /my_counter N
|
|
42
|
+
capture(:stdout){ Thor::Runner.start }.must =~ /my_counter N/
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
it "invokes a task from a specific Thor class" do
|
|
@@ -68,7 +68,7 @@ describe Thor::Runner do
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
it "raises an error if class/task can't be found" do
|
|
71
|
-
|
|
71
|
+
Thor::Runner.should_receive(:exit).with(1)
|
|
72
72
|
ARGV.replace ["unknown"]
|
|
73
73
|
capture(:stderr){ Thor::Runner.start }.must =~ /could not find Thor class or task 'unknown'/
|
|
74
74
|
end
|
|
@@ -78,12 +78,12 @@ describe Thor::Runner do
|
|
|
78
78
|
lambda { Thor::Runner.start }.must raise_error(NoMethodError)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
it "does not swallow Thor::Group
|
|
81
|
+
it "does not swallow Thor::Group InvocationError" do
|
|
82
82
|
ARGV.replace ["whiny_generator"]
|
|
83
83
|
lambda { Thor::Runner.start }.must raise_error(ArgumentError, /Are you sure it has arity equals to 0\?/)
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
it "does not swallow Thor
|
|
86
|
+
it "does not swallow Thor InvocationError" do
|
|
87
87
|
ARGV.replace ["my_script:animal"]
|
|
88
88
|
capture(:stderr) { Thor::Runner.start }.must =~ /'animal' was called incorrectly\. Call as 'my_script:animal TYPE'/
|
|
89
89
|
end
|
|
@@ -96,26 +96,28 @@ describe Thor::Runner do
|
|
|
96
96
|
"random" => {
|
|
97
97
|
:location => @location,
|
|
98
98
|
:filename => "4a33b894ffce85d7b412fc1b36f88fe0",
|
|
99
|
-
:
|
|
99
|
+
:namespaces => ["amazing"]
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
root_file = File.join(Thor::Util.thor_root, "thor.yml")
|
|
104
|
+
|
|
103
105
|
# Stub load and save to avoid thor.yaml from being overwritten
|
|
104
|
-
stub(
|
|
105
|
-
stub(
|
|
106
|
-
stub(
|
|
106
|
+
YAML.stub!(:load_file).and_return(@original_yaml)
|
|
107
|
+
File.stub!(:exists?).with(root_file).and_return(true)
|
|
108
|
+
File.stub!(:open).with(root_file, "w")
|
|
107
109
|
end
|
|
108
110
|
|
|
109
111
|
describe "list" do
|
|
110
112
|
it "gives a list of the available tasks" do
|
|
111
113
|
ARGV.replace ["list"]
|
|
112
114
|
content = capture(:stdout) { Thor::Runner.start }
|
|
113
|
-
content.must =~ /amazing:describe NAME
|
|
115
|
+
content.must =~ /amazing:describe NAME\s+# say that someone is amazing/m
|
|
114
116
|
end
|
|
115
117
|
|
|
116
118
|
it "gives a list of the available Thor::Group classes" do
|
|
117
119
|
ARGV.replace ["list"]
|
|
118
|
-
capture(:stdout) { Thor::Runner.start }.must =~ /my_counter N
|
|
120
|
+
capture(:stdout) { Thor::Runner.start }.must =~ /my_counter N/
|
|
119
121
|
end
|
|
120
122
|
|
|
121
123
|
it "can filter a list of the available tasks by --group" do
|
|
@@ -141,33 +143,19 @@ describe Thor::Runner do
|
|
|
141
143
|
|
|
142
144
|
it "presents tasks in the default namespace with an empty namespace" do
|
|
143
145
|
ARGV.replace ["list"]
|
|
144
|
-
capture(:stdout) { Thor::Runner.start }.must =~
|
|
146
|
+
capture(:stdout) { Thor::Runner.start }.must =~ /^thor :test\s+# prints 'test'/m
|
|
145
147
|
end
|
|
146
148
|
|
|
147
149
|
it "runs tasks with an empty namespace from the default namespace" do
|
|
148
150
|
ARGV.replace [":test"]
|
|
149
151
|
capture(:stdout) { Thor::Runner.start }.must == "test\n"
|
|
150
152
|
end
|
|
151
|
-
|
|
152
|
-
it "updates the yaml file when invoked" do
|
|
153
|
-
capture(:stdout) { Thor::Runner.start(["list"]) }
|
|
154
|
-
@original_yaml["random"][:namespaces].must == ["amazing"]
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
describe "update" do
|
|
159
|
-
it "updates existing thor files" do
|
|
160
|
-
mock.instance_of(Thor::Runner).install(@original_yaml["random"][:location]) { true }
|
|
161
|
-
stub(File).delete(File.join(Thor::Util.thor_root, @original_yaml["random"][:filename]))
|
|
162
|
-
silence(:stdout) { Thor::Runner.start(["update", "random"]) }
|
|
163
|
-
end
|
|
164
153
|
end
|
|
165
154
|
|
|
166
155
|
describe "uninstall" do
|
|
167
156
|
before(:each) do
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
stub(@original_yaml).delete(anything)
|
|
157
|
+
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
|
|
158
|
+
FileUtils.should_receive(:rm_rf).with(path)
|
|
171
159
|
end
|
|
172
160
|
|
|
173
161
|
it "uninstalls existing thor modules" do
|
|
@@ -177,26 +165,34 @@ describe Thor::Runner do
|
|
|
177
165
|
|
|
178
166
|
describe "installed" do
|
|
179
167
|
before(:each) do
|
|
180
|
-
|
|
168
|
+
Dir.should_receive(:[]).and_return([])
|
|
181
169
|
end
|
|
182
170
|
|
|
183
171
|
it "displays the modules installed in a pretty way" do
|
|
184
172
|
stdout = capture(:stdout) { Thor::Runner.start(["installed"]) }
|
|
185
173
|
stdout.must =~ /random\s*amazing/
|
|
186
|
-
stdout.must =~ /amazing:describe NAME
|
|
174
|
+
stdout.must =~ /amazing:describe NAME\s+# say that someone is amazing/m
|
|
187
175
|
end
|
|
188
176
|
end
|
|
189
177
|
|
|
190
|
-
describe "install" do
|
|
191
|
-
|
|
192
|
-
|
|
178
|
+
describe "install/update" do
|
|
179
|
+
before(:each) do
|
|
180
|
+
FileUtils.stub!(:mkdir_p)
|
|
181
|
+
FileUtils.stub!(:touch)
|
|
182
|
+
$stdin.stub!(:gets).and_return("Y")
|
|
193
183
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
stub(FileUtils).touch
|
|
184
|
+
path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random"))
|
|
185
|
+
File.should_receive(:open).with(path, "w")
|
|
186
|
+
end
|
|
198
187
|
|
|
199
|
-
|
|
188
|
+
it "updates existing thor files" do
|
|
189
|
+
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
|
|
190
|
+
File.should_receive(:delete).with(path)
|
|
191
|
+
silence(:stdout) { Thor::Runner.start(["update", "random"]) }
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it "installs thor files" do
|
|
195
|
+
ARGV.replace ["install", @location]
|
|
200
196
|
silence(:stdout) { Thor::Runner.start }
|
|
201
197
|
end
|
|
202
198
|
end
|
data/spec/shell/basic_spec.rb
CHANGED
|
@@ -17,107 +17,85 @@ describe Thor::Shell::Basic do
|
|
|
17
17
|
|
|
18
18
|
describe "#ask" do
|
|
19
19
|
it "prints a message to the user and gets the response" do
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
$stdout.should_receive(:print).with("Should I overwrite it? ")
|
|
21
|
+
$stdin.should_receive(:gets).and_return('Sure')
|
|
22
22
|
shell.ask("Should I overwrite it?").must == "Sure"
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
describe "#yes?" do
|
|
27
27
|
it "asks the user and returns true if the user replies yes" do
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
$stdout.should_receive(:print).with("Should I overwrite it? ")
|
|
29
|
+
$stdin.should_receive(:gets).and_return('y')
|
|
30
30
|
shell.yes?("Should I overwrite it?").must be_true
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
$stdout.should_receive(:print).with("Should I overwrite it? ")
|
|
33
|
+
$stdin.should_receive(:gets).and_return('n')
|
|
34
34
|
shell.yes?("Should I overwrite it?").must_not be_true
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
describe "#no?" do
|
|
39
39
|
it "asks the user and returns true if the user replies no" do
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
$stdout.should_receive(:print).with("Should I overwrite it? ")
|
|
41
|
+
$stdin.should_receive(:gets).and_return('n')
|
|
42
42
|
shell.no?("Should I overwrite it?").must be_true
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
$stdout.should_receive(:print).with("Should I overwrite it? ")
|
|
45
|
+
$stdin.should_receive(:gets).and_return('Yes')
|
|
46
46
|
shell.no?("Should I overwrite it?").must be_false
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
describe "#say" do
|
|
51
51
|
it "prints a message to the user" do
|
|
52
|
-
|
|
52
|
+
$stdout.should_receive(:puts).with("Running...")
|
|
53
53
|
shell.say("Running...")
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
it "prints a message to the user without new line if it ends with a whitespace" do
|
|
57
|
-
|
|
57
|
+
$stdout.should_receive(:print).with("Running... ")
|
|
58
58
|
shell.say("Running... ")
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
it "prints a message to the user without new line" do
|
|
62
|
-
|
|
62
|
+
$stdout.should_receive(:print).with("Running...")
|
|
63
63
|
shell.say("Running...", nil, false)
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
describe "#say_status" do
|
|
68
68
|
it "prints a message to the user with status" do
|
|
69
|
-
|
|
69
|
+
$stdout.should_receive(:puts).with(" create ~/.thor/task.thor")
|
|
70
70
|
shell.say_status(:create, "~/.thor/task.thor")
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
it "always use new line" do
|
|
74
|
-
|
|
74
|
+
$stdout.should_receive(:puts).with(" create ")
|
|
75
75
|
shell.say_status(:create, "")
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
it "does not print a message if base is set to quiet" do
|
|
79
79
|
base = MyCounter.new [1,2]
|
|
80
|
-
|
|
80
|
+
base.should_receive(:options).and_return(:quiet => true)
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
$stdout.should_not_receive(:puts)
|
|
83
83
|
shell.base = base
|
|
84
84
|
shell.say_status(:created, "~/.thor/task.thor")
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
it "does not print a message if log status is set to false" do
|
|
88
|
-
|
|
88
|
+
$stdout.should_not_receive(:puts)
|
|
89
89
|
shell.say_status(:created, "~/.thor/task.thor", false)
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
it "uses padding to set messages left margin" do
|
|
93
93
|
shell.padding = 2
|
|
94
|
-
|
|
94
|
+
$stdout.should_receive(:puts).with(" create ~/.thor/task.thor")
|
|
95
95
|
shell.say_status(:create, "~/.thor/task.thor")
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
-
describe "#print_list" do
|
|
100
|
-
before(:each) do
|
|
101
|
-
@list = ["abc", "#123", "first three"]
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
it "prints a list" do
|
|
105
|
-
content = capture(:stdout){ shell.print_list(@list) }
|
|
106
|
-
content.must == <<-LIST
|
|
107
|
-
abc
|
|
108
|
-
#123
|
|
109
|
-
first three
|
|
110
|
-
LIST
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
it "prints a list inline" do
|
|
114
|
-
content = capture(:stdout){ shell.print_list(@list, :mode => :inline) }
|
|
115
|
-
content.must == <<-LIST
|
|
116
|
-
abc, #123, and first three
|
|
117
|
-
LIST
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
99
|
describe "#print_table" do
|
|
122
100
|
before(:each) do
|
|
123
101
|
@table = []
|
|
@@ -141,41 +119,57 @@ TABLE
|
|
|
141
119
|
abc #123 first three
|
|
142
120
|
#0 empty
|
|
143
121
|
xyz #786 last three
|
|
122
|
+
TABLE
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "uses maximum terminal width" do
|
|
126
|
+
shell.should_receive(:terminal_width).and_return(20)
|
|
127
|
+
content = capture(:stdout){ shell.print_table(@table, :ident => 2, :truncate => true) }
|
|
128
|
+
content.must == <<-TABLE
|
|
129
|
+
abc #123 firs...
|
|
130
|
+
#0 empty
|
|
131
|
+
xyz #786 last...
|
|
144
132
|
TABLE
|
|
145
133
|
end
|
|
146
134
|
end
|
|
147
135
|
|
|
148
136
|
describe "#file_collision" do
|
|
149
137
|
it "shows a menu with options" do
|
|
150
|
-
|
|
151
|
-
|
|
138
|
+
$stdout.should_receive(:print).with('Overwrite foo? (enter "h" for help) [Ynaqh] ')
|
|
139
|
+
$stdin.should_receive(:gets).and_return('n')
|
|
152
140
|
shell.file_collision('foo')
|
|
153
141
|
end
|
|
154
142
|
|
|
143
|
+
it "returns true if the user choose default option" do
|
|
144
|
+
$stdout.stub!(:print)
|
|
145
|
+
$stdin.should_receive(:gets).and_return('')
|
|
146
|
+
shell.file_collision('foo').must be_true
|
|
147
|
+
end
|
|
148
|
+
|
|
155
149
|
it "returns false if the user choose no" do
|
|
156
|
-
|
|
157
|
-
|
|
150
|
+
$stdout.stub!(:print)
|
|
151
|
+
$stdin.should_receive(:gets).and_return('n')
|
|
158
152
|
shell.file_collision('foo').must be_false
|
|
159
153
|
end
|
|
160
154
|
|
|
161
155
|
it "returns true if the user choose yes" do
|
|
162
|
-
|
|
163
|
-
|
|
156
|
+
$stdout.stub!(:print)
|
|
157
|
+
$stdin.should_receive(:gets).and_return('y')
|
|
164
158
|
shell.file_collision('foo').must be_true
|
|
165
159
|
end
|
|
166
160
|
|
|
167
161
|
it "shows help usage if the user choose help" do
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
162
|
+
$stdout.stub!(:print)
|
|
163
|
+
$stdin.should_receive(:gets).and_return('h')
|
|
164
|
+
$stdin.should_receive(:gets).and_return('n')
|
|
171
165
|
help = capture(:stdout){ shell.file_collision('foo') }
|
|
172
166
|
help.must =~ /h \- help, show this help/
|
|
173
167
|
end
|
|
174
168
|
|
|
175
169
|
it "quits if the user choose quit" do
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
170
|
+
$stdout.stub!(:print)
|
|
171
|
+
$stdout.should_receive(:puts).with('Aborting...')
|
|
172
|
+
$stdin.should_receive(:gets).and_return('q')
|
|
179
173
|
|
|
180
174
|
lambda {
|
|
181
175
|
shell.file_collision('foo')
|
|
@@ -183,27 +177,27 @@ TABLE
|
|
|
183
177
|
end
|
|
184
178
|
|
|
185
179
|
it "always returns true if the user choose always" do
|
|
186
|
-
|
|
187
|
-
|
|
180
|
+
$stdout.should_receive(:print).with('Overwrite foo? (enter "h" for help) [Ynaqh] ')
|
|
181
|
+
$stdin.should_receive(:gets).and_return('a')
|
|
188
182
|
|
|
189
183
|
shell.file_collision('foo').must be_true
|
|
190
184
|
|
|
191
|
-
|
|
185
|
+
$stdout.should_not_receive(:print)
|
|
192
186
|
shell.file_collision('foo').must be_true
|
|
193
187
|
end
|
|
194
188
|
|
|
195
189
|
describe "when a block is given" do
|
|
196
190
|
it "displays diff options to the user" do
|
|
197
|
-
|
|
198
|
-
|
|
191
|
+
$stdout.should_receive(:print).with('Overwrite foo? (enter "h" for help) [Ynaqdh] ')
|
|
192
|
+
$stdin.should_receive(:gets).and_return('s')
|
|
199
193
|
shell.file_collision('foo'){ }
|
|
200
194
|
end
|
|
201
195
|
|
|
202
196
|
it "invokes the diff command" do
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
197
|
+
$stdout.stub!(:print)
|
|
198
|
+
$stdin.should_receive(:gets).and_return('d')
|
|
199
|
+
$stdin.should_receive(:gets).and_return('n')
|
|
200
|
+
shell.should_receive(:system).with(/diff -u/)
|
|
207
201
|
capture(:stdout){ shell.file_collision('foo'){ } }
|
|
208
202
|
end
|
|
209
203
|
end
|
data/spec/shell/color_spec.rb
CHANGED
|
@@ -7,19 +7,19 @@ describe Thor::Shell::Color do
|
|
|
7
7
|
|
|
8
8
|
describe "#say" do
|
|
9
9
|
it "set the color if specified" do
|
|
10
|
-
|
|
10
|
+
$stdout.should_receive(:puts).with("\e[32mWow! Now we have colors!\e[0m")
|
|
11
11
|
shell.say "Wow! Now we have colors!", :green
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it "does not use a new line even with colors" do
|
|
15
|
-
|
|
15
|
+
$stdout.should_receive(:print).with("\e[32mWow! Now we have colors! \e[0m")
|
|
16
16
|
shell.say "Wow! Now we have colors! ", :green
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
describe "#say_status" do
|
|
21
21
|
it "uses color to say status" do
|
|
22
|
-
|
|
22
|
+
$stdout.should_receive(:puts).with("\e[1m\e[31m conflict\e[0m README")
|
|
23
23
|
shell.say_status :conflict, "README", :red
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -27,9 +27,9 @@ describe Thor::Shell::Color do
|
|
|
27
27
|
describe "#file_collision" do
|
|
28
28
|
describe "when a block is given" do
|
|
29
29
|
it "invokes the diff command" do
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
$stdout.stub!(:print)
|
|
31
|
+
$stdin.should_receive(:gets).and_return('d')
|
|
32
|
+
$stdin.should_receive(:gets).and_return('n')
|
|
33
33
|
|
|
34
34
|
output = capture(:stdout){ shell.file_collision('spec/fixtures/doc/README'){ "README\nEND\n" } }
|
|
35
35
|
output.must =~ /\e\[31m\- __start__\e\[0m/
|
data/spec/spec.opts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
CHANGED
|
@@ -2,12 +2,15 @@ $TESTING=true
|
|
|
2
2
|
|
|
3
3
|
$:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
|
|
4
4
|
require 'thor'
|
|
5
|
+
require 'thor/group'
|
|
5
6
|
require 'stringio'
|
|
6
7
|
|
|
7
8
|
require 'rubygems'
|
|
8
|
-
require '
|
|
9
|
+
require 'rdoc'
|
|
9
10
|
require 'diff/lcs' # You need diff/lcs installed to run specs (but not to run Thor).
|
|
10
11
|
|
|
12
|
+
$thor_runner = true
|
|
13
|
+
|
|
11
14
|
# Load fixtures
|
|
12
15
|
load File.join(File.dirname(__FILE__), "fixtures", "task.thor")
|
|
13
16
|
load File.join(File.dirname(__FILE__), "fixtures", "group.thor")
|
|
@@ -25,8 +28,6 @@ Kernel.module_eval do
|
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
Spec::Runner.configure do |config|
|
|
28
|
-
config.mock_with :rr
|
|
29
|
-
|
|
30
31
|
def capture(stream)
|
|
31
32
|
begin
|
|
32
33
|
stream = stream.to_s
|
|
@@ -48,5 +49,5 @@ Spec::Runner.configure do |config|
|
|
|
48
49
|
File.join(File.dirname(__FILE__), 'sandbox')
|
|
49
50
|
end
|
|
50
51
|
|
|
51
|
-
alias silence capture
|
|
52
|
+
alias :silence :capture
|
|
52
53
|
end
|
data/spec/task_spec.rb
CHANGED
|
@@ -10,32 +10,22 @@ describe Thor::Task do
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
describe "#formatted_usage" do
|
|
13
|
-
it "shows usage with options" do
|
|
14
|
-
task('foo' => true, :bar => :required).formatted_usage.must == "can_has --bar=BAR [--foo]"
|
|
15
|
-
end
|
|
16
|
-
|
|
17
13
|
it "includes namespace within usage" do
|
|
18
|
-
stub(
|
|
19
|
-
stub(
|
|
20
|
-
task(:bar => :required).formatted_usage(Object
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
it "does not show options if required" do
|
|
24
|
-
stub(Object).namespace{ "foo" }
|
|
25
|
-
stub(Object).arguments{ [] }
|
|
26
|
-
task(:bar => :required).formatted_usage(Object, true, false).must == "foo:can_has"
|
|
14
|
+
Object.stub!(:namespace).and_return("foo")
|
|
15
|
+
Object.stub!(:arguments).and_return([])
|
|
16
|
+
task(:bar => :required).formatted_usage(Object).must == "foo:can_has --bar=BAR"
|
|
27
17
|
end
|
|
28
18
|
|
|
29
19
|
it "removes default from namespace" do
|
|
30
|
-
stub(
|
|
31
|
-
stub(
|
|
32
|
-
task(:bar => :required).formatted_usage(Object
|
|
20
|
+
Object.stub!(:namespace).and_return("default:foo")
|
|
21
|
+
Object.stub!(:arguments).and_return([])
|
|
22
|
+
task(:bar => :required).formatted_usage(Object).must == ":foo:can_has --bar=BAR"
|
|
33
23
|
end
|
|
34
24
|
|
|
35
25
|
it "injects arguments into usage" do
|
|
36
|
-
stub(
|
|
37
|
-
stub(
|
|
38
|
-
task(:foo =>
|
|
26
|
+
Object.stub!(:namespace).and_return("foo")
|
|
27
|
+
Object.stub!(:arguments).and_return([ Thor::Argument.new(:bar, nil, true, :string) ])
|
|
28
|
+
task(:foo => :required).formatted_usage(Object).must == "foo:can_has BAR --foo=FOO"
|
|
39
29
|
end
|
|
40
30
|
end
|
|
41
31
|
|
|
@@ -64,25 +54,17 @@ describe Thor::Task do
|
|
|
64
54
|
|
|
65
55
|
describe "#run" do
|
|
66
56
|
it "runs a task by calling a method in the given instance" do
|
|
67
|
-
mock = mock
|
|
57
|
+
mock = mock()
|
|
58
|
+
mock.should_receive(:send).with("can_has", 1, 2, 3)
|
|
68
59
|
task.run(mock, [1, 2, 3])
|
|
69
60
|
end
|
|
70
61
|
|
|
71
62
|
it "raises an error if the method to be invoked is private" do
|
|
72
|
-
mock = mock
|
|
63
|
+
mock = mock()
|
|
64
|
+
mock.should_receive(:private_methods).and_return(['can_has'])
|
|
73
65
|
lambda {
|
|
74
66
|
task.run(mock)
|
|
75
|
-
}.must raise_error(Thor::UndefinedTaskError, "the 'can_has' task of
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
describe "#short_description" do
|
|
80
|
-
it "returns the first line of the description" do
|
|
81
|
-
Thor::Task.new(:task, "I can has\ncheezburger", "can_has").short_description == "I can has"
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
it "returns the whole description if it's one line" do
|
|
85
|
-
Thor::Task.new(:task, "I can has cheezburger", "can_has").short_description == "I can has cheezburger"
|
|
67
|
+
}.must raise_error(Thor::UndefinedTaskError, "the 'can_has' task of Spec::Mocks::Mock is private")
|
|
86
68
|
end
|
|
87
69
|
end
|
|
88
70
|
end
|
data/spec/thor_spec.rb
CHANGED
|
@@ -72,7 +72,7 @@ describe Thor do
|
|
|
72
72
|
|
|
73
73
|
describe "when :for is supplied" do
|
|
74
74
|
it "overwrites a previous defined task" do
|
|
75
|
-
capture(:stdout) { MyChildScript.start(["help"]) }.must =~ /animal KIND \
|
|
75
|
+
capture(:stdout) { MyChildScript.start(["help"]) }.must =~ /animal KIND \s+# fish around/m
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
end
|
|
@@ -133,7 +133,7 @@ describe Thor do
|
|
|
133
133
|
end
|
|
134
134
|
|
|
135
135
|
it "raises when an exception happens within the task call" do
|
|
136
|
-
lambda { MyScript.start(["call_myself_with_wrong_arity"]) }.must raise_error
|
|
136
|
+
lambda { MyScript.start(["call_myself_with_wrong_arity"]) }.must raise_error(ArgumentError)
|
|
137
137
|
end
|
|
138
138
|
end
|
|
139
139
|
|
|
@@ -148,25 +148,31 @@ describe Thor do
|
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
it "provides useful help info for the help method itself" do
|
|
151
|
-
@content.must =~ /help \[TASK\]\s+# Describe available tasks/
|
|
151
|
+
@content.must =~ /help \[TASK\]\s+# Describe available tasks/
|
|
152
152
|
end
|
|
153
153
|
|
|
154
154
|
it "provides useful help info for a method with params" do
|
|
155
|
-
@content.must =~ /animal TYPE\s+# horse around/
|
|
155
|
+
@content.must =~ /animal TYPE\s+# horse around/
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it "uses the maximum terminal size to show tasks" do
|
|
159
|
+
@shell.should_receive(:terminal_width).and_return(80)
|
|
160
|
+
content = capture(:stdout){ MyScript.help(shell) }
|
|
161
|
+
content.must =~ /aaa\.\.\.$/
|
|
156
162
|
end
|
|
157
163
|
|
|
158
164
|
it "provides description for tasks from classes in the same namespace" do
|
|
159
|
-
@content.must =~ /baz\s+# do some bazing/
|
|
165
|
+
@content.must =~ /baz\s+# do some bazing/
|
|
160
166
|
end
|
|
161
167
|
|
|
162
168
|
it "shows superclass tasks" do
|
|
163
169
|
content = capture(:stdout){ MyChildScript.help(shell) }
|
|
164
|
-
content.must =~ /foo BAR \
|
|
170
|
+
content.must =~ /foo BAR \s+# do some fooing/
|
|
165
171
|
end
|
|
166
172
|
|
|
167
173
|
it "shows class options information" do
|
|
168
174
|
content = capture(:stdout){ MyChildScript.help(shell) }
|
|
169
|
-
content.must =~ /
|
|
175
|
+
content.must =~ /Options\:/
|
|
170
176
|
content.must =~ /\[\-\-param=N\]/
|
|
171
177
|
end
|
|
172
178
|
|
|
@@ -178,11 +184,11 @@ describe Thor do
|
|
|
178
184
|
|
|
179
185
|
describe "for a specific task" do
|
|
180
186
|
it "provides full help info when talking about a specific task" do
|
|
181
|
-
capture(:stdout) { MyScript.
|
|
187
|
+
capture(:stdout) { MyScript.task_help(shell, "foo") }.must == <<END
|
|
182
188
|
Usage:
|
|
183
|
-
foo BAR
|
|
189
|
+
thor my_script:foo BAR
|
|
184
190
|
|
|
185
|
-
|
|
191
|
+
Options:
|
|
186
192
|
[--force] # Force to do some fooing
|
|
187
193
|
|
|
188
194
|
do some fooing
|
|
@@ -193,25 +199,18 @@ END
|
|
|
193
199
|
|
|
194
200
|
it "raises an error if the task can't be found" do
|
|
195
201
|
lambda {
|
|
196
|
-
MyScript.
|
|
202
|
+
MyScript.task_help(shell, "unknown")
|
|
197
203
|
}.must raise_error(Thor::Error, "task 'unknown' could not be found in namespace 'my_script'")
|
|
198
204
|
end
|
|
199
205
|
end
|
|
200
206
|
|
|
201
|
-
describe "
|
|
202
|
-
it "
|
|
203
|
-
capture(:stdout){ MyScript.help
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
it "does not show superclass tasks if required" do
|
|
207
|
-
capture(:stdout){ MyScript.help(shell, nil, :short => true) }.must_not =~ /help/
|
|
207
|
+
describe "instance method" do
|
|
208
|
+
it "calls the class method" do
|
|
209
|
+
capture(:stdout){ MyScript.start(["help"]) }.must =~ /Tasks:/
|
|
208
210
|
end
|
|
209
|
-
end
|
|
210
211
|
|
|
211
|
-
describe "instance method" do
|
|
212
212
|
it "calls the class method" do
|
|
213
|
-
|
|
214
|
-
MyScript.start(["help"])
|
|
213
|
+
capture(:stdout){ MyScript.start(["help", "foo"]) }.must =~ /Usage:/
|
|
215
214
|
end
|
|
216
215
|
end
|
|
217
216
|
end
|