ppl 0.0.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/.gitignore +2 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +7 -3
  5. data/Gemfile.lock +15 -7
  6. data/README.md +47 -34
  7. data/bin/ppl +7 -6
  8. data/lib/ppl/adapter/storage/disk.rb +40 -0
  9. data/lib/ppl/adapter/storage.rb +28 -0
  10. data/lib/ppl/adapter/vcard/vpim.rb +45 -0
  11. data/lib/ppl/adapter/vcard.rb +13 -0
  12. data/lib/ppl/application/bootstrap.rb +62 -0
  13. data/lib/ppl/application/command.rb +13 -0
  14. data/lib/ppl/application/command_suite.rb +25 -0
  15. data/lib/ppl/application/input.rb +13 -0
  16. data/lib/ppl/application/output.rb +21 -0
  17. data/lib/ppl/application/router.rb +19 -0
  18. data/lib/ppl/application/shell.rb +34 -0
  19. data/lib/ppl/command/command_list.rb +21 -0
  20. data/lib/ppl/command/contact_add.rb +26 -0
  21. data/lib/ppl/command/contact_delete.rb +16 -0
  22. data/lib/ppl/command/contact_list.rb +24 -0
  23. data/lib/ppl/command/contact_rename.rb +23 -0
  24. data/lib/ppl/command/contact_show.rb +20 -0
  25. data/lib/ppl/entity/address_book.rb +21 -0
  26. data/lib/ppl/entity/contact.rb +10 -0
  27. data/lib/ppl/error/contact_not_found.rb +4 -0
  28. data/lib/ppl/error/incorrect_usage.rb +4 -0
  29. data/lib/ppl.rb +51 -11
  30. data/ppl.gemspec +3 -3
  31. data/spec/ppl/adapter/output_spec.rb +43 -0
  32. data/spec/ppl/adapter/storage/disk_spec.rb +83 -0
  33. data/spec/ppl/adapter/storage_spec.rb +46 -0
  34. data/spec/ppl/adapter/vcard/vpim_spec.rb +77 -0
  35. data/spec/ppl/adapter/vcard_spec.rb +24 -0
  36. data/spec/ppl/application/bootstrap_spec.rb +88 -0
  37. data/spec/ppl/application/command_spec.rb +19 -0
  38. data/spec/ppl/application/command_suite_spec.rb +44 -0
  39. data/spec/ppl/application/input_spec.rb +21 -0
  40. data/spec/ppl/application/router_spec.rb +43 -0
  41. data/spec/ppl/application/shell_spec.rb +79 -0
  42. data/spec/ppl/command/command_list_spec.rb +37 -0
  43. data/spec/ppl/command/contact_add_spec.rb +41 -0
  44. data/spec/ppl/command/contact_delete_spec.rb +31 -0
  45. data/spec/ppl/command/contact_list_spec.rb +15 -0
  46. data/spec/ppl/command/contact_rename_spec.rb +42 -0
  47. data/spec/ppl/command/contact_show_spec.rb +35 -0
  48. data/spec/ppl/entity/address_book_spec.rb +26 -0
  49. data/spec/ppl/entity/contact_spec.rb +34 -0
  50. data/spec/spec_helper.rb +9 -0
  51. metadata +47 -14
  52. data/lib/ppl/address_book.rb +0 -74
  53. data/lib/ppl/cli.rb +0 -49
  54. data/lib/ppl/command/add.rb +0 -40
  55. data/lib/ppl/command/birthdays.rb +0 -34
  56. data/lib/ppl/command/help.rb +0 -32
  57. data/lib/ppl/command/list.rb +0 -31
  58. data/lib/ppl/command/rm.rb +0 -38
  59. data/lib/ppl/command/set.rb +0 -49
  60. data/lib/ppl/command/show.rb +0 -43
  61. data/lib/ppl/command.rb +0 -55
  62. data/lib/ppl/contact.rb +0 -43
@@ -0,0 +1,10 @@
1
+
2
+ class Ppl::Entity::Contact
3
+
4
+ attr_accessor :id
5
+ attr_accessor :name
6
+ attr_accessor :email_address
7
+ attr_accessor :birthday
8
+
9
+ end
10
+
@@ -0,0 +1,4 @@
1
+
2
+ class Ppl::Error::ContactNotFound < StandardError
3
+ end
4
+
@@ -0,0 +1,4 @@
1
+
2
+ class Ppl::Error::IncorrectUsage < StandardError
3
+ end
4
+
data/lib/ppl.rb CHANGED
@@ -1,16 +1,56 @@
1
1
 
2
2
  module Ppl
3
+
4
+ Version = "0.2.0"
5
+
6
+ module Adapter
7
+ end
8
+
9
+ module Application
10
+ end
11
+
12
+ module Command
13
+ end
14
+
15
+ module Entity
16
+ end
17
+
18
+ module Error
19
+ end
20
+
21
+ module Factory
22
+ end
23
+
3
24
  end
4
25
 
5
- require "ppl/address_book"
6
- require "ppl/contact"
7
- require "ppl/cli"
8
- require "ppl/command"
9
- require "ppl/command/add"
10
- require "ppl/command/birthdays"
11
- require "ppl/command/help"
12
- require "ppl/command/list"
13
- require "ppl/command/rm"
14
- require "ppl/command/set"
15
- require "ppl/command/show"
26
+
27
+ require "ppl/adapter/storage"
28
+ require "ppl/adapter/storage/disk"
29
+ require "ppl/adapter/vcard"
30
+ require "ppl/adapter/vcard/vpim"
31
+
32
+ require "ppl/application/bootstrap"
33
+ require "ppl/application/command"
34
+ require "ppl/application/command_suite"
35
+ require "ppl/application/input"
36
+ require "ppl/application/output"
37
+ require "ppl/application/router"
38
+ require "ppl/application/shell"
39
+
40
+ require "ppl/command/command_list"
41
+ require "ppl/command/contact_add"
42
+ require "ppl/command/contact_delete"
43
+ require "ppl/command/contact_list"
44
+ require "ppl/command/contact_show"
45
+ require "ppl/command/contact_rename"
46
+
47
+ require "ppl/entity/address_book"
48
+ require "ppl/entity/contact"
49
+
50
+ require "ppl/error/contact_not_found"
51
+ require "ppl/error/incorrect_usage"
52
+
53
+ class String
54
+ alias_method :each, :each_line
55
+ end
16
56
 
data/ppl.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
  Gem::Specification.new do |spec|
3
3
 
4
4
  spec.name = "ppl"
5
- spec.version = "0.0.5"
6
- spec.date = "2012-11-13"
5
+ spec.version = "0.2.0"
6
+ spec.date = "2012-11-23"
7
7
 
8
8
  spec.summary = "CLI Address Book"
9
- spec.description = "Command-line driven address book"
9
+ spec.description = "CLI Address Book"
10
10
  spec.license = "GPL-2"
11
11
 
12
12
  spec.authors = ["Henry Smith"]
@@ -0,0 +1,43 @@
1
+
2
+ describe Ppl::Application::Output, "#initialize" do
3
+
4
+ it "should accept stdout" do
5
+ stdout = Object.new
6
+ @output = Ppl::Application::Output.new(stdout, nil)
7
+ @output.stdout.should be stdout
8
+ end
9
+
10
+ it "should accept stderr" do
11
+ stderr = Object.new
12
+ @output = Ppl::Application::Output.new(nil, stderr)
13
+ @output.stderr.should be stderr
14
+ end
15
+
16
+ end
17
+
18
+ describe Ppl::Application::Output do
19
+
20
+ before(:each) do
21
+ @stderr = double(IO)
22
+ @stdout = double(IO)
23
+ @output = Ppl::Application::Output.new(@stdout, @stderr)
24
+ end
25
+
26
+ describe "#error" do
27
+ it "should delegate to stderr's puts method" do
28
+ string = "COMPUTER OVER. VIRUS = VERY YES"
29
+ @stderr.should_receive(:puts).with(string)
30
+ @output.error(string)
31
+ end
32
+ end
33
+
34
+ describe "#line" do
35
+ it "should delegate to stdout's puts method" do
36
+ string = "The quick brown fox"
37
+ @stdout.should_receive(:puts).with(string)
38
+ @output.line(string)
39
+ end
40
+ end
41
+
42
+ end
43
+
@@ -0,0 +1,83 @@
1
+
2
+ describe Ppl::Adapter::Storage::Disk, "#initialize" do
3
+
4
+ it "should accept a path" do
5
+ @storage = Ppl::Adapter::Storage::Disk.new("/tmp")
6
+ @storage.path.should eq "/tmp"
7
+ end
8
+
9
+ end
10
+
11
+ describe Ppl::Adapter::Storage::Disk do
12
+
13
+ before(:each) do
14
+ @storage = Ppl::Adapter::Storage::Disk.new(nil)
15
+ end
16
+
17
+ describe "#vcard_adapter=" do
18
+ it "should accept a vcard adapter" do
19
+ adapter = double(Ppl::Adapter::Vcard)
20
+ @storage.vcard_adapter = adapter
21
+ @storage.vcard_adapter.should be adapter
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ describe Ppl::Adapter::Storage::Disk do
28
+
29
+ before(:each) do
30
+ @storage = Ppl::Adapter::Storage::Disk.new("/contacts")
31
+ @adapter = double(Ppl::Adapter::Vcard)
32
+ @contact = Ppl::Entity::Contact.new
33
+ @storage.vcard_adapter = @adapter
34
+
35
+ FakeFS.activate!
36
+ Dir.mkdir "/contacts"
37
+ end
38
+
39
+ after(:each) do
40
+ FileUtils.rm_rf "/contacts"
41
+ FakeFS.deactivate!
42
+ end
43
+
44
+ describe "#load_address_book" do
45
+
46
+ it "should return a Ppl::Entity::AddressBook" do
47
+ @storage.load_address_book.should be_a(Ppl::Entity::AddressBook)
48
+ end
49
+
50
+ it "should fill the address book with the contacts in the directory" do
51
+ FileUtils.touch "/contacts/one.vcf"
52
+ FileUtils.touch "/contacts/two.vcf"
53
+
54
+ @adapter.should_receive(:decode).twice
55
+
56
+ address_book = @storage.load_address_book
57
+ address_book.count.should eq 2
58
+ end
59
+
60
+ end
61
+
62
+ describe "#load_contact" do
63
+
64
+ it "should return nil if the given contact doesn't exist" do
65
+ @storage.load_contact("xyz").should be nil
66
+ end
67
+
68
+ it "should return a Ppl::Entity::Contact" do
69
+ FileUtils.touch "/contacts/one.vcf"
70
+ @adapter.should_receive(:decode).once.and_return(@contact)
71
+ @storage.load_contact("one").should be_a(Ppl::Entity::Contact)
72
+ end
73
+
74
+ it "should populate the contact's id" do
75
+ FileUtils.touch "/contacts/one.vcf"
76
+ @adapter.should_receive(:decode).once.and_return(@contact)
77
+ @storage.load_contact("one").id.should eq "one"
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
@@ -0,0 +1,46 @@
1
+
2
+ describe Ppl::Adapter::Storage do
3
+
4
+ before(:each) do
5
+ @storage = Ppl::Adapter::Storage.new
6
+ end
7
+
8
+ describe "#delete_contact" do
9
+ it "should raise not implemented error" do
10
+ expect{@storage.delete_contact(nil)}.to raise_error(NotImplementedError)
11
+ end
12
+ end
13
+
14
+ describe "#load_address_book" do
15
+ it "should raise not implemented error" do
16
+ expect{@storage.load_address_book}.to raise_error(NotImplementedError)
17
+ end
18
+ end
19
+
20
+ describe "#load_contact" do
21
+ it "should raise not implemented error" do
22
+ expect{@storage.load_contact(nil)}.to raise_error(NotImplementedError)
23
+ end
24
+ end
25
+
26
+ describe "#require_contact" do
27
+
28
+ it "should raise Ppl::Error::ContactNotFound if load fails" do
29
+ @storage.stub(:load_contact) do |id| end
30
+ expect{@storage.require_contact("joe")}.to raise_error(Ppl::Error::ContactNotFound)
31
+ end
32
+
33
+ it "should return the loaded contact" do
34
+ @storage.stub(:load_contact) do |id| Object.new end
35
+ @storage.require_contact("joe").should be_an(Object)
36
+ end
37
+ end
38
+
39
+ describe "#save_contact" do
40
+ it "should raise not implemented error" do
41
+ expect{@storage.save_contact(nil)}.to raise_error(NotImplementedError)
42
+ end
43
+ end
44
+
45
+ end
46
+
@@ -0,0 +1,77 @@
1
+
2
+ describe Ppl::Adapter::Vcard::Vpim, "#encode" do
3
+
4
+ before(:each) do
5
+ @adapter = Ppl::Adapter::Vcard::Vpim.new
6
+ @contact = Ppl::Entity::Contact.new
7
+ @contact.id = "test"
8
+ end
9
+
10
+ it "should encode the contact's birthday" do
11
+ @contact.birthday = Date.parse "2000-01-01"
12
+ @adapter.encode(@contact).should include("BDAY:20000101")
13
+ end
14
+
15
+ it "should encode the contact's name" do
16
+ @contact.name = "John Doe"
17
+ @adapter.encode(@contact).should include("FN:John Doe")
18
+ end
19
+
20
+ end
21
+
22
+
23
+ describe Ppl::Adapter::Vcard::Vpim, "#decode" do
24
+
25
+ before(:each) do
26
+ @adapter = Ppl::Adapter::Vcard::Vpim.new
27
+ end
28
+
29
+ it "should return a Ppl::Entity::Contact" do
30
+ vcard = [
31
+ "BEGIN:VCARD",
32
+ "VERSION:3.0",
33
+ "N:,test",
34
+ "END:VCARD",
35
+ ].join("\n")
36
+ @adapter.decode(vcard).should be_a(Ppl::Entity::Contact)
37
+ end
38
+
39
+ it "should decode the contact's birthday" do
40
+ vcard = [
41
+ "BEGIN:VCARD",
42
+ "VERSION:3.0",
43
+ "N:,test",
44
+ "BDAY:20120102",
45
+ "END:VCARD",
46
+ ].join("\n")
47
+ @adapter.decode(vcard).birthday.strftime('%Y-%m-%d').should eq "2012-01-02"
48
+ end
49
+
50
+ it "should decode the contact's name" do
51
+
52
+ vcard = [
53
+ "BEGIN:VCARD",
54
+ "VERSION:3.0",
55
+ "N:,test",
56
+ "FN:John Doe",
57
+ "END:VCARD",
58
+ ].join("\n")
59
+ contact = @adapter.decode(vcard)
60
+
61
+ contact.name.should eq "John Doe"
62
+ end
63
+
64
+ it "should decode the contact's email address" do
65
+ vcard = [
66
+ "BEGIN:VCARD",
67
+ "N:,test",
68
+ "VERSION:3.0",
69
+ "EMAIL;TYPE=home:home@example.org",
70
+ "END:VCARD",
71
+ ].join("\n")
72
+ contact = @adapter.decode(vcard)
73
+ contact.email_address.should eq "home@example.org"
74
+ end
75
+
76
+ end
77
+
@@ -0,0 +1,24 @@
1
+
2
+ describe Ppl::Adapter::Vcard, "#encode" do
3
+
4
+ describe "#encode" do
5
+ before(:each) do
6
+ @adapter = Ppl::Adapter::Vcard.new
7
+ end
8
+ it "should raise not implemented error" do
9
+ expect{@adapter.encode(nil)}.to raise_error(NotImplementedError)
10
+ end
11
+ end
12
+
13
+
14
+ describe "#decode" do
15
+ before(:each) do
16
+ @adapter = Ppl::Adapter::Vcard.new
17
+ end
18
+ it "should raise not implemented error" do
19
+ expect{@adapter.decode(nil)}.to raise_error(NotImplementedError)
20
+ end
21
+ end
22
+
23
+ end
24
+
@@ -0,0 +1,88 @@
1
+
2
+ describe Ppl::Application::Bootstrap do
3
+
4
+ before(:each) do
5
+ @bootstrap = Ppl::Application::Bootstrap.new
6
+ end
7
+
8
+ describe "#commands" do
9
+ it "should return an array" do
10
+ @bootstrap.commands.should be_an(Array)
11
+ end
12
+ it "should return commands" do
13
+ @bootstrap.commands.each do |command|
14
+ command.should be_a(Ppl::Application::Command)
15
+ end
16
+ end
17
+ it "should inject a storage adapter into each command" do
18
+ @bootstrap.commands.each do |command|
19
+ command.storage.should be_a(Ppl::Adapter::Storage)
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "#command_suite" do
25
+ it "should return a Ppl::Application::CommandSuite" do
26
+ @bootstrap.command_suite.should be_a(Ppl::Application::CommandSuite)
27
+ end
28
+ it "should contain the 'add' command" do
29
+ @bootstrap.command_suite.find_command("add").should_not be nil
30
+ end
31
+ it "should contain the 'ls' command" do
32
+ @bootstrap.command_suite.find_command("ls").should_not be nil
33
+ end
34
+ it "should contain the 'mv' command" do
35
+ @bootstrap.command_suite.find_command("mv").should_not be nil
36
+ end
37
+ it "should contain the 'rm' command" do
38
+ @bootstrap.command_suite.find_command("rm").should_not be nil
39
+ end
40
+ it "should contain the 'show' command" do
41
+ @bootstrap.command_suite.find_command("show").should_not be nil
42
+ end
43
+ it "should contain the 'help' command" do
44
+ @bootstrap.command_suite.find_command("help").should_not be nil
45
+ end
46
+ end
47
+
48
+ describe "#input" do
49
+ it "should return a Ppl::Application::Input" do
50
+ @bootstrap.input.should be_a(Ppl::Application::Input)
51
+ end
52
+ end
53
+
54
+ describe "#output" do
55
+ it "should return a Ppl::Application::Output" do
56
+ @bootstrap.output.should be_a(Ppl::Application::Output)
57
+ end
58
+ end
59
+
60
+ describe "#router" do
61
+ it "should return a Ppl::Application::Router" do
62
+ @bootstrap.router.should be_a(Ppl::Application::Router)
63
+ end
64
+ it "should set the 'help' command as the default" do
65
+ @bootstrap.router.default.should eq "help"
66
+ end
67
+ end
68
+
69
+ describe "#shell" do
70
+ it "should return a Ppl::Application::Shell" do
71
+ @bootstrap.shell.should be_a(Ppl::Application::Shell)
72
+ end
73
+ end
74
+
75
+ describe "#storage_adapter" do
76
+ it "should return a Ppl::Adapter::Storage::Disk" do
77
+ @bootstrap.storage_adapter.should be_a(Ppl::Adapter::Storage::Disk)
78
+ end
79
+ end
80
+
81
+ describe "#vcard_adapter" do
82
+ it "should return a Ppl::Adapter::Vcard::Vpim" do
83
+ @bootstrap.vcard_adapter.should be_a(Ppl::Adapter::Vcard::Vpim)
84
+ end
85
+ end
86
+
87
+ end
88
+
@@ -0,0 +1,19 @@
1
+
2
+ describe Ppl::Application::Command, "#execute" do
3
+
4
+ before(:each) do
5
+ @command = Ppl::Application::Command.new
6
+ end
7
+
8
+ it "should raise not implemented error" do
9
+ expect{@command.execute(nil, nil)}.to raise_error(NotImplementedError)
10
+ end
11
+
12
+ it "should accept a storage adapter" do
13
+ storage = double(Ppl::Adapter::Storage)
14
+ @command.storage = storage
15
+ @command.storage.should be storage
16
+ end
17
+
18
+ end
19
+
@@ -0,0 +1,44 @@
1
+
2
+ describe Ppl::Application::CommandSuite do
3
+
4
+ before(:each) do
5
+ @command_suite = Ppl::Application::CommandSuite.new
6
+
7
+ @foo_command = Ppl::Application::Command.new
8
+ @foo_command.name = "foo"
9
+
10
+ @bar_command = Ppl::Application::Command.new
11
+ @bar_command.name = "bar"
12
+
13
+ @command_suite.add_command(@foo_command)
14
+ @command_suite.add_command(@bar_command)
15
+ end
16
+
17
+ describe "#add_command" do
18
+ it "should accept a command" do
19
+ @command_suite.add_command(Ppl::Application::Command.new)
20
+ @command_suite.count.should be 3
21
+ end
22
+ end
23
+
24
+ describe "#find_command" do
25
+ it "should find a command matching the given name" do
26
+ @command_suite.find_command("foo").should be @foo_command
27
+ end
28
+ it "should return nil if no commands match the given name" do
29
+ @command_suite.find_command("baz").should be nil
30
+ end
31
+ end
32
+
33
+ describe "#each" do
34
+ it "should yield commands" do
35
+ @command_suite
36
+ .should_receive(:each)
37
+ .and_yield(@foo_command)
38
+ .and_yield(@bar_command)
39
+ @command_suite.each do |c| end
40
+ end
41
+ end
42
+
43
+ end
44
+
@@ -0,0 +1,21 @@
1
+
2
+ describe Ppl::Application::Input do
3
+
4
+ before(:each) do
5
+ @input = Ppl::Application::Input.new
6
+ end
7
+
8
+ describe "#arguments" do
9
+ it "should be an array" do
10
+ @input.arguments.should be_an(Array)
11
+ end
12
+ end
13
+
14
+ describe "#options" do
15
+ it "should be a hash" do
16
+ @input.options.should be_a(Hash)
17
+ end
18
+ end
19
+
20
+ end
21
+
@@ -0,0 +1,43 @@
1
+
2
+ describe Ppl::Application::Router do
3
+
4
+ before(:each) do
5
+ @suite = Ppl::Application::CommandSuite.new
6
+ @router = Ppl::Application::Router.new(@suite)
7
+
8
+ @cmd_one = Ppl::Application::Command.new
9
+ @cmd_one.name = "one"
10
+
11
+ @cmd_two = Ppl::Application::Command.new
12
+ @cmd_two.name = "two"
13
+
14
+ @suite.add_command(@cmd_one)
15
+ @suite.add_command(@cmd_two)
16
+ end
17
+
18
+ describe "#default=" do
19
+ it "should accept the name of the default command" do
20
+ @router.default = "one"
21
+ @router.default.should eq "one"
22
+ end
23
+ end
24
+
25
+ describe "#route" do
26
+
27
+ it "should return the command whose name matches the given argument" do
28
+ @router.route("two").should be @cmd_two
29
+ end
30
+
31
+ it "should return nil if no matching command can be found" do
32
+ @router.route("three").should be nil
33
+ end
34
+
35
+ it "should fall back to the default command if the given one isn't found" do
36
+ @router.default = "one"
37
+ @router.route("three").should be @cmd_one
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
@@ -0,0 +1,79 @@
1
+
2
+ describe Ppl::Application::Shell do
3
+
4
+ before(:each) do
5
+ @shell = Ppl::Application::Shell.new
6
+ @input = Ppl::Application::Input.new
7
+ @output = double(Ppl::Application::Output)
8
+
9
+ @router = double(Ppl::Application::Router)
10
+ @command = double(Ppl::Application::Command)
11
+
12
+ @shell.router = @router
13
+ end
14
+
15
+ describe "#run" do
16
+
17
+ it "should return false if the given command isn't found" do
18
+ @input.arguments = ["foo"]
19
+ @router
20
+ .should_receive(:route)
21
+ .with("foo")
22
+ .and_return(nil)
23
+ @shell.run(@input, @output).should eq false
24
+ end
25
+
26
+ it "should execute the given command" do
27
+ @input.arguments = ["foo"]
28
+ @router
29
+ .should_receive(:route)
30
+ .with("foo")
31
+ .and_return(@command)
32
+
33
+ @command
34
+ .should_receive(:execute)
35
+ .and_return(true)
36
+
37
+ @shell.run(@input, @output).should eq true
38
+ end
39
+
40
+ it "should not pass the command name in the input to the command itself" do
41
+ @input.arguments = ["mv", "foo", "bar"]
42
+ @router
43
+ .should_receive(:route)
44
+ .with("mv")
45
+ .and_return(@command)
46
+
47
+ @command.should_receive(:execute) do |input, output|
48
+ input.arguments.should eq ["foo", "bar"]
49
+ end
50
+ @shell.run(@input, @output)
51
+ end
52
+
53
+ it "should return false if the command throws an exception" do
54
+ @command
55
+ .should_receive(:execute)
56
+ .and_raise(StandardError)
57
+
58
+ @router
59
+ .should_receive(:route)
60
+ .and_return(@command)
61
+
62
+ @output.should_receive(:error)
63
+
64
+ @shell.run(@input, @output)
65
+ end
66
+
67
+ it "should send exception messages to stderr" do
68
+ @command.should_receive(:execute) { raise "Pool's Closed" }
69
+ @router.should_receive(:route).and_return(@command)
70
+
71
+ @output.should_receive(:error).with("ppl: Pool's Closed")
72
+
73
+ @shell.run(@input, @output)
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+