rspec-rayo 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. data/.document +5 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +72 -0
  7. data/Rakefile +22 -0
  8. data/lib/rspec-rayo/rayo/call.rb +135 -0
  9. data/lib/rspec-rayo/rayo/driver.rb +110 -0
  10. data/lib/rspec-rayo/rayo/matchers/ask.rb +60 -0
  11. data/lib/rspec-rayo/rayo/matchers/call_control.rb +105 -0
  12. data/lib/rspec-rayo/rayo/matchers/conference.rb +73 -0
  13. data/lib/rspec-rayo/rayo/matchers/dtmf.rb +21 -0
  14. data/lib/rspec-rayo/rayo/matchers/input.rb +60 -0
  15. data/lib/rspec-rayo/rayo/matchers/join.rb +56 -0
  16. data/lib/rspec-rayo/rayo/matchers/output.rb +15 -0
  17. data/lib/rspec-rayo/rayo/matchers/recording.rb +32 -0
  18. data/lib/rspec-rayo/rayo/matchers/say.rb +15 -0
  19. data/lib/rspec-rayo/rayo/matchers/transfer.rb +31 -0
  20. data/lib/rspec-rayo/rayo/matchers.rb +138 -0
  21. data/lib/rspec-rayo/tropo1/driver.rb +51 -0
  22. data/lib/rspec-rayo/version.rb +3 -0
  23. data/lib/rspec-rayo.rb +7 -0
  24. data/rspec-rayo.gemspec +31 -0
  25. data/spec/rspec-rayo/rayo/matchers/ask_spec.rb +43 -0
  26. data/spec/rspec-rayo/rayo/matchers/call_control_spec.rb +83 -0
  27. data/spec/rspec-rayo/rayo/matchers/conference_spec.rb +54 -0
  28. data/spec/rspec-rayo/rayo/matchers/dtmf_spec.rb +16 -0
  29. data/spec/rspec-rayo/rayo/matchers/input_spec.rb +43 -0
  30. data/spec/rspec-rayo/rayo/matchers/join_spec.rb +33 -0
  31. data/spec/rspec-rayo/rayo/matchers/output_spec.rb +23 -0
  32. data/spec/rspec-rayo/rayo/matchers/say_spec.rb +23 -0
  33. data/spec/rspec-rayo/rayo/matchers/transfer_spec.rb +23 -0
  34. data/spec/rspec-rayo/rayo/matchers_spec.rb +30 -0
  35. data/spec/spec_helper.rb +8 -0
  36. metadata +193 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ Gemfile.lock
2
+
3
+ # rcov generated
4
+ coverage
5
+
6
+ # rdoc generated
7
+ rdoc
8
+
9
+ # yard generated
10
+ doc
11
+ .yardoc
12
+
13
+ # bundler
14
+ .bundle
15
+ pkg
16
+
17
+ spec/reports
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --tty
3
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Voxeo Corporation
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ rspec-rayo
2
+ ============
3
+
4
+ This library extends the Rspec testing library for Rayo specific expectations. The library also provides classes for Tropo1 and Rayo drivers.
5
+
6
+ Howto Install
7
+ -------------
8
+
9
+ gem install rspec-rayo
10
+
11
+ Example Driver Setup
12
+ --------------------
13
+
14
+ ap "Starting RayoDriver to manage events over XMPP."
15
+ @rayo = RSpecRayo::RayoDriver.new :username => @config['rayo_server']['jid'],
16
+ :password => @config['rayo_server']['password'],
17
+ :wire_logger => Logger.new(@config['rayo_server']['wire_log']),
18
+ :transport_logger => Logger.new(@config['rayo_server']['transport_log'])
19
+
20
+ ap "Starting Tropo1Driver to host scripts via DRb and launch calls via HTTP."
21
+ @tropo1 = RSpecRayo::Tropo1Driver.new(@config['tropo1']['druby_uri'])
22
+
23
+ Custom Matchers
24
+ ---------------
25
+
26
+ * have_executed_correctly
27
+ * have_dialed_correctly
28
+ * be_a_valid_complete_hangup_event
29
+ * be_a_valid_complete_error_event
30
+ * be_a_valid_complete_stopped_event
31
+
32
+ * be_a_valid_successful_ask_event
33
+ * be_a_valid_ask_noinput_event
34
+ * be_a_valid_ask_nomatch_event
35
+
36
+ * be_a_valid_offer_event
37
+ * be_a_valid_answered_event
38
+ * be_a_valid_hangup_event
39
+ * be_a_valid_ringing_event
40
+ * be_a_valid_redirect_event
41
+ * be_a_valid_reject_event
42
+
43
+ * be_a_valid_conference_offhold_event
44
+ * be_a_valid_speaking_event
45
+ * be_a_valid_finished_speaking_event
46
+ * be_a_valid_conference_complete_terminator_event
47
+
48
+ * be_a_valid_dtmf_event
49
+
50
+ * be_a_valid_successful_input_event
51
+ * be_a_valid_input_noinput_event
52
+ * be_a_valid_input_nomatch_event
53
+
54
+ * be_a_valid_joined_event
55
+ * be_a_valid_unjoined_event
56
+
57
+ * be_a_valid_output_event
58
+
59
+ * be_a_valid_complete_recording_event
60
+ * be_a_valid_stopped_recording_event
61
+
62
+ * be_a_valid_say_event
63
+
64
+ * be_a_valid_transfer_event
65
+ * be_a_valid_transfer_timeout_event
66
+
67
+
68
+ Copyright
69
+ ---------
70
+
71
+ Copyright (c) 2011 Voxeo Corporation. See LICENSE.txt for further details.
72
+
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require 'rspec/core'
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.pattern = FileList['spec/**/*_spec.rb']
9
+ end
10
+
11
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
12
+ spec.pattern = 'spec/**/*_spec.rb'
13
+ spec.rcov = true
14
+ end
15
+
16
+ task :default => :spec
17
+
18
+ require 'ci/reporter/rake/rspec'
19
+ task :hudson => ['ci:setup:rspec', :spec]
20
+
21
+ require 'yard'
22
+ YARD::Rake::YardocTask.new
@@ -0,0 +1,135 @@
1
+ require 'future-resource'
2
+
3
+ module RSpecRayo
4
+ class Call
5
+ attr_accessor :status, :call_id
6
+ attr_reader :queue
7
+
8
+ def initialize(options)
9
+ @call_event = FutureResource.new
10
+ self.call_event = options[:call_event] if options[:call_event]
11
+ @ring_event = FutureResource.new
12
+ @protocol = options[:protocol]
13
+ @queue = options[:queue]
14
+ @read_timeout = options[:read_timeout] || 5
15
+ @write_timeout = options[:write_timeout] || 5
16
+ @status = :offered
17
+ end
18
+
19
+ def accept
20
+ write(Punchblock::Command::Accept.new).tap do |response|
21
+ @status = :accepted if response
22
+ end
23
+ end
24
+
25
+ def answer
26
+ write Punchblock::Command::Answer.new
27
+ end
28
+
29
+ def ask(options = {})
30
+ write Punchblock::Component::Tropo::Ask.new(options)
31
+ end
32
+
33
+ def conference(options = {})
34
+ write Punchblock::Component::Tropo::Conference.new(options)
35
+ end
36
+
37
+ def dial(options = {})
38
+ write Punchblock::Command::Dial.new(options)
39
+ end
40
+
41
+ def hangup
42
+ write(Punchblock::Command::Hangup.new).tap do |response|
43
+ @status = :finished if response
44
+ end
45
+ end
46
+
47
+ def redirect(options = {})
48
+ write Punchblock::Command::Redirect.new(options)
49
+ end
50
+
51
+ def reject(reason = nil)
52
+ write(Punchblock::Command::Reject.new(reason)).tap do |response|
53
+ @status = :finished if response
54
+ end
55
+ end
56
+
57
+ def say(options = {})
58
+ write Punchblock::Component::Tropo::Say.new(options)
59
+ end
60
+
61
+ def transfer(options = {})
62
+ write Punchblock::Component::Tropo::Transfer.new(options)
63
+ end
64
+
65
+ def record(options = {})
66
+ write Punchblock::Component::Record.new(options)
67
+ end
68
+
69
+ def output(options = {})
70
+ write Punchblock::Component::Output.new(options)
71
+ end
72
+
73
+ def input(options = {})
74
+ write Punchblock::Component::Input.new(options)
75
+ end
76
+
77
+ def join(options = {})
78
+ write Punchblock::Command::Join.new(options)
79
+ end
80
+
81
+ def unjoin(options = {})
82
+ write Punchblock::Command::Unjoin.new(options)
83
+ end
84
+
85
+ def mute
86
+ write Punchblock::Command::Mute.new
87
+ end
88
+
89
+ def unmute
90
+ write Punchblock::Command::Unmute.new
91
+ end
92
+
93
+ def dtmf(tones)
94
+ write Punchblock::Command::DTMF.new(:tones => tones)
95
+ end
96
+
97
+ def last_event?(timeout = 2)
98
+ begin
99
+ next_event timeout
100
+ rescue Timeout::Error
101
+ true
102
+ end
103
+ end
104
+
105
+ def next_event(timeout = nil)
106
+ Timeout::timeout(timeout || @read_timeout) { @queue.pop }
107
+ end
108
+
109
+ def call_event
110
+ @call_event.resource @write_timeout
111
+ end
112
+
113
+ def call_event=(other)
114
+ raise ArgumentError, 'Call event must be a Punchblock::Event::Offer' unless other.is_a? Punchblock::Event::Offer
115
+ @call_event.resource = other
116
+ @call_id = other.call_id
117
+ end
118
+
119
+ def ring_event
120
+ @ring_event.resource @write_timeout
121
+ end
122
+
123
+ def ring_event=(other)
124
+ raise ArgumentError, 'Ring event must be a Punchblock::Event::Ringing' unless other.is_a? Punchblock::Event::Ringing
125
+ @ring_event.resource = other
126
+ end
127
+
128
+ private
129
+
130
+ def write(msg)
131
+ response = @protocol.write @call_id, msg
132
+ msg if response
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,110 @@
1
+ module RSpecRayo
2
+ class RayoDriver
3
+ attr_reader :event_queue, :threads
4
+ attr_accessor :calls
5
+
6
+ def initialize(options)
7
+ @calls = {}
8
+ @call_queue = Queue.new
9
+ @queue_timeout = options[:queue_timeout] || 5
10
+ @write_timeout = options[:write_timeout] || 5
11
+ @threads = []
12
+
13
+ initialize_rayo options
14
+ end
15
+
16
+ def get_call
17
+ read_queue @call_queue
18
+ end
19
+
20
+ def cleanup_calls
21
+ @calls.each_pair do |call_id, call|
22
+ call.hangup unless call.status == :finished
23
+ end
24
+ @calls = {}
25
+ end
26
+
27
+ def dial(options)
28
+ Call.new(:protocol => @rayo, :queue => Queue.new, :read_timeout => @queue_timeout, :write_timeout => @write_timeout).tap do |call|
29
+ dial = call.dial options
30
+ call.call_id = dial.call_id
31
+ @calls.merge! call.call_id => call
32
+ end
33
+ end
34
+
35
+ def start_event_dispatcher
36
+ @threads << Thread.new do
37
+ event = nil
38
+
39
+ until event == 'STOP' do
40
+ event = @event_queue.pop
41
+ case event
42
+ when Punchblock::Event::Offer
43
+ call = Call.new :call_event => event,
44
+ :protocol => @rayo,
45
+ :queue => Queue.new,
46
+ :read_timeout => @queue_timeout,
47
+ :write_timeout => @write_timeout
48
+ @calls.merge! event.call_id => call
49
+ @call_queue.push call
50
+ when Punchblock::Event::Ringing
51
+ call = @calls[event.call_id]
52
+ call.ring_event = event if call
53
+ else
54
+ # Temp based on this nil returned on conference: https://github.com/tropo/punchblock/issues/27
55
+ begin
56
+ if event.is_a?(Punchblock::Event::End)
57
+ @calls[event.call_id].status = :finished
58
+ end
59
+ @calls[event.call_id].queue.push event unless event.nil?
60
+ rescue => error
61
+ # Event nil issue to be addressed here: https://github.com/tropo/rspec-rayo/issues/2
62
+ end
63
+ end
64
+ end
65
+
66
+ end
67
+ end
68
+
69
+ def read_queue(queue)
70
+ Timeout::timeout(@queue_timeout) { queue.pop }
71
+ end
72
+
73
+ def initialize_rayo(options)
74
+ initialize_logging options
75
+
76
+ # Setup our Rayo environment
77
+ @rayo = Punchblock::Connection.new :username => options[:username],
78
+ :password => options[:password],
79
+ :wire_logger => @wire_logger,
80
+ :transport_logger => @transport_logger,
81
+ :auto_reconnect => false,
82
+ :write_timeout => options[:write_timeout]
83
+ @event_queue = @rayo.event_queue
84
+
85
+ start_rayo
86
+ end
87
+
88
+ def initialize_logging(options)
89
+ @wire_logger = options[:wire_logger]
90
+ @wire_logger.level = options[:log_level]
91
+ #@wire_logger.info "Starting up..." if @wire_logger
92
+
93
+ @transport_logger = options[:transport_logger]
94
+ @transport_logger.level = options[:log_level]
95
+ #@transport_logger.info "Starting up..." if @transport_logger
96
+ end
97
+
98
+ def start_rayo
99
+ # Launch the Rayo thread
100
+ @threads << Thread.new do
101
+ begin
102
+ @rayo.run
103
+ rescue => e
104
+ puts "Exception in XMPP thread! #{e.message}"
105
+ puts e.backtrace.join("\t\n")
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,60 @@
1
+ RSpec::Matchers.define :be_a_valid_successful_ask_event do
2
+ chain :with_utterance do |utterance|
3
+ @utterance = utterance
4
+ end
5
+
6
+ chain :with_interpretation do |interpretation|
7
+ @interpretation = interpretation
8
+ end
9
+
10
+ match_for_should do |event|
11
+ basic_validation event, Punchblock::Event::Complete, true do
12
+ match_type event.reason, Punchblock::Component::Tropo::Ask::Complete::Success
13
+ @error = "The utterance was not correct. Expected '#{@utterance}', got '#{event.reason.utterance}'" if @utterance && event.reason.utterance != @utterance
14
+ @error = "The interpretation was not correct. Expected '#{@interpretation}', got '#{event.reason.interpretation}'" if @interpretation && event.reason.interpretation != @interpretation
15
+ end
16
+ end
17
+
18
+ failure_message_for_should do |actual|
19
+ "The ask event was not valid: #{@error}"
20
+ end
21
+
22
+ description do
23
+ "be a valid successful ask event".tap do |d|
24
+ d << " with utterance '#{@utterance}'" if @utterance
25
+ d << " with interpretation '#{@interpretation}'" if @interpretation
26
+ end
27
+ end
28
+ end
29
+
30
+ RSpec::Matchers.define :be_a_valid_ask_noinput_event do
31
+ match_for_should do |event|
32
+ basic_validation event, Punchblock::Event::Complete, true do
33
+ match_type event.reason, Punchblock::Component::Tropo::Ask::Complete::NoInput
34
+ end
35
+ end
36
+
37
+ failure_message_for_should do |actual|
38
+ "The ask event was not valid: #{@error}"
39
+ end
40
+
41
+ description do
42
+ "be a valid noinput ask event"
43
+ end
44
+ end
45
+
46
+ RSpec::Matchers.define :be_a_valid_ask_nomatch_event do
47
+ match_for_should do |event|
48
+ basic_validation event, Punchblock::Event::Complete, true do
49
+ match_type event.reason, Punchblock::Component::Tropo::Ask::Complete::NoMatch
50
+ end
51
+ end
52
+
53
+ failure_message_for_should do |actual|
54
+ "The ask event was not valid: #{@error}"
55
+ end
56
+
57
+ description do
58
+ "be a valid nomatch ask event"
59
+ end
60
+ end
@@ -0,0 +1,105 @@
1
+ RSpec::Matchers.define :be_a_valid_offer_event do
2
+ match_for_should do |event|
3
+ basic_validation event, Punchblock::Event::Offer do
4
+ event.headers_hash.each do |k,v|
5
+ if v.nil?
6
+ @error = "#{k.to_s} is nil - expected a value"
7
+ raise RSpec::Expectations::ExpectationNotMetError
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ failure_message_for_should do |actual|
14
+ "The offer event was not valid: #{@error}"
15
+ end
16
+
17
+ description do
18
+ "be a valid offer event"
19
+ end
20
+ end
21
+
22
+ RSpec::Matchers.define :be_a_valid_answered_event do
23
+ match_for_should do |event|
24
+ basic_validation event, Punchblock::Event::Answered
25
+ end
26
+
27
+ failure_message_for_should do |actual|
28
+ "The answer event was not valid: #{@error}"
29
+ end
30
+
31
+ description do
32
+ "be a valid answered event"
33
+ end
34
+ end
35
+
36
+ RSpec::Matchers.define :be_a_valid_hangup_event do
37
+ match_for_should do |event|
38
+ basic_validation event, Punchblock::Event::End do
39
+ unless event.reason == :hangup
40
+ @error = "got #{event.reason.inspect} - expected :hangup"
41
+ raise RSpec::Expectations::ExpectationNotMetError
42
+ end
43
+ end
44
+ end
45
+
46
+ failure_message_for_should do |actual|
47
+ "The hangup event was not valid: #{@error}"
48
+ end
49
+
50
+ description do
51
+ "be a valid hangup event"
52
+ end
53
+ end
54
+
55
+ RSpec::Matchers.define :be_a_valid_ringing_event do
56
+ match_for_should do |event|
57
+ basic_validation event, Punchblock::Event::Ringing
58
+ end
59
+
60
+ failure_message_for_should do |actual|
61
+ "The ring event was not valid: #{@error}"
62
+ end
63
+
64
+ description do
65
+ "be a valid ringing event"
66
+ end
67
+ end
68
+
69
+ RSpec::Matchers.define :be_a_valid_redirect_event do
70
+ match_for_should do |event|
71
+ basic_validation event, Punchblock::Event::End do
72
+ unless event.reason == :redirect
73
+ @error = "got #{event.reason.inspect} - expected :redirect"
74
+ raise RSpec::Expectations::ExpectationNotMetError
75
+ end
76
+ end
77
+ end
78
+
79
+ failure_message_for_should do |actual|
80
+ "The reject event was not valid: #{@error}"
81
+ end
82
+
83
+ description do
84
+ "be a valid redirect event"
85
+ end
86
+ end
87
+
88
+ RSpec::Matchers.define :be_a_valid_reject_event do
89
+ match_for_should do |event|
90
+ basic_validation event, Punchblock::Event::End do
91
+ unless event.reason == :reject
92
+ @error = "got #{event.reason.inspect} - expected :reject"
93
+ raise RSpec::Expectations::ExpectationNotMetError
94
+ end
95
+ end
96
+ end
97
+
98
+ failure_message_for_should do |actual|
99
+ "The reject event was not valid: #{@error}"
100
+ end
101
+
102
+ description do
103
+ "be a valid reject event"
104
+ end
105
+ end
@@ -0,0 +1,73 @@
1
+ RSpec::Matchers.define :be_a_valid_conference_offhold_event do
2
+ match_for_should do |event|
3
+ basic_validation event, Punchblock::Component::Tropo::Conference::OffHold, true
4
+ end
5
+
6
+ failure_message_for_should do |actual|
7
+ "The ask event was not valid: #{@error}"
8
+ end
9
+
10
+ description do
11
+ "Validate an ask event"
12
+ end
13
+ end
14
+
15
+ RSpec::Matchers.define :be_a_valid_speaking_event do
16
+ chain :for_call_id do |call_id|
17
+ @call_id = call_id
18
+ end
19
+
20
+ match_for_should do |event|
21
+ basic_validation event, Punchblock::Component::Tropo::Conference::Speaking, true do
22
+ @error = "The speaking call ID was not correct. Expected '#{@call_id}', got '#{event.speaking_call_id}'" if @call_id && event.speaking_call_id != @call_id
23
+ end
24
+ end
25
+
26
+ failure_message_for_should do |actual|
27
+ "The speaking event was not valid: #{@error}"
28
+ end
29
+
30
+ description do
31
+ "be a valid speaking event".tap do |d|
32
+ d << " with call ID '#{@call_id}'" if @call_id
33
+ end
34
+ end
35
+ end
36
+
37
+ RSpec::Matchers.define :be_a_valid_finished_speaking_event do
38
+ chain :for_call_id do |call_id|
39
+ @call_id = call_id
40
+ end
41
+
42
+ match_for_should do |event|
43
+ basic_validation event, Punchblock::Component::Tropo::Conference::FinishedSpeaking, true do
44
+ @error = "The finished-speaking call ID was not correct. Expected '#{@call_id}', got '#{event.speaking_call_id}'" if @call_id && event.speaking_call_id != @call_id
45
+ end
46
+ end
47
+
48
+ failure_message_for_should do |actual|
49
+ "The finished speaking event was not valid: #{@error}"
50
+ end
51
+
52
+ description do
53
+ "be a valid finished speaking event".tap do |d|
54
+ d << " with call ID '#{@call_id}'" if @call_id
55
+ end
56
+ end
57
+ end
58
+
59
+ RSpec::Matchers.define :be_a_valid_conference_complete_terminator_event do
60
+ match_for_should do |event|
61
+ basic_validation event, Punchblock::Event::Complete, true do
62
+ match_type event.reason, Punchblock::Component::Tropo::Conference::Complete::Terminator
63
+ end
64
+ end
65
+
66
+ failure_message_for_should do |actual|
67
+ "The conference complete terminator event was not valid: #{@error}"
68
+ end
69
+
70
+ description do
71
+ "be a valid conference complete terminator event"
72
+ end
73
+ end
@@ -0,0 +1,21 @@
1
+ RSpec::Matchers.define :be_a_valid_dtmf_event do
2
+ chain :with_signal do |signal|
3
+ @signal = signal
4
+ end
5
+
6
+ match_for_should do |event|
7
+ basic_validation event, Punchblock::Event::DTMF do
8
+ @error = "The signal was not correct. Expected '#{@signal}', got '#{event.signal}'" if @signal && event.signal != @signal
9
+ end
10
+ end
11
+
12
+ failure_message_for_should do |actual|
13
+ "The DTMF event was not valid: #{@error}"
14
+ end
15
+
16
+ description do
17
+ "be a valid DTMF event".tap do |d|
18
+ d << " with signal '#{@signal}'" if @signal
19
+ end
20
+ end
21
+ end