ppl 0.0.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +7 -3
- data/Gemfile.lock +15 -7
- data/README.md +47 -34
- data/bin/ppl +7 -6
- data/lib/ppl/adapter/storage/disk.rb +40 -0
- data/lib/ppl/adapter/storage.rb +28 -0
- data/lib/ppl/adapter/vcard/vpim.rb +45 -0
- data/lib/ppl/adapter/vcard.rb +13 -0
- data/lib/ppl/application/bootstrap.rb +62 -0
- data/lib/ppl/application/command.rb +13 -0
- data/lib/ppl/application/command_suite.rb +25 -0
- data/lib/ppl/application/input.rb +13 -0
- data/lib/ppl/application/output.rb +21 -0
- data/lib/ppl/application/router.rb +19 -0
- data/lib/ppl/application/shell.rb +34 -0
- data/lib/ppl/command/command_list.rb +21 -0
- data/lib/ppl/command/contact_add.rb +26 -0
- data/lib/ppl/command/contact_delete.rb +16 -0
- data/lib/ppl/command/contact_list.rb +24 -0
- data/lib/ppl/command/contact_rename.rb +23 -0
- data/lib/ppl/command/contact_show.rb +20 -0
- data/lib/ppl/entity/address_book.rb +21 -0
- data/lib/ppl/entity/contact.rb +10 -0
- data/lib/ppl/error/contact_not_found.rb +4 -0
- data/lib/ppl/error/incorrect_usage.rb +4 -0
- data/lib/ppl.rb +51 -11
- data/ppl.gemspec +3 -3
- data/spec/ppl/adapter/output_spec.rb +43 -0
- data/spec/ppl/adapter/storage/disk_spec.rb +83 -0
- data/spec/ppl/adapter/storage_spec.rb +46 -0
- data/spec/ppl/adapter/vcard/vpim_spec.rb +77 -0
- data/spec/ppl/adapter/vcard_spec.rb +24 -0
- data/spec/ppl/application/bootstrap_spec.rb +88 -0
- data/spec/ppl/application/command_spec.rb +19 -0
- data/spec/ppl/application/command_suite_spec.rb +44 -0
- data/spec/ppl/application/input_spec.rb +21 -0
- data/spec/ppl/application/router_spec.rb +43 -0
- data/spec/ppl/application/shell_spec.rb +79 -0
- data/spec/ppl/command/command_list_spec.rb +37 -0
- data/spec/ppl/command/contact_add_spec.rb +41 -0
- data/spec/ppl/command/contact_delete_spec.rb +31 -0
- data/spec/ppl/command/contact_list_spec.rb +15 -0
- data/spec/ppl/command/contact_rename_spec.rb +42 -0
- data/spec/ppl/command/contact_show_spec.rb +35 -0
- data/spec/ppl/entity/address_book_spec.rb +26 -0
- data/spec/ppl/entity/contact_spec.rb +34 -0
- data/spec/spec_helper.rb +9 -0
- metadata +47 -14
- data/lib/ppl/address_book.rb +0 -74
- data/lib/ppl/cli.rb +0 -49
- data/lib/ppl/command/add.rb +0 -40
- data/lib/ppl/command/birthdays.rb +0 -34
- data/lib/ppl/command/help.rb +0 -32
- data/lib/ppl/command/list.rb +0 -31
- data/lib/ppl/command/rm.rb +0 -38
- data/lib/ppl/command/set.rb +0 -49
- data/lib/ppl/command/show.rb +0 -43
- data/lib/ppl/command.rb +0 -55
- data/lib/ppl/contact.rb +0 -43
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
|
-
|
6
|
-
require "ppl/
|
7
|
-
require "ppl/
|
8
|
-
require "ppl/
|
9
|
-
require "ppl/
|
10
|
-
|
11
|
-
require "ppl/
|
12
|
-
require "ppl/command
|
13
|
-
require "ppl/
|
14
|
-
require "ppl/
|
15
|
-
require "ppl/
|
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
|
6
|
-
spec.date = "2012-11-
|
5
|
+
spec.version = "0.2.0"
|
6
|
+
spec.date = "2012-11-23"
|
7
7
|
|
8
8
|
spec.summary = "CLI Address Book"
|
9
|
-
spec.description = "
|
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
|
+
|