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
|
@@ -8,334 +8,1238 @@ module Adhearsion
|
|
|
8
8
|
describe Input do
|
|
9
9
|
include CallControllerTestHelpers
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
let(:sound_file) { "press a button" }
|
|
16
|
-
let(:sound_files) { [sound_file] }
|
|
17
|
-
|
|
18
|
-
it "should play the sound files for the menu" do
|
|
19
|
-
expect(subject).to receive(:interruptible_play).with(sound_file, renderer_options).and_return("1")
|
|
20
|
-
expect(subject.play_sound_files_for_menu(menu_instance, sound_files)).to eq('1')
|
|
11
|
+
def self.temp_config_value(key, value, namespace = Adhearsion.config.core.media)
|
|
12
|
+
before do
|
|
13
|
+
@original_value = namespace[key]
|
|
14
|
+
namespace[key] = value
|
|
21
15
|
end
|
|
22
16
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
expect(subject).to receive(:wait_for_digit).with(menu_instance.timeout).and_return("1")
|
|
26
|
-
expect(subject.play_sound_files_for_menu(menu_instance, sound_files)).to eq('1')
|
|
27
|
-
end
|
|
17
|
+
after { namespace[key] = @original_value }
|
|
18
|
+
end
|
|
28
19
|
|
|
29
|
-
|
|
30
|
-
let(:options) { { :renderer => :native } }
|
|
31
|
-
let(:renderer_options) { { renderer: :native } }
|
|
32
|
-
it "should play the sound files for the menu" do
|
|
33
|
-
expect(subject).to receive(:interruptible_play).with(sound_file, renderer_options).and_return("1")
|
|
34
|
-
expect(subject.play_sound_files_for_menu(menu_instance, sound_files)).to eq('1')
|
|
35
|
-
end
|
|
20
|
+
let(:prompts) { ['http://example.com/nice-to-meet-you.mp3', 'http://example.com/press-some-buttons.mp3'] }
|
|
36
21
|
|
|
22
|
+
let :expected_ssml do
|
|
23
|
+
RubySpeech::SSML.draw do
|
|
24
|
+
audio src: 'http://example.com/nice-to-meet-you.mp3'
|
|
25
|
+
audio src: 'http://example.com/press-some-buttons.mp3'
|
|
37
26
|
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
let :expected_output_options do
|
|
30
|
+
{
|
|
31
|
+
render_document: {value: expected_ssml},
|
|
32
|
+
renderer: nil
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
let :expected_input_options do
|
|
37
|
+
{
|
|
38
|
+
mode: :dtmf,
|
|
39
|
+
initial_timeout: 5000,
|
|
40
|
+
inter_digit_timeout: 2000,
|
|
41
|
+
max_silence: 5000,
|
|
42
|
+
min_confidence: 0.5,
|
|
43
|
+
recognizer: nil,
|
|
44
|
+
language: 'en-US',
|
|
45
|
+
grammar: { value: expected_grxml }
|
|
46
|
+
}
|
|
47
|
+
end
|
|
38
48
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
let(:expected_barge_in) { true }
|
|
50
|
+
|
|
51
|
+
let :expected_prompt do
|
|
52
|
+
Adhearsion::Rayo::Component::Prompt.new expected_output_options, expected_input_options, barge_in: expected_barge_in
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
let(:reason) { Adhearsion::Rayo::Component::Input::Complete::NoMatch.new }
|
|
56
|
+
|
|
57
|
+
before { allow_any_instance_of(Adhearsion::Rayo::Component::Prompt).to receive(:complete_event).and_return(double(reason: reason)) }
|
|
58
|
+
|
|
59
|
+
describe "#ask" do
|
|
60
|
+
let :digit_limit_grammar do
|
|
61
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'digits', tag_format: 'semantics/1.0-literals' do
|
|
62
|
+
rule id: 'digits', scope: 'public' do
|
|
63
|
+
item repeat: '0-5' do
|
|
64
|
+
one_of do
|
|
65
|
+
0.upto(9) { |d| item { d.to_s } }
|
|
66
|
+
item { "#" }
|
|
67
|
+
item { "*" }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
45
71
|
end
|
|
46
72
|
end
|
|
47
73
|
|
|
48
|
-
context "
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
it "should pass the renderer option to #play" do
|
|
52
|
-
expect(subject).to receive(:play).with(sound_file, renderer_options).and_return true
|
|
53
|
-
expect(subject).to receive(:wait_for_digit).with(menu_instance.timeout).and_return("1")
|
|
54
|
-
expect(subject.play_sound_files_for_menu(menu_instance, sound_files)).to eq('1')
|
|
74
|
+
context "without a digit limit, terminator digit or grammar" do
|
|
75
|
+
it "raises ArgumentError" do
|
|
76
|
+
expect { subject.ask prompts }.to raise_error(ArgumentError, "You must specify at least one of limit, terminator or grammar")
|
|
55
77
|
end
|
|
56
78
|
end
|
|
57
|
-
end#play_sound_files_for_menu
|
|
58
79
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
let(:timeout_ms) { 2000 }
|
|
80
|
+
context "with a digit limit" do
|
|
81
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
62
82
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
83
|
+
it "executes a Prompt component with the correct prompts and grammar" do
|
|
84
|
+
expect_component_execution expected_prompt
|
|
85
|
+
|
|
86
|
+
subject.ask prompts, limit: 5
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context "with nil prompts" do
|
|
90
|
+
let(:prompts) { [nil, 'http://example.com/nice-to-meet-you.mp3', 'http://example.com/press-some-buttons.mp3'] }
|
|
91
|
+
|
|
92
|
+
it "executes a Prompt component with the correct prompts and grammar" do
|
|
93
|
+
expect_component_execution expected_prompt
|
|
94
|
+
subject.ask prompts, limit: 5
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
context "with no prompts" do
|
|
99
|
+
it "executes an Input component with the correct grammar" do
|
|
100
|
+
allow_any_instance_of(Adhearsion::Rayo::Component::Input).to receive(:complete_event).and_return(double(reason: reason))
|
|
101
|
+
expect_component_execution Adhearsion::Rayo::Component::Input.new(expected_input_options)
|
|
102
|
+
subject.ask limit: 5
|
|
71
103
|
end
|
|
72
104
|
end
|
|
73
|
-
}
|
|
74
105
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
:grammar => {
|
|
81
|
-
:value => grxml.to_s
|
|
106
|
+
context "with no prompts, but with a render_document option" do
|
|
107
|
+
let :expected_output_options do
|
|
108
|
+
{
|
|
109
|
+
render_document: {url: 'http://foo.com/bar'},
|
|
110
|
+
renderer: nil
|
|
82
111
|
}
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
}
|
|
112
|
+
end
|
|
86
113
|
|
|
87
|
-
|
|
114
|
+
it "executes an Input component with the correct grammar" do
|
|
115
|
+
allow_any_instance_of(Adhearsion::Rayo::Component::Input).to receive(:complete_event).and_return(double(reason: reason))
|
|
116
|
+
expect_component_execution expected_prompt
|
|
117
|
+
subject.ask limit: 5, render_document: {url: 'http://foo.com/bar'}
|
|
118
|
+
end
|
|
119
|
+
end
|
|
88
120
|
|
|
89
|
-
|
|
90
|
-
|
|
121
|
+
context "with only nil prompts" do
|
|
122
|
+
it "executes an Input component with the correct grammar" do
|
|
123
|
+
allow_any_instance_of(Adhearsion::Rayo::Component::Input).to receive(:complete_event).and_return(double(reason: reason))
|
|
124
|
+
expect_component_execution Adhearsion::Rayo::Component::Input.new(expected_input_options)
|
|
125
|
+
subject.ask nil, limit: 5
|
|
126
|
+
end
|
|
127
|
+
end
|
|
91
128
|
end
|
|
92
129
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
130
|
+
context "with a terminator" do
|
|
131
|
+
let :expected_grxml do
|
|
132
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'digits', tag_format: 'semantics/1.0-literals' do
|
|
133
|
+
rule id: 'digits', scope: 'public' do
|
|
134
|
+
item repeat: '0-' do
|
|
135
|
+
one_of do
|
|
136
|
+
0.upto(9) { |d| item { d.to_s } }
|
|
137
|
+
item { "#" }
|
|
138
|
+
item { "*" }
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
before do
|
|
146
|
+
expected_input_options.merge! terminator: '#'
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "executes a Prompt component with the correct prompts and grammar" do
|
|
150
|
+
expect_component_execution expected_prompt
|
|
98
151
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
expect(subject).to receive(:execute_component_and_await_completion).once.with(kind_of(Punchblock::Component::Input)).and_return input_component
|
|
102
|
-
expect(subject.wait_for_digit(timeout)).to eq('5')
|
|
152
|
+
subject.ask prompts, terminator: '#'
|
|
153
|
+
end
|
|
103
154
|
end
|
|
104
155
|
|
|
105
|
-
context "
|
|
106
|
-
let
|
|
156
|
+
context "with a digit limit and a terminator" do
|
|
157
|
+
let :expected_grxml do
|
|
158
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'digits', tag_format: 'semantics/1.0-literals' do
|
|
159
|
+
rule id: 'digits', scope: 'public' do
|
|
160
|
+
item repeat: '0-5' do
|
|
161
|
+
one_of do
|
|
162
|
+
0.upto(9) { |d| item { d.to_s } }
|
|
163
|
+
item { "#" }
|
|
164
|
+
item { "*" }
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
before do
|
|
172
|
+
expected_input_options.merge! grammar: { value: expected_grxml },
|
|
173
|
+
terminator: '#'
|
|
174
|
+
end
|
|
107
175
|
|
|
108
|
-
it "
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
176
|
+
it "executes a Prompt component with the correct prompts and grammar" do
|
|
177
|
+
expect_component_execution expected_prompt
|
|
178
|
+
|
|
179
|
+
subject.ask prompts, limit: 5, terminator: '#'
|
|
112
180
|
end
|
|
113
181
|
end
|
|
114
182
|
|
|
115
|
-
context "with
|
|
116
|
-
let
|
|
117
|
-
|
|
183
|
+
context "with an inline GRXML grammar specified" do
|
|
184
|
+
let :expected_grxml do
|
|
185
|
+
RubySpeech::GRXML.draw root: 'main', language: 'en-us', mode: :voice, tag_format: 'semantics/1.0-literals' do
|
|
186
|
+
rule id: 'main', scope: 'public' do
|
|
187
|
+
one_of do
|
|
188
|
+
item { 'yes' }
|
|
189
|
+
item { 'no' }
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
before do
|
|
196
|
+
expected_input_options.merge! grammar: { value: expected_grxml }
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it "executes a Prompt component with the correct prompts and grammar" do
|
|
200
|
+
expect_component_execution expected_prompt
|
|
118
201
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
202
|
+
subject.ask prompts, grammar: expected_grxml
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
context "with multiple grammars specified" do
|
|
206
|
+
let :other_expected_grxml do
|
|
207
|
+
RubySpeech::GRXML.draw root: 'main', mode: :dtmf, tag_format: 'semantics/1.0-literals' do
|
|
208
|
+
rule id: 'main', scope: 'public' do
|
|
209
|
+
one_of do
|
|
210
|
+
item { 1 }
|
|
211
|
+
item { 2 }
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
before do
|
|
218
|
+
expected_input_options.merge! grammars: [{ value: expected_grxml }, { value: other_expected_grxml }]
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "executes a Prompt component with the correct prompts and grammar" do
|
|
222
|
+
expect_component_execution expected_prompt
|
|
223
|
+
|
|
224
|
+
subject.ask prompts, grammar: [expected_grxml, other_expected_grxml]
|
|
225
|
+
end
|
|
123
226
|
end
|
|
124
227
|
end
|
|
125
|
-
end # wait_for_digit
|
|
126
228
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
229
|
+
context "with a grammar URL specified" do
|
|
230
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
231
|
+
let(:grammar_url) { 'http://example.com/cities.grxml' }
|
|
232
|
+
|
|
233
|
+
before do
|
|
234
|
+
expected_input_options.merge! grammar: { url: grammar_url }
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it "executes a Prompt component with the correct prompts and grammar" do
|
|
238
|
+
expect_component_execution expected_prompt
|
|
239
|
+
|
|
240
|
+
subject.ask prompts, grammar_url: grammar_url
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
context "with multiple grammar URLs specified" do
|
|
244
|
+
let(:other_grammar_url) { 'http://example.com/states.grxml' }
|
|
245
|
+
|
|
246
|
+
before do
|
|
247
|
+
expected_input_options.merge! grammars: [{ url: grammar_url }, { url: other_grammar_url }]
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
it "executes a Prompt component with the correct prompts and grammar" do
|
|
251
|
+
expect_component_execution expected_prompt
|
|
252
|
+
|
|
253
|
+
subject.ask prompts, grammar_url: [grammar_url, other_grammar_url]
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
context "with grammars specified inline and by URL" do
|
|
258
|
+
before do
|
|
259
|
+
expected_input_options.merge! grammars: [{ value: expected_grxml }, { url: grammar_url }]
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it "executes a Prompt component with the correct prompts and grammar" do
|
|
263
|
+
expect_component_execution expected_prompt
|
|
131
264
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
subject.jump_to(match_object, overrides)
|
|
265
|
+
subject.ask prompts, grammar: expected_grxml, grammar_url: [grammar_url]
|
|
266
|
+
end
|
|
267
|
+
end
|
|
136
268
|
end
|
|
137
269
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
270
|
+
context "with interruptible: false" do
|
|
271
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
272
|
+
|
|
273
|
+
let(:expected_barge_in) { false }
|
|
274
|
+
|
|
275
|
+
it "executes a Prompt with barge-in disabled" do
|
|
276
|
+
expect_component_execution expected_prompt
|
|
277
|
+
|
|
278
|
+
subject.ask prompts, limit: 5, interruptible: false
|
|
279
|
+
end
|
|
143
280
|
end
|
|
144
|
-
end#jump_to
|
|
145
281
|
|
|
146
|
-
|
|
147
|
-
|
|
282
|
+
context "with a timeout specified" do
|
|
283
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
284
|
+
|
|
285
|
+
before do
|
|
286
|
+
expected_input_options.merge! initial_timeout: 10000,
|
|
287
|
+
inter_digit_timeout: 2000,
|
|
288
|
+
max_silence: 10000
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
it "executes a Prompt with correct timeout (initial, inter-digit & max-silence)" do
|
|
292
|
+
expect_component_execution expected_prompt
|
|
148
293
|
|
|
149
|
-
|
|
150
|
-
|
|
294
|
+
subject.ask prompts, limit: 5, timeout: 10
|
|
295
|
+
end
|
|
151
296
|
end
|
|
152
297
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
298
|
+
context "with a negative timeout specified" do
|
|
299
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
300
|
+
|
|
301
|
+
before do
|
|
302
|
+
expected_input_options.merge! initial_timeout: -1,
|
|
303
|
+
inter_digit_timeout: -1,
|
|
304
|
+
max_silence: -1
|
|
305
|
+
end
|
|
160
306
|
|
|
161
|
-
|
|
162
|
-
|
|
307
|
+
it "executes a Prompt with correct timeout (initial, inter-digit & max-silence)" do
|
|
308
|
+
expect_component_execution expected_prompt
|
|
163
309
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
expect(MenuDSL::Menu).to receive(:new).and_return(menu_instance)
|
|
310
|
+
subject.ask prompts, limit: 5, timeout: -1, inter_digit_timeout: -1
|
|
311
|
+
end
|
|
167
312
|
end
|
|
168
313
|
|
|
169
|
-
|
|
170
|
-
|
|
314
|
+
context "with a different default timeout" do
|
|
315
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
171
316
|
|
|
172
|
-
|
|
173
|
-
|
|
317
|
+
before do
|
|
318
|
+
expected_input_options.merge! initial_timeout: 10000,
|
|
319
|
+
inter_digit_timeout: 2000,
|
|
320
|
+
max_silence: 10000
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
temp_config_value :timeout, 10
|
|
324
|
+
|
|
325
|
+
it "executes a Prompt with correct timeout (initial, inter-digit & max-silence)" do
|
|
326
|
+
expect_component_execution expected_prompt
|
|
327
|
+
|
|
328
|
+
subject.ask prompts, limit: 5
|
|
329
|
+
end
|
|
174
330
|
end
|
|
175
331
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
332
|
+
context "with a different default minimum confidence" do
|
|
333
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
334
|
+
|
|
335
|
+
before do
|
|
336
|
+
expected_input_options.merge! min_confidence: 0.8
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
temp_config_value :min_confidence, 0.8
|
|
340
|
+
|
|
341
|
+
it "executes a Prompt with correct minimum confidence" do
|
|
342
|
+
expect_component_execution expected_prompt
|
|
343
|
+
|
|
344
|
+
subject.ask prompts, limit: 5
|
|
345
|
+
end
|
|
182
346
|
end
|
|
183
347
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
348
|
+
context "with a different default recognizer" do
|
|
349
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
350
|
+
|
|
351
|
+
before do
|
|
352
|
+
expected_input_options.merge! recognizer: 'something_else'
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
temp_config_value :recognizer, 'something_else'
|
|
356
|
+
|
|
357
|
+
it "executes a Prompt with correct recognizer" do
|
|
358
|
+
expect_component_execution expected_prompt
|
|
359
|
+
|
|
360
|
+
subject.ask prompts, limit: 5
|
|
361
|
+
end
|
|
190
362
|
end
|
|
191
363
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
364
|
+
context "with a different default input language" do
|
|
365
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
366
|
+
|
|
367
|
+
before do
|
|
368
|
+
expected_input_options.merge! language: 'pt-BR'
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
temp_config_value :input_language, 'pt-BR'
|
|
372
|
+
|
|
373
|
+
it "executes a Prompt with correct input language" do
|
|
374
|
+
expect_component_execution expected_prompt
|
|
375
|
+
|
|
376
|
+
subject.ask prompts, limit: 5
|
|
377
|
+
end
|
|
198
378
|
end
|
|
199
379
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
380
|
+
context "with a different default output renderer" do
|
|
381
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
382
|
+
|
|
383
|
+
before do
|
|
384
|
+
expected_output_options.merge! renderer: 'something_else'
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
temp_config_value :default_renderer, 'something_else', Adhearsion.config.core.media
|
|
388
|
+
|
|
389
|
+
it "executes a Prompt with correct renderer" do
|
|
390
|
+
expect_component_execution expected_prompt
|
|
391
|
+
|
|
392
|
+
subject.ask prompts, limit: 5
|
|
393
|
+
end
|
|
206
394
|
end
|
|
207
395
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
396
|
+
context "with a different default output voice" do
|
|
397
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
398
|
+
|
|
399
|
+
before do
|
|
400
|
+
expected_output_options.merge! voice: 'something_else'
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
temp_config_value :default_voice, 'something_else', Adhearsion.config.core.media
|
|
404
|
+
|
|
405
|
+
it "executes a Prompt with correct voice" do
|
|
406
|
+
expect_component_execution expected_prompt
|
|
407
|
+
|
|
408
|
+
subject.ask prompts, limit: 5
|
|
409
|
+
end
|
|
216
410
|
end
|
|
217
411
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
412
|
+
context "with overridden input options" do
|
|
413
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
414
|
+
|
|
415
|
+
before do
|
|
416
|
+
expected_input_options.merge! inter_digit_timeout: 35000
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
it "executes a Prompt with correct input options" do
|
|
420
|
+
expect_component_execution expected_prompt
|
|
421
|
+
|
|
422
|
+
subject.ask prompts, limit: 5, input_options: {inter_digit_timeout: 35000}
|
|
423
|
+
end
|
|
225
424
|
end
|
|
226
425
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
426
|
+
context "with overridden output options" do
|
|
427
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
428
|
+
|
|
429
|
+
before do
|
|
430
|
+
expected_output_options.merge! max_time: 35000
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
it "executes a Prompt with correct output options" do
|
|
434
|
+
expect_component_execution expected_prompt
|
|
435
|
+
|
|
436
|
+
subject.ask prompts, limit: 5, output_options: {max_time: 35000}
|
|
437
|
+
end
|
|
233
438
|
end
|
|
234
439
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
440
|
+
context "when the call is dead when trying to execute the prompt" do
|
|
441
|
+
before { call.terminate }
|
|
442
|
+
|
|
443
|
+
it "should raise Adhearsion::Call::Hangup" do
|
|
444
|
+
expect { subject.ask prompts, limit: 5 }.to raise_error Adhearsion::Call::Hangup
|
|
445
|
+
end
|
|
241
446
|
end
|
|
242
447
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
448
|
+
context "when a utterance is received" do
|
|
449
|
+
let(:expected_grxml) { digit_limit_grammar }
|
|
450
|
+
|
|
451
|
+
before { expect_component_execution expected_prompt }
|
|
452
|
+
|
|
453
|
+
let(:result) { subject.ask prompts, limit: 5 }
|
|
454
|
+
|
|
455
|
+
context "that is a match" do
|
|
456
|
+
let(:mode) { :dtmf }
|
|
457
|
+
let(:utterance) { '123' }
|
|
458
|
+
|
|
459
|
+
let :nlsml do
|
|
460
|
+
utterance = self.utterance
|
|
461
|
+
mode = self.mode
|
|
462
|
+
RubySpeech::NLSML.draw do
|
|
463
|
+
interpretation confidence: 1 do
|
|
464
|
+
input utterance, mode: mode
|
|
465
|
+
instance 'Foo'
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
let(:reason) { Adhearsion::Rayo::Component::Input::Complete::Match.new nlsml: nlsml }
|
|
471
|
+
|
|
472
|
+
it "returns :match status and the utterance" do
|
|
473
|
+
expect(result.status).to be :match
|
|
474
|
+
expect(result).to be_match
|
|
475
|
+
expect(result.mode).to be :dtmf
|
|
476
|
+
expect(result.confidence).to eq(1)
|
|
477
|
+
expect(result.utterance).to eq('123')
|
|
478
|
+
expect(result.interpretation).to eq('Foo')
|
|
479
|
+
expect(result.nlsml).to eq(nlsml)
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
context "with speech input" do
|
|
483
|
+
let(:mode) { :speech }
|
|
484
|
+
let(:utterance) { 'Hello world' }
|
|
485
|
+
|
|
486
|
+
it "should not alter the utterance" do
|
|
487
|
+
expect(result.utterance).to eq('Hello world')
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
context "with a single DTMF digit" do
|
|
492
|
+
context 'with dtmf- prefixes' do
|
|
493
|
+
let(:utterance) { 'dtmf-3' }
|
|
494
|
+
|
|
495
|
+
it "removes dtmf- previxes" do
|
|
496
|
+
expect(result.utterance).to eq('3')
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
context 'with "star"' do
|
|
501
|
+
let(:utterance) { "dtmf-star" }
|
|
502
|
+
|
|
503
|
+
it "interprets as *" do
|
|
504
|
+
expect(result.utterance).to eq('*')
|
|
505
|
+
end
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
context 'with "*"' do
|
|
509
|
+
let(:utterance) { '*' }
|
|
510
|
+
|
|
511
|
+
it "interprets as *" do
|
|
512
|
+
expect(result.utterance).to eq('*')
|
|
513
|
+
end
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
context 'with "pound"' do
|
|
517
|
+
let(:utterance) { 'dtmf-pound' }
|
|
518
|
+
|
|
519
|
+
it "interprets pound as #" do
|
|
520
|
+
expect(result.utterance).to eq('#')
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
context 'with "#"' do
|
|
525
|
+
let(:utterance) { '#' }
|
|
526
|
+
|
|
527
|
+
it "interprets # as #" do
|
|
528
|
+
expect(result.utterance).to eq('#')
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
context 'without a dtmf- prefix' do
|
|
533
|
+
let(:utterance) { '1' }
|
|
534
|
+
|
|
535
|
+
it "correctly interprets the digits" do
|
|
536
|
+
expect(result.utterance).to eq('1')
|
|
537
|
+
end
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
context 'with "star"' do
|
|
541
|
+
let(:utterance) { nil }
|
|
542
|
+
|
|
543
|
+
it "is nil when utterance is nil" do
|
|
544
|
+
expect(result.utterance).to eq(nil)
|
|
545
|
+
end
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
context "with multiple digits separated by spaces" do
|
|
550
|
+
let(:utterance) { '1 dtmf-5 dtmf-star # 2' }
|
|
551
|
+
|
|
552
|
+
it "returns the digits without space separation" do
|
|
553
|
+
expect(result.utterance).to eq('15*#2')
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
context "that is a nomatch" do
|
|
559
|
+
let(:reason) { Adhearsion::Rayo::Component::Input::Complete::NoMatch.new }
|
|
560
|
+
|
|
561
|
+
it "returns :nomatch status and a nil utterance" do
|
|
562
|
+
expect(result.status).to eql(:nomatch)
|
|
563
|
+
expect(result).not_to be_match
|
|
564
|
+
expect(result.utterance).to be_nil
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
context "that is a noinput" do
|
|
569
|
+
let(:reason) { Adhearsion::Rayo::Component::Input::Complete::NoInput.new }
|
|
570
|
+
|
|
571
|
+
it "returns :noinput status and a nil utterance" do
|
|
572
|
+
expect(result.status).to eql(:noinput)
|
|
573
|
+
expect(result).not_to be_match
|
|
574
|
+
expect(result.utterance).to be_nil
|
|
575
|
+
end
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
context "that is a hangup" do
|
|
579
|
+
let(:reason) { Adhearsion::Event::Complete::Hangup.new }
|
|
580
|
+
|
|
581
|
+
it "returns :hangup status and a nil utterance" do
|
|
582
|
+
expect(result.status).to eql(:hangup)
|
|
583
|
+
expect(result).not_to be_match
|
|
584
|
+
expect(result.utterance).to be_nil
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
context "that is a stop" do
|
|
589
|
+
let(:reason) { Adhearsion::Event::Complete::Stop.new }
|
|
590
|
+
|
|
591
|
+
it "returns :stop status and a nil utterance" do
|
|
592
|
+
expect(result.status).to eql(:stop)
|
|
593
|
+
expect(result).not_to be_match
|
|
594
|
+
expect(result.utterance).to be_nil
|
|
595
|
+
end
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
context "that is an error" do
|
|
599
|
+
let(:reason) { Adhearsion::Event::Complete::Error.new details: 'foobar' }
|
|
600
|
+
|
|
601
|
+
it "should raise an error with a message of 'foobar" do
|
|
602
|
+
expect { subject.ask prompts, limit: 5 }.to raise_error(Adhearsion::CallController::Input::InputError, /foobar/)
|
|
603
|
+
end
|
|
604
|
+
end
|
|
250
605
|
end
|
|
606
|
+
end
|
|
251
607
|
|
|
252
|
-
|
|
253
|
-
|
|
608
|
+
describe "#menu" do
|
|
609
|
+
context "with no block" do
|
|
610
|
+
it "should raise ArgumentError" do
|
|
611
|
+
expect { subject.menu }.to raise_error(ArgumentError, /specify a block to build the menu/)
|
|
612
|
+
end
|
|
254
613
|
end
|
|
255
614
|
|
|
256
|
-
context "
|
|
257
|
-
it "should raise
|
|
615
|
+
context "with no matches" do
|
|
616
|
+
it "should raise ArgumentError" do
|
|
617
|
+
expect do
|
|
618
|
+
subject.menu "Hello?" do
|
|
619
|
+
end
|
|
620
|
+
end.to raise_error(ArgumentError, /specify one or more matches/)
|
|
621
|
+
end
|
|
258
622
|
end
|
|
259
623
|
|
|
260
|
-
|
|
624
|
+
context "with several matches specified" do
|
|
625
|
+
let :expected_grxml do
|
|
626
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'options', tag_format: 'semantics/1.0-literals' do
|
|
627
|
+
rule id: 'options', scope: 'public' do
|
|
628
|
+
item do
|
|
629
|
+
one_of do
|
|
630
|
+
item do
|
|
631
|
+
tag { '0' }
|
|
632
|
+
'1'
|
|
633
|
+
end
|
|
634
|
+
end
|
|
635
|
+
end
|
|
636
|
+
end
|
|
637
|
+
end
|
|
638
|
+
end
|
|
261
639
|
|
|
262
|
-
|
|
263
|
-
let(:sound_files) { ["press", "button"] }
|
|
640
|
+
let(:foo) { :bar }
|
|
264
641
|
|
|
265
|
-
|
|
266
|
-
|
|
642
|
+
it "makes the block context available" do
|
|
643
|
+
expect_component_execution expected_prompt
|
|
644
|
+
doo = nil
|
|
645
|
+
subject.menu prompts do
|
|
646
|
+
doo = foo
|
|
647
|
+
match(1) { do_nothing }
|
|
648
|
+
end
|
|
649
|
+
expect(doo).to eq(:bar)
|
|
650
|
+
end
|
|
267
651
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
let(:result_limit_reached) { MenuDSL::Menu::MenuLimitReached.new }
|
|
271
|
-
let(:result_invalid) { MenuDSL::Menu::MenuResultInvalid.new }
|
|
272
|
-
let(:result_get_another_or_timeout) { MenuDSL::Menu::MenuGetAnotherDigitOrTimeout.new }
|
|
273
|
-
let(:result_get_another_or_finish) { MenuDSL::Menu::MenuGetAnotherDigitOrFinish.new(:match_object, :new_extension) }
|
|
274
|
-
let(:result_found) { MenuDSL::Menu::MenuResultFound.new(:match_object, :new_extension) }
|
|
652
|
+
context "with nil prompts" do
|
|
653
|
+
let(:prompts) { [nil, 'http://example.com/nice-to-meet-you.mp3', 'http://example.com/press-some-buttons.mp3'] }
|
|
275
654
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
655
|
+
it "executes a Prompt component with the correct prompts and grammar" do
|
|
656
|
+
expect_component_execution expected_prompt
|
|
657
|
+
subject.menu prompts do
|
|
658
|
+
match(1) {}
|
|
659
|
+
end
|
|
660
|
+
end
|
|
279
661
|
end
|
|
280
662
|
|
|
281
|
-
|
|
282
|
-
|
|
663
|
+
context "with no prompts" do
|
|
664
|
+
it "executes an Input component with the correct grammar" do
|
|
665
|
+
allow_any_instance_of(Adhearsion::Rayo::Component::Input).to receive(:complete_event).and_return(double(reason: reason))
|
|
666
|
+
expect_component_execution Adhearsion::Rayo::Component::Input.new(expected_input_options)
|
|
667
|
+
subject.menu do
|
|
668
|
+
match(1) {}
|
|
669
|
+
end
|
|
670
|
+
end
|
|
671
|
+
end
|
|
283
672
|
|
|
284
|
-
|
|
285
|
-
|
|
673
|
+
context "with only nil prompts" do
|
|
674
|
+
it "executes an Input component with the correct grammar" do
|
|
675
|
+
allow_any_instance_of(Adhearsion::Rayo::Component::Input).to receive(:complete_event).and_return(double(reason: reason))
|
|
676
|
+
expect_component_execution Adhearsion::Rayo::Component::Input.new(expected_input_options)
|
|
677
|
+
subject.menu nil do
|
|
678
|
+
match(1) {}
|
|
679
|
+
end
|
|
680
|
+
end
|
|
286
681
|
end
|
|
287
682
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
683
|
+
context "with interruptible: false" do
|
|
684
|
+
let(:expected_barge_in) { false }
|
|
685
|
+
|
|
686
|
+
it "executes a Prompt with barge-in disabled" do
|
|
687
|
+
expect_component_execution expected_prompt
|
|
688
|
+
|
|
689
|
+
subject.menu prompts, interruptible: false do
|
|
690
|
+
match(1) {}
|
|
691
|
+
end
|
|
692
|
+
end
|
|
293
693
|
end
|
|
294
694
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
695
|
+
context "with a timeout specified" do
|
|
696
|
+
before do
|
|
697
|
+
expected_input_options.merge! initial_timeout: 10000,
|
|
698
|
+
inter_digit_timeout: 10000,
|
|
699
|
+
max_silence: 10000
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
it "executes a Prompt with correct timeout (initial, inter-digit & max-silence)" do
|
|
703
|
+
expect_component_execution expected_prompt
|
|
704
|
+
|
|
705
|
+
subject.menu prompts, timeout: 10, inter_digit_timeout: 10 do
|
|
706
|
+
match(1) {}
|
|
707
|
+
end
|
|
708
|
+
end
|
|
300
709
|
end
|
|
301
710
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
711
|
+
context "with a different default timeout" do
|
|
712
|
+
before do
|
|
713
|
+
expected_input_options.merge! initial_timeout: 10000,
|
|
714
|
+
max_silence: 10000
|
|
715
|
+
end
|
|
716
|
+
|
|
717
|
+
temp_config_value :timeout, 10
|
|
718
|
+
|
|
719
|
+
it "executes a Prompt with correct timeout (initial & max-silence)" do
|
|
720
|
+
expect_component_execution expected_prompt
|
|
721
|
+
|
|
722
|
+
subject.menu prompts do
|
|
723
|
+
match(1) {}
|
|
724
|
+
end
|
|
725
|
+
end
|
|
307
726
|
end
|
|
308
727
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
728
|
+
context "with a different default inter-digit timeout" do
|
|
729
|
+
before do
|
|
730
|
+
expected_input_options.merge! inter_digit_timeout: 10000
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
temp_config_value :inter_digit_timeout, 10
|
|
734
|
+
|
|
735
|
+
it "executes a Prompt with correct timeout (inter-digit)" do
|
|
736
|
+
expect_component_execution expected_prompt
|
|
737
|
+
|
|
738
|
+
subject.menu prompts do
|
|
739
|
+
match(1) {}
|
|
740
|
+
end
|
|
741
|
+
end
|
|
316
742
|
end
|
|
317
743
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
744
|
+
context "with a different default minimum confidence" do
|
|
745
|
+
before do
|
|
746
|
+
expected_input_options.merge! min_confidence: 0.8
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
temp_config_value :min_confidence, 0.8
|
|
750
|
+
|
|
751
|
+
it "executes a Prompt with correct minimum confidence" do
|
|
752
|
+
expect_component_execution expected_prompt
|
|
753
|
+
|
|
754
|
+
subject.menu prompts do
|
|
755
|
+
match(1) {}
|
|
756
|
+
end
|
|
757
|
+
end
|
|
323
758
|
end
|
|
324
|
-
end
|
|
325
759
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
760
|
+
context "with a different default recognizer" do
|
|
761
|
+
before do
|
|
762
|
+
expected_input_options.merge! recognizer: 'something_else'
|
|
763
|
+
end
|
|
764
|
+
|
|
765
|
+
temp_config_value :recognizer, 'something_else'
|
|
766
|
+
|
|
767
|
+
it "executes a Prompt with correct recognizer" do
|
|
768
|
+
expect_component_execution expected_prompt
|
|
769
|
+
|
|
770
|
+
subject.menu prompts do
|
|
771
|
+
match(1) {}
|
|
772
|
+
end
|
|
331
773
|
end
|
|
332
|
-
expect(result.status).to eq(:validator_terminated)
|
|
333
|
-
expect(result.response).to eq('11')
|
|
334
774
|
end
|
|
335
|
-
end
|
|
336
775
|
|
|
337
|
-
|
|
776
|
+
context "with a different default input language" do
|
|
777
|
+
before do
|
|
778
|
+
expected_input_options.merge! language: 'pt-BR'
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
temp_config_value :input_language, 'pt-BR'
|
|
782
|
+
|
|
783
|
+
it "executes a Prompt with correct input language" do
|
|
784
|
+
expect_component_execution expected_prompt
|
|
785
|
+
|
|
786
|
+
subject.menu prompts do
|
|
787
|
+
match(1) {}
|
|
788
|
+
end
|
|
789
|
+
end
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
context "with a different default output renderer" do
|
|
793
|
+
before do
|
|
794
|
+
expected_output_options.merge! renderer: 'something_else'
|
|
795
|
+
end
|
|
796
|
+
|
|
797
|
+
temp_config_value :default_renderer, 'something_else', Adhearsion.config.core.media
|
|
798
|
+
|
|
799
|
+
it "executes a Prompt with correct renderer" do
|
|
800
|
+
expect_component_execution expected_prompt
|
|
801
|
+
|
|
802
|
+
subject.menu prompts do
|
|
803
|
+
match(1) {}
|
|
804
|
+
end
|
|
805
|
+
end
|
|
806
|
+
end
|
|
807
|
+
|
|
808
|
+
context "with a different default output voice" do
|
|
809
|
+
before do
|
|
810
|
+
expected_output_options.merge! voice: 'something_else'
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
temp_config_value :default_voice, 'something_else', Adhearsion.config.core.media
|
|
814
|
+
|
|
815
|
+
it "executes a Prompt with correct voice" do
|
|
816
|
+
expect_component_execution expected_prompt
|
|
817
|
+
|
|
818
|
+
subject.menu prompts do
|
|
819
|
+
match(1) {}
|
|
820
|
+
end
|
|
821
|
+
end
|
|
822
|
+
end
|
|
823
|
+
|
|
824
|
+
context "with overridden input options" do
|
|
825
|
+
before do
|
|
826
|
+
expected_input_options.merge! inter_digit_timeout: 35000
|
|
827
|
+
end
|
|
828
|
+
|
|
829
|
+
it "executes a Prompt with correct input options" do
|
|
830
|
+
expect_component_execution expected_prompt
|
|
831
|
+
|
|
832
|
+
subject.menu prompts, input_options: {inter_digit_timeout: 35000} do
|
|
833
|
+
match(1) {}
|
|
834
|
+
end
|
|
835
|
+
end
|
|
836
|
+
end
|
|
837
|
+
|
|
838
|
+
context "with overridden output options" do
|
|
839
|
+
before do
|
|
840
|
+
expected_output_options.merge! max_time: 35000
|
|
841
|
+
end
|
|
842
|
+
|
|
843
|
+
it "executes a Prompt with correct output options" do
|
|
844
|
+
expect_component_execution expected_prompt
|
|
845
|
+
|
|
846
|
+
subject.menu prompts, output_options: {max_time: 35000} do
|
|
847
|
+
match(1) {}
|
|
848
|
+
end
|
|
849
|
+
end
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
context "when using ASR mode" do
|
|
853
|
+
before do
|
|
854
|
+
expected_input_options.merge! mode: :voice
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
let :expected_grxml do
|
|
858
|
+
RubySpeech::GRXML.draw mode: 'voice', root: 'options', tag_format: 'semantics/1.0-literals' do
|
|
859
|
+
rule id: 'options', scope: 'public' do
|
|
860
|
+
item do
|
|
861
|
+
one_of do
|
|
862
|
+
item do
|
|
863
|
+
tag { '0' }
|
|
864
|
+
'Hello world'
|
|
865
|
+
end
|
|
866
|
+
end
|
|
867
|
+
end
|
|
868
|
+
end
|
|
869
|
+
end
|
|
870
|
+
end
|
|
871
|
+
|
|
872
|
+
it "executes a Prompt with correct input mode, and the correct grammar mode" do
|
|
873
|
+
expect_component_execution expected_prompt
|
|
874
|
+
|
|
875
|
+
subject.menu prompts, mode: :voice do
|
|
876
|
+
match("Hello world") {}
|
|
877
|
+
end
|
|
878
|
+
end
|
|
879
|
+
end
|
|
880
|
+
|
|
881
|
+
context "when the call is dead when trying to execute the prompt" do
|
|
882
|
+
before { call.terminate }
|
|
883
|
+
|
|
884
|
+
it "should raise Adhearsion::Call::Hangup" do
|
|
885
|
+
expect do
|
|
886
|
+
subject.menu prompts do
|
|
887
|
+
match(1) {}
|
|
888
|
+
end
|
|
889
|
+
end.to raise_error Adhearsion::Call::Hangup
|
|
890
|
+
end
|
|
891
|
+
end
|
|
892
|
+
|
|
893
|
+
context "when input completes with an error" do
|
|
894
|
+
let(:reason) { Adhearsion::Event::Complete::Error.new details: 'foobar' }
|
|
895
|
+
|
|
896
|
+
it "should raise an error with a message of 'foobar'" do
|
|
897
|
+
expect_component_execution expected_prompt
|
|
898
|
+
|
|
899
|
+
expect do
|
|
900
|
+
subject.menu prompts do
|
|
901
|
+
match(1) {}
|
|
902
|
+
end
|
|
903
|
+
end.to raise_error(Adhearsion::CallController::Input::InputError, /foobar/)
|
|
904
|
+
end
|
|
905
|
+
end
|
|
906
|
+
|
|
907
|
+
context "when input doesn't match any of the specified matches" do
|
|
908
|
+
it "runs the invalid and failure handlers" do
|
|
909
|
+
expect_component_execution expected_prompt
|
|
910
|
+
expect(self).to receive(:do_something_on_invalid).once.ordered
|
|
911
|
+
expect(self).to receive(:do_something_on_failure).once.ordered
|
|
912
|
+
|
|
913
|
+
subject.menu prompts do
|
|
914
|
+
match(1) {}
|
|
915
|
+
|
|
916
|
+
invalid { do_something_on_invalid }
|
|
917
|
+
failure { do_something_on_failure }
|
|
918
|
+
end
|
|
919
|
+
end
|
|
920
|
+
|
|
921
|
+
context "when allowed multiple tries" do
|
|
922
|
+
let :nlsml do
|
|
923
|
+
RubySpeech::NLSML.draw do
|
|
924
|
+
interpretation confidence: 1 do
|
|
925
|
+
input '1', mode: :dtmf
|
|
926
|
+
instance '0'
|
|
927
|
+
end
|
|
928
|
+
end
|
|
929
|
+
end
|
|
930
|
+
|
|
931
|
+
let(:reason2) { Adhearsion::Rayo::Component::Input::Complete::Match.new nlsml: nlsml }
|
|
932
|
+
|
|
933
|
+
it "executes the prompt repeatedly until it gets a match" do
|
|
934
|
+
some_controller_class = Class.new Adhearsion::CallController
|
|
935
|
+
|
|
936
|
+
expect_component_execution(expected_prompt).twice
|
|
937
|
+
expect(self).to receive(:do_something_on_invalid).once.ordered
|
|
938
|
+
expect(self).to receive(:invoke).once.with(some_controller_class, extension: '1').ordered
|
|
939
|
+
expect(self).to receive(:do_something_on_failure).never
|
|
940
|
+
|
|
941
|
+
invocation_count = 0
|
|
942
|
+
allow_any_instance_of(Adhearsion::Rayo::Component::Prompt).to receive(:complete_event) do
|
|
943
|
+
invocation_count += 1
|
|
944
|
+
case invocation_count
|
|
945
|
+
when 1 then double(reason: reason)
|
|
946
|
+
when 2 then double(reason: reason2)
|
|
947
|
+
else raise('Too many attempts')
|
|
948
|
+
end
|
|
949
|
+
end
|
|
950
|
+
|
|
951
|
+
subject.menu prompts, tries: 3 do
|
|
952
|
+
match 1, some_controller_class
|
|
953
|
+
|
|
954
|
+
invalid { do_something_on_invalid }
|
|
955
|
+
failure { do_something_on_failure }
|
|
956
|
+
end
|
|
957
|
+
end
|
|
958
|
+
end
|
|
959
|
+
end
|
|
960
|
+
|
|
961
|
+
context "when we don't get any input" do
|
|
962
|
+
let(:reason) { Adhearsion::Rayo::Component::Input::Complete::NoInput.new }
|
|
963
|
+
|
|
964
|
+
it "runs the timeout and failure handlers" do
|
|
965
|
+
expect_component_execution expected_prompt
|
|
966
|
+
expect(self).to receive(:do_something_on_timeout).once.ordered
|
|
967
|
+
expect(self).to receive(:do_something_on_failure).once.ordered
|
|
968
|
+
|
|
969
|
+
subject.menu prompts do
|
|
970
|
+
match(1) {}
|
|
338
971
|
|
|
339
|
-
|
|
972
|
+
timeout { do_something_on_timeout }
|
|
973
|
+
failure { do_something_on_failure }
|
|
974
|
+
end
|
|
975
|
+
end
|
|
976
|
+
|
|
977
|
+
context "when allowed multiple tries" do
|
|
978
|
+
let :nlsml do
|
|
979
|
+
RubySpeech::NLSML.draw do
|
|
980
|
+
interpretation confidence: 1 do
|
|
981
|
+
input '1', mode: :dtmf
|
|
982
|
+
instance '0'
|
|
983
|
+
end
|
|
984
|
+
end
|
|
985
|
+
end
|
|
986
|
+
|
|
987
|
+
let(:reason2) { Adhearsion::Rayo::Component::Input::Complete::Match.new nlsml: nlsml }
|
|
988
|
+
|
|
989
|
+
it "executes the prompt repeatedly until it gets a match" do
|
|
990
|
+
some_controller_class = Class.new Adhearsion::CallController
|
|
991
|
+
|
|
992
|
+
expect_component_execution(expected_prompt).twice
|
|
993
|
+
expect(self).to receive(:do_something_on_timeout).once.ordered
|
|
994
|
+
expect(self).to receive(:invoke).once.with(some_controller_class, extension: '1').ordered
|
|
995
|
+
expect(self).to receive(:do_something_on_failure).never
|
|
996
|
+
|
|
997
|
+
invocation_count = 0
|
|
998
|
+
allow_any_instance_of(Adhearsion::Rayo::Component::Prompt).to receive(:complete_event) do
|
|
999
|
+
invocation_count += 1
|
|
1000
|
+
case invocation_count
|
|
1001
|
+
when 1 then double(reason: reason)
|
|
1002
|
+
when 2 then double(reason: reason2)
|
|
1003
|
+
else raise('Too many attempts')
|
|
1004
|
+
end
|
|
1005
|
+
end
|
|
1006
|
+
|
|
1007
|
+
subject.menu prompts, tries: 3 do
|
|
1008
|
+
match 1, some_controller_class
|
|
1009
|
+
|
|
1010
|
+
timeout { do_something_on_timeout }
|
|
1011
|
+
failure { do_something_on_failure }
|
|
1012
|
+
end
|
|
1013
|
+
end
|
|
1014
|
+
end
|
|
1015
|
+
end
|
|
1016
|
+
|
|
1017
|
+
context "when the input unambiguously matches a specified match" do
|
|
1018
|
+
let :expected_grxml do
|
|
1019
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'options', tag_format: 'semantics/1.0-literals' do
|
|
1020
|
+
rule id: 'options', scope: 'public' do
|
|
1021
|
+
item do
|
|
1022
|
+
one_of do
|
|
1023
|
+
item do
|
|
1024
|
+
tag { '0' }
|
|
1025
|
+
'2'
|
|
1026
|
+
end
|
|
1027
|
+
item do
|
|
1028
|
+
tag { '1' }
|
|
1029
|
+
'1'
|
|
1030
|
+
end
|
|
1031
|
+
item do
|
|
1032
|
+
tag { '2' }
|
|
1033
|
+
'3'
|
|
1034
|
+
end
|
|
1035
|
+
end
|
|
1036
|
+
end
|
|
1037
|
+
end
|
|
1038
|
+
end
|
|
1039
|
+
end
|
|
1040
|
+
|
|
1041
|
+
let :nlsml do
|
|
1042
|
+
RubySpeech::NLSML.draw do
|
|
1043
|
+
interpretation confidence: 1 do
|
|
1044
|
+
input '3', mode: :dtmf
|
|
1045
|
+
instance '2'
|
|
1046
|
+
end
|
|
1047
|
+
end
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
let(:reason) { Adhearsion::Rayo::Component::Input::Complete::Match.new nlsml: nlsml }
|
|
1051
|
+
|
|
1052
|
+
context "which specifies a controller class" do
|
|
1053
|
+
it "invokes the specfied controller, with the matched input as the :extension key in its metadata" do
|
|
1054
|
+
some_controller_class = Class.new Adhearsion::CallController
|
|
1055
|
+
|
|
1056
|
+
expect_component_execution expected_prompt
|
|
1057
|
+
expect(self).to receive(:invoke).once.with(some_controller_class, extension: '3')
|
|
1058
|
+
|
|
1059
|
+
subject.menu prompts do
|
|
1060
|
+
match(2) {}
|
|
1061
|
+
match(1) {}
|
|
1062
|
+
match 3, some_controller_class
|
|
1063
|
+
end
|
|
1064
|
+
end
|
|
1065
|
+
end
|
|
1066
|
+
|
|
1067
|
+
context "which specifies a block to be run" do
|
|
1068
|
+
it "invokes the block, passing in the input that matched" do
|
|
1069
|
+
expect_component_execution expected_prompt
|
|
1070
|
+
expect(self).to receive(:do_something_on_match).once.with('3')
|
|
1071
|
+
|
|
1072
|
+
subject.menu prompts do
|
|
1073
|
+
match(2) {}
|
|
1074
|
+
match(1) {}
|
|
1075
|
+
match(3) { |v| do_something_on_match v }
|
|
1076
|
+
end
|
|
1077
|
+
end
|
|
1078
|
+
end
|
|
1079
|
+
|
|
1080
|
+
context "when the match was a set of options" do
|
|
1081
|
+
let :expected_grxml do
|
|
1082
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'options', tag_format: 'semantics/1.0-literals' do
|
|
1083
|
+
rule id: 'options', scope: 'public' do
|
|
1084
|
+
item do
|
|
1085
|
+
one_of do
|
|
1086
|
+
item do
|
|
1087
|
+
tag { '0' }
|
|
1088
|
+
'0'
|
|
1089
|
+
end
|
|
1090
|
+
item do
|
|
1091
|
+
tag { '1' }
|
|
1092
|
+
'1'
|
|
1093
|
+
end
|
|
1094
|
+
item do
|
|
1095
|
+
tag { '2' }
|
|
1096
|
+
one_of do
|
|
1097
|
+
item { '2' }
|
|
1098
|
+
item { '3' }
|
|
1099
|
+
end
|
|
1100
|
+
end
|
|
1101
|
+
end
|
|
1102
|
+
end
|
|
1103
|
+
end
|
|
1104
|
+
end
|
|
1105
|
+
end
|
|
1106
|
+
|
|
1107
|
+
it "invokes the match payload" do
|
|
1108
|
+
expect_component_execution expected_prompt
|
|
1109
|
+
expect(self).to receive(:do_something_on_match).once.with('3')
|
|
1110
|
+
|
|
1111
|
+
subject.menu prompts do
|
|
1112
|
+
match(0) {}
|
|
1113
|
+
match(1) {}
|
|
1114
|
+
match(2,3) { |v| do_something_on_match v }
|
|
1115
|
+
end
|
|
1116
|
+
end
|
|
1117
|
+
end
|
|
1118
|
+
|
|
1119
|
+
context "when the match was a range" do
|
|
1120
|
+
let :expected_grxml do
|
|
1121
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'options', tag_format: 'semantics/1.0-literals' do
|
|
1122
|
+
rule id: 'options', scope: 'public' do
|
|
1123
|
+
item do
|
|
1124
|
+
one_of do
|
|
1125
|
+
item do
|
|
1126
|
+
tag { '0' }
|
|
1127
|
+
'0'
|
|
1128
|
+
end
|
|
1129
|
+
item do
|
|
1130
|
+
tag { '1' }
|
|
1131
|
+
'1'
|
|
1132
|
+
end
|
|
1133
|
+
item do
|
|
1134
|
+
tag { '2' }
|
|
1135
|
+
one_of do
|
|
1136
|
+
item { '2' }
|
|
1137
|
+
item { '3' }
|
|
1138
|
+
end
|
|
1139
|
+
end
|
|
1140
|
+
end
|
|
1141
|
+
end
|
|
1142
|
+
end
|
|
1143
|
+
end
|
|
1144
|
+
end
|
|
1145
|
+
|
|
1146
|
+
it "invokes the match payload" do
|
|
1147
|
+
expect_component_execution expected_prompt
|
|
1148
|
+
expect(self).to receive(:do_something_on_match).once.with('3')
|
|
1149
|
+
|
|
1150
|
+
subject.menu prompts do
|
|
1151
|
+
match(0) {}
|
|
1152
|
+
match(1) {}
|
|
1153
|
+
match(2..3) { |v| do_something_on_match v }
|
|
1154
|
+
end
|
|
1155
|
+
end
|
|
1156
|
+
end
|
|
1157
|
+
|
|
1158
|
+
context "when the match was an array of options" do
|
|
1159
|
+
let :expected_grxml do
|
|
1160
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'options', tag_format: 'semantics/1.0-literals' do
|
|
1161
|
+
rule id: 'options', scope: 'public' do
|
|
1162
|
+
item do
|
|
1163
|
+
one_of do
|
|
1164
|
+
item do
|
|
1165
|
+
tag { '0' }
|
|
1166
|
+
'0'
|
|
1167
|
+
end
|
|
1168
|
+
item do
|
|
1169
|
+
tag { '1' }
|
|
1170
|
+
'1'
|
|
1171
|
+
end
|
|
1172
|
+
item do
|
|
1173
|
+
tag { '2' }
|
|
1174
|
+
one_of do
|
|
1175
|
+
item { '2' }
|
|
1176
|
+
item { '3' }
|
|
1177
|
+
end
|
|
1178
|
+
end
|
|
1179
|
+
end
|
|
1180
|
+
end
|
|
1181
|
+
end
|
|
1182
|
+
end
|
|
1183
|
+
end
|
|
1184
|
+
|
|
1185
|
+
it "invokes the match payload" do
|
|
1186
|
+
expect_component_execution expected_prompt
|
|
1187
|
+
expect(self).to receive(:do_something_on_match).once.with('3')
|
|
1188
|
+
|
|
1189
|
+
subject.menu prompts do
|
|
1190
|
+
match(0) {}
|
|
1191
|
+
match(1) {}
|
|
1192
|
+
match([2,3]) { |v| do_something_on_match v }
|
|
1193
|
+
end
|
|
1194
|
+
end
|
|
1195
|
+
end
|
|
1196
|
+
end
|
|
1197
|
+
|
|
1198
|
+
context "when the input abmiguously matches multiple specified matches" do
|
|
1199
|
+
let :expected_grxml do
|
|
1200
|
+
RubySpeech::GRXML.draw mode: 'dtmf', root: 'options', tag_format: 'semantics/1.0-literals' do
|
|
1201
|
+
rule id: 'options', scope: 'public' do
|
|
1202
|
+
item do
|
|
1203
|
+
one_of do
|
|
1204
|
+
item do
|
|
1205
|
+
tag { '0' }
|
|
1206
|
+
'1'
|
|
1207
|
+
end
|
|
1208
|
+
item do
|
|
1209
|
+
tag { '1' }
|
|
1210
|
+
'1'
|
|
1211
|
+
end
|
|
1212
|
+
end
|
|
1213
|
+
end
|
|
1214
|
+
end
|
|
1215
|
+
end
|
|
1216
|
+
end
|
|
1217
|
+
|
|
1218
|
+
let :nlsml do
|
|
1219
|
+
RubySpeech::NLSML.draw do
|
|
1220
|
+
interpretation confidence: 1 do
|
|
1221
|
+
input '1', mode: :dtmf
|
|
1222
|
+
instance '0'
|
|
1223
|
+
instance '1'
|
|
1224
|
+
end
|
|
1225
|
+
end
|
|
1226
|
+
end
|
|
1227
|
+
|
|
1228
|
+
let(:reason) { Adhearsion::Rayo::Component::Input::Complete::Match.new nlsml: nlsml }
|
|
1229
|
+
|
|
1230
|
+
it "executes the first successful match" do
|
|
1231
|
+
expect_component_execution expected_prompt
|
|
1232
|
+
expect(self).to receive(:do_something_on_match).once.with('1')
|
|
1233
|
+
expect(self).to receive(:do_otherthing_on_match).never
|
|
1234
|
+
|
|
1235
|
+
subject.menu prompts do
|
|
1236
|
+
match(1) { |v| do_something_on_match v }
|
|
1237
|
+
match(1) { |v| do_otherthing_on_match v }
|
|
1238
|
+
end
|
|
1239
|
+
end
|
|
1240
|
+
end
|
|
1241
|
+
end
|
|
1242
|
+
end
|
|
1243
|
+
end
|
|
340
1244
|
end
|
|
341
1245
|
end
|