adhearsion 2.6.4 → 3.0.0.beta1
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.
- checksums.yaml +4 -4
- data/.travis.yml +6 -9
- data/CHANGELOG.md +22 -7
- data/Gemfile +2 -0
- data/README.markdown +4 -5
- data/Rakefile +1 -2
- data/adhearsion.gemspec +19 -8
- data/features/cli_create.feature +19 -3
- data/features/step_definitions/cli_steps.rb +0 -11
- data/features/support/env.rb +3 -4
- data/lib/adhearsion.rb +48 -27
- data/lib/adhearsion/call.rb +34 -50
- data/lib/adhearsion/call_controller.rb +6 -12
- data/lib/adhearsion/call_controller/dial.rb +15 -53
- data/lib/adhearsion/call_controller/input.rb +39 -162
- data/lib/adhearsion/call_controller/input/ask_grammar_builder.rb +44 -0
- data/lib/adhearsion/call_controller/input/menu_builder.rb +136 -0
- data/lib/adhearsion/call_controller/input/prompt_builder.rb +78 -0
- data/lib/adhearsion/call_controller/input/result.rb +46 -0
- data/lib/adhearsion/call_controller/output.rb +48 -67
- data/lib/adhearsion/call_controller/output/abstract_player.rb +3 -3
- data/lib/adhearsion/call_controller/output/async_player.rb +3 -3
- data/lib/adhearsion/call_controller/output/player.rb +1 -1
- data/lib/adhearsion/call_controller/record.rb +23 -8
- data/lib/adhearsion/calls.rb +1 -1
- data/lib/adhearsion/cli_commands/ahn_command.rb +2 -65
- data/lib/adhearsion/cli_commands/thor_errors.rb +0 -6
- data/lib/adhearsion/configuration.rb +91 -39
- data/lib/adhearsion/core_ext/blather/stanza.rb +41 -0
- data/lib/adhearsion/core_ext/blather/stanza/presence.rb +13 -0
- data/lib/adhearsion/error.rb +5 -0
- data/lib/adhearsion/event.rb +21 -0
- data/lib/adhearsion/event/active_speaker.rb +11 -0
- data/lib/adhearsion/event/answered.rb +11 -0
- data/lib/adhearsion/event/asterisk.rb +10 -0
- data/lib/adhearsion/event/asterisk/ami.rb +34 -0
- data/lib/adhearsion/event/complete.rb +75 -0
- data/lib/adhearsion/event/dtmf.rb +11 -0
- data/lib/adhearsion/event/end.rb +22 -0
- data/lib/adhearsion/event/input_timers_started.rb +9 -0
- data/lib/adhearsion/event/joined.rb +17 -0
- data/lib/adhearsion/event/offer.rb +14 -0
- data/lib/adhearsion/event/ringing.rb +11 -0
- data/lib/adhearsion/event/started_speaking.rb +13 -0
- data/lib/adhearsion/event/stopped_speaking.rb +13 -0
- data/lib/adhearsion/event/unjoined.rb +17 -0
- data/lib/adhearsion/events.rb +47 -66
- data/lib/adhearsion/foundation.rb +0 -1
- data/lib/adhearsion/foundation/object.rb +0 -5
- data/lib/adhearsion/generators/app/app_generator.rb +4 -1
- data/lib/adhearsion/generators/app/templates/Gemfile.erb +2 -10
- data/lib/adhearsion/generators/app/templates/adhearsion.erb +9 -9
- data/lib/adhearsion/generators/app/templates/config.ru +7 -0
- data/lib/adhearsion/generators/app/templates/en.yml +4 -0
- data/lib/adhearsion/generators/app/templates/events.erb +2 -2
- data/lib/adhearsion/generators/app/templates/hello_world.wav +0 -0
- data/lib/adhearsion/generators/app/templates/simon_game.rb +2 -1
- data/lib/adhearsion/generators/app/templates/simon_game_spec.rb +2 -2
- data/lib/adhearsion/has_headers.rb +34 -0
- data/lib/adhearsion/http_server.rb +37 -0
- data/lib/adhearsion/initializer.rb +19 -153
- data/lib/adhearsion/logging.rb +6 -25
- data/lib/adhearsion/outbound_call.rb +5 -5
- data/lib/adhearsion/plugin.rb +1 -0
- data/lib/adhearsion/protocol_error.rb +26 -0
- data/lib/adhearsion/rayo.rb +30 -0
- data/lib/adhearsion/rayo/client.rb +62 -0
- data/lib/adhearsion/rayo/client/component_registry.rb +33 -0
- data/lib/adhearsion/rayo/command.rb +21 -0
- data/lib/adhearsion/rayo/command/accept.rb +16 -0
- data/lib/adhearsion/rayo/command/answer.rb +16 -0
- data/lib/adhearsion/rayo/command/dial.rb +57 -0
- data/lib/adhearsion/rayo/command/hangup.rb +16 -0
- data/lib/adhearsion/rayo/command/join.rb +43 -0
- data/lib/adhearsion/rayo/command/mute.rb +13 -0
- data/lib/adhearsion/rayo/command/redirect.rb +23 -0
- data/lib/adhearsion/rayo/command/reject.rb +40 -0
- data/lib/adhearsion/rayo/command/unjoin.rb +24 -0
- data/lib/adhearsion/rayo/command/unmute.rb +13 -0
- data/lib/adhearsion/rayo/command_node.rb +47 -0
- data/lib/adhearsion/rayo/component.rb +21 -0
- data/lib/adhearsion/rayo/component/asterisk.rb +13 -0
- data/lib/adhearsion/rayo/component/asterisk/agi.rb +14 -0
- data/lib/adhearsion/rayo/component/asterisk/agi/command.rb +46 -0
- data/lib/adhearsion/rayo/component/asterisk/ami.rb +14 -0
- data/lib/adhearsion/rayo/component/asterisk/ami/action.rb +61 -0
- data/lib/adhearsion/rayo/component/component_node.rb +90 -0
- data/lib/adhearsion/rayo/component/input.rb +186 -0
- data/lib/adhearsion/rayo/component/output.rb +471 -0
- data/lib/adhearsion/rayo/component/prompt.rb +53 -0
- data/lib/adhearsion/rayo/component/receive_fax.rb +26 -0
- data/lib/adhearsion/rayo/component/record.rb +165 -0
- data/lib/adhearsion/rayo/component/send_fax.rb +64 -0
- data/lib/adhearsion/rayo/component/stop.rb +11 -0
- data/lib/adhearsion/rayo/connection.rb +12 -0
- data/lib/adhearsion/rayo/connection/asterisk.rb +74 -0
- data/lib/adhearsion/rayo/connection/connected.rb +22 -0
- data/lib/adhearsion/rayo/connection/generic_connection.rb +22 -0
- data/lib/adhearsion/rayo/connection/xmpp.rb +198 -0
- data/lib/adhearsion/rayo/disconnected_error.rb +22 -0
- data/lib/adhearsion/{punchblock_plugin → rayo}/initializer.rb +19 -19
- data/lib/adhearsion/rayo/rayo_node.rb +127 -0
- data/lib/adhearsion/rayo/ref.rb +57 -0
- data/lib/adhearsion/statistics.rb +1 -1
- data/lib/adhearsion/tasks.rb +1 -2
- data/lib/adhearsion/tasks/configuration.rb +1 -1
- data/lib/adhearsion/tasks/environment.rb +0 -2
- data/lib/adhearsion/tasks/i18n.rb +49 -0
- data/lib/adhearsion/translator.rb +11 -0
- data/lib/adhearsion/translator/asterisk.rb +234 -0
- data/lib/adhearsion/translator/asterisk/agi_app.rb +17 -0
- data/lib/adhearsion/translator/asterisk/agi_command.rb +45 -0
- data/lib/adhearsion/translator/asterisk/ami_error_converter.rb +20 -0
- data/lib/adhearsion/translator/asterisk/call.rb +416 -0
- data/lib/adhearsion/translator/asterisk/channel.rb +43 -0
- data/lib/adhearsion/translator/asterisk/component.rb +88 -0
- data/lib/adhearsion/translator/asterisk/component/asterisk.rb +15 -0
- data/lib/adhearsion/translator/asterisk/component/asterisk/agi_command.rb +42 -0
- data/lib/adhearsion/translator/asterisk/component/asterisk/ami_action.rb +68 -0
- data/lib/adhearsion/translator/asterisk/component/composed_prompt.rb +76 -0
- data/lib/adhearsion/translator/asterisk/component/dtmf_recognizer.rb +137 -0
- data/lib/adhearsion/translator/asterisk/component/input.rb +34 -0
- data/lib/adhearsion/translator/asterisk/component/input_component.rb +90 -0
- data/lib/adhearsion/translator/asterisk/component/mrcp_native_prompt.rb +71 -0
- data/lib/adhearsion/translator/asterisk/component/mrcp_prompt.rb +55 -0
- data/lib/adhearsion/translator/asterisk/component/mrcp_recog_prompt.rb +165 -0
- data/lib/adhearsion/translator/asterisk/component/output.rb +233 -0
- data/lib/adhearsion/translator/asterisk/component/record.rb +101 -0
- data/lib/adhearsion/translator/asterisk/component/stop_by_redirect.rb +30 -0
- data/lib/adhearsion/translator/asterisk/unimrcp_app.rb +28 -0
- data/lib/adhearsion/uri_list.rb +21 -0
- data/lib/adhearsion/version.rb +1 -1
- data/spec/adhearsion/call_controller/dial_spec.rb +79 -1420
- data/spec/adhearsion/call_controller/input_spec.rb +1141 -237
- data/spec/adhearsion/call_controller/output/async_player_spec.rb +10 -10
- data/spec/adhearsion/call_controller/output/player_spec.rb +8 -8
- data/spec/adhearsion/call_controller/output_spec.rb +162 -215
- data/spec/adhearsion/call_controller/record_spec.rb +15 -16
- data/spec/adhearsion/call_controller_spec.rb +23 -40
- data/spec/adhearsion/call_spec.rb +123 -129
- data/spec/adhearsion/calls_spec.rb +3 -3
- data/spec/adhearsion/configuration_spec.rb +94 -108
- data/spec/adhearsion/event/answered_spec.rb +50 -0
- data/spec/adhearsion/event/asterisk/Find Results +402 -0
- data/spec/adhearsion/event/asterisk/ami_spec.rb +81 -0
- data/spec/adhearsion/event/complete_spec.rb +176 -0
- data/spec/adhearsion/event/dtmf_spec.rb +35 -0
- data/spec/adhearsion/event/end_spec.rb +85 -0
- data/spec/adhearsion/event/input_timers_started_spec.rb +19 -0
- data/spec/adhearsion/event/joined_spec.rb +53 -0
- data/spec/adhearsion/event/offer_spec.rb +106 -0
- data/spec/adhearsion/event/ringing_spec.rb +50 -0
- data/spec/adhearsion/event/started_speaking_spec.rb +37 -0
- data/spec/adhearsion/event/stopped_speaking_spec.rb +37 -0
- data/spec/adhearsion/event/unjoined_spec.rb +48 -0
- data/spec/adhearsion/event/untitled +0 -0
- data/spec/adhearsion/events_spec.rb +19 -45
- data/spec/adhearsion/initializer_spec.rb +12 -184
- data/spec/adhearsion/logging_spec.rb +5 -20
- data/spec/adhearsion/outbound_call_spec.rb +13 -13
- data/spec/adhearsion/plugin_spec.rb +3 -4
- data/spec/adhearsion/protocol_error_spec.rb +91 -0
- data/spec/adhearsion/rayo/client/component_registry_spec.rb +26 -0
- data/spec/adhearsion/rayo/client_spec.rb +134 -0
- data/spec/adhearsion/rayo/command/accept_spec.rb +63 -0
- data/spec/adhearsion/rayo/command/answer_spec.rb +73 -0
- data/spec/adhearsion/rayo/command/dial_spec.rb +156 -0
- data/spec/adhearsion/rayo/command/hangup_spec.rb +63 -0
- data/spec/adhearsion/rayo/command/join_spec.rb +158 -0
- data/spec/adhearsion/rayo/command/mute_spec.rb +32 -0
- data/spec/adhearsion/rayo/command/redirect_spec.rb +89 -0
- data/spec/adhearsion/rayo/command/reject_spec.rb +117 -0
- data/spec/adhearsion/rayo/command/unjoin_spec.rb +82 -0
- data/spec/adhearsion/rayo/command/unmute_spec.rb +32 -0
- data/spec/adhearsion/rayo/command_node_spec.rb +101 -0
- data/spec/adhearsion/rayo/component/asterisk/agi/command_spec.rb +111 -0
- data/spec/adhearsion/rayo/component/asterisk/ami/action_spec.rb +173 -0
- data/spec/adhearsion/rayo/component/component_node_spec.rb +110 -0
- data/spec/adhearsion/rayo/component/input_spec.rb +715 -0
- data/spec/adhearsion/rayo/component/output_spec.rb +1030 -0
- data/spec/adhearsion/rayo/component/prompt_spec.rb +171 -0
- data/spec/adhearsion/rayo/component/receive_fax_spec.rb +136 -0
- data/spec/adhearsion/rayo/component/record_spec.rb +497 -0
- data/spec/adhearsion/rayo/component/send_fax_spec.rb +144 -0
- data/spec/adhearsion/rayo/connection/asterisk_spec.rb +118 -0
- data/spec/adhearsion/rayo/connection/xmpp_spec.rb +449 -0
- data/spec/adhearsion/rayo/initializer_spec.rb +353 -0
- data/spec/adhearsion/rayo/ref_spec.rb +168 -0
- data/spec/adhearsion/rayo_spec.rb +7 -0
- data/spec/adhearsion/router/route_spec.rb +1 -1
- data/spec/adhearsion/statistics_spec.rb +2 -5
- data/spec/adhearsion/translator/asterisk/call_spec.rb +2047 -0
- data/spec/adhearsion/translator/asterisk/component/asterisk/agi_command_spec.rb +256 -0
- data/spec/adhearsion/translator/asterisk/component/asterisk/ami_action_spec.rb +151 -0
- data/spec/adhearsion/translator/asterisk/component/composed_prompt_spec.rb +257 -0
- data/spec/adhearsion/translator/asterisk/component/input_spec.rb +571 -0
- data/spec/adhearsion/translator/asterisk/component/mrcp_native_prompt_spec.rb +774 -0
- data/spec/adhearsion/translator/asterisk/component/mrcp_prompt_spec.rb +1244 -0
- data/spec/adhearsion/translator/asterisk/component/output_spec.rb +1850 -0
- data/spec/adhearsion/translator/asterisk/component/record_spec.rb +426 -0
- data/spec/adhearsion/translator/asterisk/component/stop_by_redirect_spec.rb +62 -0
- data/spec/adhearsion/translator/asterisk/component_spec.rb +83 -0
- data/spec/adhearsion/translator/asterisk_spec.rb +685 -0
- data/spec/adhearsion/uri_list_spec.rb +88 -0
- data/spec/adhearsion_spec.rb +89 -14
- data/spec/fixtures/locale/en.yml +13 -0
- data/spec/fixtures/locale/it.yml +13 -0
- data/spec/spec_helper.rb +18 -5
- data/spec/support/call_controller_test_helpers.rb +3 -2
- data/spec/support/initializer_stubs.rb +3 -1
- data/spec/support/punchblock_examples.rb +65 -0
- data/spec/support/punchblock_mocks.rb +12 -0
- metadata +412 -70
- data/features/cli_daemon.feature +0 -20
- data/features/cli_restart.feature +0 -52
- data/features/cli_stop.feature +0 -50
- data/lib/adhearsion/call_controller/menu_dsl.rb +0 -21
- data/lib/adhearsion/call_controller/menu_dsl/array_match_calculator.rb +0 -26
- data/lib/adhearsion/call_controller/menu_dsl/calculated_match.rb +0 -43
- data/lib/adhearsion/call_controller/menu_dsl/calculated_match_collection.rb +0 -45
- data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +0 -11
- data/lib/adhearsion/call_controller/menu_dsl/match_calculator.rb +0 -40
- data/lib/adhearsion/call_controller/menu_dsl/menu.rb +0 -207
- data/lib/adhearsion/call_controller/menu_dsl/menu_builder.rb +0 -92
- data/lib/adhearsion/call_controller/menu_dsl/range_match_calculator.rb +0 -60
- data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +0 -25
- data/lib/adhearsion/call_controller/utility.rb +0 -77
- data/lib/adhearsion/foundation/custom_daemonizer.rb +0 -52
- data/lib/adhearsion/punchblock_plugin.rb +0 -63
- data/scripts/cloc-1.64.pl +0 -10483
- data/spec/adhearsion/call_controller/menu_dsl/array_match_calculator_spec.rb +0 -76
- data/spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb +0 -60
- data/spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb +0 -61
- data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +0 -39
- data/spec/adhearsion/call_controller/menu_dsl/match_calculator_spec.rb +0 -17
- data/spec/adhearsion/call_controller/menu_dsl/menu_builder_spec.rb +0 -165
- data/spec/adhearsion/call_controller/menu_dsl/menu_spec.rb +0 -420
- data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +0 -32
- data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +0 -40
- data/spec/adhearsion/call_controller/utility_spec.rb +0 -90
- data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +0 -356
- data/spec/adhearsion/punchblock_plugin_spec.rb +0 -59
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
module Adhearsion
|
|
6
|
+
module Translator
|
|
7
|
+
class Asterisk
|
|
8
|
+
module Component
|
|
9
|
+
describe Input do
|
|
10
|
+
include HasMockCallbackConnection
|
|
11
|
+
|
|
12
|
+
let(:ami_client) { double('AMI') }
|
|
13
|
+
let(:translator) { Translator::Asterisk.new ami_client, connection }
|
|
14
|
+
let(:call) { Translator::Asterisk::Call.new 'foo', translator, ami_client, connection }
|
|
15
|
+
let(:original_command_options) { {} }
|
|
16
|
+
|
|
17
|
+
let :original_command do
|
|
18
|
+
Adhearsion::Rayo::Component::Input.new original_command_options
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
let :grammar do
|
|
22
|
+
RubySpeech::GRXML.draw :mode => 'dtmf', :root => 'pin' do
|
|
23
|
+
rule id: 'digit' do
|
|
24
|
+
one_of do
|
|
25
|
+
0.upto(9) { |d| item { d.to_s } }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
rule id: 'pin', scope: 'public' do
|
|
30
|
+
item repeat: '2' do
|
|
31
|
+
ruleref uri: '#digit'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
subject { Input.new original_command, call }
|
|
38
|
+
|
|
39
|
+
describe '#execute' do
|
|
40
|
+
before { original_command.request! }
|
|
41
|
+
|
|
42
|
+
it "calls send_progress on the call" do
|
|
43
|
+
expect(call).to receive(:send_progress)
|
|
44
|
+
subject.execute
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
before { allow(call).to receive :send_progress }
|
|
48
|
+
|
|
49
|
+
let(:original_command_opts) { {} }
|
|
50
|
+
|
|
51
|
+
let :original_command_options do
|
|
52
|
+
{ :mode => :dtmf, :grammar => { :value => grammar } }.merge(original_command_opts)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
let (:ast13mode) { false }
|
|
56
|
+
|
|
57
|
+
def ami_event_for_dtmf(digit, position)
|
|
58
|
+
if ast13mode
|
|
59
|
+
RubyAMI::Event.new 'DTMF' + (position == :start ? 'Begin' : '') + (position == :end ? 'End' : ''),
|
|
60
|
+
'Digit' => digit.to_s
|
|
61
|
+
else
|
|
62
|
+
RubyAMI::Event.new 'DTMF',
|
|
63
|
+
'Digit' => digit.to_s,
|
|
64
|
+
'Start' => position == :start ? 'Yes' : 'No',
|
|
65
|
+
'End' => position == :end ? 'Yes' : 'No'
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def send_ami_events_for_dtmf(digit)
|
|
70
|
+
call.process_ami_event ami_event_for_dtmf(digit, :start)
|
|
71
|
+
call.process_ami_event ami_event_for_dtmf(digit, :end)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
let(:reason) { original_command.complete_event(5).reason }
|
|
75
|
+
|
|
76
|
+
describe "receiving DTMF events" do
|
|
77
|
+
before do
|
|
78
|
+
subject.execute
|
|
79
|
+
expected_event
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context "when a match is found" do
|
|
83
|
+
before do
|
|
84
|
+
send_ami_events_for_dtmf 1
|
|
85
|
+
send_ami_events_for_dtmf 2
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
let :expected_nlsml do
|
|
89
|
+
RubySpeech::NLSML.draw do
|
|
90
|
+
interpretation confidence: 1 do
|
|
91
|
+
instance "dtmf-1 dtmf-2"
|
|
92
|
+
input "12", mode: :dtmf
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
let :expected_event do
|
|
98
|
+
Adhearsion::Rayo::Component::Input::Complete::Match.new nlsml: expected_nlsml
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "should send a success complete event with the relevant data" do
|
|
102
|
+
expect(reason).to eq(expected_event)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "should not process further dtmf events" do
|
|
106
|
+
expect(subject).to receive(:process_dtmf).never
|
|
107
|
+
send_ami_events_for_dtmf 3
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "should not leave the recognizer running" do
|
|
111
|
+
expect(Celluloid::Actor.all.any? { |a| a.class == Translator::Asterisk::Component::DTMFRecognizer rescue false }).to eq(false)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
context 'with an Asterisk 13 DTMFEnd event' do
|
|
115
|
+
let(:ast13mode) { true }
|
|
116
|
+
it "should send a success complete event with the relevant data" do
|
|
117
|
+
expect(reason).to eq(expected_event)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
context "when the match is invalid" do
|
|
123
|
+
before do
|
|
124
|
+
send_ami_events_for_dtmf 1
|
|
125
|
+
send_ami_events_for_dtmf '#'
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
let :expected_event do
|
|
129
|
+
Adhearsion::Rayo::Component::Input::Complete::NoMatch.new
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "should send a nomatch complete event" do
|
|
133
|
+
expect(reason).to eq(expected_event)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
context 'with an Asterisk 13 DTMFEnd event' do
|
|
137
|
+
let(:ast13mode) { true }
|
|
138
|
+
it "should send a nomatch complete event" do
|
|
139
|
+
expect(reason).to eq(expected_event)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
context "dtmf event received after recognizer has terminated" do
|
|
145
|
+
before do
|
|
146
|
+
send_ami_events_for_dtmf 1
|
|
147
|
+
send_ami_events_for_dtmf '#'
|
|
148
|
+
subject.execute
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
let :expected_event do
|
|
152
|
+
Adhearsion::Rayo::Component::Input::Complete::NoMatch.new
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "should not crash the translator if the recognizer is dead" do
|
|
156
|
+
expect(Celluloid::Actor.all.map { |a| a.class }).to include(Translator::Asterisk::Component::DTMFRecognizer)
|
|
157
|
+
recognizer = Celluloid::Actor.all.find { |a| a.class == Translator::Asterisk::Component::DTMFRecognizer }
|
|
158
|
+
recognizer.terminate if recognizer
|
|
159
|
+
expect(Celluloid::Actor.all.map { |a| a.class }).not_to include(Translator::Asterisk::Component::DTMFRecognizer)
|
|
160
|
+
subject.process_dtmf 1 # trigger failure
|
|
161
|
+
expect(Celluloid::Actor.all.map { |a| a.class }).to include(translator.class)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
describe 'grammar' do
|
|
167
|
+
context 'unset' do
|
|
168
|
+
let(:original_command_opts) { { :grammar => nil } }
|
|
169
|
+
it "should return an error and not execute any actions" do
|
|
170
|
+
subject.execute
|
|
171
|
+
error = Adhearsion::ProtocolError.new.setup 'option error', 'A grammar document is required.'
|
|
172
|
+
expect(original_command.response(0.1)).to eq(error)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
context 'with a builtin grammar' do
|
|
177
|
+
let(:original_command_opts) { { grammar: { url: 'builtin:dtmf/boolean' } } }
|
|
178
|
+
|
|
179
|
+
before do
|
|
180
|
+
subject.execute
|
|
181
|
+
expected_event
|
|
182
|
+
send_ami_events_for_dtmf 1
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
let :expected_nlsml do
|
|
186
|
+
RubySpeech::NLSML.draw do
|
|
187
|
+
interpretation confidence: 1 do
|
|
188
|
+
instance "true"
|
|
189
|
+
input "1", mode: :dtmf
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
let :expected_event do
|
|
195
|
+
Adhearsion::Rayo::Component::Input::Complete::Match.new nlsml: expected_nlsml
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it "should use RubySpeech builtin grammar" do
|
|
199
|
+
expect(reason).to eq(expected_event)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
context 'with a parameterized builtin grammar' do
|
|
204
|
+
let(:original_command_opts) { { grammar: { url: 'builtin:dtmf/boolean?n=3;y=4' } } }
|
|
205
|
+
|
|
206
|
+
before do
|
|
207
|
+
subject.execute
|
|
208
|
+
expected_event
|
|
209
|
+
send_ami_events_for_dtmf 4
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
let :expected_nlsml do
|
|
213
|
+
RubySpeech::NLSML.draw do
|
|
214
|
+
interpretation confidence: 1 do
|
|
215
|
+
instance "true"
|
|
216
|
+
input "4", mode: :dtmf
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
let :expected_event do
|
|
222
|
+
Adhearsion::Rayo::Component::Input::Complete::Match.new nlsml: expected_nlsml
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "should use RubySpeech builtin grammar" do
|
|
226
|
+
expect(reason).to eq(expected_event)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
context 'with multiple grammars' do
|
|
231
|
+
let(:original_command_opts) { { :grammars => [{:value => grammar}, {:value => grammar}] } }
|
|
232
|
+
it "should return an error and not execute any actions" do
|
|
233
|
+
subject.execute
|
|
234
|
+
error = Adhearsion::ProtocolError.new.setup 'option error', 'Only a single grammar is supported.'
|
|
235
|
+
expect(original_command.response(0.1)).to eq(error)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
describe 'mode' do
|
|
241
|
+
context 'unset' do
|
|
242
|
+
let(:original_command_opts) { { :mode => nil } }
|
|
243
|
+
it "should return an error and not execute any actions" do
|
|
244
|
+
subject.execute
|
|
245
|
+
error = Adhearsion::ProtocolError.new.setup 'option error', 'A mode value other than DTMF is unsupported.'
|
|
246
|
+
expect(original_command.response(0.1)).to eq(error)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
context 'any' do
|
|
251
|
+
let(:original_command_opts) { { :mode => :any } }
|
|
252
|
+
it "should return an error and not execute any actions" do
|
|
253
|
+
subject.execute
|
|
254
|
+
error = Adhearsion::ProtocolError.new.setup 'option error', 'A mode value other than DTMF is unsupported.'
|
|
255
|
+
expect(original_command.response(0.1)).to eq(error)
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
context 'voice' do
|
|
260
|
+
let(:original_command_opts) { { :mode => :voice } }
|
|
261
|
+
it "should return an error and not execute any actions" do
|
|
262
|
+
subject.execute
|
|
263
|
+
error = Adhearsion::ProtocolError.new.setup 'option error', 'A mode value other than DTMF is unsupported.'
|
|
264
|
+
expect(original_command.response(0.1)).to eq(error)
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
describe 'terminator' do
|
|
270
|
+
context 'set' do
|
|
271
|
+
let(:original_command_opts) { { terminator: '#' } }
|
|
272
|
+
|
|
273
|
+
before do
|
|
274
|
+
subject.execute
|
|
275
|
+
expected_event
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
let :grammar do
|
|
279
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'digits' do
|
|
280
|
+
rule id: 'digits' do
|
|
281
|
+
item repeat: '2-5' do
|
|
282
|
+
one_of do
|
|
283
|
+
0.upto(9) { |d| item { d.to_s } }
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
let :expected_nlsml do
|
|
291
|
+
RubySpeech::NLSML.draw do
|
|
292
|
+
interpretation confidence: 1 do
|
|
293
|
+
instance "dtmf-1 dtmf-2"
|
|
294
|
+
input "12", mode: :dtmf
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
let :expected_event do
|
|
300
|
+
Adhearsion::Rayo::Component::Input::Complete::Match.new nlsml: expected_nlsml
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
context "when encountered with a match" do
|
|
304
|
+
before do
|
|
305
|
+
send_ami_events_for_dtmf 1
|
|
306
|
+
send_ami_events_for_dtmf 2
|
|
307
|
+
send_ami_events_for_dtmf '#'
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
it "should send a match complete event with the relevant data" do
|
|
311
|
+
expect(reason).to eq(expected_event)
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it "should not process further dtmf events" do
|
|
315
|
+
expect(subject).to receive(:process_dtmf).never
|
|
316
|
+
send_ami_events_for_dtmf 3
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
context "when encountered with a NoMatch" do
|
|
321
|
+
before do
|
|
322
|
+
send_ami_events_for_dtmf '#'
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
let :expected_event do
|
|
326
|
+
Adhearsion::Rayo::Component::Input::Complete::NoMatch.new
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
it "should send a nomatch complete event with the relevant data" do
|
|
330
|
+
expect(reason).to eq(expected_event)
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
context "when encountered with a PotentialMatch" do
|
|
335
|
+
before do
|
|
336
|
+
send_ami_events_for_dtmf 1
|
|
337
|
+
send_ami_events_for_dtmf '#'
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
let :expected_event do
|
|
341
|
+
Adhearsion::Rayo::Component::Input::Complete::NoMatch.new
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
it "should send a nomatch complete event with the relevant data" do
|
|
345
|
+
expect(reason).to eq(expected_event)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
describe 'recognizer' do
|
|
352
|
+
skip
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
describe 'initial-timeout' do
|
|
356
|
+
context 'a positive number' do
|
|
357
|
+
let(:original_command_opts) { { :initial_timeout => 1000 } }
|
|
358
|
+
|
|
359
|
+
it "should not cause a NoInput if first input is received in time" do
|
|
360
|
+
subject.execute
|
|
361
|
+
send_ami_events_for_dtmf 1
|
|
362
|
+
sleep 1.5
|
|
363
|
+
send_ami_events_for_dtmf 2
|
|
364
|
+
expect(reason).to be_a Adhearsion::Rayo::Component::Input::Complete::Match
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
it "should cause a NoInput complete event to be sent after the timeout" do
|
|
368
|
+
subject.execute
|
|
369
|
+
sleep 1.5
|
|
370
|
+
send_ami_events_for_dtmf 1
|
|
371
|
+
send_ami_events_for_dtmf 2
|
|
372
|
+
expect(reason).to be_a Adhearsion::Rayo::Component::Input::Complete::NoInput
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
context '-1' do
|
|
377
|
+
let(:original_command_opts) { { :initial_timeout => -1 } }
|
|
378
|
+
|
|
379
|
+
it "should not start a timer" do
|
|
380
|
+
expect(subject).to receive(:begin_initial_timer).never
|
|
381
|
+
subject.execute
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
context 'unset' do
|
|
386
|
+
let(:original_command_opts) { { :initial_timeout => nil } }
|
|
387
|
+
|
|
388
|
+
it "should not start a timer" do
|
|
389
|
+
expect(subject).to receive(:begin_initial_timer).never
|
|
390
|
+
subject.execute
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
context 'a negative number other than -1' do
|
|
395
|
+
let(:original_command_opts) { { :initial_timeout => -1000 } }
|
|
396
|
+
|
|
397
|
+
it "should return an error and not execute any actions" do
|
|
398
|
+
subject.execute
|
|
399
|
+
error = Adhearsion::ProtocolError.new.setup 'option error', 'An initial timeout value that is negative (and not -1) is invalid.'
|
|
400
|
+
expect(original_command.response(0.1)).to eq(error)
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
describe 'inter-digit-timeout' do
|
|
406
|
+
context 'a positive number' do
|
|
407
|
+
let(:original_command_opts) { { :inter_digit_timeout => 1000 } }
|
|
408
|
+
|
|
409
|
+
it "should not prevent a Match if input is received in time" do
|
|
410
|
+
subject.execute
|
|
411
|
+
sleep 1.5
|
|
412
|
+
send_ami_events_for_dtmf 1
|
|
413
|
+
sleep 0.5
|
|
414
|
+
send_ami_events_for_dtmf 2
|
|
415
|
+
expect(reason).to be_a Adhearsion::Rayo::Component::Input::Complete::Match
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
it "should cause a NoMatch complete event to be sent after the timeout" do
|
|
419
|
+
subject.execute
|
|
420
|
+
sleep 1.5
|
|
421
|
+
send_ami_events_for_dtmf 1
|
|
422
|
+
sleep 1.5
|
|
423
|
+
send_ami_events_for_dtmf 2
|
|
424
|
+
expect(reason).to be_a Adhearsion::Rayo::Component::Input::Complete::NoMatch
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
context "with a trailing range repeat" do
|
|
428
|
+
let :grammar do
|
|
429
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'digits' do
|
|
430
|
+
rule id: 'digits', scope: 'public' do
|
|
431
|
+
item repeat: '2-5' do
|
|
432
|
+
'1'
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
context "when the buffer potentially matches the grammar" do
|
|
439
|
+
it "should cause a NoMatch complete event to be sent after the timeout" do
|
|
440
|
+
subject.execute
|
|
441
|
+
sleep 1.5
|
|
442
|
+
send_ami_events_for_dtmf 1
|
|
443
|
+
sleep 1.5
|
|
444
|
+
expect(reason).to be_a Adhearsion::Rayo::Component::Input::Complete::NoMatch
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
context "when the buffer matches the grammar" do
|
|
449
|
+
let :expected_nlsml do
|
|
450
|
+
RubySpeech::NLSML.draw do
|
|
451
|
+
interpretation confidence: 1 do
|
|
452
|
+
instance "dtmf-1 dtmf-1"
|
|
453
|
+
input '11', mode: :dtmf
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
it "should fire a match on timeout" do
|
|
459
|
+
subject.execute
|
|
460
|
+
sleep 1.5
|
|
461
|
+
send_ami_events_for_dtmf 1
|
|
462
|
+
sleep 0.5
|
|
463
|
+
send_ami_events_for_dtmf 1
|
|
464
|
+
sleep 1.5
|
|
465
|
+
expect(reason).to be_a Adhearsion::Rayo::Component::Input::Complete::Match
|
|
466
|
+
expect(reason.nlsml).to eq(expected_nlsml)
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
context "on the first keypress" do
|
|
470
|
+
let :grammar do
|
|
471
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'digits' do
|
|
472
|
+
rule id: 'digits', scope: 'public' do
|
|
473
|
+
item repeat: '1-5' do
|
|
474
|
+
'1'
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
it "should fire a match on timeout" do
|
|
481
|
+
subject.execute
|
|
482
|
+
sleep 1.5
|
|
483
|
+
send_ami_events_for_dtmf 1
|
|
484
|
+
sleep 0.5
|
|
485
|
+
send_ami_events_for_dtmf 1
|
|
486
|
+
sleep 1.5
|
|
487
|
+
expect(reason).to be_a Adhearsion::Rayo::Component::Input::Complete::Match
|
|
488
|
+
expect(reason.nlsml).to eq(expected_nlsml)
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
context '-1' do
|
|
496
|
+
let(:original_command_opts) { { :inter_digit_timeout => -1 } }
|
|
497
|
+
|
|
498
|
+
it "should not start a timer" do
|
|
499
|
+
expect(subject).to receive(:begin_inter_digit_timer).never
|
|
500
|
+
subject.execute
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
context 'unset' do
|
|
505
|
+
let(:original_command_opts) { { :inter_digit_timeout => nil } }
|
|
506
|
+
|
|
507
|
+
it "should not start a timer" do
|
|
508
|
+
expect(subject).to receive(:begin_inter_digit_timer).never
|
|
509
|
+
subject.execute
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
context 'a negative number other than -1' do
|
|
514
|
+
let(:original_command_opts) { { :inter_digit_timeout => -1000 } }
|
|
515
|
+
|
|
516
|
+
it "should return an error and not execute any actions" do
|
|
517
|
+
subject.execute
|
|
518
|
+
error = Adhearsion::ProtocolError.new.setup 'option error', 'An inter-digit timeout value that is negative (and not -1) is invalid.'
|
|
519
|
+
expect(original_command.response(0.1)).to eq(error)
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
describe 'sensitivity' do
|
|
525
|
+
skip
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
describe 'min-confidence' do
|
|
529
|
+
skip
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
describe 'max-silence' do
|
|
533
|
+
skip
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
describe "#execute_command" do
|
|
538
|
+
context "with a command it does not understand" do
|
|
539
|
+
let(:command) { Adhearsion::Rayo::Component::Output::Pause.new }
|
|
540
|
+
|
|
541
|
+
before { command.request! }
|
|
542
|
+
|
|
543
|
+
it "returns a Adhearsion::ProtocolError response" do
|
|
544
|
+
subject.execute_command command
|
|
545
|
+
expect(command.response(0.1)).to be_a Adhearsion::ProtocolError
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
context "with a Stop command" do
|
|
550
|
+
let(:command) { Adhearsion::Rayo::Component::Stop.new }
|
|
551
|
+
let(:reason) { original_command.complete_event(5).reason }
|
|
552
|
+
|
|
553
|
+
before do
|
|
554
|
+
command.request!
|
|
555
|
+
original_command.request!
|
|
556
|
+
original_command.execute!
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
it "sets the command response to true" do
|
|
560
|
+
subject.execute_command command
|
|
561
|
+
expect(command.response(0.1)).to eq(true)
|
|
562
|
+
expect(reason).to be_a Adhearsion::Event::Complete::Stop
|
|
563
|
+
end
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
end
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
end
|