tp-blather 0.8.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.
Files changed (150) hide show
  1. data/.autotest +13 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +8 -0
  6. data/CHANGELOG.md +249 -0
  7. data/Gemfile +4 -0
  8. data/Guardfile +5 -0
  9. data/LICENSE +22 -0
  10. data/README.md +413 -0
  11. data/Rakefile +20 -0
  12. data/TODO.md +2 -0
  13. data/blather.gemspec +51 -0
  14. data/examples/certs/README +20 -0
  15. data/examples/certs/ca-bundle.crt +3987 -0
  16. data/examples/echo.rb +19 -0
  17. data/examples/execute.rb +17 -0
  18. data/examples/ping_pong.rb +38 -0
  19. data/examples/print_hierarchy.rb +77 -0
  20. data/examples/rosterprint.rb +15 -0
  21. data/examples/stream_only.rb +28 -0
  22. data/examples/trusted_echo.rb +21 -0
  23. data/examples/xmpp4r/echo.rb +36 -0
  24. data/lib/blather.rb +112 -0
  25. data/lib/blather/cert_store.rb +53 -0
  26. data/lib/blather/client.rb +95 -0
  27. data/lib/blather/client/client.rb +345 -0
  28. data/lib/blather/client/dsl.rb +320 -0
  29. data/lib/blather/client/dsl/pubsub.rb +174 -0
  30. data/lib/blather/core_ext/eventmachine.rb +125 -0
  31. data/lib/blather/core_ext/ipaddr.rb +20 -0
  32. data/lib/blather/errors.rb +69 -0
  33. data/lib/blather/errors/sasl_error.rb +44 -0
  34. data/lib/blather/errors/stanza_error.rb +110 -0
  35. data/lib/blather/errors/stream_error.rb +84 -0
  36. data/lib/blather/file_transfer.rb +107 -0
  37. data/lib/blather/file_transfer/ibb.rb +68 -0
  38. data/lib/blather/file_transfer/s5b.rb +114 -0
  39. data/lib/blather/jid.rb +141 -0
  40. data/lib/blather/roster.rb +118 -0
  41. data/lib/blather/roster_item.rb +146 -0
  42. data/lib/blather/stanza.rb +167 -0
  43. data/lib/blather/stanza/disco.rb +32 -0
  44. data/lib/blather/stanza/disco/capabilities.rb +161 -0
  45. data/lib/blather/stanza/disco/disco_info.rb +205 -0
  46. data/lib/blather/stanza/disco/disco_items.rb +134 -0
  47. data/lib/blather/stanza/iq.rb +144 -0
  48. data/lib/blather/stanza/iq/command.rb +339 -0
  49. data/lib/blather/stanza/iq/ibb.rb +86 -0
  50. data/lib/blather/stanza/iq/ping.rb +50 -0
  51. data/lib/blather/stanza/iq/query.rb +53 -0
  52. data/lib/blather/stanza/iq/roster.rb +185 -0
  53. data/lib/blather/stanza/iq/s5b.rb +208 -0
  54. data/lib/blather/stanza/iq/si.rb +415 -0
  55. data/lib/blather/stanza/iq/vcard.rb +149 -0
  56. data/lib/blather/stanza/message.rb +428 -0
  57. data/lib/blather/stanza/message/muc_user.rb +119 -0
  58. data/lib/blather/stanza/muc/muc_user_base.rb +54 -0
  59. data/lib/blather/stanza/presence.rb +172 -0
  60. data/lib/blather/stanza/presence/c.rb +100 -0
  61. data/lib/blather/stanza/presence/muc.rb +35 -0
  62. data/lib/blather/stanza/presence/muc_user.rb +147 -0
  63. data/lib/blather/stanza/presence/status.rb +218 -0
  64. data/lib/blather/stanza/presence/subscription.rb +100 -0
  65. data/lib/blather/stanza/pubsub.rb +119 -0
  66. data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
  67. data/lib/blather/stanza/pubsub/create.rb +65 -0
  68. data/lib/blather/stanza/pubsub/errors.rb +18 -0
  69. data/lib/blather/stanza/pubsub/event.rb +139 -0
  70. data/lib/blather/stanza/pubsub/items.rb +103 -0
  71. data/lib/blather/stanza/pubsub/publish.rb +103 -0
  72. data/lib/blather/stanza/pubsub/retract.rb +92 -0
  73. data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
  74. data/lib/blather/stanza/pubsub/subscription.rb +135 -0
  75. data/lib/blather/stanza/pubsub/subscriptions.rb +83 -0
  76. data/lib/blather/stanza/pubsub/unsubscribe.rb +84 -0
  77. data/lib/blather/stanza/pubsub_owner.rb +51 -0
  78. data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
  79. data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
  80. data/lib/blather/stanza/x.rb +416 -0
  81. data/lib/blather/stream.rb +266 -0
  82. data/lib/blather/stream/client.rb +32 -0
  83. data/lib/blather/stream/component.rb +39 -0
  84. data/lib/blather/stream/features.rb +70 -0
  85. data/lib/blather/stream/features/register.rb +38 -0
  86. data/lib/blather/stream/features/resource.rb +63 -0
  87. data/lib/blather/stream/features/sasl.rb +190 -0
  88. data/lib/blather/stream/features/session.rb +45 -0
  89. data/lib/blather/stream/features/tls.rb +29 -0
  90. data/lib/blather/stream/parser.rb +102 -0
  91. data/lib/blather/version.rb +3 -0
  92. data/lib/blather/xmpp_node.rb +94 -0
  93. data/spec/blather/client/client_spec.rb +687 -0
  94. data/spec/blather/client/dsl/pubsub_spec.rb +492 -0
  95. data/spec/blather/client/dsl_spec.rb +266 -0
  96. data/spec/blather/errors/sasl_error_spec.rb +33 -0
  97. data/spec/blather/errors/stanza_error_spec.rb +129 -0
  98. data/spec/blather/errors/stream_error_spec.rb +108 -0
  99. data/spec/blather/errors_spec.rb +33 -0
  100. data/spec/blather/file_transfer_spec.rb +135 -0
  101. data/spec/blather/jid_spec.rb +87 -0
  102. data/spec/blather/roster_item_spec.rb +134 -0
  103. data/spec/blather/roster_spec.rb +107 -0
  104. data/spec/blather/stanza/discos/disco_info_spec.rb +247 -0
  105. data/spec/blather/stanza/discos/disco_items_spec.rb +154 -0
  106. data/spec/blather/stanza/iq/command_spec.rb +206 -0
  107. data/spec/blather/stanza/iq/ibb_spec.rb +124 -0
  108. data/spec/blather/stanza/iq/ping_spec.rb +45 -0
  109. data/spec/blather/stanza/iq/query_spec.rb +64 -0
  110. data/spec/blather/stanza/iq/roster_spec.rb +139 -0
  111. data/spec/blather/stanza/iq/s5b_spec.rb +57 -0
  112. data/spec/blather/stanza/iq/si_spec.rb +98 -0
  113. data/spec/blather/stanza/iq/vcard_spec.rb +93 -0
  114. data/spec/blather/stanza/iq_spec.rb +61 -0
  115. data/spec/blather/stanza/message/muc_user_spec.rb +152 -0
  116. data/spec/blather/stanza/message_spec.rb +282 -0
  117. data/spec/blather/stanza/presence/c_spec.rb +56 -0
  118. data/spec/blather/stanza/presence/muc_spec.rb +37 -0
  119. data/spec/blather/stanza/presence/muc_user_spec.rb +83 -0
  120. data/spec/blather/stanza/presence/status_spec.rb +144 -0
  121. data/spec/blather/stanza/presence/subscription_spec.rb +102 -0
  122. data/spec/blather/stanza/presence_spec.rb +125 -0
  123. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  124. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  125. data/spec/blather/stanza/pubsub/event_spec.rb +98 -0
  126. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  127. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  128. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  129. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  130. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  131. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  132. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +74 -0
  133. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  134. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  135. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  136. data/spec/blather/stanza/pubsub_spec.rb +68 -0
  137. data/spec/blather/stanza/x_spec.rb +231 -0
  138. data/spec/blather/stanza_spec.rb +134 -0
  139. data/spec/blather/stream/client_spec.rb +1090 -0
  140. data/spec/blather/stream/component_spec.rb +108 -0
  141. data/spec/blather/stream/parser_spec.rb +152 -0
  142. data/spec/blather/stream/ssl_spec.rb +32 -0
  143. data/spec/blather/xmpp_node_spec.rb +47 -0
  144. data/spec/blather_spec.rb +34 -0
  145. data/spec/fixtures/pubsub.rb +311 -0
  146. data/spec/spec_helper.rb +17 -0
  147. data/yard/templates/default/class/html/handlers.erb +18 -0
  148. data/yard/templates/default/class/setup.rb +10 -0
  149. data/yard/templates/default/class/text/handlers.erb +1 -0
  150. metadata +459 -0
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ def ibb_open_xml
4
+ <<-XML
5
+ <iq from='romeo@montague.net/orchard'
6
+ id='jn3h8g65'
7
+ to='juliet@capulet.com/balcony'
8
+ type='set'>
9
+ <open xmlns='http://jabber.org/protocol/ibb'
10
+ block-size='4096'
11
+ sid='i781hf64'
12
+ stanza='iq'/>
13
+ </iq>
14
+ XML
15
+ end
16
+
17
+ def ibb_data_xml
18
+ <<-XML
19
+ <iq from='romeo@montague.net/orchard'
20
+ id='kr91n475'
21
+ to='juliet@capulet.com/balcony'
22
+ type='set'>
23
+ <data xmlns='http://jabber.org/protocol/ibb' seq='0' sid='i781hf64'>
24
+ qANQR1DBwU4DX7jmYZnncmUQB/9KuKBddzQH+tZ1ZywKK0yHKnq57kWq+RFtQdCJ
25
+ WpdWpR0uQsuJe7+vh3NWn59/gTc5MDlX8dS9p0ovStmNcyLhxVgmqS8ZKhsblVeu
26
+ IpQ0JgavABqibJolc3BKrVtVV1igKiX/N7Pi8RtY1K18toaMDhdEfhBRzO/XB0+P
27
+ AQhYlRjNacGcslkhXqNjK5Va4tuOAPy2n1Q8UUrHbUd0g+xJ9Bm0G0LZXyvCWyKH
28
+ kuNEHFQiLuCY6Iv0myq6iX6tjuHehZlFSh80b5BVV9tNLwNR5Eqz1klxMhoghJOA
29
+ </data>
30
+ </iq>
31
+ XML
32
+ end
33
+
34
+ def ibb_close_xml
35
+ <<-XML
36
+ <iq from='romeo@montague.net/orchard'
37
+ id='us71g45j'
38
+ to='juliet@capulet.com/balcony'
39
+ type='set'>
40
+ <close xmlns='http://jabber.org/protocol/ibb' sid='i781hf64'/>
41
+ </iq>
42
+ XML
43
+ end
44
+
45
+ describe Blather::Stanza::Iq::Ibb::Open do
46
+ it 'registers itself' do
47
+ Blather::XMPPNode.class_from_registration(:open, 'http://jabber.org/protocol/ibb').should == Blather::Stanza::Iq::Ibb::Open
48
+ end
49
+
50
+ it 'can be imported' do
51
+ node = Blather::XMPPNode.parse ibb_open_xml
52
+ node.should be_instance_of Blather::Stanza::Iq::Ibb::Open
53
+ end
54
+
55
+ it 'has open node' do
56
+ node = Blather::XMPPNode.parse ibb_open_xml
57
+ node.open.should be_kind_of Nokogiri::XML::Element
58
+ end
59
+
60
+ it 'can get sid' do
61
+ node = Blather::XMPPNode.parse ibb_open_xml
62
+ node.sid.should == 'i781hf64'
63
+ end
64
+
65
+ it 'deleted open node on reply' do
66
+ node = Blather::XMPPNode.parse ibb_open_xml
67
+ reply = node.reply
68
+ reply.open.should be_nil
69
+ end
70
+ end
71
+
72
+ describe Blather::Stanza::Iq::Ibb::Data do
73
+ it 'registers itself' do
74
+ Blather::XMPPNode.class_from_registration(:data, 'http://jabber.org/protocol/ibb').should == Blather::Stanza::Iq::Ibb::Data
75
+ end
76
+
77
+ it 'can be imported' do
78
+ node = Blather::XMPPNode.parse ibb_data_xml
79
+ node.should be_instance_of Blather::Stanza::Iq::Ibb::Data
80
+ end
81
+
82
+ it 'has data node' do
83
+ node = Blather::XMPPNode.parse ibb_data_xml
84
+ node.data.should be_kind_of Nokogiri::XML::Element
85
+ end
86
+
87
+ it 'can get sid' do
88
+ node = Blather::XMPPNode.parse ibb_data_xml
89
+ node.sid.should == 'i781hf64'
90
+ end
91
+
92
+ it 'deleted data node on reply' do
93
+ node = Blather::XMPPNode.parse ibb_data_xml
94
+ reply = node.reply
95
+ reply.data.should be_nil
96
+ end
97
+ end
98
+
99
+ describe Blather::Stanza::Iq::Ibb::Close do
100
+ it 'registers itself' do
101
+ Blather::XMPPNode.class_from_registration(:close, 'http://jabber.org/protocol/ibb').should == Blather::Stanza::Iq::Ibb::Close
102
+ end
103
+
104
+ it 'can be imported' do
105
+ node = Blather::XMPPNode.parse ibb_close_xml
106
+ node.should be_instance_of Blather::Stanza::Iq::Ibb::Close
107
+ end
108
+
109
+ it 'has close node' do
110
+ node = Blather::XMPPNode.parse ibb_close_xml
111
+ node.close.should be_kind_of Nokogiri::XML::Element
112
+ end
113
+
114
+ it 'can get sid' do
115
+ node = Blather::XMPPNode.parse ibb_close_xml
116
+ node.sid.should == 'i781hf64'
117
+ end
118
+
119
+ it 'deleted close node on reply' do
120
+ node = Blather::XMPPNode.parse ibb_close_xml
121
+ reply = node.reply
122
+ reply.close.should be_nil
123
+ end
124
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ def ping_xml
4
+ <<-XML
5
+ <iq from='capulet.lit' to='juliet@capulet.lit/balcony' id='s2c1' type='get'>
6
+ <ping xmlns='urn:xmpp:ping'/>
7
+ </iq>
8
+ XML
9
+ end
10
+
11
+ describe Blather::Stanza::Iq::Ping do
12
+ it 'registers itself' do
13
+ Blather::XMPPNode.class_from_registration(:ping, 'urn:xmpp:ping').should == Blather::Stanza::Iq::Ping
14
+ end
15
+
16
+ it 'can be imported' do
17
+ node = Blather::XMPPNode.parse ping_xml
18
+ node.should be_instance_of Blather::Stanza::Iq::Ping
19
+ end
20
+
21
+ it 'ensures a ping node is present on create' do
22
+ iq = Blather::Stanza::Iq::Ping.new
23
+ iq.xpath('ns:ping', :ns => 'urn:xmpp:ping').should_not be_empty
24
+ end
25
+
26
+ it 'ensures a ping node exists when calling #ping' do
27
+ iq = Blather::Stanza::Iq::Ping.new
28
+ iq.ping.remove
29
+ iq.xpath('ns:ping', :ns => 'urn:xmpp:ping').should be_empty
30
+
31
+ iq.ping.should_not be_nil
32
+ iq.xpath('ns:ping', :ns => 'urn:xmpp:ping').should_not be_empty
33
+ end
34
+
35
+ it 'responds with an empty IQ' do
36
+ ping = Blather::Stanza::Iq::Ping.new :get, 'one@example.com', 'abc123'
37
+ ping.from = 'two@example.com'
38
+ expected_pong = Blather::Stanza::Iq::Ping.new(:result, 'two@example.com', 'abc123').tap do |pong|
39
+ pong.from = 'one@example.com'
40
+ end
41
+ reply = ping.reply
42
+ reply.should == expected_pong
43
+ reply.children.count.should == 0
44
+ end
45
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Blather::Stanza::Iq::Query do
4
+ it 'registers itself' do
5
+ Blather::XMPPNode.class_from_registration(:query, nil).should == Blather::Stanza::Iq::Query
6
+ end
7
+
8
+ it 'can be imported' do
9
+ string = <<-XML
10
+ <iq from='juliet@example.com/balcony' type='set' id='roster_4'>
11
+ <query>
12
+ <item jid='nurse@example.com' subscription='remove'/>
13
+ </query>
14
+ </iq>
15
+ XML
16
+ Blather::XMPPNode.parse(string).should be_instance_of Blather::Stanza::Iq::Query
17
+ end
18
+
19
+ it 'ensures a query node is present on create' do
20
+ query = Blather::Stanza::Iq::Query.new
21
+ query.xpath('query').should_not be_empty
22
+ end
23
+
24
+ it 'ensures a query node exists when calling #query' do
25
+ query = Blather::Stanza::Iq::Query.new
26
+ query.remove_child :query
27
+ query.xpath('query').should be_empty
28
+
29
+ query.query.should_not be_nil
30
+ query.xpath('query').should_not be_empty
31
+ end
32
+
33
+ [:get, :set, :result, :error].each do |type|
34
+ it "can be set as \"#{type}\"" do
35
+ query = Blather::Stanza::Iq::Query.new type
36
+ query.type.should == type
37
+ end
38
+ end
39
+
40
+ it 'sets type to "result" on reply' do
41
+ query = Blather::Stanza::Iq::Query.new
42
+ query.type.should == :get
43
+ reply = query.reply.type.should == :result
44
+ end
45
+
46
+ it 'sets type to "result" on reply!' do
47
+ query = Blather::Stanza::Iq::Query.new
48
+ query.type.should == :get
49
+ query.reply!
50
+ query.type.should == :result
51
+ end
52
+
53
+ it 'can be registered under a namespace' do
54
+ class QueryNs < Blather::Stanza::Iq::Query; register :query_ns, nil, 'query:ns'; end
55
+ Blather::XMPPNode.class_from_registration(:query, 'query:ns').should == QueryNs
56
+ query_ns = QueryNs.new
57
+ query_ns.xpath('query').should be_empty
58
+ query_ns.xpath('ns:query', :ns => 'query:ns').size.should == 1
59
+
60
+ query_ns.query
61
+ query_ns.query
62
+ query_ns.xpath('ns:query', :ns => 'query:ns').size.should == 1
63
+ end
64
+ end
@@ -0,0 +1,139 @@
1
+ require 'spec_helper'
2
+
3
+ def roster_xml
4
+ <<-XML
5
+ <iq to='juliet@example.com/balcony' type='result' id='roster_1'>
6
+ <query xmlns='jabber:iq:roster'>
7
+ <item jid='romeo@example.net'
8
+ name='Romeo'
9
+ subscription='both'>
10
+ <group>Friends</group>
11
+ </item>
12
+ <item jid='mercutio@example.org'
13
+ name='Mercutio'
14
+ subscription='from'>
15
+ <group>Friends</group>
16
+ </item>
17
+ <item jid='benvolio@example.org'
18
+ name='Benvolio'
19
+ subscription='both'>
20
+ <group>Friends</group>
21
+ </item>
22
+ </query>
23
+ </iq>
24
+ XML
25
+ end
26
+
27
+ describe Blather::Stanza::Iq::Roster do
28
+ it 'registers itself' do
29
+ Blather::XMPPNode.class_from_registration(:query, 'jabber:iq:roster').should == Blather::Stanza::Iq::Roster
30
+ end
31
+
32
+ it 'ensures newly inherited items are RosterItem objects' do
33
+ n = parse_stanza roster_xml
34
+ r = Blather::Stanza::Iq::Roster.new.inherit n.root
35
+ r.items.map { |i| i.class }.uniq.should == [Blather::Stanza::Iq::Roster::RosterItem]
36
+ end
37
+
38
+ it 'can be created with #import' do
39
+ Blather::XMPPNode.parse(roster_xml).should be_instance_of Blather::Stanza::Iq::Roster
40
+ end
41
+ end
42
+
43
+ describe Blather::Stanza::Iq::Roster::RosterItem do
44
+ it 'can be initialized with just a Blather::JID' do
45
+ i = Blather::Stanza::Iq::Roster::RosterItem.new 'n@d/r'
46
+ i.jid.should == Blather::JID.new('n@d/r').stripped
47
+ end
48
+
49
+ it 'can be initialized with a name' do
50
+ i = Blather::Stanza::Iq::Roster::RosterItem.new nil, 'foobar'
51
+ i.name.should == 'foobar'
52
+ end
53
+
54
+ it 'can be initialized with a subscription' do
55
+ i = Blather::Stanza::Iq::Roster::RosterItem.new nil, nil, :both
56
+ i.subscription.should == :both
57
+ end
58
+
59
+ it 'can be initialized with ask (subscription sub-type)' do
60
+ i = Blather::Stanza::Iq::Roster::RosterItem.new nil, nil, nil, :subscribe
61
+ i.ask.should == :subscribe
62
+ end
63
+
64
+ it 'can be initailized with a hash' do
65
+ control = { :jid => 'j@d/r',
66
+ :name => 'name',
67
+ :subscription => :both,
68
+ :ask => :subscribe }
69
+ i = Blather::Stanza::Iq::Roster::RosterItem.new control
70
+ i.jid.should == Blather::JID.new(control[:jid]).stripped
71
+ i.name.should == control[:name]
72
+ i.subscription.should == control[:subscription]
73
+ i.ask.should == control[:ask]
74
+ end
75
+
76
+ it 'inherits a node when initialized with one' do
77
+ n = Blather::XMPPNode.new 'item'
78
+ n[:jid] = 'n@d/r'
79
+ n[:subscription] = 'both'
80
+
81
+ i = Blather::Stanza::Iq::Roster::RosterItem.new n
82
+ i.jid.should == Blather::JID.new('n@d/r')
83
+ i.subscription.should == :both
84
+ end
85
+
86
+ it 'has a #groups helper that gives an array of groups' do
87
+ n = parse_stanza "<item jid='romeo@example.net' subscription='both'><group>foo</group><group>bar</group><group>baz</group></item>"
88
+ i = Blather::Stanza::Iq::Roster::RosterItem.new n.root
89
+ i.should respond_to :groups
90
+ i.groups.sort.should == %w[bar baz foo]
91
+ end
92
+
93
+ it 'has a helper to set the groups' do
94
+ n = parse_stanza "<item jid='romeo@example.net' subscription='both'><group>foo</group><group>bar</group><group>baz</group></item>"
95
+ i = Blather::Stanza::Iq::Roster::RosterItem.new n.root
96
+ i.should respond_to :groups=
97
+ i.groups.sort.should == %w[bar baz foo]
98
+ i.groups = %w[a b c]
99
+ i.groups.sort.should == %w[a b c]
100
+ end
101
+
102
+ it 'can be easily converted into a proper stanza' do
103
+ xml = "<item jid='romeo@example.net' subscription='both'><group>foo</group><group>bar</group><group>baz</group></item>"
104
+ n = parse_stanza xml
105
+ i = Blather::Stanza::Iq::Roster::RosterItem.new n.root
106
+ i.should respond_to :to_stanza
107
+ s = i.to_stanza
108
+ s.should be_kind_of Blather::Stanza::Iq::Roster
109
+ s.items.first.jid.should == Blather::JID.new('romeo@example.net')
110
+ s.items.first.groups.sort.should == %w[bar baz foo]
111
+ end
112
+
113
+ it 'has an "attr_accessor" for jid' do
114
+ i = Blather::Stanza::Iq::Roster::RosterItem.new
115
+ i.should respond_to :jid
116
+ i.jid.should be_nil
117
+ i.should respond_to :jid=
118
+ i.jid = 'n@d/r'
119
+ i.jid.should == Blather::JID.new('n@d/r').stripped
120
+ end
121
+
122
+ it 'has a name attribute' do
123
+ i = Blather::Stanza::Iq::Roster::RosterItem.new
124
+ i.name = 'name'
125
+ i.name.should == 'name'
126
+ end
127
+
128
+ it 'has a subscription attribute' do
129
+ i = Blather::Stanza::Iq::Roster::RosterItem.new
130
+ i.subscription = :both
131
+ i.subscription.should == :both
132
+ end
133
+
134
+ it 'has an ask attribute' do
135
+ i = Blather::Stanza::Iq::Roster::RosterItem.new
136
+ i.ask = :subscribe
137
+ i.ask.should == :subscribe
138
+ end
139
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ def s5b_open_xml
4
+ <<-XML
5
+ <iq from='requester@example.com/foo'
6
+ id='hu3vax16'
7
+ to='target@example.org/bar'
8
+ type='set'>
9
+ <query xmlns='http://jabber.org/protocol/bytestreams'
10
+ sid='vxf9n471bn46'>
11
+ <streamhost
12
+ jid='requester@example.com/foo'
13
+ host='192.168.4.1'
14
+ port='5086'/>
15
+ <streamhost
16
+ jid='requester2@example.com/foo'
17
+ host='192.168.4.2'
18
+ port='5087'/>
19
+ </query>
20
+ </iq>
21
+ XML
22
+ end
23
+
24
+ describe Blather::Stanza::Iq::S5b do
25
+ it 'registers itself' do
26
+ Blather::XMPPNode.class_from_registration(:query, 'http://jabber.org/protocol/bytestreams').should == Blather::Stanza::Iq::S5b
27
+ end
28
+
29
+ it 'can be imported' do
30
+ node = Blather::XMPPNode.parse s5b_open_xml
31
+ node.should be_instance_of Blather::Stanza::Iq::S5b
32
+ end
33
+
34
+ it 'can get sid' do
35
+ node = Blather::XMPPNode.parse s5b_open_xml
36
+ node.sid.should == 'vxf9n471bn46'
37
+ end
38
+
39
+ it 'can get streamhosts' do
40
+ node = Blather::XMPPNode.parse s5b_open_xml
41
+ node.streamhosts.size.should == 2
42
+ end
43
+
44
+ it 'can set streamhosts' do
45
+ node = Blather::Stanza::Iq::S5b.new
46
+ node.streamhosts += [{:jid => 'test@example.com/foo', :host => '192.168.5.1', :port => 123}]
47
+ node.streamhosts.size.should == 1
48
+ node.streamhosts += [Blather::Stanza::Iq::S5b::StreamHost.new('test2@example.com/foo', '192.168.5.2', 123)]
49
+ node.streamhosts.size.should == 2
50
+ end
51
+
52
+ it 'can get and set streamhost-used' do
53
+ node = Blather::Stanza::Iq::S5b.new
54
+ node.streamhost_used = 'used@example.com/foo'
55
+ node.streamhost_used.jid.to_s.should == 'used@example.com/foo'
56
+ end
57
+ end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ def si_xml
4
+ <<-XML
5
+ <iq type='set' id='offer1' to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard'>
6
+ <si xmlns='http://jabber.org/protocol/si'
7
+ id='a0'
8
+ mime-type='text/plain'
9
+ profile='http://jabber.org/protocol/si/profile/file-transfer'>
10
+ <file xmlns='http://jabber.org/protocol/si/profile/file-transfer'
11
+ name='test.txt'
12
+ size='1022'>
13
+ <range/>
14
+ </file>
15
+ <feature xmlns='http://jabber.org/protocol/feature-neg'>
16
+ <x xmlns='jabber:x:data' type='form'>
17
+ <field var='stream-method' type='list-single'>
18
+ <option><value>http://jabber.org/protocol/bytestreams</value></option>
19
+ <option><value>http://jabber.org/protocol/ibb</value></option>
20
+ </field>
21
+ </x>
22
+ </feature>
23
+ </si>
24
+ </iq>
25
+ XML
26
+ end
27
+
28
+ describe Blather::Stanza::Iq::Si do
29
+ it 'registers itself' do
30
+ Blather::XMPPNode.class_from_registration(:si, 'http://jabber.org/protocol/si').should == Blather::Stanza::Iq::Si
31
+ end
32
+
33
+ it 'can be imported' do
34
+ node = Blather::XMPPNode.parse si_xml
35
+ node.should be_instance_of Blather::Stanza::Iq::Si
36
+ node.si.should be_instance_of Blather::Stanza::Iq::Si::Si
37
+ end
38
+
39
+ it 'ensures a si node is present on create' do
40
+ iq = Blather::Stanza::Iq::Si.new
41
+ iq.xpath('ns:si', :ns => 'http://jabber.org/protocol/si').should_not be_empty
42
+ end
43
+
44
+ it 'ensures a si node exists when calling #si' do
45
+ iq = Blather::Stanza::Iq::Si.new
46
+ iq.si.remove
47
+ iq.xpath('ns:si', :ns => 'http://jabber.org/protocol/si').should be_empty
48
+
49
+ iq.si.should_not be_nil
50
+ iq.xpath('ns:si', :ns => 'http://jabber.org/protocol/si').should_not be_empty
51
+ end
52
+
53
+ it 'ensures a si node is replaced when calling #si=' do
54
+ iq = Blather::XMPPNode.parse si_xml
55
+
56
+ new_si = Blather::Stanza::Iq::Si::Si.new
57
+ new_si.id = 'a1'
58
+
59
+ iq.si = new_si
60
+
61
+ iq.xpath('ns:si', :ns => 'http://jabber.org/protocol/si').size.should == 1
62
+ iq.si.id.should == 'a1'
63
+ end
64
+ end
65
+
66
+ describe Blather::Stanza::Iq::Si::Si do
67
+ it 'can set and get attributes' do
68
+ si = Blather::Stanza::Iq::Si::Si.new
69
+ si.id = 'a1'
70
+ si.mime_type = 'text/plain'
71
+ si.profile = 'http://jabber.org/protocol/si/profile/file-transfer'
72
+ si.id.should == 'a1'
73
+ si.mime_type.should == 'text/plain'
74
+ si.profile.should == 'http://jabber.org/protocol/si/profile/file-transfer'
75
+ end
76
+ end
77
+
78
+ describe Blather::Stanza::Iq::Si::Si::File do
79
+ it 'can be initialized with name and size' do
80
+ file = Blather::Stanza::Iq::Si::Si::File.new('test.txt', 123)
81
+ file.name.should == 'test.txt'
82
+ file.size.should == 123
83
+ end
84
+
85
+ it 'can be initialized with node' do
86
+ node = Blather::XMPPNode.parse si_xml
87
+
88
+ file = Blather::Stanza::Iq::Si::Si::File.new node.find_first('.//ns:file', :ns => 'http://jabber.org/protocol/si/profile/file-transfer')
89
+ file.name.should == 'test.txt'
90
+ file.size.should == 1022
91
+ end
92
+
93
+ it 'can set and get description' do
94
+ file = Blather::Stanza::Iq::Si::Si::File.new('test.txt', 123)
95
+ file.desc = 'This is a test. If this were a real file...'
96
+ file.desc.should == 'This is a test. If this were a real file...'
97
+ end
98
+ end