thor 0.9.9 → 0.11.5
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 +29 -4
- data/README.rdoc +234 -0
- data/Thorfile +57 -0
- data/VERSION +1 -0
- data/bin/rake2thor +4 -0
- data/bin/thor +1 -1
- data/lib/thor.rb +216 -119
- data/lib/thor/actions.rb +272 -0
- data/lib/thor/actions/create_file.rb +102 -0
- data/lib/thor/actions/directory.rb +87 -0
- data/lib/thor/actions/empty_directory.rb +133 -0
- data/lib/thor/actions/file_manipulation.rb +195 -0
- data/lib/thor/actions/inject_into_file.rb +78 -0
- data/lib/thor/base.rb +510 -0
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
- data/lib/thor/core_ext/ordered_hash.rb +100 -0
- data/lib/thor/error.rb +25 -1
- data/lib/thor/group.rb +263 -0
- data/lib/thor/invocation.rb +178 -0
- data/lib/thor/parser.rb +4 -0
- data/lib/thor/parser/argument.rb +67 -0
- data/lib/thor/parser/arguments.rb +145 -0
- data/lib/thor/parser/option.rb +132 -0
- data/lib/thor/parser/options.rb +142 -0
- data/lib/thor/rake_compat.rb +67 -0
- data/lib/thor/runner.rb +232 -242
- data/lib/thor/shell.rb +72 -0
- data/lib/thor/shell/basic.rb +220 -0
- data/lib/thor/shell/color.rb +108 -0
- data/lib/thor/task.rb +97 -60
- data/lib/thor/util.rb +230 -55
- data/spec/actions/create_file_spec.rb +170 -0
- data/spec/actions/directory_spec.rb +118 -0
- data/spec/actions/empty_directory_spec.rb +91 -0
- data/spec/actions/file_manipulation_spec.rb +242 -0
- data/spec/actions/inject_into_file_spec.rb +80 -0
- data/spec/actions_spec.rb +291 -0
- data/spec/base_spec.rb +236 -0
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +43 -0
- data/spec/core_ext/ordered_hash_spec.rb +115 -0
- data/spec/fixtures/bundle/execute.rb +6 -0
- data/spec/fixtures/doc/config.rb +1 -0
- data/spec/group_spec.rb +177 -0
- data/spec/invocation_spec.rb +107 -0
- data/spec/parser/argument_spec.rb +47 -0
- data/spec/parser/arguments_spec.rb +64 -0
- data/spec/parser/option_spec.rb +212 -0
- data/spec/parser/options_spec.rb +255 -0
- data/spec/rake_compat_spec.rb +64 -0
- data/spec/runner_spec.rb +204 -0
- data/spec/shell/basic_spec.rb +206 -0
- data/spec/shell/color_spec.rb +41 -0
- data/spec/shell_spec.rb +25 -0
- data/spec/spec_helper.rb +52 -0
- data/spec/task_spec.rb +82 -0
- data/spec/thor_spec.rb +234 -0
- data/spec/util_spec.rb +196 -0
- metadata +69 -25
- data/README.markdown +0 -76
- data/Rakefile +0 -6
- data/lib/thor/options.rb +0 -242
- data/lib/thor/ordered_hash.rb +0 -64
- data/lib/thor/task_hash.rb +0 -22
- data/lib/thor/tasks.rb +0 -77
- data/lib/thor/tasks/package.rb +0 -18
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'thor/rake_compat'
|
3
|
+
require 'rake/tasklib'
|
4
|
+
|
5
|
+
class RakeTask < Rake::TaskLib
|
6
|
+
def initialize
|
7
|
+
define
|
8
|
+
end
|
9
|
+
|
10
|
+
def define
|
11
|
+
desc "Say it's cool"
|
12
|
+
task :cool do
|
13
|
+
puts "COOL"
|
14
|
+
end
|
15
|
+
|
16
|
+
namespace :hiper_mega do
|
17
|
+
task :super do
|
18
|
+
puts "HIPER MEGA SUPER"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class ThorTask < Thor
|
25
|
+
include Thor::RakeCompat
|
26
|
+
RakeTask.new
|
27
|
+
end
|
28
|
+
|
29
|
+
describe Thor::RakeCompat do
|
30
|
+
it "adds rake tasks to thor classes too" do
|
31
|
+
task = ThorTask.tasks["cool"]
|
32
|
+
task.must be
|
33
|
+
end
|
34
|
+
|
35
|
+
it "uses rake tasks descriptions on thor" do
|
36
|
+
ThorTask.tasks["cool"].description.must == "Say it's cool"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "gets usage from rake tasks name" do
|
40
|
+
ThorTask.tasks["cool"].usage.must == "cool"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "uses non namespaced name as description if non is available" do
|
44
|
+
ThorTask::HiperMega.tasks["super"].description.must == "super"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "converts namespaces to classes" do
|
48
|
+
ThorTask.const_get(:HiperMega).must == ThorTask::HiperMega
|
49
|
+
end
|
50
|
+
|
51
|
+
it "does not add tasks from higher namespaces in lowers namespaces" do
|
52
|
+
ThorTask.tasks["super"].must_not be
|
53
|
+
end
|
54
|
+
|
55
|
+
it "invoking the thor task invokes the rake task" do
|
56
|
+
capture(:stdout) do
|
57
|
+
ThorTask.start ["cool"]
|
58
|
+
end.must == "COOL\n"
|
59
|
+
|
60
|
+
capture(:stdout) do
|
61
|
+
ThorTask::HiperMega.start ["super"]
|
62
|
+
end.must == "HIPER MEGA SUPER\n"
|
63
|
+
end
|
64
|
+
end
|
data/spec/runner_spec.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
|
2
|
+
require 'thor/runner'
|
3
|
+
|
4
|
+
describe Thor::Runner do
|
5
|
+
describe "#help" do
|
6
|
+
it "shows information about Thor::Runner itself" do
|
7
|
+
capture(:stdout){ Thor::Runner.start(["help"]) }.must =~ /List the available thor tasks/
|
8
|
+
end
|
9
|
+
|
10
|
+
it "shows information about an specific Thor::Runner task" do
|
11
|
+
content = capture(:stdout){ Thor::Runner.start(["help", "list"]) }
|
12
|
+
content.must =~ /List the available thor tasks/
|
13
|
+
content.must_not =~ /help \[TASK\]/
|
14
|
+
end
|
15
|
+
|
16
|
+
it "shows information about a specific Thor class" do
|
17
|
+
content = capture(:stdout){ Thor::Runner.start(["help", "my_script"]) }
|
18
|
+
content.must =~ /zoo\s+# zoo around/m
|
19
|
+
end
|
20
|
+
|
21
|
+
it "shows information about an specific task from an specific Thor class" do
|
22
|
+
content = capture(:stdout){ Thor::Runner.start(["help", "my_script:zoo"]) }
|
23
|
+
content.must =~ /zoo around/
|
24
|
+
content.must_not =~ /help \[TASK\]/
|
25
|
+
end
|
26
|
+
|
27
|
+
it "shows information about a specific Thor group class" do
|
28
|
+
content = capture(:stdout){ Thor::Runner.start(["help", "my_counter"]) }
|
29
|
+
content.must =~ /my_counter N \[N\]/
|
30
|
+
end
|
31
|
+
|
32
|
+
it "raises error if a class/task cannot be found" do
|
33
|
+
content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
|
34
|
+
content.must =~ /could not find Thor class or task 'unknown'/
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#start" do
|
39
|
+
it "invokes a task from Thor::Runner" do
|
40
|
+
ARGV.replace ["list"]
|
41
|
+
capture(:stdout){ Thor::Runner.start }.must =~ /my_counter N \[N\]/
|
42
|
+
end
|
43
|
+
|
44
|
+
it "invokes a task from a specific Thor class" do
|
45
|
+
ARGV.replace ["my_script:zoo"]
|
46
|
+
Thor::Runner.start.must be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "invokes the default task from a specific Thor class if none is specified" do
|
50
|
+
ARGV.replace ["my_script"]
|
51
|
+
Thor::Runner.start.must == "default task"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "forwads arguments to the invoked task" do
|
55
|
+
ARGV.replace ["my_script:animal", "horse"]
|
56
|
+
Thor::Runner.start.must == ["horse"]
|
57
|
+
end
|
58
|
+
|
59
|
+
it "invokes tasks through shortcuts" do
|
60
|
+
ARGV.replace ["my_script", "-T", "horse"]
|
61
|
+
Thor::Runner.start.must == ["horse"]
|
62
|
+
end
|
63
|
+
|
64
|
+
it "invokes a Thor::Group" do
|
65
|
+
ARGV.replace ["my_counter", "1", "2", "--third", "3"]
|
66
|
+
Thor::Runner.start.must == [1, 2, 3]
|
67
|
+
end
|
68
|
+
|
69
|
+
it "raises an error if class/task can't be found" do
|
70
|
+
ARGV.replace ["unknown"]
|
71
|
+
capture(:stderr){ Thor::Runner.start }.must =~ /could not find Thor class or task 'unknown'/
|
72
|
+
end
|
73
|
+
|
74
|
+
it "does not swallow NoMethodErrors that occur inside the called method" do
|
75
|
+
ARGV.replace ["my_script:call_unexistent_method"]
|
76
|
+
lambda { Thor::Runner.start }.must raise_error(NoMethodError)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "does not swallow Thor::Group ArgumentError" do
|
80
|
+
ARGV.replace ["whiny_generator"]
|
81
|
+
lambda { Thor::Runner.start }.must raise_error(ArgumentError, /Are you sure it has arity equals to 0\?/)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "does not swallow Thor ArgumentError" do
|
85
|
+
ARGV.replace ["my_script:animal"]
|
86
|
+
capture(:stderr) { Thor::Runner.start }.must =~ /'animal' was called incorrectly\. Call as 'my_script:animal TYPE'/
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "tasks" do
|
91
|
+
before(:each) do
|
92
|
+
@location = "#{File.dirname(__FILE__)}/fixtures/task.thor"
|
93
|
+
@original_yaml = {
|
94
|
+
"random" => {
|
95
|
+
:location => @location,
|
96
|
+
:filename => "4a33b894ffce85d7b412fc1b36f88fe0",
|
97
|
+
:constants => ["Amazing"]
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
# Stub load and save to avoid thor.yaml from being overwritten
|
102
|
+
stub(YAML).load_file { @original_yaml }
|
103
|
+
stub(File).exists?(File.join(Thor::Util.thor_root, "thor.yml")){ true }
|
104
|
+
stub(File).open(File.join(Thor::Util.thor_root, "thor.yml"), "w")
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "list" do
|
108
|
+
it "gives a list of the available tasks" do
|
109
|
+
ARGV.replace ["list"]
|
110
|
+
content = capture(:stdout) { Thor::Runner.start }
|
111
|
+
content.must =~ /amazing:describe NAME \[\-\-forcefully\]\s+# say that someone is amazing/m
|
112
|
+
end
|
113
|
+
|
114
|
+
it "gives a list of the available Thor::Group classes" do
|
115
|
+
ARGV.replace ["list"]
|
116
|
+
capture(:stdout) { Thor::Runner.start }.must =~ /my_counter N \[N\]/
|
117
|
+
end
|
118
|
+
|
119
|
+
it "can filter a list of the available tasks by --group" do
|
120
|
+
ARGV.replace ["list", "--group", "standard"]
|
121
|
+
capture(:stdout) { Thor::Runner.start }.must =~ /amazing:describe NAME/
|
122
|
+
ARGV.replace []
|
123
|
+
capture(:stdout) { Thor::Runner.start }.must_not =~ /my_script:animal TYPE/
|
124
|
+
ARGV.replace ["list", "--group", "script"]
|
125
|
+
capture(:stdout) { Thor::Runner.start }.must =~ /my_script:animal TYPE/
|
126
|
+
end
|
127
|
+
|
128
|
+
it "can skip all filters to show all tasks using --all" do
|
129
|
+
ARGV.replace ["list", "--all"]
|
130
|
+
content = capture(:stdout) { Thor::Runner.start }
|
131
|
+
content.must =~ /amazing:describe NAME/
|
132
|
+
content.must =~ /my_script:animal TYPE/
|
133
|
+
end
|
134
|
+
|
135
|
+
it "doesn't list superclass tasks in the subclass" do
|
136
|
+
ARGV.replace ["list"]
|
137
|
+
capture(:stdout) { Thor::Runner.start }.must_not =~ /amazing:help/
|
138
|
+
end
|
139
|
+
|
140
|
+
it "presents tasks in the default namespace with an empty namespace" do
|
141
|
+
ARGV.replace ["list"]
|
142
|
+
capture(:stdout) { Thor::Runner.start }.must =~ /^:test\s+# prints 'test'/m
|
143
|
+
end
|
144
|
+
|
145
|
+
it "runs tasks with an empty namespace from the default namespace" do
|
146
|
+
ARGV.replace [":test"]
|
147
|
+
capture(:stdout) { Thor::Runner.start }.must == "test\n"
|
148
|
+
end
|
149
|
+
|
150
|
+
it "updates the yaml file when invoked" do
|
151
|
+
capture(:stdout) { Thor::Runner.start(["list"]) }
|
152
|
+
@original_yaml["random"][:namespaces].must == ["amazing"]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "update" do
|
157
|
+
it "updates existing thor files" do
|
158
|
+
mock.instance_of(Thor::Runner).install(@original_yaml["random"][:location]) { true }
|
159
|
+
stub(File).delete(File.join(Thor::Util.thor_root, @original_yaml["random"][:filename]))
|
160
|
+
silence(:stdout) { Thor::Runner.start(["update", "random"]) }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "uninstall" do
|
165
|
+
before(:each) do
|
166
|
+
stub.instance_of(Thor::Runner).save_yaml(anything)
|
167
|
+
stub(File).delete(anything)
|
168
|
+
stub(@original_yaml).delete(anything)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "uninstalls existing thor modules" do
|
172
|
+
silence(:stdout) { Thor::Runner.start(["uninstall", "random"]) }
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "installed" do
|
177
|
+
before(:each) do
|
178
|
+
stub(Dir).[](anything) { [] }
|
179
|
+
end
|
180
|
+
|
181
|
+
it "displays the modules installed in a pretty way" do
|
182
|
+
stdout = capture(:stdout) { Thor::Runner.start(["installed"]) }
|
183
|
+
|
184
|
+
stdout.must =~ /random\s*amazing/
|
185
|
+
stdout.must =~ /amazing:describe NAME \[\-\-forcefully\]\s+# say that someone is amazing/m
|
186
|
+
stdout.must =~ /amazing:hello\s+# say hello/m
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "install" do
|
191
|
+
it "installs thor files" do
|
192
|
+
ARGV.replace ["install", @location]
|
193
|
+
|
194
|
+
# Stubs for the file system interactions
|
195
|
+
stub.instance_of(Thor::Base.shell).no? { false }
|
196
|
+
stub(FileUtils).mkdir_p
|
197
|
+
stub(FileUtils).touch
|
198
|
+
|
199
|
+
mock(File).open(File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random")), "w")
|
200
|
+
silence(:stdout) { Thor::Runner.start }
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Thor::Shell::Basic do
|
4
|
+
def shell
|
5
|
+
@shell ||= Thor::Shell::Basic.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#padding" do
|
9
|
+
it "cannot be set to below zero" do
|
10
|
+
shell.padding = 10
|
11
|
+
shell.padding.must == 10
|
12
|
+
|
13
|
+
shell.padding = -1
|
14
|
+
shell.padding.must == 0
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#ask" do
|
19
|
+
it "prints a message to the user and gets the response" do
|
20
|
+
mock($stdout).print("Should I overwrite it? ")
|
21
|
+
mock($stdin).gets{ "Sure" }
|
22
|
+
shell.ask("Should I overwrite it?").must == "Sure"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#yes?" do
|
27
|
+
it "asks the user and returns true if the user replies yes" do
|
28
|
+
mock($stdout).print("Should I overwrite it? ")
|
29
|
+
mock($stdin).gets{ "y" }
|
30
|
+
shell.yes?("Should I overwrite it?").must be_true
|
31
|
+
|
32
|
+
mock($stdout).print("Should I overwrite it? ")
|
33
|
+
mock($stdin).gets{ "n" }
|
34
|
+
shell.yes?("Should I overwrite it?").must_not be_true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#no?" do
|
39
|
+
it "asks the user and returns true if the user replies no" do
|
40
|
+
mock($stdout).print("Should I overwrite it? ")
|
41
|
+
mock($stdin).gets{ "n" }
|
42
|
+
shell.no?("Should I overwrite it?").must be_true
|
43
|
+
|
44
|
+
mock($stdout).print("Should I overwrite it? ")
|
45
|
+
mock($stdin).gets{ "Yes" }
|
46
|
+
shell.no?("Should I overwrite it?").must be_false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#say" do
|
51
|
+
it "prints a message to the user" do
|
52
|
+
mock($stdout).puts("Running...")
|
53
|
+
shell.say("Running...")
|
54
|
+
end
|
55
|
+
|
56
|
+
it "prints a message to the user without new line if it ends with a whitespace" do
|
57
|
+
mock($stdout).print("Running... ")
|
58
|
+
shell.say("Running... ")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#say_status" do
|
63
|
+
it "prints a message to the user with status" do
|
64
|
+
mock($stdout).puts(" create ~/.thor/task.thor")
|
65
|
+
shell.say_status(:create, "~/.thor/task.thor")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "always use new line" do
|
69
|
+
mock($stdout).puts(" create ")
|
70
|
+
shell.say_status(:create, "")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "does not print a message if base is set to quiet" do
|
74
|
+
base = MyCounter.new [1,2]
|
75
|
+
mock(base).options { Hash.new(:quiet => true) }
|
76
|
+
|
77
|
+
dont_allow($stdout).puts
|
78
|
+
shell.base = base
|
79
|
+
shell.say_status(:created, "~/.thor/task.thor")
|
80
|
+
end
|
81
|
+
|
82
|
+
it "does not print a message if log status is set to false" do
|
83
|
+
dont_allow($stdout).puts
|
84
|
+
shell.say_status(:created, "~/.thor/task.thor", false)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "uses padding to set messages left margin" do
|
88
|
+
shell.padding = 2
|
89
|
+
mock($stdout).puts(" create ~/.thor/task.thor")
|
90
|
+
shell.say_status(:create, "~/.thor/task.thor")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#print_list" do
|
95
|
+
before(:each) do
|
96
|
+
@list = ["abc", "#123", "first three"]
|
97
|
+
end
|
98
|
+
|
99
|
+
it "prints a list" do
|
100
|
+
content = capture(:stdout){ shell.print_list(@list) }
|
101
|
+
content.must == <<-LIST
|
102
|
+
abc
|
103
|
+
#123
|
104
|
+
first three
|
105
|
+
LIST
|
106
|
+
end
|
107
|
+
|
108
|
+
it "prints a list inline" do
|
109
|
+
content = capture(:stdout){ shell.print_list(@list, :mode => :inline) }
|
110
|
+
content.must == <<-LIST
|
111
|
+
abc, #123, and first three
|
112
|
+
LIST
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#print_table" do
|
117
|
+
before(:each) do
|
118
|
+
@table = []
|
119
|
+
@table << ["abc", "#123", "first three"]
|
120
|
+
@table << ["", "#0", "empty"]
|
121
|
+
@table << ["xyz", "#786", "last three"]
|
122
|
+
end
|
123
|
+
|
124
|
+
it "prints a table" do
|
125
|
+
content = capture(:stdout){ shell.print_table(@table) }
|
126
|
+
content.must == <<-TABLE
|
127
|
+
abc #123 first three
|
128
|
+
#0 empty
|
129
|
+
xyz #786 last three
|
130
|
+
TABLE
|
131
|
+
end
|
132
|
+
|
133
|
+
it "prints a table with identation" do
|
134
|
+
content = capture(:stdout){ shell.print_table(@table, :ident => 2) }
|
135
|
+
content.must == <<-TABLE
|
136
|
+
abc #123 first three
|
137
|
+
#0 empty
|
138
|
+
xyz #786 last three
|
139
|
+
TABLE
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "#file_collision" do
|
144
|
+
it "shows a menu with options" do
|
145
|
+
mock($stdout).print('Overwrite foo? (enter "h" for help) [Ynaqh] ')
|
146
|
+
mock($stdin).gets{ 'n' }
|
147
|
+
shell.file_collision('foo')
|
148
|
+
end
|
149
|
+
|
150
|
+
it "returns false if the user choose no" do
|
151
|
+
stub($stdout).print
|
152
|
+
mock($stdin).gets{ 'n' }
|
153
|
+
shell.file_collision('foo').must be_false
|
154
|
+
end
|
155
|
+
|
156
|
+
it "returns true if the user choose yes" do
|
157
|
+
stub($stdout).print
|
158
|
+
mock($stdin).gets{ 'y' }
|
159
|
+
shell.file_collision('foo').must be_true
|
160
|
+
end
|
161
|
+
|
162
|
+
it "shows help usage if the user choose help" do
|
163
|
+
stub($stdout).print
|
164
|
+
mock($stdin).gets{ 'h' }
|
165
|
+
mock($stdin).gets{ 'n' }
|
166
|
+
help = capture(:stdout){ shell.file_collision('foo') }
|
167
|
+
help.must =~ /h \- help, show this help/
|
168
|
+
end
|
169
|
+
|
170
|
+
it "quits if the user choose quit" do
|
171
|
+
stub($stdout).print
|
172
|
+
mock($stdout).puts('Aborting...')
|
173
|
+
mock($stdin).gets{ 'q' }
|
174
|
+
|
175
|
+
lambda {
|
176
|
+
shell.file_collision('foo')
|
177
|
+
}.must raise_error(SystemExit)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "always returns true if the user choose always" do
|
181
|
+
mock($stdout).print('Overwrite foo? (enter "h" for help) [Ynaqh] ')
|
182
|
+
mock($stdin).gets{ 'a' }
|
183
|
+
|
184
|
+
shell.file_collision('foo').must be_true
|
185
|
+
|
186
|
+
dont_allow($stdout).print
|
187
|
+
shell.file_collision('foo').must be_true
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "when a block is given" do
|
191
|
+
it "displays diff options to the user" do
|
192
|
+
mock($stdout).print('Overwrite foo? (enter "h" for help) [Ynaqdh] ')
|
193
|
+
mock($stdin).gets{ 's' }
|
194
|
+
shell.file_collision('foo'){ }
|
195
|
+
end
|
196
|
+
|
197
|
+
it "invokes the diff command" do
|
198
|
+
stub($stdout).print
|
199
|
+
mock($stdin).gets{ 'd' }
|
200
|
+
mock($stdin).gets{ 'n' }
|
201
|
+
mock(shell).system(/diff -u/)
|
202
|
+
capture(:stdout){ shell.file_collision('foo'){ } }
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|