voicemail 0.1.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.
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