voicemail 0.2.0 → 1.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
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