tp-blather 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
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