blather 0.1 → 0.2
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.
- data/CHANGELOG +2 -0
- data/Manifest +36 -33
- data/README.rdoc +11 -17
- data/Rakefile +4 -3
- data/blather.gemspec +9 -9
- data/examples/drb_client.rb +7 -0
- data/examples/echo.rb +9 -18
- data/lib/blather.rb +140 -31
- data/lib/blather/{core/errors.rb → errors.rb} +0 -0
- data/lib/blather/{core/jid.rb → jid.rb} +0 -0
- data/lib/blather/{core/roster.rb → roster.rb} +0 -0
- data/lib/blather/{core/roster_item.rb → roster_item.rb} +0 -0
- data/lib/blather/{core/stanza.rb → stanza.rb} +6 -14
- data/lib/blather/stanza/error.rb +31 -0
- data/lib/blather/{core/stanza → stanza}/iq.rb +2 -2
- data/lib/blather/stanza/iq/query.rb +50 -0
- data/lib/blather/{core/stanza → stanza}/iq/roster.rb +3 -3
- data/lib/blather/{core/stanza → stanza}/message.rb +6 -2
- data/lib/blather/{core/stanza → stanza}/presence.rb +10 -0
- data/lib/blather/{core/stanza → stanza}/presence/status.rb +8 -6
- data/lib/blather/{core/stanza → stanza}/presence/subscription.rb +1 -1
- data/lib/blather/{core/stream.rb → stream.rb} +1 -1
- data/lib/blather/{core/stream → stream}/parser.rb +0 -5
- data/lib/blather/{core/stream → stream}/resource.rb +0 -0
- data/lib/blather/{core/stream → stream}/sasl.rb +16 -5
- data/lib/blather/{core/stream → stream}/session.rb +0 -0
- data/lib/blather/{core/stream → stream}/tls.rb +0 -0
- data/lib/blather/{core/sugar.rb → sugar.rb} +4 -0
- data/lib/blather/{core/xmpp_node.rb → xmpp_node.rb} +1 -3
- data/spec/blather/{core/jid_spec.rb → jid_spec.rb} +16 -1
- data/spec/blather/{core/roster_item_spec.rb → roster_item_spec.rb} +1 -1
- data/spec/blather/{core/roster_spec.rb → roster_spec.rb} +11 -1
- data/spec/blather/stanza/iq/query_spec.rb +34 -0
- data/spec/blather/stanza/iq/roster_spec.rb +7 -0
- data/spec/blather/stanza/iq_spec.rb +11 -0
- data/spec/blather/stanza/message_spec.rb +52 -0
- data/spec/blather/stanza/presence/status_spec.rb +102 -0
- data/spec/blather/stanza/presence/subscription_spec.rb +74 -0
- data/spec/blather/stanza/presence_spec.rb +24 -0
- data/spec/blather/{core/stanza_spec.rb → stanza_spec.rb} +1 -1
- data/spec/blather/{core/stream_spec.rb → stream_spec.rb} +208 -9
- data/spec/blather/{core/xmpp_node_spec.rb → xmpp_node_spec.rb} +1 -1
- metadata +75 -69
- data/examples/shell_client.rb +0 -28
- data/lib/blather/callback.rb +0 -24
- data/lib/blather/client.rb +0 -81
- data/lib/blather/core/stanza/iq/query.rb +0 -42
- data/lib/blather/extensions.rb +0 -4
- data/lib/blather/extensions/last_activity.rb +0 -55
- data/lib/blather/extensions/version.rb +0 -85
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            module Blather
         | 
| 2 | 
            +
            class Stanza
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              ##
         | 
| 5 | 
            +
              # Base Error stanza
         | 
| 6 | 
            +
              class Error < Stanza
         | 
| 7 | 
            +
                def self.new_from(stanza, defined_condition, type, text = nil)
         | 
| 8 | 
            +
                  err = XMPPNode.new(defined_condition)
         | 
| 9 | 
            +
                  err['type'] = type
         | 
| 10 | 
            +
                  err.xmlns = 'urn:ietf:params:xml:ns:xmpp-stanzas'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  if text
         | 
| 13 | 
            +
                    text = XMPPNode.new('text', text)
         | 
| 14 | 
            +
                    text.xmlns = 'urn:ietf:params:xml:ns:xmpp-stanzas'
         | 
| 15 | 
            +
                    err << text
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  elem = stanza.copy(true)
         | 
| 19 | 
            +
                  elem.type = 'error'
         | 
| 20 | 
            +
                  elem << err
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  elem
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def error?
         | 
| 26 | 
            +
                  true
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end #ErrorStanza
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            end #Stanza
         | 
| 31 | 
            +
            end
         | 
| @@ -13,10 +13,10 @@ class Stanza | |
| 13 13 | 
             
                  (klass || self).new(node['type']).inherit(node)
         | 
| 14 14 | 
             
                end
         | 
| 15 15 |  | 
| 16 | 
            -
                def self.new(type, to = nil, id = nil)
         | 
| 16 | 
            +
                def self.new(type = nil, to = nil, id = nil)
         | 
| 17 17 | 
             
                  elem = super :iq
         | 
| 18 18 | 
             
                  elem.xmlns = nil
         | 
| 19 | 
            -
                  elem.type = type
         | 
| 19 | 
            +
                  elem.type = type || :get
         | 
| 20 20 | 
             
                  elem.to = to
         | 
| 21 21 | 
             
                  elem.id = id if id
         | 
| 22 22 | 
             
                  elem
         | 
| @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            module Blather
         | 
| 2 | 
            +
            class Stanza
         | 
| 3 | 
            +
            class Iq
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              class Query < Iq
         | 
| 6 | 
            +
                register :query, :query
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                ##
         | 
| 9 | 
            +
                # Ensure the namespace is set to the query node
         | 
| 10 | 
            +
                def self.new(type = nil)
         | 
| 11 | 
            +
                  elem = super
         | 
| 12 | 
            +
                  elem.query.xmlns = self.xmlns
         | 
| 13 | 
            +
                  elem
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                ##
         | 
| 17 | 
            +
                # Kill the query node before running inherit
         | 
| 18 | 
            +
                def inherit(node)
         | 
| 19 | 
            +
                  query.remove!
         | 
| 20 | 
            +
                  @query = nil
         | 
| 21 | 
            +
                  super
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                ##
         | 
| 25 | 
            +
                # Query node accessor
         | 
| 26 | 
            +
                # This will ensure there actually is a query node
         | 
| 27 | 
            +
                def query
         | 
| 28 | 
            +
                  (self << (q = XMPPNode.new('query'))) unless q = find_first('query')
         | 
| 29 | 
            +
                  q
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                ##
         | 
| 33 | 
            +
                # A query reply should have type set to "result"
         | 
| 34 | 
            +
                def reply
         | 
| 35 | 
            +
                  elem = super
         | 
| 36 | 
            +
                  elem.type = :result
         | 
| 37 | 
            +
                  elem
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                ##
         | 
| 41 | 
            +
                # A query reply should have type set to "result"
         | 
| 42 | 
            +
                def reply!
         | 
| 43 | 
            +
                  self.type = :result
         | 
| 44 | 
            +
                  super
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end #Query
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            end #Iq
         | 
| 49 | 
            +
            end #Stanza
         | 
| 50 | 
            +
            end
         | 
| @@ -5,9 +5,9 @@ class Iq | |
| 5 5 | 
             
              class Roster < Query
         | 
| 6 6 | 
             
                register :roster, nil, 'jabber:iq:roster'
         | 
| 7 7 |  | 
| 8 | 
            -
                def self.new(type, item = nil)
         | 
| 8 | 
            +
                def self.new(type = nil, item = nil)
         | 
| 9 9 | 
             
                  elem = super(type)
         | 
| 10 | 
            -
                  elem.query << item
         | 
| 10 | 
            +
                  elem.query << item if item
         | 
| 11 11 | 
             
                  elem
         | 
| 12 12 | 
             
                end
         | 
| 13 13 |  | 
| @@ -21,7 +21,7 @@ class Iq | |
| 21 21 | 
             
                end
         | 
| 22 22 |  | 
| 23 23 | 
             
                def items
         | 
| 24 | 
            -
                   | 
| 24 | 
            +
                  query.find('item')#.map { |g| RosterItem.new g }
         | 
| 25 25 | 
             
                end
         | 
| 26 26 |  | 
| 27 27 | 
             
                class RosterItem < XMPPNode
         | 
| @@ -8,7 +8,7 @@ class Stanza | |
| 8 8 |  | 
| 9 9 | 
             
                register :message
         | 
| 10 10 |  | 
| 11 | 
            -
                def self.new(to = nil,  | 
| 11 | 
            +
                def self.new(to = nil, body = nil, type = :chat)
         | 
| 12 12 | 
             
                  elem = super()
         | 
| 13 13 | 
             
                  elem.to = to
         | 
| 14 14 | 
             
                  elem.type = type
         | 
| @@ -16,6 +16,10 @@ class Stanza | |
| 16 16 | 
             
                  elem
         | 
| 17 17 | 
             
                end
         | 
| 18 18 |  | 
| 19 | 
            +
                VALID_TYPES.each do |valid_type|
         | 
| 20 | 
            +
                  define_method("#{valid_type}?") { self.type == valid_type }
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 19 23 | 
             
                ##
         | 
| 20 24 | 
             
                # Ensures type is :chat, :error, :groupchat, :headline or :normal
         | 
| 21 25 | 
             
                def type=(type)
         | 
| @@ -43,7 +47,7 @@ class Stanza | |
| 43 47 |  | 
| 44 48 | 
             
                def thread=(thread)
         | 
| 45 49 | 
             
                  remove_child :thread
         | 
| 46 | 
            -
                  self << XMPPNode.new(' | 
| 50 | 
            +
                  self << XMPPNode.new('thread', thread) if thread
         | 
| 47 51 | 
             
                end
         | 
| 48 52 |  | 
| 49 53 | 
             
                def thread
         | 
| @@ -8,6 +8,12 @@ class Stanza | |
| 8 8 |  | 
| 9 9 | 
             
                register :presence
         | 
| 10 10 |  | 
| 11 | 
            +
                ##
         | 
| 12 | 
            +
                # Ensure element_name is "presence" for all subclasses
         | 
| 13 | 
            +
                def self.new
         | 
| 14 | 
            +
                  super :presence
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 11 17 | 
             
                ##
         | 
| 12 18 | 
             
                # Creates a class based on the presence type
         | 
| 13 19 | 
             
                # either a Status or Subscription object is created based
         | 
| @@ -22,6 +28,10 @@ class Stanza | |
| 22 28 | 
             
                  klass.new.inherit(node)
         | 
| 23 29 | 
             
                end
         | 
| 24 30 |  | 
| 31 | 
            +
                VALID_TYPES.each do |valid_type|
         | 
| 32 | 
            +
                  define_method("#{valid_type}?") { self.type == valid_type }
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 25 35 | 
             
                ##
         | 
| 26 36 | 
             
                # Ensures type is one of :unavailable, :subscribe, :subscribed, :unsubscribe, :unsubscribed, :probe or :error
         | 
| 27 37 | 
             
                def type=(type)
         | 
| @@ -7,7 +7,7 @@ class Presence | |
| 7 7 |  | 
| 8 8 | 
             
                include Comparable
         | 
| 9 9 |  | 
| 10 | 
            -
                register :status
         | 
| 10 | 
            +
                register :status, :status
         | 
| 11 11 |  | 
| 12 12 | 
             
                def self.new(state = nil, message = nil)
         | 
| 13 13 | 
             
                  elem = super()
         | 
| @@ -42,15 +42,15 @@ class Presence | |
| 42 42 |  | 
| 43 43 | 
             
                ##
         | 
| 44 44 | 
             
                # Ensure priority is between -128 and 127
         | 
| 45 | 
            -
                def priority=( | 
| 46 | 
            -
                  raise ArgumentError, 'Priority must be between -128 and +127' if  | 
| 45 | 
            +
                def priority=(new_priority)
         | 
| 46 | 
            +
                  raise ArgumentError, 'Priority must be between -128 and +127' if new_priority && !(-128..127).include?(new_priority.to_i)
         | 
| 47 47 |  | 
| 48 48 | 
             
                  remove_child :priority
         | 
| 49 | 
            -
                  self << XMPPNode.new('priority',  | 
| 49 | 
            +
                  self << XMPPNode.new('priority', new_priority) if new_priority
         | 
| 50 50 | 
             
                end
         | 
| 51 51 |  | 
| 52 52 | 
             
                def priority
         | 
| 53 | 
            -
                   | 
| 53 | 
            +
                  content_from(:priority).to_i
         | 
| 54 54 | 
             
                end
         | 
| 55 55 |  | 
| 56 56 | 
             
                def message=(msg)
         | 
| @@ -66,7 +66,9 @@ class Presence | |
| 66 66 | 
             
                # Compare status based on priority
         | 
| 67 67 | 
             
                # raises an error if the JIDs aren't the same
         | 
| 68 68 | 
             
                def <=>(o)
         | 
| 69 | 
            -
                   | 
| 69 | 
            +
                  unless self.from && o.from && self.from.stripped == o.from.stripped
         | 
| 70 | 
            +
                    raise ArgumentError, "Cannot compare status from different JIDs: #{[self.from, o.from].inspect}"
         | 
| 71 | 
            +
                  end
         | 
| 70 72 | 
             
                  self.priority <=> o.priority
         | 
| 71 73 | 
             
                end
         | 
| 72 74 |  | 
| @@ -50,11 +50,6 @@ module Stream # :nodoc: | |
| 50 50 | 
             
                  @current << XML::Node.new_text(chars) if @current
         | 
| 51 51 | 
             
                end
         | 
| 52 52 |  | 
| 53 | 
            -
                def on_cdata_block(block)
         | 
| 54 | 
            -
                  LOG.debug "CDATA: #{block}" if @@debug
         | 
| 55 | 
            -
                  @current << XML::Node.new_cdata(block) if @current
         | 
| 56 | 
            -
                end
         | 
| 57 | 
            -
             | 
| 58 53 | 
             
                def on_end_element(elem)
         | 
| 59 54 | 
             
                  return if elem =~ STREAM_REGEX
         | 
| 60 55 |  | 
| 
            File without changes
         | 
| @@ -2,6 +2,8 @@ module Blather # :nodoc: | |
| 2 2 | 
             
            module Stream # :nodoc:
         | 
| 3 3 |  | 
| 4 4 | 
             
              class SASL # :nodoc:
         | 
| 5 | 
            +
                class UnknownMechanism < BlatherError; end
         | 
| 6 | 
            +
             | 
| 5 7 | 
             
                SASL_NS = 'urn:ietf:params:xml:ns:xmpp-sasl'
         | 
| 6 8 |  | 
| 7 9 | 
             
                def initialize(stream, jid, pass = nil)
         | 
| @@ -9,20 +11,24 @@ module Stream # :nodoc: | |
| 9 11 | 
             
                  @jid = jid
         | 
| 10 12 | 
             
                  @pass = pass
         | 
| 11 13 | 
             
                  @callbacks = {}
         | 
| 14 | 
            +
                  @mechanism = 0
         | 
| 15 | 
            +
                  @mechanisms = []
         | 
| 12 16 |  | 
| 13 17 | 
             
                  init_callbacks
         | 
| 14 18 | 
             
                end
         | 
| 15 19 |  | 
| 16 20 | 
             
                def init_callbacks
         | 
| 17 | 
            -
                  @callbacks['mechanisms'] = proc { set_mechanism; authenticate }
         | 
| 21 | 
            +
                  @callbacks['mechanisms'] = proc { @mechanisms = @node.children; set_mechanism; authenticate }
         | 
| 18 22 | 
             
                end
         | 
| 19 23 |  | 
| 20 24 | 
             
                def set_mechanism
         | 
| 21 | 
            -
                  mod = case (mechanism = @ | 
| 25 | 
            +
                  mod = case (mechanism = @mechanisms[@mechanism].content)
         | 
| 22 26 | 
             
                  when 'DIGEST-MD5' then DigestMD5
         | 
| 23 27 | 
             
                  when 'PLAIN'      then Plain
         | 
| 24 28 | 
             
                  when 'ANONYMOUS'  then Anonymous
         | 
| 25 | 
            -
                  else | 
| 29 | 
            +
                  else
         | 
| 30 | 
            +
                    @stream.send "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><invalid-mechanism/></failure>"
         | 
| 31 | 
            +
                    raise UnknownMechanism, "Unknown SASL mechanism (#{mechanism})"
         | 
| 26 32 | 
             
                  end
         | 
| 27 33 |  | 
| 28 34 | 
             
                  extend mod
         | 
| @@ -30,7 +36,12 @@ module Stream # :nodoc: | |
| 30 36 |  | 
| 31 37 | 
             
                def receive(node)
         | 
| 32 38 | 
             
                  @node = node
         | 
| 33 | 
            -
                  @ | 
| 39 | 
            +
                  if @node.element_name == 'failure' && @mechanisms[@mechanism += 1]
         | 
| 40 | 
            +
                    set_mechanism
         | 
| 41 | 
            +
                    authenticate
         | 
| 42 | 
            +
                  else
         | 
| 43 | 
            +
                    @callbacks[@node.element_name].call if @callbacks[@node.element_name]
         | 
| 44 | 
            +
                  end
         | 
| 34 45 | 
             
                end
         | 
| 35 46 |  | 
| 36 47 | 
             
                def success(&callback)
         | 
| @@ -106,7 +117,7 @@ module Stream # :nodoc: | |
| 106 117 | 
             
                      LOG.debug "CH RESP TXT: #{@response.map { |k,v| "#{k}=#{v}" } * ','}"
         | 
| 107 118 |  | 
| 108 119 | 
             
                      # order is to simplify testing
         | 
| 109 | 
            -
                      order = [:nonce, :charset, :username, :realm, :cnonce, :nc, :qop, :'digest-uri']
         | 
| 120 | 
            +
                      order = [:nonce, :charset, :username, :realm, :cnonce, :nc, :qop, :'digest-uri', :response]
         | 
| 110 121 | 
             
                      node.content = b64(order.map { |k| v = @response[k]; "#{k}=#{v}" } * ',')
         | 
| 111 122 | 
             
                    end
         | 
| 112 123 |  | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| @@ -7,8 +7,6 @@ module Blather | |
| 7 7 | 
             
              class XMPPNode < XML::Node
         | 
| 8 8 | 
             
                @@registrations = {}
         | 
| 9 9 |  | 
| 10 | 
            -
                alias_method :element_name, :name
         | 
| 11 | 
            -
             | 
| 12 10 | 
             
                class_inheritable_accessor  :xmlns,
         | 
| 13 11 | 
             
                                            :name
         | 
| 14 12 |  | 
| @@ -35,7 +33,7 @@ module Blather | |
| 35 33 | 
             
                def self.register(name, xmlns = nil)
         | 
| 36 34 | 
             
                  self.name = name.to_s
         | 
| 37 35 | 
             
                  self.xmlns = xmlns
         | 
| 38 | 
            -
                  @@registrations[[name, xmlns]] = self
         | 
| 36 | 
            +
                  @@registrations[[self.name, self.xmlns]] = self
         | 
| 39 37 | 
             
                end
         | 
| 40 38 |  | 
| 41 39 | 
             
                ##
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            require File.join(File.dirname(__FILE__), *%w[..  | 
| 1 | 
            +
            require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe 'Blather::JID' do
         | 
| 4 4 | 
             
              it 'does nothing if creaded from JID' do
         | 
| @@ -75,4 +75,19 @@ describe 'Blather::JID' do | |
| 75 75 | 
             
                JID.new('n', 'd', 'r').to_s.must_equal 'n@d/r'
         | 
| 76 76 | 
             
                JID.new('n', 'd').to_s.must_equal 'n@d'
         | 
| 77 77 | 
             
              end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
              it 'falls back to basic ruby if idn gem is not present' do
         | 
| 80 | 
            +
                JID.const_set 'USE_STRINGPREP', false
         | 
| 81 | 
            +
                jid = JID.new 'AB#$cdE@&^FE'
         | 
| 82 | 
            +
                jid.node.must_equal 'ab#$cde'
         | 
| 83 | 
            +
                jid.domain.must_equal '&^fe'
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              it 'provides a #stripped? helper' do
         | 
| 87 | 
            +
                jid = JID.new 'a@b/c'
         | 
| 88 | 
            +
                jid.must_respond_to :stripped?
         | 
| 89 | 
            +
                jid.stripped?.wont_equal true
         | 
| 90 | 
            +
                jid.strip!
         | 
| 91 | 
            +
                jid.stripped?.must_equal true
         | 
| 92 | 
            +
              end
         | 
| 78 93 | 
             
            end
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            require File.join(File.dirname(__FILE__), *%w[..  | 
| 1 | 
            +
            require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe 'Blather::Roster' do
         | 
| 4 4 | 
             
              before do
         | 
| @@ -40,6 +40,16 @@ describe 'Blather::Roster' do | |
| 40 40 | 
             
                @roster[jid].wont_be_nil
         | 
| 41 41 | 
             
              end
         | 
| 42 42 |  | 
| 43 | 
            +
              it 'aliases #<< to #push and returns self to allow for chaining' do
         | 
| 44 | 
            +
                jid = 'a@b/c'
         | 
| 45 | 
            +
                item = RosterItem.new(JID.new(jid))
         | 
| 46 | 
            +
                jid2 = 'd@e/f'
         | 
| 47 | 
            +
                item2 = RosterItem.new(JID.new(jid2))
         | 
| 48 | 
            +
                proc { @roster << item << item2 }.must_change('@roster.items', :length, :by => 2)
         | 
| 49 | 
            +
                @roster[jid].wont_be_nil
         | 
| 50 | 
            +
                @roster[jid2].wont_be_nil
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 43 53 | 
             
              it 'sends a @roster addition over the wire' do
         | 
| 44 54 | 
             
                stream = mock()
         | 
| 45 55 | 
             
                stream.expects(:send_data)
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe 'Blather::Stanza::Iq::Query' do
         | 
| 4 | 
            +
              it 'registers itself' do
         | 
| 5 | 
            +
                XMPPNode.class_from_registration(:query, nil).must_equal Stanza::Iq::Query
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              it 'ensures a query node is present on create' do
         | 
| 9 | 
            +
                query = Stanza::Iq::Query.new
         | 
| 10 | 
            +
                query.children.detect { |n| n.element_name == 'query' }.wont_be_nil
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              it 'ensures a query node exists when calling #query' do
         | 
| 14 | 
            +
                query = Stanza::Iq::Query.new
         | 
| 15 | 
            +
                query.remove_child :query
         | 
| 16 | 
            +
                query.children.detect { |n| n.element_name == 'query' }.must_be_nil
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                query.query.wont_be_nil
         | 
| 19 | 
            +
                query.children.detect { |n| n.element_name == 'query' }.wont_be_nil
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              it 'sets type to "reslut" on reply' do
         | 
| 23 | 
            +
                query = Stanza::Iq::Query.new
         | 
| 24 | 
            +
                query.type.must_equal :get
         | 
| 25 | 
            +
                reply = query.reply.type.must_equal :result
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              it 'sets type to "reslut" on reply!' do
         | 
| 29 | 
            +
                query = Stanza::Iq::Query.new
         | 
| 30 | 
            +
                query.type.must_equal :get
         | 
| 31 | 
            +
                query.reply!
         | 
| 32 | 
            +
                query.type.must_equal :result
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe 'Blather::Stanza::Iq' do
         | 
| 4 | 
            +
              it 'registers itself' do
         | 
| 5 | 
            +
                XMPPNode.class_from_registration(:iq, nil).must_equal Stanza::Iq
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              it 'creates a new Iq stanza defaulted as a get' do
         | 
| 9 | 
            +
                Stanza::Iq.new.type.must_equal :get
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
            end
         |