webbynode 1.0.4.3 → 1.0.5.beta2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of webbynode might be problematic. Click here for more details.
- data/Gemfile +2 -0
- data/Gemfile.lock +4 -0
- data/Guardfile +1 -1
- data/Manifest +5 -1
- data/Rakefile +6 -1
- data/lib/webbynode.rb +21 -2
- data/lib/webbynode/command.rb +26 -0
- data/lib/webbynode/commands/accounts.rb +77 -0
- data/lib/webbynode/commands/guides.rb +11 -0
- data/lib/webbynode/commands/help.rb +3 -3
- data/lib/webbynode/commands/init.rb +21 -21
- data/lib/webbynode/commands/push.rb +7 -7
- data/lib/webbynode/commands/remote.rb +6 -2
- data/lib/webbynode/commands/settings.rb +1 -1
- data/lib/webbynode/commands/tasks.rb +3 -3
- data/lib/webbynode/commands/version.rb +1 -1
- data/lib/webbynode/commands/webbies.rb +20 -12
- data/lib/webbynode/engines/rails.rb +8 -5
- data/lib/webbynode/engines/rails3.rb +13 -6
- data/lib/webbynode/io.rb +4 -0
- data/lib/webbynode/notify.rb +1 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/webbynode/commands/accounts_spec.rb +119 -0
- data/spec/webbynode/commands/guides_spec.rb +9 -0
- data/spec/webbynode/commands/init_spec.rb +11 -8
- data/spec/webbynode/commands/remote_spec.rb +3 -3
- data/spec/webbynode/commands/tasks_spec.rb +7 -7
- data/spec/webbynode/commands/version_spec.rb +1 -1
- data/spec/webbynode/engines/html_spec.rb +1 -1
- data/spec/webbynode/engines/rails3_spec.rb +12 -1
- data/spec/webbynode/engines/rails_spec.rb +11 -0
- data/spec/webbynode/io_spec.rb +7 -0
- data/webbynode.gemspec +13 -5
- metadata +33 -8
- data/spec/fixtures/settings.py +0 -94
@@ -34,11 +34,11 @@ module Webbynode::Commands
|
|
34
34
|
perform_before_tasks if before_tasks.has_tasks?
|
35
35
|
|
36
36
|
# Logs a initialization message to the user
|
37
|
-
io.log "Pushing #{app_name}", :start
|
37
|
+
io.log "Pushing #{app_name.color(:cyan)}", :start
|
38
38
|
|
39
39
|
# Checks for server-side updates
|
40
40
|
if check_for_updates
|
41
|
-
io.log "Note: Rapp Engine updated"
|
41
|
+
io.log "Note: Rapp Engine updated".color(:yellow)
|
42
42
|
io.log ""
|
43
43
|
end
|
44
44
|
|
@@ -50,7 +50,7 @@ module Webbynode::Commands
|
|
50
50
|
after_tasks.read_tasks(Webbynode::Commands::Tasks::AfterPushTasksFile)
|
51
51
|
perform_after_tasks if after_tasks.has_tasks?
|
52
52
|
|
53
|
-
io.log "Finished pushing #{app_name}", :finish
|
53
|
+
io.log "Finished pushing #{app_name.color(:cyan)}", :finish
|
54
54
|
end
|
55
55
|
|
56
56
|
|
@@ -58,18 +58,18 @@ module Webbynode::Commands
|
|
58
58
|
|
59
59
|
# Performs the before push tasks locally
|
60
60
|
def perform_before_tasks
|
61
|
-
io.log "Performing Before Push Tasks...", :action
|
61
|
+
io.log "Performing #{"Before Push".color(:yellow)} Tasks...", :action
|
62
62
|
before_tasks.session_tasks.each do |task|
|
63
|
-
io.log " Performing Task: #{task}", :action
|
63
|
+
io.log " Performing Task: #{task.color(:cyan)}", :action
|
64
64
|
io.exec(task)
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
68
|
# Performs the after push tasks remotely from the application root
|
69
69
|
def perform_after_tasks
|
70
|
-
io.log "Performing After Push Tasks...", :action
|
70
|
+
io.log "Performing #{"After Push".color(:yellow)} Tasks...", :action
|
71
71
|
after_tasks.session_tasks.each do |task|
|
72
|
-
io.log " Performing Task: #{task}", :action
|
72
|
+
io.log " Performing Task: #{task.color(:cyan)}", :action
|
73
73
|
remote_executor.exec("cd #{pushand.parse_remote_app_name}; #{task}", true)
|
74
74
|
end
|
75
75
|
end
|
@@ -19,10 +19,14 @@ module Webbynode::Commands
|
|
19
19
|
remote_app_name = pushand.parse_remote_app_name
|
20
20
|
|
21
21
|
# Notify the user
|
22
|
-
io.log
|
22
|
+
io.log "Executing remote command...".color(:cyan)
|
23
23
|
|
24
24
|
# Executes the command on the remote server inside the application root folder
|
25
|
-
|
25
|
+
result = spinner {
|
26
|
+
remote_executor.exec("cd #{remote_app_name}; #{param_values.join(" ")}", false)
|
27
|
+
}
|
28
|
+
|
29
|
+
puts result
|
26
30
|
end
|
27
31
|
end
|
28
32
|
end
|
@@ -117,11 +117,11 @@ module Webbynode::Commands
|
|
117
117
|
def show_tasks(from_file = false)
|
118
118
|
read_tasks(session_file, true) if from_file
|
119
119
|
if session_tasks.empty?
|
120
|
-
io.log_and_exit "You haven't set up any
|
120
|
+
io.log_and_exit "You haven't set up any #{type.gsub('_',' ').capitalize.color(:yellow)} tasks yet."
|
121
121
|
end
|
122
|
-
io.log "
|
122
|
+
io.log "#{type.gsub('_',' ').capitalize.color(:yellow)} tasks:"
|
123
123
|
session_tasks.each_with_index do |task, index|
|
124
|
-
io.log "[#{index}] #{task}"
|
124
|
+
io.log "[#{index}] #{task.color(:cyan)}"
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
@@ -2,7 +2,7 @@ module Webbynode::Commands
|
|
2
2
|
class Version < Webbynode::Command
|
3
3
|
summary "Displays current version of Webbynode Gem"
|
4
4
|
def execute
|
5
|
-
io.log "Rapid Deployment Gem v#{Webbynode::VERSION}"
|
5
|
+
io.log "#{"Rapid Deployment Gem".color(:white).bright} v#{Webbynode::VERSION.color(:yellow)}"
|
6
6
|
end
|
7
7
|
end
|
8
8
|
end
|
@@ -1,28 +1,36 @@
|
|
1
1
|
module Webbynode::Commands
|
2
2
|
class Webbies < Webbynode::Command
|
3
3
|
summary "Lists the Webbies you currently own"
|
4
|
+
add_alias "list"
|
4
5
|
|
5
6
|
def execute
|
6
7
|
puts "Fetching list of your Webbies..."
|
7
8
|
puts ""
|
8
9
|
|
9
10
|
header = " "
|
10
|
-
header << "Webbies".ljust(
|
11
|
-
header << "
|
12
|
-
header << "
|
13
|
-
header << "
|
14
|
-
header << "
|
11
|
+
header << "Webbies".ljust(15).color(:white).bright.underline
|
12
|
+
header << " "
|
13
|
+
header << "IP".ljust(15).color(:white).bright.underline
|
14
|
+
header << " "
|
15
|
+
header << "Node".ljust(11).color(:white).bright.underline
|
16
|
+
header << " "
|
17
|
+
header << "Plan".ljust(15).color(:white).bright.underline
|
18
|
+
header << " "
|
19
|
+
header << "Status".ljust(14).color(:white).bright.underline
|
20
|
+
header << " "
|
15
21
|
|
16
22
|
puts header
|
23
|
+
|
24
|
+
webbies = spinner { api.webbies }
|
17
25
|
|
18
|
-
|
26
|
+
webbies.each_pair do |name, webby|
|
19
27
|
str = " "
|
20
|
-
str << name.ljust(16)
|
21
|
-
str << webby['ip'].ljust(16)
|
22
|
-
str << webby['node'].ljust(
|
23
|
-
str << webby['plan'].ljust(16)
|
24
|
-
str << webby['status']
|
25
|
-
|
28
|
+
str << name.ljust(16).color(:yellow).bright
|
29
|
+
str << webby['ip'].ljust(16).color(:cyan).bright
|
30
|
+
str << webby['node'].ljust(12).color(:cyan).bright
|
31
|
+
str << webby['plan'].ljust(16).color(:cyan).bright
|
32
|
+
str << (webby['status'] == 'on' ? "on".color(:cyan).bright : "off")
|
33
|
+
|
26
34
|
puts str
|
27
35
|
end
|
28
36
|
end
|
@@ -10,12 +10,15 @@ module Webbynode::Engines
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def prepare
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
if io.file_exists?("config/database.yml")
|
14
|
+
contents = io.read_file("config/database.yml")
|
15
|
+
if contents =~ /mysql2/
|
16
|
+
io.add_setting "rails_adapter", "mysql2"
|
17
|
+
return
|
18
|
+
end
|
18
19
|
end
|
20
|
+
|
21
|
+
io.remove_setting "rails_adapter"
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
@@ -15,15 +15,22 @@ module Webbynode::Engines
|
|
15
15
|
|
16
16
|
private
|
17
17
|
|
18
|
+
def handle_adapter
|
19
|
+
if io.file_exists?("config/database.yml")
|
20
|
+
contents = io.read_file("config/database.yml")
|
21
|
+
if contents =~ /mysql2/
|
22
|
+
io.add_setting "rails3_adapter", "mysql2"
|
23
|
+
return
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
io.remove_setting "rails3_adapter"
|
28
|
+
end
|
29
|
+
|
18
30
|
def check_gemfile
|
19
31
|
return unless gemfile.present?
|
20
32
|
|
21
|
-
|
22
|
-
if contents =~ /mysql2/
|
23
|
-
io.add_setting "rails3_adapter", "mysql2"
|
24
|
-
else
|
25
|
-
io.remove_setting "rails3_adapter"
|
26
|
-
end
|
33
|
+
handle_adapter
|
27
34
|
|
28
35
|
dependencies = gemfile.dependencies(:without => [:development, :test])
|
29
36
|
if dependencies.include? 'sqlite3-ruby'
|
data/lib/webbynode/io.rb
CHANGED
data/lib/webbynode/notify.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,119 @@
|
|
1
|
+
# Load Spec Helper
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'spec_helper')
|
3
|
+
|
4
|
+
describe Webbynode::Commands::Accounts do
|
5
|
+
let(:api) { double("API") }
|
6
|
+
let(:io) { double("Io").as_null_object }
|
7
|
+
|
8
|
+
def prepare(*params)
|
9
|
+
Webbynode::Commands::Accounts.new(*params).tap do |a|
|
10
|
+
a.stub(:api).and_return(api)
|
11
|
+
a.stub(:io).and_return(io)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#default' do
|
16
|
+
subject { prepare nil }
|
17
|
+
|
18
|
+
it "shows current account" do
|
19
|
+
api.should_receive(:credentials).and_return({"email" => "fcoury@me.com", "token" => "apitoken"})
|
20
|
+
io.should_receive(:log).with("Current account: fcoury@me.com")
|
21
|
+
subject.execute
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#list' do
|
26
|
+
subject { prepare "list" }
|
27
|
+
|
28
|
+
it "shows all available accounts" do
|
29
|
+
io.should_receive(:list_files).with("#{Webbynode::Io.home_dir}/.webbynode_*").and_return(["#{Webbynode::Io.home_dir}/.webbynode_personal", "#{Webbynode::Io.home_dir}/.webbynode_biz"])
|
30
|
+
io.should_receive(:log).with("personal")
|
31
|
+
io.should_receive(:log).with("biz")
|
32
|
+
subject.execute
|
33
|
+
end
|
34
|
+
|
35
|
+
it "tells when no configs found" do
|
36
|
+
io.should_receive(:list_files).with("#{Webbynode::Io.home_dir}/.webbynode_*").and_return([])
|
37
|
+
io.should_receive(:log).with("No accounts found. Use 'wn accounts save' to save current account with an alias.")
|
38
|
+
subject.execute
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#save' do
|
43
|
+
subject { prepare "save", "name" }
|
44
|
+
|
45
|
+
it "copies the properties file" do
|
46
|
+
io.should_receive(:file_exists?).with("#{Webbynode::Io.home_dir}/.webbynode_name").and_return(false)
|
47
|
+
io.should_receive(:copy_file).with("#{Webbynode::Io.home_dir}/.webbynode", "#{Webbynode::Io.home_dir}/.webbynode_name")
|
48
|
+
subject.execute
|
49
|
+
end
|
50
|
+
|
51
|
+
context "file exists" do
|
52
|
+
context "when confirms overwriting" do
|
53
|
+
it "overwrites the file" do
|
54
|
+
io.should_receive(:file_exists?).with("#{Webbynode::Io.home_dir}/.webbynode_name").and_return(true)
|
55
|
+
subject.should_receive(:ask).with("Do you want to overwrite saved account name (y/n)? ").once.ordered.and_return("y")
|
56
|
+
io.should_receive(:copy_file).with("#{Webbynode::Io.home_dir}/.webbynode", "#{Webbynode::Io.home_dir}/.webbynode_name")
|
57
|
+
|
58
|
+
subject.execute
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when aborts overwriting" do
|
63
|
+
it "doesn't overwrite the file" do
|
64
|
+
io.should_receive(:file_exists?).with("#{Webbynode::Io.home_dir}/.webbynode_name").and_return(true)
|
65
|
+
subject.should_receive(:ask).with("Do you want to overwrite saved account name (y/n)? ").once.ordered.and_return("n")
|
66
|
+
io.should_receive(:copy_file).with("#{Webbynode::Io.home_dir}/.webbynode", "#{Webbynode::Io.home_dir}/.webbynode_name").never
|
67
|
+
io.should_receive(:log).with("Save aborted.")
|
68
|
+
|
69
|
+
subject.execute
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#use' do
|
76
|
+
subject { prepare "use", "name" }
|
77
|
+
|
78
|
+
it "renames the properties file" do
|
79
|
+
io.should_receive(:file_exists?).with("#{Webbynode::Io.home_dir}/.webbynode_name").and_return(true)
|
80
|
+
io.should_receive(:copy_file).with("#{Webbynode::Io.home_dir}/.webbynode_name", "#{Webbynode::Io.home_dir}/.webbynode")
|
81
|
+
subject.execute
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when file doesn't exist" do
|
85
|
+
it "shows an error message" do
|
86
|
+
io.should_receive(:file_exists?).with("#{Webbynode::Io.home_dir}/.webbynode_name").and_return(false)
|
87
|
+
io.should_receive(:log).with("Account alias 'name' not found. Use 'wn account list' for a full list.")
|
88
|
+
subject.execute
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '#new' do
|
94
|
+
subject { prepare "new" }
|
95
|
+
|
96
|
+
it "reinitializes the account" do
|
97
|
+
api.should_receive(:init_credentials).with(true)
|
98
|
+
subject.execute
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#delete' do
|
103
|
+
subject { prepare "delete", "name" }
|
104
|
+
|
105
|
+
it "deletes the account" do
|
106
|
+
io.should_receive(:file_exists?).with("#{Webbynode::Io.home_dir}/.webbynode_name").and_return(true)
|
107
|
+
io.should_receive(:delete_file).with("#{Webbynode::Io.home_dir}/.webbynode_name")
|
108
|
+
subject.execute
|
109
|
+
end
|
110
|
+
|
111
|
+
context "when account doesn't exist" do
|
112
|
+
it "shows an error" do
|
113
|
+
io.should_receive(:file_exists?).with("#{Webbynode::Io.home_dir}/.webbynode_name").and_return(false)
|
114
|
+
io.should_receive(:log).with("Account alias 'name' not found. Use 'wn account list' for a full list.")
|
115
|
+
subject.execute
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Load Spec Helper
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'spec_helper')
|
3
|
+
|
4
|
+
describe Webbynode::Commands::Guides do
|
5
|
+
it "opens Rapp guides in browser" do
|
6
|
+
Launchy.should_receive(:open).with('http://wbno.de/rapp')
|
7
|
+
subject.execute
|
8
|
+
end
|
9
|
+
end
|
@@ -201,14 +201,16 @@ describe Webbynode::Commands::Init do
|
|
201
201
|
context "when no engine was detected" do
|
202
202
|
it "prompts for the engine" do
|
203
203
|
io_handler.should_receive(:log).with("Supported engines:")
|
204
|
-
io_handler.should_receive(:log).with(" 1.
|
205
|
-
io_handler.should_receive(:log).with(" 2.
|
206
|
-
io_handler.should_receive(:log).with(" 3.
|
207
|
-
io_handler.should_receive(:log).with(" 4.
|
208
|
-
io_handler.should_receive(:log).with(" 5.
|
209
|
-
io_handler.should_receive(:log).with(" 6. Rails
|
204
|
+
io_handler.should_receive(:log).with(" 1. Html")
|
205
|
+
io_handler.should_receive(:log).with(" 2. Django")
|
206
|
+
io_handler.should_receive(:log).with(" 3. WSGI")
|
207
|
+
io_handler.should_receive(:log).with(" 4. PHP")
|
208
|
+
io_handler.should_receive(:log).with(" 5. Rack")
|
209
|
+
io_handler.should_receive(:log).with(" 6. Rails 2")
|
210
|
+
io_handler.should_receive(:log).with(" 7. Rails 3")
|
211
|
+
io_handler.should_receive(:log).with(" 8. NodeJS")
|
210
212
|
|
211
|
-
subject.should_receive(:ask).with('Select the engine your app uses:', Integer).and_return(
|
213
|
+
subject.should_receive(:ask).with('Select the engine your app uses:', Integer).and_return(2)
|
212
214
|
|
213
215
|
io_handler.should_receive(:add_setting).with("engine", "django")
|
214
216
|
io_handler.should_receive(:log).with("Initializing with Django engine...")
|
@@ -267,6 +269,7 @@ describe Webbynode::Commands::Init do
|
|
267
269
|
io.stub(:file_exists?).with("script/rails").and_return(false)
|
268
270
|
io.stub(:directory?).with('app').and_return(true)
|
269
271
|
io.stub(:directory?).with('app/controllers').and_return(true)
|
272
|
+
io.stub(:file_exists?).with('config/database.yml').and_return(false)
|
270
273
|
io.stub(:file_exists?).with('config/environment.rb').and_return(true)
|
271
274
|
|
272
275
|
Webbynode::Io.stub(:new).and_return(io)
|
@@ -731,7 +734,7 @@ describe Webbynode::Commands::Init do
|
|
731
734
|
git_handler.should_receive(:clean?).and_return(false)
|
732
735
|
|
733
736
|
lambda { @command.execute }.should raise_error(Webbynode::Command::CommandError,
|
734
|
-
"Cannot initialize: git has pending changes
|
737
|
+
"Cannot initialize: git has pending changes.\nExecute a git commit or add changes to .gitignore and try again.")
|
735
738
|
end
|
736
739
|
|
737
740
|
it "shows that a commit is being added" do
|
@@ -24,7 +24,7 @@ describe Webbynode::Commands::Remote do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should notify the user" do
|
27
|
-
io.should_receive(:log).with("
|
27
|
+
io.should_receive(:log).with("Executing remote command...")
|
28
28
|
remote.run
|
29
29
|
end
|
30
30
|
|
@@ -44,7 +44,7 @@ describe Webbynode::Commands::Remote do
|
|
44
44
|
remote.stub(:validate_initialization)
|
45
45
|
load_all_mocks(remote)
|
46
46
|
pushand.should_receive(:parse_remote_app_name).and_return('test.webbynode.com')
|
47
|
-
re.should_receive(:exec).with("cd test.webbynode.com; ls -la",
|
47
|
+
re.should_receive(:exec).with("cd test.webbynode.com; ls -la", false)
|
48
48
|
remote.run
|
49
49
|
end
|
50
50
|
|
@@ -55,7 +55,7 @@ describe Webbynode::Commands::Remote do
|
|
55
55
|
remote.stub(:validate_initialization)
|
56
56
|
remote.stub(:validate_remote_application_availability)
|
57
57
|
|
58
|
-
re.should_receive(:exec).with("cd webbynode; these are the params",
|
58
|
+
re.should_receive(:exec).with("cd webbynode; these are the params", false).and_return("something")
|
59
59
|
remote.run
|
60
60
|
end
|
61
61
|
|
@@ -186,15 +186,15 @@ describe Webbynode::Commands::Tasks do
|
|
186
186
|
end
|
187
187
|
|
188
188
|
it "should display no tasks, since there are none initially" do
|
189
|
-
io.should_receive(:log).with("
|
190
|
-
io.should_not_receive(:log)
|
189
|
+
io.should_receive(:log).with("After push tasks:")
|
190
|
+
# io.should_not_receive(:log)
|
191
191
|
stask.execute
|
192
192
|
stask.should have(0).session_tasks
|
193
193
|
end
|
194
194
|
|
195
195
|
it "should display 3 tasks: task0 task1 task2" do
|
196
196
|
3.times {|num| stask.session_tasks << "task#{num}"}
|
197
|
-
io.should_receive(:log).with("
|
197
|
+
io.should_receive(:log).with("After push tasks:")
|
198
198
|
stask.stub!(:read_tasks)
|
199
199
|
io.should_not_receive(:log_and_exit)
|
200
200
|
io.should_receive(:log).with("[0] task0")
|
@@ -206,8 +206,8 @@ describe Webbynode::Commands::Tasks do
|
|
206
206
|
|
207
207
|
it "should tell the user that there are no tasks if there aren't any" do
|
208
208
|
stask.stub!(:read_tasks)
|
209
|
-
io.should_receive(:log_and_exit).with("You haven't set up any
|
210
|
-
io.should_not_receive(:log).with("
|
209
|
+
io.should_receive(:log_and_exit).with("You haven't set up any After push tasks yet.")
|
210
|
+
# io.should_not_receive(:log).with("After push tasks:")
|
211
211
|
stask.execute
|
212
212
|
end
|
213
213
|
end
|
@@ -241,7 +241,7 @@ describe Webbynode::Commands::Tasks do
|
|
241
241
|
end
|
242
242
|
|
243
243
|
it "should display the updated list of tasks" do
|
244
|
-
io.should_receive(:log).with("
|
244
|
+
io.should_receive(:log).with("After push tasks:")
|
245
245
|
io.should_receive(:log).with("[0] rake db:migrate RAILS_ENV=production")
|
246
246
|
task.execute
|
247
247
|
end
|
@@ -274,7 +274,7 @@ describe Webbynode::Commands::Tasks do
|
|
274
274
|
it "should display the updated list of tasks" do
|
275
275
|
3.times {|num| rtask.session_tasks << "task#{num}" }
|
276
276
|
rtask.stub(:read_tasks)
|
277
|
-
io.should_receive(:log).with("
|
277
|
+
io.should_receive(:log).with("After push tasks:")
|
278
278
|
io.should_receive(:log).with("[0] task0")
|
279
279
|
io.should_not_receive(:log).with("[1] task1")
|
280
280
|
io.should_receive(:log).with("[1] task2")
|