punchblock 0.4.0

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 (94) hide show
  1. data/.document +5 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.markdown +31 -0
  7. data/Rakefile +23 -0
  8. data/assets/ozone/ask-1.0.xsd +56 -0
  9. data/assets/ozone/conference-1.0.xsd +17 -0
  10. data/assets/ozone/ozone-1.0.xsd +127 -0
  11. data/assets/ozone/say-1.0.xsd +24 -0
  12. data/assets/ozone/transfer-1.0.xsd +32 -0
  13. data/bin/punchblock-console +125 -0
  14. data/lib/punchblock/command/accept.rb +30 -0
  15. data/lib/punchblock/command/answer.rb +30 -0
  16. data/lib/punchblock/command/dial.rb +88 -0
  17. data/lib/punchblock/command/hangup.rb +25 -0
  18. data/lib/punchblock/command/join.rb +81 -0
  19. data/lib/punchblock/command/mute.rb +7 -0
  20. data/lib/punchblock/command/redirect.rb +49 -0
  21. data/lib/punchblock/command/reject.rb +61 -0
  22. data/lib/punchblock/command/unjoin.rb +50 -0
  23. data/lib/punchblock/command/unmute.rb +7 -0
  24. data/lib/punchblock/command.rb +16 -0
  25. data/lib/punchblock/command_node.rb +46 -0
  26. data/lib/punchblock/component/input.rb +320 -0
  27. data/lib/punchblock/component/output.rb +449 -0
  28. data/lib/punchblock/component/record.rb +216 -0
  29. data/lib/punchblock/component/tropo/ask.rb +197 -0
  30. data/lib/punchblock/component/tropo/conference.rb +328 -0
  31. data/lib/punchblock/component/tropo/say.rb +113 -0
  32. data/lib/punchblock/component/tropo/transfer.rb +178 -0
  33. data/lib/punchblock/component/tropo.rb +12 -0
  34. data/lib/punchblock/component.rb +73 -0
  35. data/lib/punchblock/connection.rb +209 -0
  36. data/lib/punchblock/core_ext/blather/stanza/presence.rb +11 -0
  37. data/lib/punchblock/core_ext/blather/stanza.rb +26 -0
  38. data/lib/punchblock/dsl.rb +46 -0
  39. data/lib/punchblock/event/answered.rb +7 -0
  40. data/lib/punchblock/event/complete.rb +65 -0
  41. data/lib/punchblock/event/dtmf.rb +19 -0
  42. data/lib/punchblock/event/end.rb +15 -0
  43. data/lib/punchblock/event/info.rb +15 -0
  44. data/lib/punchblock/event/joined.rb +50 -0
  45. data/lib/punchblock/event/offer.rb +29 -0
  46. data/lib/punchblock/event/ringing.rb +7 -0
  47. data/lib/punchblock/event/unjoined.rb +50 -0
  48. data/lib/punchblock/event.rb +16 -0
  49. data/lib/punchblock/generic_connection.rb +18 -0
  50. data/lib/punchblock/has_headers.rb +34 -0
  51. data/lib/punchblock/header.rb +47 -0
  52. data/lib/punchblock/media_container.rb +39 -0
  53. data/lib/punchblock/media_node.rb +17 -0
  54. data/lib/punchblock/protocol_error.rb +16 -0
  55. data/lib/punchblock/rayo_node.rb +88 -0
  56. data/lib/punchblock/ref.rb +26 -0
  57. data/lib/punchblock/version.rb +3 -0
  58. data/lib/punchblock.rb +42 -0
  59. data/log/.gitkeep +0 -0
  60. data/punchblock.gemspec +42 -0
  61. data/spec/punchblock/command/accept_spec.rb +13 -0
  62. data/spec/punchblock/command/answer_spec.rb +13 -0
  63. data/spec/punchblock/command/dial_spec.rb +54 -0
  64. data/spec/punchblock/command/hangup_spec.rb +13 -0
  65. data/spec/punchblock/command/join_spec.rb +21 -0
  66. data/spec/punchblock/command/mute_spec.rb +11 -0
  67. data/spec/punchblock/command/redirect_spec.rb +19 -0
  68. data/spec/punchblock/command/reject_spec.rb +43 -0
  69. data/spec/punchblock/command/unjoin_spec.rb +19 -0
  70. data/spec/punchblock/command/unmute_spec.rb +11 -0
  71. data/spec/punchblock/command_node_spec.rb +80 -0
  72. data/spec/punchblock/component/input_spec.rb +188 -0
  73. data/spec/punchblock/component/output_spec.rb +531 -0
  74. data/spec/punchblock/component/record_spec.rb +235 -0
  75. data/spec/punchblock/component/tropo/ask_spec.rb +183 -0
  76. data/spec/punchblock/component/tropo/conference_spec.rb +360 -0
  77. data/spec/punchblock/component/tropo/say_spec.rb +171 -0
  78. data/spec/punchblock/component/tropo/transfer_spec.rb +153 -0
  79. data/spec/punchblock/component_spec.rb +126 -0
  80. data/spec/punchblock/connection_spec.rb +194 -0
  81. data/spec/punchblock/event/answered_spec.rb +23 -0
  82. data/spec/punchblock/event/complete_spec.rb +80 -0
  83. data/spec/punchblock/event/dtmf_spec.rb +24 -0
  84. data/spec/punchblock/event/end_spec.rb +30 -0
  85. data/spec/punchblock/event/info_spec.rb +30 -0
  86. data/spec/punchblock/event/joined_spec.rb +32 -0
  87. data/spec/punchblock/event/offer_spec.rb +35 -0
  88. data/spec/punchblock/event/ringing_spec.rb +23 -0
  89. data/spec/punchblock/event/unjoined_spec.rb +32 -0
  90. data/spec/punchblock/header_spec.rb +44 -0
  91. data/spec/punchblock/protocol_error_spec.rb +9 -0
  92. data/spec/punchblock/ref_spec.rb +21 -0
  93. data/spec/spec_helper.rb +43 -0
  94. metadata +353 -0
@@ -0,0 +1,50 @@
1
+ module Punchblock
2
+ class Event
3
+ class Joined < Event
4
+ register :joined, :core
5
+
6
+ ##
7
+ # Create a joined event
8
+ #
9
+ # @param [Hash] options
10
+ # @option options [String, Optional] :other_call_id the call ID that was joined
11
+ # @option options [String, Optional] :mixer_id the mixer name that was joined
12
+ #
13
+ # @return [Event::Joined] a formatted Rayo joined event
14
+ #
15
+ def self.new(options = {})
16
+ super().tap do |new_node|
17
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
18
+ end
19
+ end
20
+
21
+ ##
22
+ # @return [String] the call ID that was joined
23
+ def other_call_id
24
+ read_attr :'call-id'
25
+ end
26
+
27
+ ##
28
+ # @param [String] other the call ID that was joined
29
+ def other_call_id=(other)
30
+ write_attr :'call-id', other
31
+ end
32
+
33
+ ##
34
+ # @return [String] the mixer name that was joined
35
+ def mixer_id
36
+ read_attr :'mixer-id'
37
+ end
38
+
39
+ ##
40
+ # @param [String] other the mixer name that was joined
41
+ def mixer_id=(other)
42
+ write_attr :'mixer-id', other
43
+ end
44
+
45
+ def inspect_attributes # :nodoc:
46
+ [:other_call_id, :mixer_id] + super
47
+ end
48
+ end # Joined
49
+ end
50
+ end # Punchblock
@@ -0,0 +1,29 @@
1
+ module Punchblock
2
+ class Event
3
+ class Offer < Event
4
+ register :offer, :core
5
+
6
+ include HasHeaders
7
+
8
+ def to
9
+ read_attr :to
10
+ end
11
+
12
+ def to=(offer_to)
13
+ write_attr :to, offer_to
14
+ end
15
+
16
+ def from
17
+ read_attr :from
18
+ end
19
+
20
+ def from=(offer_from)
21
+ write_attr :from, offer_from
22
+ end
23
+
24
+ def inspect_attributes # :nodoc:
25
+ [:to, :from] + super
26
+ end
27
+ end # Offer
28
+ end
29
+ end # Punchblock
@@ -0,0 +1,7 @@
1
+ module Punchblock
2
+ class Event
3
+ class Ringing < Event
4
+ register :ringing, :core
5
+ end # End
6
+ end # Event
7
+ end # Punchblock
@@ -0,0 +1,50 @@
1
+ module Punchblock
2
+ class Event
3
+ class Unjoined < Event
4
+ register :unjoined, :core
5
+
6
+ ##
7
+ # Create an unjoined event
8
+ #
9
+ # @param [Hash] options
10
+ # @option options [String, Optional] :other_call_id the call ID that was unjoined
11
+ # @option options [String, Optional] :mixer_id the mixer name that was unjoined
12
+ #
13
+ # @return [Event::Unjoined] a formatted Rayo unjoined event
14
+ #
15
+ def self.new(options = {})
16
+ super().tap do |new_node|
17
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
18
+ end
19
+ end
20
+
21
+ ##
22
+ # @return [String] the call ID that was unjoined
23
+ def other_call_id
24
+ read_attr :'call-id'
25
+ end
26
+
27
+ ##
28
+ # @param [String] other the call ID that was unjoined
29
+ def other_call_id=(other)
30
+ write_attr :'call-id', other
31
+ end
32
+
33
+ ##
34
+ # @return [String] the mixer name that was unjoined
35
+ def mixer_id
36
+ read_attr :'mixer-id'
37
+ end
38
+
39
+ ##
40
+ # @param [String] other the mixer name that was unjoined
41
+ def mixer_id=(other)
42
+ write_attr :'mixer-id', other
43
+ end
44
+
45
+ def inspect_attributes # :nodoc:
46
+ [:other_call_id, :mixer_id] + super
47
+ end
48
+ end # Unjoined
49
+ end
50
+ end # Punchblock
@@ -0,0 +1,16 @@
1
+ module Punchblock
2
+ class Event < RayoNode
3
+ end
4
+ end
5
+
6
+ %w{
7
+ answered
8
+ complete
9
+ dtmf
10
+ end
11
+ info
12
+ joined
13
+ offer
14
+ ringing
15
+ unjoined
16
+ }.each { |e| require "punchblock/event/#{e}"}
@@ -0,0 +1,18 @@
1
+ module Punchblock
2
+ class GenericConnection
3
+ attr_accessor :event_queue
4
+
5
+ ##
6
+ # @param [Hash] options
7
+ # @option options [Logger] :transport_logger The logger to which transport events will be logged
8
+ #
9
+ def initialize(options = {})
10
+ @event_queue = Queue.new
11
+ @logger = options.delete(:transport_logger) if options[:transport_logger]
12
+ end
13
+
14
+ def connected
15
+ 'CONNECTED'
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ module Punchblock
2
+ module HasHeaders
3
+ ##
4
+ # @return [Hash] hash of key-value pairs of headers
5
+ #
6
+ def headers_hash
7
+ headers.inject({}) do |hash, header|
8
+ hash[header.name] = header.value
9
+ hash
10
+ end
11
+ end
12
+
13
+ ##
14
+ # @return [Array[Header]] headers
15
+ #
16
+ def headers
17
+ find('//ns:header', :ns => self.class.registered_ns).map do |i|
18
+ Header.new i
19
+ end
20
+ end
21
+
22
+ ##
23
+ # @param [Hash, Array] headers A hash of key-value header pairs, or an array of Header objects
24
+ #
25
+ def headers=(headers)
26
+ find('//ns:header', :ns => self.class.registered_ns).each &:remove
27
+ if headers.is_a? Hash
28
+ headers.each_pair { |k,v| self << Header.new(k, v) }
29
+ elsif headers.is_a? Array
30
+ [headers].flatten.each { |i| self << Header.new(i) }
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,47 @@
1
+ module Punchblock
2
+ class Header < RayoNode
3
+ ##
4
+ # @param [String] name
5
+ # @param [String] value
6
+ #
7
+ def self.new(name, value = '')
8
+ super(:header).tap do |new_node|
9
+ case name
10
+ when Nokogiri::XML::Node
11
+ new_node.inherit name
12
+ else
13
+ new_node.name = name
14
+ new_node.value = value
15
+ end
16
+ end
17
+ end
18
+
19
+ # The Header's name
20
+ # @return [Symbol]
21
+ def name
22
+ read_attr(:name).gsub('-', '_').to_sym
23
+ end
24
+
25
+ # Set the Header's name
26
+ # @param [Symbol] name the new name for the header
27
+ def name=(name)
28
+ write_attr :name, name.to_s.gsub('_', '-')
29
+ end
30
+
31
+ # The Header's value
32
+ # @return [String]
33
+ def value
34
+ read_attr :value
35
+ end
36
+
37
+ # Set the Header's value
38
+ # @param [String] value the new value for the header
39
+ def value=(value)
40
+ write_attr :value, value
41
+ end
42
+
43
+ def inspect_attributes # :nodoc:
44
+ [:name, :value] + super
45
+ end
46
+ end
47
+ end # Punchblock
@@ -0,0 +1,39 @@
1
+ module Punchblock
2
+ module MediaContainer
3
+ ##
4
+ # @return [String] the TTS voice to use
5
+ #
6
+ def voice
7
+ read_attr :voice
8
+ end
9
+
10
+ ##
11
+ # @param [String] voice to use when rendering TTS
12
+ #
13
+ def voice=(voice)
14
+ write_attr :voice, voice
15
+ end
16
+
17
+ ##
18
+ # @return [String] the SSML document to render TTS
19
+ #
20
+ def ssml
21
+ children.to_xml
22
+ end
23
+
24
+ ##
25
+ # @param [String] ssml the SSML document to render TTS
26
+ #
27
+ def ssml=(ssml)
28
+ if ssml.instance_of?(String)
29
+ self << RayoNode.new('').parse(ssml) do |config|
30
+ config.noblanks.strict
31
+ end
32
+ end
33
+ end
34
+
35
+ def inspect_attributes # :nodoc:
36
+ [:voice, :ssml] + super
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,17 @@
1
+ module Punchblock
2
+ class MediaNode < RayoNode
3
+ include MediaContainer
4
+
5
+ def self.new(options = {})
6
+ super().tap do |new_node|
7
+ case options
8
+ when Hash
9
+ new_node << options.delete(:text) if options[:text]
10
+ options.each_pair { |k,v| new_node.send :"#{k}=", v }
11
+ when Nokogiri::XML::Element
12
+ new_node.inherit options
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Punchblock
2
+ ##
3
+ # This exception may be raised if a transport error is detected.
4
+ class ProtocolError < StandardError
5
+ attr_accessor :name, :text, :call_id, :component_id
6
+
7
+ def initialize(name = nil, text = nil, call_id = nil, component_id = nil)
8
+ @name, @text, @call_id, @component_id = name, text, call_id, component_id
9
+ end
10
+
11
+ def to_s
12
+ "#<#{self.class}: name=#{name.inspect} text=#{text.inspect} call_id=#{call_id.inspect} component_id=#{component_id.inspect}>"
13
+ end
14
+ alias :inspect :to_s
15
+ end
16
+ end
@@ -0,0 +1,88 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+ require 'niceogiri'
3
+
4
+ module Punchblock
5
+ class RayoNode < Niceogiri::XML::Node
6
+ @@registrations = {}
7
+
8
+ class_attribute :registered_ns, :registered_name
9
+
10
+ attr_accessor :call_id, :component_id, :connection, :original_component
11
+
12
+ # Register a new stanza class to a name and/or namespace
13
+ #
14
+ # This registers a namespace that is used when looking
15
+ # up the class name of the object to instantiate when a new
16
+ # stanza is received
17
+ #
18
+ # @param [#to_s] name the name of the node
19
+ # @param [String, nil] ns the namespace the node belongs to
20
+ def self.register(name, ns = nil)
21
+ self.registered_name = name.to_s
22
+ self.registered_ns = ns.is_a?(Symbol) ? RAYO_NAMESPACES[ns] : ns
23
+ @@registrations[[self.registered_name, self.registered_ns]] = self
24
+ end
25
+
26
+ # Find the class to use given the name and namespace of a stanza
27
+ #
28
+ # @param [#to_s] name the name to lookup
29
+ # @param [String, nil] xmlns the namespace the node belongs to
30
+ # @return [Class, nil] the class appropriate for the name/ns combination
31
+ def self.class_from_registration(name, ns = nil)
32
+ @@registrations[[name.to_s, ns]]
33
+ end
34
+
35
+ # Import an XML::Node to the appropriate class
36
+ #
37
+ # Looks up the class the node should be then creates it based on the
38
+ # elements of the XML::Node
39
+ # @param [XML::Node] node the node to import
40
+ # @return the appropriate object based on the node name and namespace
41
+ def self.import(node, call_id = nil, component_id = nil)
42
+ ns = (node.namespace.href if node.namespace)
43
+ klass = class_from_registration(node.element_name, ns)
44
+ event = if klass && klass != self
45
+ klass.import node, call_id, component_id
46
+ else
47
+ new.inherit node
48
+ end
49
+ event.tap do |event|
50
+ event.call_id = call_id
51
+ event.component_id = component_id
52
+ end
53
+ end
54
+
55
+ # Create a new Node object
56
+ #
57
+ # @param [String, nil] name the element name
58
+ # @param [XML::Document, nil] doc the document to attach the node to. If
59
+ # not provided one will be created
60
+ # @return a new object with the registered name and namespace
61
+ def self.new(name = registered_name, doc = nil)
62
+ super name, doc, registered_ns
63
+ end
64
+
65
+ def inspect_attributes # :nodoc:
66
+ [:call_id, :component_id]
67
+ end
68
+
69
+ def inspect
70
+ "#<#{self.class} #{inspect_attributes.map { |c| "#{c}=#{self.__send__(c).inspect}" rescue nil }.compact * ', '}>"
71
+ end
72
+
73
+ def eql?(o, *fields)
74
+ super o, *(fields + inspect_attributes)
75
+ end
76
+
77
+ ##
78
+ # @return [RayoNode] the original command issued that lead to this event
79
+ #
80
+ def source
81
+ @source ||= connection.original_component_from_id component_id if connection && component_id
82
+ @source ||= original_component
83
+ end
84
+
85
+ alias :to_s :inspect
86
+ alias :xmlns :namespace_href
87
+ end
88
+ end
@@ -0,0 +1,26 @@
1
+ module Punchblock
2
+ ##
3
+ # An rayo Ref message. This provides the command ID in response to execution of a command.
4
+ #
5
+ class Ref < RayoNode
6
+ register :ref, :core
7
+
8
+ ##
9
+ # @return [String] the command ID
10
+ #
11
+ def id
12
+ read_attr :id
13
+ end
14
+
15
+ ##
16
+ # @param [String] ref_id the command ID
17
+ #
18
+ def id=(ref_id)
19
+ write_attr :id, ref_id
20
+ end
21
+
22
+ def inspect_attributes # :nodoc:
23
+ [:id] + super
24
+ end
25
+ end # Offer
26
+ end # Punchblock
@@ -0,0 +1,3 @@
1
+ module Punchblock
2
+ VERSION = "0.4.0"
3
+ end
data/lib/punchblock.rb ADDED
@@ -0,0 +1,42 @@
1
+ require 'active_support/dependencies/autoload'
2
+ require 'active_support/core_ext/object/blank'
3
+ require 'future-resource'
4
+
5
+ module Punchblock
6
+ extend ActiveSupport::Autoload
7
+
8
+ autoload :Command
9
+ autoload :CommandNode
10
+ autoload :Component
11
+ autoload :Connection
12
+ autoload :DSL
13
+ autoload :GenericConnection
14
+ autoload :HasHeaders
15
+ autoload :Header
16
+ autoload :MediaContainer
17
+ autoload :MediaNode
18
+ autoload :ProtocolError
19
+ autoload :RayoNode
20
+
21
+ ##
22
+ # This exception may be raised if a transport error is detected.
23
+ TransportError = Class.new StandardError
24
+
25
+ BASE_RAYO_NAMESPACE = 'urn:xmpp:rayo'
26
+ BASE_TROPO_NAMESPACE = 'urn:xmpp:tropo'
27
+ RAYO_VERSION = '1'
28
+ RAYO_NAMESPACES = {:core => [BASE_RAYO_NAMESPACE, RAYO_VERSION].compact.join(':')}
29
+
30
+ [:ext, :record, :output, :input].each do |ns|
31
+ RAYO_NAMESPACES[ns] = [BASE_RAYO_NAMESPACE, ns.to_s, RAYO_VERSION].compact.join(':')
32
+ RAYO_NAMESPACES[:"#{ns}_complete"] = [BASE_RAYO_NAMESPACE, ns.to_s, 'complete', RAYO_VERSION].compact.join(':')
33
+ end
34
+
35
+ [:ask, :conference, :say, :transfer].each do |ns|
36
+ RAYO_NAMESPACES[ns] = [BASE_TROPO_NAMESPACE, ns.to_s, RAYO_VERSION].compact.join(':')
37
+ RAYO_NAMESPACES[:"#{ns}_complete"] = [BASE_TROPO_NAMESPACE, ns.to_s, 'complete', RAYO_VERSION].compact.join(':')
38
+ end
39
+ end
40
+
41
+ require 'punchblock/event'
42
+ require 'punchblock/ref'
data/log/.gitkeep ADDED
File without changes
@@ -0,0 +1,42 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "punchblock/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{punchblock}
7
+ s.version = Punchblock::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.licenses = ["MIT"]
10
+ s.authors = ["Jason Goecke", "Ben Klang", "Ben Langfeld"]
11
+ s.email = %q{punchblock@adhearsion.com}
12
+ s.homepage = %q{http://github.com/adhearsion/punchblock}
13
+ s.summary = "Punchblock is a telephony middleware library"
14
+ s.description = "Like Rack is to Rails and Sinatra, Punchblock provides a consistent API on top of several underlying third-party call control protocols."
15
+
16
+ s.rubyforge_project = "punchblock"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+
23
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.3.7") if s.respond_to? :required_rubygems_version=
24
+
25
+ s.add_runtime_dependency %q<niceogiri>, [">= 0.0.4"]
26
+ s.add_runtime_dependency %q<blather>, [">= 0.5.3"]
27
+ s.add_runtime_dependency %q<pry>, [">= 0.8.3"]
28
+ s.add_runtime_dependency %q<activesupport>, [">= 2.1.0"]
29
+ s.add_runtime_dependency %q<state_machine>, [">= 1.0.1"]
30
+ s.add_runtime_dependency %q<future-resource>, [">= 0.0.2"]
31
+
32
+ s.add_development_dependency %q<bundler>, ["~> 1.0.0"]
33
+ s.add_development_dependency %q<rspec>, ["~> 2.3.0"]
34
+ s.add_development_dependency %q<ci_reporter>, [">= 1.6.3"]
35
+ s.add_development_dependency %q<yard>, ["~> 0.6.0"]
36
+ s.add_development_dependency %q<bluecloth>, [">= 0"]
37
+ s.add_development_dependency %q<rcov>, [">= 0"]
38
+ s.add_development_dependency %q<rake>, [">= 0"]
39
+ s.add_development_dependency %q<mocha>, [">= 0"]
40
+ s.add_development_dependency %q<i18n>, [">= 0"]
41
+ s.add_development_dependency %q<countdownlatch>, [">= 0"]
42
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ module Punchblock
4
+ module Command
5
+ describe Accept do
6
+ it 'registers itself' do
7
+ RayoNode.class_from_registration(:accept, 'urn:xmpp:rayo:1').should == Accept
8
+ end
9
+
10
+ it_should_behave_like 'command_headers'
11
+ end
12
+ end
13
+ end # Punchblock
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ module Punchblock
4
+ module Command
5
+ describe Answer do
6
+ it 'registers itself' do
7
+ RayoNode.class_from_registration(:answer, 'urn:xmpp:rayo:1').should == Answer
8
+ end
9
+
10
+ it_should_behave_like 'command_headers'
11
+ end
12
+ end
13
+ end # Punchblock
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ %w{
4
+ blather/client/dsl
5
+ punchblock/core_ext/blather/stanza
6
+ punchblock/core_ext/blather/stanza/presence
7
+ }.each { |f| require f }
8
+
9
+ module Punchblock
10
+ module Command
11
+ describe Dial do
12
+
13
+ it 'registers itself' do
14
+ RayoNode.class_from_registration(:dial, 'urn:xmpp:rayo:1').should == Dial
15
+ end
16
+
17
+ describe "when setting options in initializer" do
18
+ let(:join_params) { {:other_call_id => 'abc123'} }
19
+
20
+ subject { Dial.new :to => 'tel:+14155551212', :from => 'tel:+13035551212', :headers => { :x_skill => 'agent', :x_customer_id => 8877 }, :join => join_params }
21
+
22
+ it_should_behave_like 'command_headers'
23
+
24
+ its(:to) { should == 'tel:+14155551212' }
25
+ its(:from) { should == 'tel:+13035551212' }
26
+ its(:join) { should == Join.new(join_params) }
27
+ end
28
+
29
+ describe "#response=" do
30
+ before { subject.request! }
31
+
32
+ let(:call_id) { 'abc123' }
33
+
34
+ let :ref do
35
+ Ref.new.tap do |ref|
36
+ ref.id = call_id
37
+ end
38
+ end
39
+
40
+ let :iq do
41
+ Blather::Stanza::Iq.new(:result, 'blah').tap do |iq|
42
+ iq.from = "call.rayo.net"
43
+ iq << ref
44
+ end
45
+ end
46
+
47
+ it "should set the call ID from the ref" do
48
+ subject.response = iq
49
+ subject.call_id.should == call_id
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end # Punchblock
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ module Punchblock
4
+ module Command
5
+ describe Hangup do
6
+ it 'registers itself' do
7
+ RayoNode.class_from_registration(:hangup, 'urn:xmpp:rayo:1').should == Hangup
8
+ end
9
+
10
+ it_should_behave_like 'command_headers'
11
+ end
12
+ end
13
+ end # Punchblock
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ module Punchblock
4
+ module Command
5
+ describe Join do
6
+
7
+ it 'registers itself' do
8
+ RayoNode.class_from_registration(:join, 'urn:xmpp:rayo:1').should == Join
9
+ end
10
+
11
+ describe "when setting options in initializer" do
12
+ subject { Join.new :other_call_id => 'abc123', :mixer_id => 'blah', :direction => :duplex, :media => :bridge }
13
+
14
+ its(:other_call_id) { should == 'abc123' }
15
+ its(:mixer_id) { should == 'blah' }
16
+ its(:direction) { should == :duplex }
17
+ its(:media) { should == :bridge }
18
+ end
19
+ end
20
+ end
21
+ end # Punchblock
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ module Punchblock
4
+ module Command
5
+ describe Mute do
6
+ it 'registers itself' do
7
+ RayoNode.class_from_registration(:mute, 'urn:xmpp:rayo:1').should == Mute
8
+ end
9
+ end
10
+ end
11
+ end # Punchblock