voicemail 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +26 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +3 -0
  5. data/Guardfile +5 -0
  6. data/LICENSE +20 -0
  7. data/README.md +62 -0
  8. data/Rakefile +11 -0
  9. data/lib/voicemail/application_controller.rb +27 -0
  10. data/lib/voicemail/mailbox_controller.rb +56 -0
  11. data/lib/voicemail/mailbox_main_menu_controller.rb +41 -0
  12. data/lib/voicemail/mailbox_messages_controller.rb +55 -0
  13. data/lib/voicemail/mailbox_play_message_controller.rb +69 -0
  14. data/lib/voicemail/mailbox_set_greeting_controller.rb +75 -0
  15. data/lib/voicemail/mailbox_set_pin_controller.rb +45 -0
  16. data/lib/voicemail/plugin.rb +86 -0
  17. data/lib/voicemail/storage.rb +7 -0
  18. data/lib/voicemail/storage_pstore.rb +93 -0
  19. data/lib/voicemail/version.rb +3 -0
  20. data/lib/voicemail/voicemail_controller.rb +32 -0
  21. data/lib/voicemail.rb +14 -0
  22. data/spec/spec_helper.rb +14 -0
  23. data/spec/support/voicemail_controller_spec_helper.rb +39 -0
  24. data/spec/voicemail/mailbox_controller_spec.rb +79 -0
  25. data/spec/voicemail/mailbox_main_menu_controller_spec.rb +35 -0
  26. data/spec/voicemail/mailbox_messages_controller_spec.rb +71 -0
  27. data/spec/voicemail/mailbox_play_message_controller_spec.rb +70 -0
  28. data/spec/voicemail/mailbox_set_greeting_controller_spec.rb +61 -0
  29. data/spec/voicemail/mailbox_set_pin_controller_spec.rb +53 -0
  30. data/spec/voicemail/storage_pstore_spec.rb +45 -0
  31. data/spec/voicemail/storage_spec.rb +13 -0
  32. data/spec/voicemail/voicemail_controller_spec.rb +65 -0
  33. data/tmp/.gitignore +2 -0
  34. data/voicemail.gemspec +29 -0
  35. metadata +200 -0
@@ -0,0 +1,93 @@
1
+ require 'pstore'
2
+
3
+ module Voicemail
4
+ class StoragePstore
5
+ attr_accessor :store
6
+
7
+ def initialize
8
+ @store = PStore.new config.storage.pstore_location
9
+ setup_schema
10
+ end
11
+
12
+ def get_mailbox(mailbox_id)
13
+ store.transaction true do
14
+ store[:mailboxes][mailbox_id]
15
+ end
16
+ end
17
+
18
+ def count_new_messages(mailbox_id)
19
+ store.transaction true do
20
+ store[:recordings][mailbox_id].size
21
+ end
22
+ end
23
+
24
+ def next_new_message(mailbox_id)
25
+ store.transaction true do
26
+ store[:recordings][mailbox_id].first
27
+ end
28
+ end
29
+
30
+ def archive_message(mailbox_id, message_id)
31
+ store.transaction do
32
+ item = store[:recordings][mailbox_id].select { |i| i[:id] == message_id }
33
+ rec = item.first
34
+ if rec
35
+ store[:archived][mailbox_id] << rec
36
+ store[:recordings][mailbox_id].delete(rec)
37
+ end
38
+ end
39
+ end
40
+
41
+ def delete_message(mailbox_id, message_id)
42
+ File.unlink(rec[:uri]) if File.exists?(rec[:uri])
43
+ store[:recordings][mailbox_id].delete(rec)
44
+ end
45
+
46
+ def save_greeting_for_mailbox(mailbox_id, recording_uri)
47
+ store.transaction do
48
+ store[:mailboxes][mailbox_id][:greeting_message] = recording_uri
49
+ end
50
+ end
51
+
52
+ def change_pin_for_mailbox(mailbox_id, new_pin)
53
+ store.transaction do
54
+ store[:mailboxes][mailbox_id][:pin] = new_pin
55
+ end
56
+ end
57
+
58
+ def save_recording(mailbox_id, from, recording_uri)
59
+ store.transaction do
60
+ recording = {
61
+ id: SecureRandom.uuid,
62
+ from: from,
63
+ received: Time.now,
64
+ uri: recording_uri.gsub(/file:\/\//, '')
65
+ }
66
+ logger.fatal "store[:recordings][#{mailbox_id}] << recording"
67
+ store[:recordings][mailbox_id] << recording
68
+ logger.info "Saving recording: #{recording.inspect}"
69
+ end
70
+ end
71
+
72
+ def create_mailbox
73
+ end
74
+
75
+ private
76
+
77
+ def setup_schema
78
+ store.transaction do
79
+ store[:mailboxes] ||= {}
80
+ store[:recordings] ||= {}
81
+ store[:archived] ||= {}
82
+
83
+ store[:mailboxes][1] = {greeting_message: "Hello.", id: 1, pin: '1234'}
84
+ store[:recordings][1] ||= []
85
+ store[:archived][1] ||= []
86
+ end
87
+ end
88
+
89
+ def config
90
+ Voicemail::Plugin.config
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,3 @@
1
+ module Voicemail
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,32 @@
1
+ module Voicemail
2
+ class VoicemailController < ApplicationController
3
+ def run
4
+ answer
5
+ if mailbox
6
+ play_greeting
7
+ handle_recording
8
+ else
9
+ mailbox_not_found
10
+ end
11
+ end
12
+
13
+ def play_greeting
14
+ play mailbox[:greeting_message] || config.default_greeting
15
+ end
16
+
17
+ def handle_recording
18
+ @from = call.from
19
+ record_comp = record config.recording.to_hash.merge(interruptible: true, max_duration: 30_000, direction: :recv)
20
+ save_recording record_comp.complete_event.recording.uri
21
+ end
22
+
23
+ def mailbox_not_found
24
+ play config.mailbox_not_found
25
+ hangup
26
+ end
27
+
28
+ def save_recording(uri)
29
+ storage.save_recording mailbox[:id], @from, uri
30
+ end
31
+ end
32
+ end
data/lib/voicemail.rb ADDED
@@ -0,0 +1,14 @@
1
+ module Voicemail; end
2
+ require "voicemail/version"
3
+ require "voicemail/storage_pstore"
4
+ require "voicemail/storage"
5
+ require "voicemail/application_controller"
6
+ require "voicemail/voicemail_controller"
7
+ require "voicemail/mailbox_controller"
8
+ require "voicemail/mailbox_main_menu_controller"
9
+ require "voicemail/mailbox_messages_controller"
10
+ require "voicemail/mailbox_play_message_controller"
11
+ require "voicemail/mailbox_set_greeting_controller"
12
+ require "voicemail/mailbox_set_pin_controller"
13
+
14
+ require "voicemail/plugin"
@@ -0,0 +1,14 @@
1
+ require 'adhearsion'
2
+ require 'flexmock'
3
+ require 'voicemail'
4
+
5
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
6
+
7
+ RSpec.configure do |config|
8
+ config.color_enabled = true
9
+ config.tty = true
10
+
11
+ config.mock_framework = :flexmock
12
+ config.filter_run :focus => true
13
+ config.run_all_when_everything_filtered = true
14
+ end
@@ -0,0 +1,39 @@
1
+ module VoicemailControllerSpecHelper
2
+ def self.included(test_case)
3
+ test_case.let(:from) { "sip:user@server.com" }
4
+ test_case.let(:call) { flexmock 'Call', from: from }
5
+ test_case.let(:config) { Voicemail::Plugin.config }
6
+ test_case.let(:greeting_message) { nil }
7
+ test_case.let(:mailbox) do
8
+ {
9
+ id: 100,
10
+ pin: 1234,
11
+ greeting_message: greeting_message,
12
+ send_email: true,
13
+ email_address: 'lpradovera@mojolingo.com'
14
+ }
15
+ end
16
+ test_case.let(:storage_instance) { flexmock 'StorageInstance' }
17
+ test_case.let(:metadata) do
18
+ { :mailbox => '100', :storage => storage_instance }
19
+ end
20
+
21
+ test_case.subject(:controller) { flexmock test_case.described_class.new(call, metadata) }
22
+
23
+ test_case.before(:each) do
24
+ storage_instance.should_receive(:get_mailbox).with(metadata[:mailbox]).and_return(mailbox)
25
+ end
26
+ end
27
+
28
+ def should_play(*args)
29
+ subject.should_receive(:play).once.tap { |exp| exp.with(*args) if args.count > 0 }
30
+ end
31
+
32
+ def should_ask(*args)
33
+ subject.should_receive(:ask).with(*args).once
34
+ end
35
+
36
+ def should_invoke(*args)
37
+ subject.should_receive(:invoke).once.with(*args)
38
+ end
39
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe Voicemail::MailboxController do
4
+ include VoicemailControllerSpecHelper
5
+
6
+ describe "#run" do
7
+ context "with a missing mailbox parameter in metadata" do
8
+ let(:metadata) { Hash.new }
9
+
10
+ it "should raise an error if there is no mailbox in the metadata" do
11
+ expect { controller.run }.to raise_error ArgumentError
12
+ end
13
+ end
14
+
15
+ context "with a present mailbox parameter in metadata" do
16
+ context "with an invalid mailbox" do
17
+ let(:mailbox) { nil }
18
+
19
+ it "plays the mailbox not found message and hangs up" do
20
+ should_play config.mailbox_not_found
21
+ subject.should_receive(:hangup).once
22
+ controller.run
23
+ end
24
+ end
25
+
26
+ context "with an existing mailbox" do
27
+ it "plays the mailbox greeting message" do
28
+ should_play config.mailbox.greeting_message
29
+ subject.should_receive(:authenticate).and_return(true)
30
+ subject.should_receive(:play_number_of_messages).and_return(true)
31
+ subject.should_receive(:main_menu).and_return(true)
32
+ controller.run
33
+ end
34
+ end
35
+ end
36
+
37
+ describe "#authenticate" do
38
+ it "authenticates an user that enters the correct pin" do
39
+ should_ask(config.mailbox.please_enter_pin, terminator: "#", timeout: config.prompt_timeout).once.and_return(1234)
40
+ controller.authenticate.should == true
41
+ end
42
+
43
+ it "tell a user his pin is wrong and retries" do
44
+ subject.should_receive(:ask).times(2).and_return(1111, 1234)
45
+ should_play config.mailbox.pin_wrong
46
+ controller.authenticate.should == true
47
+ end
48
+
49
+ it "fails with a message if the user enters a wrong PIN the set number of times" do
50
+ subject.should_receive(:ask).times(3).and_return(1111, 2222, 3333)
51
+ subject.should_receive(:play).with(config.mailbox.pin_wrong).times(3)
52
+ controller.authenticate.should == false
53
+ end
54
+ end
55
+
56
+ describe "#play_number_of_messages" do
57
+ it "plays the number of new messages if there is at least one" do
58
+ storage_instance.should_receive(:count_new_messages).once.with(mailbox[:id]).and_return(3)
59
+ should_play(config.mailbox.number_before).ordered
60
+ subject.should_receive(:play_numeric).ordered.with(3)
61
+ should_play(config.mailbox.number_after).ordered
62
+ controller.play_number_of_messages
63
+ end
64
+
65
+ it "does play the no messages audio if there are none" do
66
+ storage_instance.should_receive(:count_new_messages).once.with(mailbox[:id]).and_return(0)
67
+ should_play(config.messages.no_new_messages).ordered
68
+ controller.play_number_of_messages
69
+ end
70
+ end
71
+
72
+ describe "#main_menu" do
73
+ it "passes to MainMenuController" do
74
+ subject.should_receive(:pass).once.with(Voicemail::MailboxMainMenuController, mailbox: mailbox[:id])
75
+ controller.main_menu
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Voicemail::MailboxMainMenuController do
4
+ include VoicemailControllerSpecHelper
5
+
6
+ describe "#main_menu" do
7
+ it "calls #menu with the proper parameters" do
8
+ subject.should_receive(:menu).once.with(config.mailbox.menu_greeting,
9
+ { timeout: config.menu_timeout,
10
+ tries: config.menu_tries }, Proc)
11
+ controller.main_menu
12
+ end
13
+ end
14
+
15
+ describe "#set_greeting" do
16
+ it "invokes MailboxSetGreetingController" do
17
+ should_invoke Voicemail::MailboxSetGreetingController, mailbox: mailbox[:id]
18
+ controller.set_greeting
19
+ end
20
+ end
21
+
22
+ describe "#set_pin" do
23
+ it "invokes MailboxSetGreetingController" do
24
+ should_invoke Voicemail::MailboxSetPinController, mailbox: mailbox[:id]
25
+ controller.set_pin
26
+ end
27
+ end
28
+
29
+ describe "#listen_to_messages" do
30
+ it "invokes MailboxMessagesController" do
31
+ should_invoke Voicemail::MailboxMessagesController, mailbox: mailbox[:id]
32
+ controller.listen_to_messages
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ module Voicemail
4
+ describe MailboxMessagesController do
5
+ include VoicemailControllerSpecHelper
6
+
7
+ let(:call) { flexmock('Call') }
8
+ let(:config) { Voicemail::Plugin.config }
9
+ let(:metadata) do
10
+ { :mailbox => '100' }
11
+ end
12
+ let(:mailbox) do
13
+ {
14
+ :id => 100,
15
+ :pin => 1234,
16
+ :greeting_message => nil,
17
+ :send_email => true,
18
+ :email_address => "lpradovera@mojolingo.com"
19
+ }
20
+ end
21
+ let(:message) do
22
+ {
23
+ :id => 123,
24
+ :from => "+39-335135335",
25
+ :received => Time.local(2012, 5, 1, 9, 0, 0),
26
+ :uri => "/path/to/file"
27
+ }
28
+ end
29
+
30
+ let(:storage_instance) { flexmock('StorageInstance') }
31
+
32
+ let(:controller){ Voicemail::MailboxMessagesController.new call, metadata }
33
+ subject { flexmock controller }
34
+
35
+ before(:each) do
36
+ storage_instance.should_receive(:get_mailbox).with(metadata[:mailbox]).and_return(mailbox)
37
+ flexmock(Storage).should_receive(:instance).and_return(storage_instance)
38
+ end
39
+
40
+ describe "#message_loop" do
41
+ it "calls #next_message if there are new messages" do
42
+ storage_instance.should_receive(:count_new_messages).once.with(mailbox[:id]).and_return(3)
43
+ subject.should_receive(:next_message).once
44
+ controller.message_loop
45
+ end
46
+
47
+ it "plays a message and goes to the main menu if there are no new messages" do
48
+ storage_instance.should_receive(:count_new_messages).once.with(mailbox[:id]).and_return(0)
49
+ subject.should_receive(:play).with(config.messages.no_new_messages).once
50
+ subject.should_receive(:main_menu).once
51
+ controller.message_loop
52
+ end
53
+ end
54
+
55
+ describe "#next_message" do
56
+ it "gets the next message and calls #handle_message" do
57
+ storage_instance.should_receive(:next_new_message).once.with(mailbox[:id]).and_return(message)
58
+ subject.should_receive(:handle_message).once.with(message)
59
+ subject.should_receive(:message_loop).once
60
+ controller.next_message
61
+ end
62
+ end
63
+
64
+ describe "#handle_message" do
65
+ it "invokes MailboxPlayMessageController" do
66
+ should_invoke Voicemail::MailboxPlayMessageController, message: message, mailbox: mailbox[:id]
67
+ controller.handle_message message
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe Voicemail::MailboxPlayMessageController do
4
+ include VoicemailControllerSpecHelper
5
+
6
+ let(:message) do
7
+ {
8
+ id: 123,
9
+ from: "+39-335135335",
10
+ received: Time.local(2012, 5, 1, 9, 0, 0),
11
+ uri: "/path/to/file"
12
+ }
13
+ end
14
+
15
+ describe "#archive_message" do
16
+ it "archives the message" do
17
+ subject.should_receive(:current_message).once.and_return(message)
18
+ storage_instance.should_receive(:archive_message).once.with(mailbox[:id], message[:id])
19
+ controller.archive_message
20
+ end
21
+ end
22
+
23
+ describe "#delete_message" do
24
+ it "deletes the message" do
25
+ subject.should_receive(:current_message).once.and_return(message)
26
+ storage_instance.should_receive(:delete_message).once.with(mailbox[:id], message[:id])
27
+ controller.delete_message
28
+ end
29
+ end
30
+
31
+ describe "#intro_message" do
32
+ it "plays the message introduction" do
33
+ subject.should_receive(:current_message).and_return(message)
34
+ should_play config.messages.message_received_on
35
+ subject.should_receive(:play_time).once.with(message[:received], format: config.datetime_format)
36
+ should_play config.messages.from
37
+ subject.should_receive(:execute).once.with("SayDigits", "39335135335")
38
+ controller.intro_message
39
+ end
40
+ end
41
+
42
+ describe "#play_message" do
43
+ it "plays the message, followed by the menu" do
44
+ subject.should_receive(:current_message).once.and_return(message)
45
+ subject.should_receive(:menu).once.with(message[:uri], config.messages.menu,
46
+ { timeout: config.menu_timeout, tries: config.menu_tries }, Proc)
47
+ subject.play_message
48
+ end
49
+ end
50
+
51
+ describe "#load_message" do
52
+
53
+ context "with a message" do
54
+ let(:metadata) { {message: "foo"} }
55
+
56
+ it "loads the messge" do
57
+ subject.load_message
58
+ subject.current_message.should == "foo"
59
+ end
60
+ end
61
+
62
+ context "with no message passed" do
63
+ let(:metadata) { {message: nil} }
64
+
65
+ it "raises an error" do
66
+ expect { subject.load_message }.to raise_error ArgumentError
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe Voicemail::MailboxSetGreetingController do
4
+ include VoicemailControllerSpecHelper
5
+
6
+ describe "#section_menu" do
7
+ it "calls #menu with the proper parameters" do
8
+ subject.should_receive(:menu).once.with(config.set_greeting.prompt,
9
+ { timeout: config.menu_timeout,
10
+ tries: config.menu_tries }, Proc)
11
+ controller.section_menu
12
+ end
13
+ end
14
+
15
+ describe "#listen_to_current_greeting" do
16
+ context "without a greeting message" do
17
+ it "plays the default greeting if one is not specified" do
18
+ should_play config.set_greeting.no_personal_greeting
19
+ subject.should_receive(:section_menu).once.and_return(true)
20
+ controller.listen_to_current_greeting
21
+ end
22
+ end
23
+
24
+ context "with a specified greeting message" do
25
+ let(:greeting_message) { "Howdy!" }
26
+
27
+ it "plays the specific greeting message" do
28
+ should_play greeting_message
29
+ subject.should_receive(:section_menu).once.and_return(true)
30
+ controller.listen_to_current_greeting
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#record_greeting" do
36
+ let(:recording_component) { flexmock 'Record' }
37
+ let(:file_path) { "/path/to/file" }
38
+
39
+ it "plays the appropriate sounds, records, plays back recording, and calls the recording menu" do
40
+ should_play config.set_greeting.before_record
41
+ recording_component.should_receive("complete_event.recording.uri").and_return(file_path)
42
+ subject.should_receive(:record).once.with(config.set_greeting.recording.to_hash.merge(interruptible: true, max_duration: 30_000)).and_return(recording_component)
43
+ should_play file_path
44
+ subject.should_receive(:menu).once.with(config.set_greeting.after_record,
45
+ { timeout: config.menu_timeout,
46
+ tries: config.menu_tries }, Proc)
47
+ controller.record_greeting
48
+ end
49
+ end
50
+
51
+ describe "#save_greeting" do
52
+ let(:file_path) { "/path/to/file" }
53
+
54
+ it "saves the greeting and goes to the main menu" do
55
+ subject.should_receive(:temp_recording).once.and_return(file_path)
56
+ storage_instance.should_receive(:save_greeting_for_mailbox).with(mailbox[:id], file_path)
57
+ subject.should_receive(:main_menu)
58
+ controller.save_greeting
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Voicemail::MailboxSetPinController do
4
+ include VoicemailControllerSpecHelper
5
+
6
+ describe "#section_menu" do
7
+ it "calls #menu with the proper parameters" do
8
+ subject.should_receive(:menu).once.with(config.set_pin.menu,
9
+ { timeout: config.menu_timeout,
10
+ tries: config.menu_tries }, Proc)
11
+ controller.section_menu
12
+ end
13
+ end
14
+
15
+ describe "#set_pin" do
16
+ let(:pin) { "4321" }
17
+ let(:not_matching_pin) { "1234" }
18
+ let(:short_pin) { "9" }
19
+
20
+ it "makes the user enter a PIN and repeat it" do
21
+ should_ask(config.set_pin.prompt, terminator: "#").and_return(pin).ordered
22
+ should_ask(config.set_pin.repeat_prompt, terminator: "#").and_return(pin).ordered
23
+ should_play(config.set_pin.change_ok).ordered
24
+ storage_instance.should_receive(:change_pin_for_mailbox).with(mailbox[:id], pin).once.ordered
25
+ subject.should_receive(:main_menu).once
26
+ controller.set_pin
27
+ end
28
+
29
+ it "makes the user start over if the PIN is too short" do
30
+ should_ask(config.set_pin.prompt, terminator: "#").and_return(short_pin).ordered
31
+ should_ask(config.set_pin.repeat_prompt, terminator: "#").and_return(short_pin).ordered
32
+ should_play(config.set_pin.pin_error).ordered
33
+ should_ask(config.set_pin.prompt, terminator: "#").and_return(pin).ordered
34
+ should_ask(config.set_pin.repeat_prompt, terminator: "#").and_return(pin).ordered
35
+ should_play(config.set_pin.change_ok).ordered
36
+ storage_instance.should_receive(:change_pin_for_mailbox).with(mailbox[:id], pin).once.ordered
37
+ subject.should_receive(:main_menu).once
38
+ controller.set_pin
39
+ end
40
+
41
+ it "makes the user start over if the PIN does not match confirmation" do
42
+ should_ask(config.set_pin.prompt, terminator: "#").and_return(pin).ordered
43
+ should_ask(config.set_pin.repeat_prompt, terminator: "#").and_return(not_matching_pin).ordered
44
+ should_play(config.set_pin.match_error).ordered
45
+ should_ask(config.set_pin.prompt, terminator: "#").and_return(pin).ordered
46
+ should_ask(config.set_pin.repeat_prompt, terminator: "#").and_return(pin).ordered
47
+ should_play(config.set_pin.change_ok).ordered
48
+ storage_instance.should_receive(:change_pin_for_mailbox).with(mailbox[:id], pin).once.ordered
49
+ subject.should_receive(:main_menu).once
50
+ controller.set_pin
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ module Voicemail
4
+ describe StoragePstore do
5
+ let(:mailbox) do
6
+ {
7
+ id: 100,
8
+ pin: 1234,
9
+ greeting_message: nil,
10
+ send_email: true,
11
+ email_address: 'lpradovera@mojolingo.com'
12
+ }
13
+ end
14
+
15
+ let(:config) { Voicemail::Plugin.config }
16
+
17
+ subject :storage do
18
+ basedir = File.expand_path("../../../tmp/", __FILE__)
19
+ pstore_path = File.join(basedir, 'voicemail.pstore')
20
+ File.unlink(pstore_path) if File.exists?(pstore_path)
21
+ config.storage.pstore_location = pstore_path
22
+ StoragePstore.new.tap do |storage|
23
+ storage.store.transaction do
24
+ storage.store[:mailboxes][100] = mailbox
25
+ end
26
+ flexmock storage
27
+ end
28
+ end
29
+
30
+ it "is a PStore" do
31
+ storage.store.should be_a PStore
32
+ end
33
+
34
+ describe "#get_mailbox" do
35
+ it "returns the mailbox if it exists" do
36
+ storage.get_mailbox(100).should == mailbox
37
+ end
38
+
39
+ it "returns nil if the mailbox does not exist" do
40
+ storage.get_mailbox(400).should be_nil
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Voicemail::Storage do
4
+ describe "#instance" do
5
+ it "returns a StorageMain object" do
6
+ Voicemail::Storage.instance.should be_a Voicemail::StoragePstore
7
+ end
8
+
9
+ it "returns the same instance every time" do
10
+ Voicemail::Storage.instance.should be Voicemail::Storage.instance
11
+ end
12
+ end
13
+ end