sprsquish-blather 0.1 → 0.2.3

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 (73) hide show
  1. data/LICENSE +2 -0
  2. data/README.rdoc +100 -0
  3. data/Rakefile +110 -0
  4. data/examples/drb_client.rb +5 -0
  5. data/examples/echo.rb +18 -0
  6. data/ext/extconf.rb +65 -0
  7. data/ext/push_parser.c +231 -0
  8. data/lib/blather/client.rb +219 -44
  9. data/lib/blather/{core/sugar.rb → core_ext/active_support.rb} +25 -13
  10. data/lib/blather/core_ext/libxml.rb +28 -0
  11. data/lib/blather/errors/sasl_error.rb +87 -0
  12. data/lib/blather/errors/stanza_error.rb +262 -0
  13. data/lib/blather/errors/stream_error.rb +253 -0
  14. data/lib/blather/errors.rb +48 -0
  15. data/lib/blather/{core/jid.rb → jid.rb} +15 -26
  16. data/lib/blather/{core/roster.rb → roster.rb} +22 -0
  17. data/lib/blather/{core/roster_item.rb → roster_item.rb} +39 -8
  18. data/lib/blather/stanza/iq/disco.rb +11 -0
  19. data/lib/blather/stanza/iq/discos/disco_info.rb +86 -0
  20. data/lib/blather/stanza/iq/discos/disco_items.rb +61 -0
  21. data/lib/blather/stanza/iq/query.rb +51 -0
  22. data/lib/blather/stanza/iq/roster.rb +90 -0
  23. data/lib/blather/stanza/iq.rb +38 -0
  24. data/lib/blather/stanza/message.rb +58 -0
  25. data/lib/blather/stanza/presence/status.rb +78 -0
  26. data/lib/blather/stanza/presence/subscription.rb +72 -0
  27. data/lib/blather/stanza/presence.rb +45 -0
  28. data/lib/blather/stanza.rb +101 -0
  29. data/lib/blather/stream/client.rb +26 -0
  30. data/lib/blather/stream/component.rb +34 -0
  31. data/lib/blather/stream/parser.rb +70 -0
  32. data/lib/blather/stream/resource.rb +48 -0
  33. data/lib/blather/stream/sasl.rb +173 -0
  34. data/lib/blather/stream/session.rb +36 -0
  35. data/lib/blather/stream/stream_handler.rb +39 -0
  36. data/lib/blather/stream/tls.rb +33 -0
  37. data/lib/blather/stream.rb +249 -0
  38. data/lib/blather/xmpp_node.rb +199 -0
  39. data/lib/blather.rb +40 -41
  40. data/spec/blather/core_ext/libxml_spec.rb +58 -0
  41. data/spec/blather/errors/sasl_error_spec.rb +56 -0
  42. data/spec/blather/errors/stanza_error_spec.rb +148 -0
  43. data/spec/blather/errors/stream_error_spec.rb +114 -0
  44. data/spec/blather/errors_spec.rb +40 -0
  45. data/spec/blather/{core/jid_spec.rb → jid_spec.rb} +9 -1
  46. data/spec/blather/{core/roster_item_spec.rb → roster_item_spec.rb} +6 -1
  47. data/spec/blather/{core/roster_spec.rb → roster_spec.rb} +16 -6
  48. data/spec/blather/stanza/iq/discos/disco_info_spec.rb +207 -0
  49. data/spec/blather/stanza/iq/discos/disco_items_spec.rb +136 -0
  50. data/spec/blather/stanza/iq/query_spec.rb +34 -0
  51. data/spec/blather/stanza/iq/roster_spec.rb +123 -0
  52. data/spec/blather/stanza/iq_spec.rb +40 -0
  53. data/spec/blather/stanza/message_spec.rb +52 -0
  54. data/spec/blather/stanza/presence/status_spec.rb +102 -0
  55. data/spec/blather/stanza/presence/subscription_spec.rb +85 -0
  56. data/spec/blather/stanza/presence_spec.rb +53 -0
  57. data/spec/blather/{core/stanza_spec.rb → stanza_spec.rb} +14 -2
  58. data/spec/blather/stream/client_spec.rb +787 -0
  59. data/spec/blather/stream/component_spec.rb +86 -0
  60. data/spec/blather/{core/xmpp_node_spec.rb → xmpp_node_spec.rb} +76 -23
  61. data/spec/build_safe.rb +20 -0
  62. data/spec/spec_helper.rb +7 -17
  63. metadata +79 -59
  64. data/CHANGELOG +0 -1
  65. data/blather.gemspec +0 -73
  66. data/lib/blather/callback.rb +0 -24
  67. data/lib/blather/core/errors.rb +0 -24
  68. data/lib/blather/core/stanza.rb +0 -90
  69. data/lib/blather/core/stream.rb +0 -179
  70. data/lib/blather/core/xmpp_node.rb +0 -95
  71. data/lib/blather/extensions/last_activity.rb +0 -57
  72. data/lib/blather/extensions/version.rb +0 -85
  73. data/spec/blather/core/stream_spec.rb +0 -263
@@ -0,0 +1,136 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. .. .. spec_helper])
2
+
3
+ def disco_items_xml
4
+ <<-XML
5
+ <iq type='result'
6
+ from='catalog.shakespeare.lit'
7
+ to='romeo@montague.net/orchard'
8
+ id='items2'>
9
+ <query xmlns='http://jabber.org/protocol/disco#items'>
10
+ <item jid='catalog.shakespeare.lit'
11
+ node='books'
12
+ name='Books by and about Shakespeare'/>
13
+ <item jid='catalog.shakespeare.lit'
14
+ node='clothing'
15
+ name='Wear your literary taste with pride'/>
16
+ <item jid='catalog.shakespeare.lit'
17
+ node='music'
18
+ name='Music from the time of Shakespeare'/>
19
+ </query>
20
+ </iq>
21
+ XML
22
+ end
23
+
24
+ describe 'Blather::Stanza::Iq::DiscoItems' do
25
+ it 'registers itself' do
26
+ XMPPNode.class_from_registration(:query, 'http://jabber.org/protocol/disco#items').must_equal Blather::Stanza::Iq::DiscoItems
27
+ end
28
+
29
+ it 'has a node attribute' do
30
+ n = Blather::Stanza::Iq::DiscoItems.new nil, 'music', []
31
+ n.node.must_equal 'music'
32
+ n.node = :foo
33
+ n.node.must_equal 'foo'
34
+ end
35
+
36
+ it 'inherits a list of identities' do
37
+ n = XML::Document.string disco_items_xml
38
+ r = Stanza::Iq::DiscoItems.new.inherit n.root
39
+ r.items.size.must_equal 3
40
+ r.items.map { |i| i.class }.uniq.must_equal [Stanza::Iq::DiscoItems::Item]
41
+ end
42
+ end
43
+
44
+ describe 'Blather::Stanza::Iq::DiscoItems items' do
45
+ it 'takes a list of hashes for items' do
46
+ items = [
47
+ {:jid => 'foo@bar/baz', :node => 'node', :name => 'name'},
48
+ {:jid => 'baz@foo/bar', :node => 'node1', :name => 'name1'},
49
+ ]
50
+
51
+ control = [ Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name]),
52
+ Stanza::Iq::DiscoItems::Item.new(*%w[baz@foo/bar node1 name1])]
53
+
54
+ di = Stanza::Iq::DiscoItems.new nil, nil, items
55
+ di.items.size.must_equal 2
56
+ di.items.each { |i| control.include?(i).must_equal true }
57
+ end
58
+
59
+ it 'takes a list of Item objects as items' do
60
+ control = [ Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name]),
61
+ Stanza::Iq::DiscoItems::Item.new(*%w[baz@foo/bar node1 name1])]
62
+
63
+ di = Stanza::Iq::DiscoItems.new nil, nil, control
64
+ di.items.size.must_equal 2
65
+ di.items.each { |i| control.include?(i).must_equal true }
66
+ end
67
+
68
+ it 'takes a single hash as identity' do
69
+ control = [Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name])]
70
+
71
+ di = Stanza::Iq::DiscoItems.new nil, nil, {:jid => 'foo@bar/baz', :node => 'node', :name => 'name'}
72
+ di.items.size.must_equal 1
73
+ di.items.each { |i| control.include?(i).must_equal true }
74
+ end
75
+
76
+ it 'takes a single identity object as identity' do
77
+ control = [Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name])]
78
+
79
+ di = Stanza::Iq::DiscoItems.new nil, nil, control.first
80
+ di.items.size.must_equal 1
81
+ di.items.each { |i| control.include?(i).must_equal true }
82
+ end
83
+
84
+ it 'takes a mix of hashes and identity objects as items' do
85
+ items = [
86
+ {:jid => 'foo@bar/baz', :node => 'node', :name => 'name'},
87
+ Stanza::Iq::DiscoItems::Item.new(*%w[baz@foo/bar node1 name1]),
88
+ ]
89
+
90
+ control = [ Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name]),
91
+ Stanza::Iq::DiscoItems::Item.new(*%w[baz@foo/bar node1 name1])]
92
+
93
+ di = Stanza::Iq::DiscoItems.new nil, nil, items
94
+ di.items.size.must_equal 2
95
+ di.items.each { |i| control.include?(i).must_equal true }
96
+ end
97
+ end
98
+
99
+ describe 'Blather::Stanza::Iq::DiscoItems::Item' do
100
+ it 'will auto-inherit nodes' do
101
+ n = XML::Document.string "<item jid='foo@bar/baz' node='music' name='Music from the time of Shakespeare' />"
102
+ i = Stanza::Iq::DiscoItems::Item.new n.root
103
+ i.jid.must_equal JID.new('foo@bar/baz')
104
+ i.node.must_equal 'music'
105
+ i.name.must_equal 'Music from the time of Shakespeare'
106
+ end
107
+
108
+ it 'has a jid attribute' do
109
+ n = Stanza::Iq::DiscoItems::Item.new 'foo@bar/baz'
110
+ n.jid.must_be_kind_of JID
111
+ n.jid.must_equal JID.new('foo@bar/baz')
112
+ n.jid = 'baz@foo/bar'
113
+ n.jid.must_equal JID.new('baz@foo/bar')
114
+ end
115
+
116
+ it 'has a node attribute' do
117
+ n = Stanza::Iq::DiscoItems::Item.new 'foo@bar/baz', 'music'
118
+ n.node.must_equal 'music'
119
+ n.node = 'book'
120
+ n.node.must_equal 'book'
121
+ end
122
+
123
+ it 'has a name attribute' do
124
+ n = Stanza::Iq::DiscoItems::Item.new 'foo@bar/baz', nil, 'Music from the time of Shakespeare'
125
+ n.name.must_equal 'Music from the time of Shakespeare'
126
+ n.name = 'Books by and about Shakespeare'
127
+ n.name.must_equal 'Books by and about Shakespeare'
128
+ end
129
+
130
+ it 'can determine equality' do
131
+ a = Stanza::Iq::DiscoItems::Item.new('foo@bar/baz')
132
+ a.must_respond_to :eql?
133
+ a.must_equal Stanza::Iq::DiscoItems::Item.new('foo@bar/baz')
134
+ a.wont_equal "<item jid='foo@bar/baz' node='music' name='Music from the time of Shakespeare' />"
135
+ end
136
+ end
@@ -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 "result" 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 "result" 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,123 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. .. 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
+ XMPPNode.class_from_registration(:query, 'jabber:iq:roster').must_equal Stanza::Iq::Roster
30
+ end
31
+
32
+ it 'ensures newly inherited items are RosterItem objects' do
33
+ n = XML::Document.string roster_xml
34
+ r = Stanza::Iq::Roster.new.inherit n.root
35
+ r.items.map { |i| i.class }.uniq.must_equal [Stanza::Iq::Roster::RosterItem]
36
+ end
37
+ end
38
+
39
+ describe 'Blather::Stanza::Iq::Roster::RosterItem' do
40
+ it 'can be initialized with just a JID' do
41
+ i = Stanza::Iq::Roster::RosterItem.new 'n@d/r'
42
+ i.jid.must_equal JID.new('n@d/r')
43
+ end
44
+
45
+ it 'can be initialized with a name' do
46
+ i = Stanza::Iq::Roster::RosterItem.new nil, 'foobar'
47
+ i.name.must_equal 'foobar'
48
+ end
49
+
50
+ it 'can be initialized with a subscription' do
51
+ i = Stanza::Iq::Roster::RosterItem.new nil, nil, :both
52
+ i.subscription.must_equal :both
53
+ end
54
+
55
+ it 'can be initialized with ask (subscription sub-type)' do
56
+ i = Stanza::Iq::Roster::RosterItem.new nil, nil, nil, :subscribe
57
+ i.ask.must_equal :subscribe
58
+ end
59
+
60
+ it 'inherits a node when initialized with one' do
61
+ n = XMPPNode.new 'item'
62
+ n['jid'] = 'n@d/r'
63
+ n['subscription'] = 'both'
64
+
65
+ i = Stanza::Iq::Roster::RosterItem.new n
66
+ i.jid.must_equal JID.new('n@d/r')
67
+ i.subscription.must_equal :both
68
+ end
69
+
70
+ it 'has a #groups helper that gives an array of groups' do
71
+ n = XML::Document.string "<item jid='romeo@example.net' subscription='both'><group>foo</group><group>bar</group><group>baz</group></item>"
72
+ i = Stanza::Iq::Roster::RosterItem.new n.root
73
+ i.must_respond_to :groups
74
+ i.groups.sort.must_equal %w[bar baz foo]
75
+ end
76
+
77
+ it 'has a helper to set the groups' do
78
+ n = XML::Document.string "<item jid='romeo@example.net' subscription='both'><group>foo</group><group>bar</group><group>baz</group></item>"
79
+ i = Stanza::Iq::Roster::RosterItem.new n.root
80
+ i.must_respond_to :groups=
81
+ i.groups.sort.must_equal %w[bar baz foo]
82
+ i.groups = %w[a b c]
83
+ i.groups.sort.must_equal %w[a b c]
84
+ end
85
+
86
+ it 'can be easily converted into a proper stanza' do
87
+ xml = "<item jid='romeo@example.net' subscription='both'><group>foo</group><group>bar</group><group>baz</group></item>"
88
+ n = XML::Document.string xml
89
+ i = Stanza::Iq::Roster::RosterItem.new n.root
90
+ i.must_respond_to :to_stanza
91
+ s = i.to_stanza
92
+ s.must_be_kind_of Stanza::Iq::Roster
93
+ s.items.first.jid.must_equal JID.new('romeo@example.net')
94
+ s.items.first.groups.sort.must_equal %w[bar baz foo]
95
+ end
96
+
97
+ it 'has an "attr_accessor" for jid' do
98
+ i = Stanza::Iq::Roster::RosterItem.new
99
+ i.must_respond_to :jid
100
+ i.jid.must_be_nil
101
+ i.must_respond_to :jid=
102
+ i.jid = 'n@d/r'
103
+ i.jid.must_equal JID.new('n@d/r')
104
+ end
105
+
106
+ it 'has a name attribute' do
107
+ i = Stanza::Iq::Roster::RosterItem.new
108
+ i.name = 'name'
109
+ i.name.must_equal 'name'
110
+ end
111
+
112
+ it 'has a subscription attribute' do
113
+ i = Stanza::Iq::Roster::RosterItem.new
114
+ i.subscription = :both
115
+ i.subscription.must_equal :both
116
+ end
117
+
118
+ it 'has an ask attribute' do
119
+ i = Stanza::Iq::Roster::RosterItem.new
120
+ i.ask = :subscribe
121
+ i.ask.must_equal :subscribe
122
+ end
123
+ end
@@ -0,0 +1,40 @@
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
+
12
+ it 'wont import non-iq stanzas' do
13
+ lambda { Stanza::Iq.import(XMPPNode.new('foo')) }.must_raise(Blather::ArgumentError)
14
+ end
15
+
16
+ it 'creates a new Stanza::Iq object on import' do
17
+ Stanza::Iq.import(XMPPNode.new('iq')).must_be_kind_of Stanza::Iq
18
+ end
19
+
20
+ it 'creates a proper object based on its children' do
21
+ n = XMPPNode.new('iq')
22
+ n << XMPPNode.new('query')
23
+ Stanza::Iq.import(n).must_be_kind_of Stanza::Iq::Query
24
+ end
25
+
26
+ it 'ensures type is one of Stanza::Iq::VALID_TYPES' do
27
+ lambda { Stanza::Iq.new :invalid_type_name }.must_raise(Blather::ArgumentError)
28
+
29
+ Stanza::Iq::VALID_TYPES.each do |valid_type|
30
+ n = Stanza::Iq.new valid_type
31
+ n.type.must_equal valid_type
32
+ end
33
+ end
34
+
35
+ Stanza::Iq::VALID_TYPES.each do |valid_type|
36
+ it "provides a helper (#{valid_type}?) for type #{valid_type}" do
37
+ Stanza::Iq.new.must_respond_to :"#{valid_type}?"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,52 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
2
+
3
+ describe 'Blather::Stanza::Message' do
4
+ it 'registers itself' do
5
+ XMPPNode.class_from_registration(:message, nil).must_equal Stanza::Message
6
+ end
7
+
8
+ it 'provides "attr_accessor" for body' do
9
+ s = Stanza::Message.new
10
+ s.body.must_be_nil
11
+ s.detect { |n| n.element_name == 'body' }.must_be_nil
12
+
13
+ s.body = 'test message'
14
+ s.body.wont_be_nil
15
+ s.detect { |n| n.element_name == 'body' }.wont_be_nil
16
+ end
17
+
18
+ it 'provides "attr_accessor" for subject' do
19
+ s = Stanza::Message.new
20
+ s.subject.must_be_nil
21
+ s.detect { |n| n.element_name == 'subject' }.must_be_nil
22
+
23
+ s.subject = 'test subject'
24
+ s.subject.wont_be_nil
25
+ s.detect { |n| n.element_name == 'subject' }.wont_be_nil
26
+ end
27
+
28
+ it 'provides "attr_accessor" for thread' do
29
+ s = Stanza::Message.new
30
+ s.thread.must_be_nil
31
+ s.detect { |n| n.element_name == 'thread' }.must_be_nil
32
+
33
+ s.thread = 1234
34
+ s.thread.wont_be_nil
35
+ s.detect { |n| n.element_name == 'thread' }.wont_be_nil
36
+ end
37
+
38
+ it 'ensures type is one of Stanza::Message::VALID_TYPES' do
39
+ lambda { Stanza::Message.new nil, nil, :invalid_type_name }.must_raise(Blather::ArgumentError)
40
+
41
+ Stanza::Message::VALID_TYPES.each do |valid_type|
42
+ msg = Stanza::Message.new nil, nil, valid_type
43
+ msg.type.must_equal valid_type
44
+ end
45
+ end
46
+
47
+ Stanza::Message::VALID_TYPES.each do |valid_type|
48
+ it "provides a helper (#{valid_type}?) for type #{valid_type}" do
49
+ Stanza::Message.new.must_respond_to :"#{valid_type}?"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,102 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
2
+
3
+ describe 'Blather::Stanza::Presence::Status' do
4
+ it 'registers itself' do
5
+ XMPPNode.class_from_registration(:status, nil).must_equal Stanza::Presence::Status
6
+ end
7
+
8
+ it 'can set state on creation' do
9
+ status = Stanza::Presence::Status.new :away
10
+ status.state.must_equal :away
11
+ end
12
+
13
+ it 'can set a message on creation' do
14
+ status = Stanza::Presence::Status.new nil, 'Say hello!'
15
+ status.message.must_equal 'Say hello!'
16
+ end
17
+
18
+ it 'ensures type is nil or :unavailable' do
19
+ status = Stanza::Presence::Status.new
20
+ lambda { status.type = :invalid_type_name }.must_raise(Blather::ArgumentError)
21
+
22
+ [nil, :unavailable].each do |valid_type|
23
+ status.type = valid_type
24
+ status.type.must_equal valid_type
25
+ end
26
+ end
27
+
28
+ it 'ensures state is one of Presence::Status::VALID_STATES' do
29
+ status = Stanza::Presence::Status.new
30
+ lambda { status.state = :invalid_type_name }.must_raise(Blather::ArgumentError)
31
+
32
+ Stanza::Presence::Status::VALID_STATES.each do |valid_state|
33
+ status.state = valid_state
34
+ status.state.must_equal valid_state
35
+ end
36
+ end
37
+
38
+ it 'returns :available if state is nil' do
39
+ Stanza::Presence::Status.new.state.must_equal :available
40
+ end
41
+
42
+ it 'returns :unavailable if type is :unavailable' do
43
+ status = Stanza::Presence::Status.new
44
+ status.type = :unavailable
45
+ status.state.must_equal :unavailable
46
+ end
47
+
48
+ it 'ensures priority is not greater than 127' do
49
+ lambda { Stanza::Presence::Status.new.priority = 128 }.must_raise(Blather::ArgumentError)
50
+ end
51
+
52
+ it 'ensures priority is not less than -128' do
53
+ lambda { Stanza::Presence::Status.new.priority = -129 }.must_raise(Blather::ArgumentError)
54
+ end
55
+
56
+ it 'has "attr_accessor" for priority' do
57
+ status = Stanza::Presence::Status.new
58
+ status.priority.must_equal 0
59
+
60
+ status.priority = 10
61
+ status.children.detect { |n| n.element_name == 'priority' }.wont_be_nil
62
+ status.priority.must_equal 10
63
+ end
64
+
65
+ it 'has "attr_accessor" for message' do
66
+ status = Stanza::Presence::Status.new
67
+ status.message.must_be_nil
68
+
69
+ status.message = 'new message'
70
+ status.children.detect { |n| n.element_name == 'status' }.wont_be_nil
71
+ status.message.must_equal 'new message'
72
+ end
73
+
74
+ it 'must be comparable by priority' do
75
+ jid = JID.new 'a@b/c'
76
+
77
+ status1 = Stanza::Presence::Status.new
78
+ status1.from = jid
79
+
80
+ status2 = Stanza::Presence::Status.new
81
+ status2.from = jid
82
+
83
+ status1.priority = 1
84
+ status2.priority = -1
85
+ (status1 <=> status2).must_equal 1
86
+ (status2 <=> status1).must_equal -1
87
+
88
+ status2.priority = 1
89
+ (status1 <=> status2).must_equal 0
90
+ end
91
+
92
+ it 'raises an argument error if compared to a status with a different JID' do
93
+ status1 = Stanza::Presence::Status.new
94
+ status1.from = 'a@b/c'
95
+
96
+ status2 = Stanza::Presence::Status.new
97
+ status2.from = 'd@e/f'
98
+
99
+ lambda { status1 <=> status2 }.must_raise(Blather::ArgumentError)
100
+ end
101
+ end
102
+
@@ -0,0 +1,85 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. .. spec_helper])
2
+
3
+ describe 'Blather::Stanza::Presence::Subscription' do
4
+ it 'registers itself' do
5
+ XMPPNode.class_from_registration(:subscription, nil).must_equal Stanza::Presence::Subscription
6
+ end
7
+
8
+ it 'can set to on creation' do
9
+ sub = Stanza::Presence::Subscription.new 'a@b'
10
+ sub.to.to_s.must_equal 'a@b'
11
+ end
12
+
13
+ it 'can set a type on creation' do
14
+ sub = Stanza::Presence::Subscription.new nil, :subscribed
15
+ sub.type.must_equal :subscribed
16
+ end
17
+
18
+ it 'strips JIDs when setting #to' do
19
+ sub = Stanza::Presence::Subscription.new 'a@b/c'
20
+ sub.to.to_s.must_equal 'a@b'
21
+ end
22
+
23
+ it 'generates an approval using #approve!' do
24
+ jid = JID.new 'a@b'
25
+ sub = Stanza::Presence::Subscription.new
26
+ sub.from = jid
27
+ sub.approve!
28
+ sub.to.must_equal jid
29
+ sub.type.must_equal :subscribed
30
+ end
31
+
32
+ it 'generates a refusal using #refuse!' do
33
+ jid = JID.new 'a@b'
34
+ sub = Stanza::Presence::Subscription.new
35
+ sub.from = jid
36
+ sub.refuse!
37
+ sub.to.must_equal jid
38
+ sub.type.must_equal :unsubscribed
39
+ end
40
+
41
+ it 'generates an unsubscript using #unsubscribe!' do
42
+ jid = JID.new 'a@b'
43
+ sub = Stanza::Presence::Subscription.new
44
+ sub.from = jid
45
+ sub.unsubscribe!
46
+ sub.to.must_equal jid
47
+ sub.type.must_equal :unsubscribe
48
+ end
49
+
50
+ it 'generates a cancellation using #cancel!' do
51
+ jid = JID.new 'a@b'
52
+ sub = Stanza::Presence::Subscription.new
53
+ sub.from = jid
54
+ sub.cancel!
55
+ sub.to.must_equal jid
56
+ sub.type.must_equal :unsubscribed
57
+ end
58
+
59
+ it 'generates a request using #request!' do
60
+ jid = JID.new 'a@b'
61
+ sub = Stanza::Presence::Subscription.new
62
+ sub.from = jid
63
+ sub.request!
64
+ sub.to.must_equal jid
65
+ sub.type.must_equal :subscribe
66
+ end
67
+
68
+ it 'has a #request? helper' do
69
+ sub = Stanza::Presence::Subscription.new
70
+ sub.must_respond_to :request?
71
+ sub.type = :subscribe
72
+ sub.request?.must_equal true
73
+ end
74
+
75
+ it "will inherit only another node's attributes" do
76
+ inheritable = XMPPNode.new 'foo'
77
+ inheritable.attributes[:bar] = 'baz'
78
+
79
+ sub = Stanza::Presence::Subscription.new
80
+ sub.must_respond_to :inherit
81
+
82
+ sub.inherit inheritable
83
+ sub.attributes[:bar].must_equal 'baz'
84
+ end
85
+ end
@@ -0,0 +1,53 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
2
+
3
+ describe 'Blather::Stanza::Presence' do
4
+ it 'registers itself' do
5
+ XMPPNode.class_from_registration(:presence, nil).must_equal Stanza::Presence
6
+ end
7
+
8
+ it 'ensures type is one of Stanza::Presence::VALID_TYPES' do
9
+ presence = Stanza::Presence.new
10
+ lambda { presence.type = :invalid_type_name }.must_raise(Blather::ArgumentError)
11
+
12
+ Stanza::Presence::VALID_TYPES.each do |valid_type|
13
+ presence.type = valid_type
14
+ presence.type.must_equal valid_type
15
+ end
16
+ end
17
+
18
+ Stanza::Presence::VALID_TYPES.each do |valid_type|
19
+ it "provides a helper (#{valid_type}?) for type #{valid_type}" do
20
+ Stanza::Presence.new.must_respond_to :"#{valid_type}?"
21
+ end
22
+ end
23
+
24
+ it 'creates a Status object when importing a node with type == nil' do
25
+ s = Stanza::Presence.import(XMPPNode.new)
26
+ s.must_be_kind_of Stanza::Presence::Status
27
+ s.state.must_equal :available
28
+ end
29
+
30
+ it 'creates a Status object when importing a node with type == "unavailable"' do
31
+ n = XMPPNode.new
32
+ n.attributes[:type] = :unavailable
33
+ s = Stanza::Presence.import(n)
34
+ s.must_be_kind_of Stanza::Presence::Status
35
+ s.state.must_equal :unavailable
36
+ end
37
+
38
+ it 'creates a Subscription object when importing a node with type == "subscribe"' do
39
+ n = XMPPNode.new
40
+ n.attributes[:type] = :subscribe
41
+ s = Stanza::Presence.import(n)
42
+ s.must_be_kind_of Stanza::Presence::Subscription
43
+ s.type.must_equal :subscribe
44
+ end
45
+
46
+ it 'creates a Presence object when importing a node with type equal to something unkown' do
47
+ n = XMPPNode.new
48
+ n.attributes[:type] = :foo
49
+ s = Stanza::Presence.import(n)
50
+ s.must_be_kind_of Stanza::Presence
51
+ s.type.must_equal :foo
52
+ end
53
+ end
@@ -1,8 +1,8 @@
1
- require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
1
+ require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
2
2
 
3
3
  describe 'Blather::Stanza' do
4
4
  it 'provides .next_id helper for generating new IDs' do
5
- proc { Stanza.next_id }.must_change 'Stanza', :next_id
5
+ proc { Stanza.next_id }.must_change 'Stanza.next_id'
6
6
  end
7
7
 
8
8
  it 'can import a node' do
@@ -92,4 +92,16 @@ describe 'Blather::Stanza' do
92
92
  s.type.wont_be_nil
93
93
  s['type'].wont_be_nil
94
94
  end
95
+
96
+ it 'can be converted into an error by error name' do
97
+ s = Stanza.new('message')
98
+ err = s.as_error 'internal-server-error', 'cancel'
99
+ err.must_be_instance_of StanzaError::InternalServerError
100
+ end
101
+
102
+ it 'can be converted into an error by error class' do
103
+ s = Stanza.new('message')
104
+ err = s.as_error StanzaError::InternalServerError, 'cancel'
105
+ err.must_be_instance_of StanzaError::InternalServerError
106
+ end
95
107
  end