ppl 0.0.5 → 0.2.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/.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
|
+
|