voicemail 0.2.0 → 1.0.0.beta

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/README.md +57 -2
  4. data/lib/voicemail.rb +15 -8
  5. data/lib/voicemail/{application_controller.rb → call_controllers/application_controller.rb} +14 -1
  6. data/lib/voicemail/call_controllers/authentication_controller.rb +60 -0
  7. data/lib/voicemail/call_controllers/mailbox_controller.rb +46 -0
  8. data/lib/voicemail/{mailbox_main_menu_controller.rb → call_controllers/mailbox_main_menu_controller.rb} +9 -4
  9. data/lib/voicemail/call_controllers/mailbox_messages_controller.rb +48 -0
  10. data/lib/voicemail/{mailbox_play_message_controller.rb → call_controllers/mailbox_play_message_controller.rb} +26 -10
  11. data/lib/voicemail/call_controllers/mailbox_play_message_intro_controller.rb +72 -0
  12. data/lib/voicemail/{mailbox_set_greeting_controller.rb → call_controllers/mailbox_set_greeting_controller.rb} +2 -2
  13. data/lib/voicemail/{mailbox_set_pin_controller.rb → call_controllers/mailbox_set_pin_controller.rb} +0 -0
  14. data/lib/voicemail/call_controllers/voicemail_controller.rb +57 -0
  15. data/lib/voicemail/localization_loader.rb +28 -0
  16. data/lib/voicemail/matcher.rb +14 -0
  17. data/lib/voicemail/plugin.rb +40 -15
  18. data/lib/voicemail/storage_pstore.rb +49 -2
  19. data/lib/voicemail/version.rb +1 -1
  20. data/spec/voicemail/call_controllers/application_controller_spec.rb +31 -0
  21. data/spec/voicemail/call_controllers/authentication_controller_spec.rb +59 -0
  22. data/spec/voicemail/call_controllers/mailbox_controller_spec.rb +107 -0
  23. data/spec/voicemail/{mailbox_main_menu_controller_spec.rb → call_controllers/mailbox_main_menu_controller_spec.rb} +9 -2
  24. data/spec/voicemail/call_controllers/mailbox_messages_controller_spec.rb +110 -0
  25. data/spec/voicemail/call_controllers/mailbox_play_message_controller_spec.rb +97 -0
  26. data/spec/voicemail/call_controllers/mailbox_play_message_intro_controller_spec.rb +81 -0
  27. data/spec/voicemail/{mailbox_set_greeting_controller_spec.rb → call_controllers/mailbox_set_greeting_controller_spec.rb} +24 -6
  28. data/spec/voicemail/{mailbox_set_pin_controller_spec.rb → call_controllers/mailbox_set_pin_controller_spec.rb} +0 -0
  29. data/spec/voicemail/call_controllers/voicemail_controller_spec.rb +97 -0
  30. data/spec/voicemail/localization_loader_spec.rb +21 -0
  31. data/spec/voicemail/storage_pstore_spec.rb +64 -2
  32. data/templates/en.yml +67 -0
  33. data/voicemail.gemspec +2 -2
  34. metadata +42 -26
  35. data/lib/voicemail/mailbox_controller.rb +0 -56
  36. data/lib/voicemail/mailbox_messages_controller.rb +0 -55
  37. data/lib/voicemail/voicemail_controller.rb +0 -33
  38. data/spec/voicemail/mailbox_controller_spec.rb +0 -79
  39. data/spec/voicemail/mailbox_messages_controller_spec.rb +0 -71
  40. data/spec/voicemail/mailbox_play_message_controller_spec.rb +0 -70
  41. data/spec/voicemail/voicemail_controller_spec.rb +0 -76
@@ -26,10 +26,17 @@ describe Voicemail::MailboxMainMenuController do
26
26
  end
27
27
  end
28
28
 
29
- describe "#listen_to_messages" do
29
+ describe "#listen_to_new_messages" do
30
30
  it "invokes MailboxMessagesController" do
31
31
  should_invoke Voicemail::MailboxMessagesController, mailbox: mailbox[:id]
32
- controller.listen_to_messages
32
+ controller.listen_to_new_messages
33
+ end
34
+ end
35
+
36
+ describe "#listen_to_saved_messages" do
37
+ it "invokes MailboxMessagesController" do
38
+ should_invoke Voicemail::MailboxMessagesController, mailbox: mailbox[:id], new_or_saved: :saved
39
+ controller.listen_to_saved_messages
33
40
  end
34
41
  end
35
42
  end
@@ -0,0 +1,110 @@
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) { {mailbox: '100', new_or_saved: message_type} }
10
+
11
+ let(:mailbox) do
12
+ {
13
+ :id => 100,
14
+ :pin => 1234,
15
+ :greeting_message => nil,
16
+ :send_email => true,
17
+ :email_address => "lpradovera@mojolingo.com"
18
+ }
19
+ end
20
+ let(:message) do
21
+ {
22
+ :id => 123,
23
+ :from => "+39-335135335",
24
+ :received => Time.local(2012, 5, 1, 9, 0, 0),
25
+ :uri => "file:///path/to/file.mp3"
26
+ }
27
+ end
28
+
29
+ let(:storage_instance) { flexmock('StorageInstance') }
30
+
31
+ let(:controller){ Voicemail::MailboxMessagesController.new call, metadata }
32
+ subject { flexmock controller }
33
+
34
+ before(:each) do
35
+ storage_instance.should_receive(:get_mailbox).with(metadata[:mailbox]).and_return(mailbox)
36
+ flexmock(Storage).should_receive(:instance).and_return(storage_instance)
37
+ end
38
+
39
+
40
+ context "with new messages" do
41
+ let(:message_type) { :new }
42
+
43
+ describe "#message_loop" do
44
+ after { controller.message_loop }
45
+
46
+ it "calls #next_message if there are new messages" do
47
+ storage_instance.should_receive(:count_new_messages).once.with(mailbox[:id]).and_return(3)
48
+ subject.should_receive(:next_message).once
49
+ end
50
+
51
+ it "plays a message and goes to the main menu if there are no new messages" do
52
+ storage_instance.should_receive(:count_new_messages).once.with(mailbox[:id]).and_return(0)
53
+ subject.should_receive(:play).with(config.messages.no_new_messages).once
54
+ subject.should_receive(:main_menu).once
55
+ end
56
+ end
57
+
58
+ describe "#next_message" do
59
+ it "gets the next message and calls #handle_message" do
60
+ storage_instance.should_receive(:next_new_message).once.with(mailbox[:id]).and_return(message)
61
+ subject.should_receive(:handle_message).once.with(message)
62
+ subject.should_receive(:message_loop).once
63
+ controller.next_message
64
+ end
65
+ end
66
+
67
+ describe "#handle_message" do
68
+ it "invokes MailboxPlayMessageController" do
69
+ should_invoke Voicemail::MailboxPlayMessageController, message: message, mailbox: mailbox[:id], new_or_saved: :new, storage: storage_instance
70
+ controller.handle_message message
71
+ end
72
+ end
73
+ end
74
+
75
+ context "with saved messages" do
76
+ let(:message_type) { :saved }
77
+
78
+ describe "#message_loop" do
79
+ after { controller.message_loop }
80
+
81
+ it "calls #next_message if there are saved messages" do
82
+ storage_instance.should_receive(:count_saved_messages).once.with(mailbox[:id]).and_return(3)
83
+ subject.should_receive(:next_message).once
84
+ end
85
+
86
+ it "plays a message and goes to the main menu if there are no saved messages" do
87
+ storage_instance.should_receive(:count_saved_messages).once.with(mailbox[:id]).and_return(0)
88
+ subject.should_receive(:play).with(config.messages.no_saved_messages).once
89
+ subject.should_receive(:main_menu).once
90
+ end
91
+ end
92
+
93
+ describe "#next_message" do
94
+ it "gets the next message and calls #handle_message" do
95
+ storage_instance.should_receive(:next_saved_message).once.with(mailbox[:id]).and_return(message)
96
+ subject.should_receive(:handle_message).once.with(message)
97
+ subject.should_receive(:message_loop).once
98
+ controller.next_message
99
+ end
100
+ end
101
+
102
+ describe "#handle_message" do
103
+ it "invokes MailboxPlayMessageController" do
104
+ should_invoke Voicemail::MailboxPlayMessageController, message: message, mailbox: mailbox[:id], new_or_saved: :saved, storage: storage_instance
105
+ controller.handle_message message
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,97 @@
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: "file:///path/to/file.mp3"
12
+ }
13
+ end
14
+
15
+ describe "#archive_or_unarchive_message" do
16
+
17
+ after { controller.archive_or_unarchive_message }
18
+
19
+ context "with a new message" do
20
+ before { subject.new_or_saved = :new }
21
+
22
+ it "archives the message" do
23
+ subject.should_receive(:current_message).once.and_return message
24
+ storage_instance.should_receive(:archive_message).once.with mailbox[:id], message[:id]
25
+ end
26
+ end
27
+
28
+ context "with a saved message" do
29
+ before { subject.new_or_saved = :saved }
30
+
31
+ it "unarchives the message" do
32
+ subject.should_receive(:current_message).once.and_return message
33
+ storage_instance.should_receive(:unarchive_message).once.with mailbox[:id], message[:id]
34
+ end
35
+ end
36
+ end
37
+
38
+ describe "#delete_message" do
39
+ it "deletes the message" do
40
+ subject.should_receive(:current_message).once.and_return(message)
41
+ storage_instance.should_receive(:delete_message).once.with(mailbox[:id], message[:id])
42
+ controller.delete_message
43
+ end
44
+ end
45
+
46
+ describe "#intro_message" do
47
+ it "plays the message introduction" do
48
+ subject.should_receive(:current_message).once.and_return message
49
+ should_invoke Voicemail::MailboxPlayMessageIntroController, message: message, mailbox: 100, storage: storage_instance
50
+ controller.intro_message
51
+ end
52
+ end
53
+
54
+ describe "#play_message" do
55
+ after { subject.play_message }
56
+
57
+ context "with a new message" do
58
+ before { subject.new_or_saved = :new }
59
+
60
+ it "plays the message, followed by the new message menu" do
61
+ subject.should_receive(:current_message).once.and_return message
62
+ subject.should_receive(:menu).once.with message[:uri], config.messages.menu_new,
63
+ { timeout: config.menu_timeout, tries: config.menu_tries }, Proc
64
+ end
65
+ end
66
+
67
+ context "with a saved message" do
68
+ before { subject.new_or_saved = :saved }
69
+
70
+ it "plays the message, followed by the saved message menu" do
71
+ subject.should_receive(:current_message).once.and_return message
72
+ subject.should_receive(:menu).once.with message[:uri], config.messages.menu_saved,
73
+ { timeout: config.menu_timeout, tries: config.menu_tries }, Proc
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "#load_message" do
79
+
80
+ context "with a message" do
81
+ let(:metadata) { {message: "foo"} }
82
+
83
+ it "loads the messge" do
84
+ subject.load_message
85
+ subject.current_message.should == "foo"
86
+ end
87
+ end
88
+
89
+ context "with no message passed" do
90
+ let(:metadata) { {message: nil} }
91
+
92
+ it "raises an error" do
93
+ expect { subject.load_message }.to raise_error ArgumentError
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ describe Voicemail::MailboxPlayMessageIntroController do
4
+ include VoicemailControllerSpecHelper
5
+
6
+ let(:some_time) { Time.local 2012, 5, 1, 9, 0, 0 }
7
+ let(:message) do
8
+ {
9
+ id: 123,
10
+ from: "+123",
11
+ received: some_time,
12
+ uri: "file:///path/to/file.mp3"
13
+ }
14
+ end
15
+
16
+ before do
17
+ config.numeric_method = numeric_method
18
+ subject.should_receive(:current_message).and_return message
19
+ end
20
+
21
+ describe "#intro_message" do
22
+
23
+ after { subject.intro_message }
24
+
25
+ context "with the default mode" do
26
+ let(:numeric_method) { :play_numeric}
27
+
28
+ it "plays the message introduction" do
29
+ should_play config.messages.message_received_on
30
+ subject.should_receive(:play_time).with some_time, format: config.datetime_format
31
+
32
+ should_play config.messages.from
33
+ subject.should_receive(:say_characters).with "123"
34
+ end
35
+ end
36
+
37
+ context "with ahnsay" do
38
+ let(:numeric_method) { :ahn_say }
39
+
40
+ it "plays the message introduction" do
41
+ should_play config.messages.message_received_on
42
+ subject.should_receive(:sounds_for_time).with(some_time, format: config.datetime_format).and_return ["timesounds", ".wav"]
43
+ should_play "timesounds", ".wav"
44
+
45
+ should_play config.messages.from
46
+ subject.should_receive(:sounds_for_digits).with("123").and_return ["digit1.wav", "digit2.wav"]
47
+ should_play "digit1.wav", "digit2.wav"
48
+ end
49
+ end
50
+
51
+ context "with i18n_string" do
52
+ let(:numeric_method) { :i18n_string }
53
+
54
+ it "plays the message introduction" do
55
+ flexmock(I18n).should_receive(:localize).with(some_time).and_return "some time"
56
+ flexmock(I18n).should_receive(:t).with("voicemail.messages.message_received_on_x", received_on: "some time").and_return "Message received on some time. "
57
+ flexmock(I18n).should_receive(:t).with("numbers.1").and_return "one "
58
+ flexmock(I18n).should_receive(:t).with("numbers.2").and_return "two "
59
+ flexmock(I18n).should_receive(:t).with("numbers.3").and_return "three"
60
+ flexmock(I18n).should_receive(:t).with("voicemail.messages.message_received_from_x", from: "one two three").and_return "Message received from one two three"
61
+
62
+ should_play "Message received on some time. "
63
+ should_play "Message received from one two three"
64
+ end
65
+ end
66
+ end
67
+
68
+ describe "#play_from_message with i18n_string and missing digit translations" do
69
+ let(:numeric_method) { :i18n_string }
70
+
71
+ after { subject.play_from_message }
72
+
73
+ it "falls back sanely" do
74
+ flexmock(I18n).should_receive(:t).with("numbers.1").and_return "translation missing"
75
+ flexmock(I18n).should_receive(:t).with("numbers.2").and_return "translation missing"
76
+ flexmock(I18n).should_receive(:t).with("numbers.3").and_return "translation missing"
77
+ flexmock(I18n).should_receive(:t).with("voicemail.messages.message_received_from_x", from: "123").and_return "Message received from 123."
78
+ should_play "Message received from 123."
79
+ end
80
+ end
81
+ end
@@ -36,15 +36,33 @@ describe Voicemail::MailboxSetGreetingController do
36
36
  let(:recording_component) { flexmock 'Record' }
37
37
  let(:file_path) { "/path/to/file" }
38
38
 
39
- it "plays the appropriate sounds, records, plays back recording, and calls the recording menu" do
39
+ before do
40
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)).and_return recording_component
41
+ recording_component.should_receive("complete_event.recording.uri").and_return file_path
43
42
  subject.should_receive(:play_audio).with 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)
43
+ subject.should_receive(:menu).once.with config.set_greeting.after_record, {timeout: config.menu_timeout, tries: config.menu_tries}, Proc
44
+ end
45
+
46
+ after do
47
47
  controller.record_greeting
48
+ config.use_mailbox_opts_for_recording = false
49
+ end
50
+
51
+ context "without mailbox settings" do
52
+ it "plays the appropriate sounds, records, plays back recording, and calls the recording menu" do
53
+ subject.should_receive(:record).once.with(config.recording.to_hash).and_return recording_component
54
+ end
55
+ end
56
+
57
+ context "with mailbox settings" do
58
+ let(:mailbox) { {id: 100, record_options: {final_timeout: 31}} }
59
+
60
+ before { config.use_mailbox_opts_for_recording = true }
61
+
62
+ it "records using the mailbox's record options" do
63
+ expected_options = {direction: :send, final_timeout: 31, interruptible: true, max_duration: 30, start_beep: true, stop_beep: false}
64
+ subject.should_receive(:record).once.with(expected_options).and_return recording_component
65
+ end
48
66
  end
49
67
  end
50
68
 
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe Voicemail::VoicemailController 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
+ subject.should_receive(:answer).once
12
+ expect { controller.run }.to raise_error ArgumentError
13
+ end
14
+ end
15
+
16
+ context "When when_to_answer is :after_greeting and there's no mailbox" do
17
+ let(:mailbox) { nil }
18
+
19
+ before { config.when_to_answer = :after_greeting }
20
+ after { config.when_to_answer = :before_greeting }
21
+
22
+ it "should not answer" do
23
+ should_play config.mailbox_not_found
24
+ subject.should_receive(:hangup).once
25
+ controller.run
26
+ end
27
+ end
28
+
29
+ context "with a present mailbox parameter in metadata" do
30
+ before { subject.should_receive(:answer).once }
31
+
32
+ context "with an invalid mailbox" do
33
+ let(:mailbox) { nil }
34
+
35
+ it "plays the mailbox not found message and hangs up" do
36
+ should_play config.mailbox_not_found
37
+ subject.should_receive(:hangup).once
38
+ controller.run
39
+ end
40
+ end
41
+
42
+ context "with an existing mailbox" do
43
+ before { subject.should_receive(:hangup).once }
44
+
45
+ context "without a greeting message" do
46
+ it "plays the default greeting if one is not specified" do
47
+ should_play config.default_greeting
48
+ subject.should_receive :record_message
49
+ controller.run
50
+ end
51
+ end
52
+
53
+ context "with a specified greeting message" do
54
+ let(:greeting_message) { "Howdy!" }
55
+
56
+ it "plays the specific greeting message" do
57
+ should_play greeting_message
58
+ subject.should_receive :record_message
59
+ controller.run
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "#record_message" do
67
+ context "handling a recording" do
68
+ let(:recording_component) { flexmock 'Record' }
69
+ let(:recording_object) { flexmock 'complete_event.recording', uri: "http://some_file.wav" }
70
+
71
+ after { subject.record_message }
72
+
73
+ context "without allow_rerecording" do
74
+ before { config.allow_rerecording = false }
75
+
76
+ it "saves the recording" do
77
+ recording_component.should_receive("complete_event.recording").and_return recording_object
78
+ subject.should_receive(:record).with(config.recording.to_hash).and_return recording_component
79
+ storage_instance.should_receive(:save_recording).with mailbox[:id], call.from, recording_object
80
+ end
81
+ end
82
+
83
+ context "without allow_rerecording" do
84
+ before { config.allow_rerecording = true }
85
+
86
+ it "sets up a callback, plays a menu, and eventually saves the message" do
87
+ call.should_receive :on_end
88
+ recording_object.should_receive :uri
89
+ subject.should_receive(:menu)
90
+ recording_component.should_receive("complete_event.recording").and_return recording_object
91
+ subject.should_receive(:record).with(config.recording.to_hash).and_return recording_component
92
+ storage_instance.should_receive(:save_recording).with mailbox[:id], call.from, recording_object
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end