class TwilioTestToolkit::CallScope
Models a scope within a call.
Public Class Methods
has_element(el, options = {})
click to toggle source
Note that el is case sensitive and must match the desired TwiML element. eg. Play (correct) vs play (incorrect).
# File lib/twilio-test-toolkit/call_scope.rb, line 7 def self.has_element(el, options = {}) define_method "has_#{el.downcase}?" do |inner = nil| return has_element?(el, inner, options) end end
Protected Class Methods
from_request(parent, path, options = {})
click to toggle source
Create a new object from a post. Options:
-
:method - the http method of the request, defaults to :post
-
:digits - becomes params, defaults to “”
# File lib/twilio-test-toolkit/call_scope.rb, line 196 def self.from_request(parent, path, options = {}) new_scope = CallScope.new new_scope.send(:root_call=, parent.root_call) new_scope.send(:request_for_twiml!, path, options) return new_scope end
from_xml(parent, xml)
click to toggle source
New object creation
# File lib/twilio-test-toolkit/call_scope.rb, line 182 def self.from_xml(parent, xml) new_scope = CallScope.new new_scope.send(:set_xml, xml) new_scope.send(:root_call=, parent.root_call) return new_scope end
Public Instance Methods
current_path()
click to toggle source
Some basic accessors
# File lib/twilio-test-toolkit/call_scope.rb, line 114 def current_path @current_path end
follow_redirect(options = {})
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 27 def follow_redirect(options = {}) el = get_redirect_node raise "No redirect" if el.nil? return CallScope.from_request(self, el.text, { :method =>el[:method]}.merge(options)) end
follow_redirect!(options = {})
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 34 def follow_redirect!(options = {}) el = get_redirect_node raise "No redirect" if el.nil? request_for_twiml!(normalize_redirect_path(el.text), { :method => el[:method] }.merge(options)) end
gather?()
click to toggle source
Stuff for gatherers
# File lib/twilio-test-toolkit/call_scope.rb, line 42 def gather? @xml.name == "Gather" end
gather_action()
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 46 def gather_action raise "Not a gather" unless gather? return @xml["action"] end
gather_finish_on_key()
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 56 def gather_finish_on_key raise "Not a gather" unless gather? return @xml["finishOnKey"] || '#' # '#' is the default finish key if not specified end
gather_method()
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 51 def gather_method raise "Not a gather" unless gather? return @xml["method"] end
has_redirect_to?(url)
click to toggle source
Stuff for redirects
# File lib/twilio-test-toolkit/call_scope.rb, line 21 def has_redirect_to?(url) el = get_redirect_node return false if el.nil? return normalize_redirect_path(el.text) == normalize_redirect_path(url) end
method_missing(meth, *args, &block)
click to toggle source
Make this easier to support TwiML elements…
Calls superclass method
# File lib/twilio-test-toolkit/call_scope.rb, line 72 def method_missing(meth, *args, &block) # support any check for a given attribute on a given element # # eg. has_action_on_dial?, has_method_on_sip?, etc. # # Attribute-checking appears to be case-sensitive, which x means: # # has_finishOnKey_on_record?("#") # # I'm not crazy about this mixed case, so we can also do a more # Rubyish way: # # has_finish_on_key_on_record?("#") # if meth.to_s =~ /^has_([a-zA-Z_]+)_on_([a-zA-Z]+)\?$/ has_attr_on_element?($2, $1, *args, &block) # support any check for the existence of a given element # with an optional check on the inner_text. elsif meth.to_s =~ /^has_([a-zA-Z]+)\?$/ has_element?($1, *args, &block) # get a given element node elsif meth.to_s =~ /^get_([a-z]+)_node$/ get_element_node($1, *args, &block) # run a block within a given node context elsif meth.to_s =~ /^within_([a-z]+)$/ within_element($1, *args, &block) else super # You *must* call super if you don't handle the # method, otherwise you'll mess up Ruby's method # lookup. end end
press(digits)
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 61 def press(digits) raise "Not a gather" unless gather? # Fetch the path and then post path = gather_action # Update the root call root_call.request_for_twiml!(path, :digits => digits, :method => gather_method, :finish_on_key => gather_finish_on_key) end
respond_to_missing?(method_name, include_private = false)
click to toggle source
Calls superclass method
# File lib/twilio-test-toolkit/call_scope.rb, line 109 def respond_to_missing?(method_name, include_private = false) method_name.to_s.match(/^(has_|get_[a-z]+_node|within_)/) || super end
response_xml()
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 118 def response_xml @response_xml end
root_call()
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 122 def root_call @root_call end
Protected Instance Methods
normalize_redirect_path(path)
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 203 def normalize_redirect_path(path) p = path # Strip off ".xml" off of the end of any path p = path[0...path.length - ".xml".length] if path.downcase.match(/\.xml$/) return p end
request_for_twiml!(path, options = {})
click to toggle source
Post and update the scope. Options: :digits - becomes params, optional (becomes “”) :is_machine - becomes params, defaults to false / human
# File lib/twilio-test-toolkit/call_scope.rb, line 214 def request_for_twiml!(path, options = {}) @current_path = normalize_redirect_path(path) # Post the query rack_test_session_wrapper = Capybara.current_session.driver @response = rack_test_session_wrapper.send(options[:method] || :post, @current_path, :format => :xml, :CallSid => @root_call.sid, :From => @root_call.from_number, :Digits => formatted_digits(options[:digits].to_s, :finish_on_key => options[:finish_on_key]), :To => @root_call.to_number, :AnsweredBy => (options[:is_machine] ? "machine" : "human"), :CallStatus => options.fetch(:call_status, "in-progress") ) # All Twilio responses must be a success. raise "Bad response: #{@response.status}" unless @response.status == 200 # Load the xml data = @response.body @response_xml = Nokogiri::XML.parse(data) set_xml(@response_xml.at_xpath("Response")) end
root_call=(val)
click to toggle source
Parent call control
# File lib/twilio-test-toolkit/call_scope.rb, line 239 def root_call=(val) @root_call = val end
set_xml(xml)
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 189 def set_xml(xml) @xml = xml end
Private Instance Methods
camel_case_lower(subject)
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 176 def camel_case_lower(subject) subject.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join end
formatted_digits(digits, options = {})
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 127 def formatted_digits(digits, options = {}) if digits.nil? '' elsif options[:finish_on_key] digits.to_s.split(options[:finish_on_key])[0] else digits end end
get_element_node(el)
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 137 def get_element_node(el) el[0] = el[0,1].upcase @xml.at_xpath(el) end
has_attr_on_element?(el, attr, value)
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 150 def has_attr_on_element?(el, attr, value) el[0] = el[0,1].upcase # convert snake case to lower camelCase if attr.match(/_/) attr = camel_case_lower(attr) end attr_on_el = @xml.xpath(el).attribute(attr) !!attr_on_el && attr_on_el.value == value end
has_element?(el, inner = nil, options = {})
click to toggle source
# File lib/twilio-test-toolkit/call_scope.rb, line 161 def has_element?(el, inner = nil, options = {}) el[0] = el[0,1].upcase return !(@xml.at_xpath(el).nil?) if inner.nil? @xml.xpath(el).each do |s| if !options[:exact_inner_match].nil? && options[:exact_inner_match] == true return true if s.inner_text.strip == inner else return true if s.inner_text.include?(inner) end end return false end
within_element(el) { |from_xml| ... }
click to toggle source
Within element returns a scope that's tied to the specified element
# File lib/twilio-test-toolkit/call_scope.rb, line 143 def within_element(el, &block) element_node = get_element_node(el) raise "No el in scope" if element_node.nil? yield(CallScope.from_xml(self, element_node)) end