shingara-blather 0.4.8
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/LICENSE +22 -0
- data/README.md +162 -0
- data/examples/echo.rb +18 -0
- data/examples/execute.rb +16 -0
- data/examples/ping_pong.rb +37 -0
- data/examples/print_hierarchy.rb +76 -0
- data/examples/rosterprint.rb +14 -0
- data/examples/stream_only.rb +27 -0
- data/examples/xmpp4r/echo.rb +35 -0
- data/lib/blather/client/client.rb +310 -0
- data/lib/blather/client/dsl/pubsub.rb +170 -0
- data/lib/blather/client/dsl.rb +264 -0
- data/lib/blather/client.rb +87 -0
- data/lib/blather/core_ext/nokogiri.rb +40 -0
- data/lib/blather/errors/sasl_error.rb +43 -0
- data/lib/blather/errors/stanza_error.rb +107 -0
- data/lib/blather/errors/stream_error.rb +82 -0
- data/lib/blather/errors.rb +69 -0
- data/lib/blather/jid.rb +142 -0
- data/lib/blather/roster.rb +111 -0
- data/lib/blather/roster_item.rb +122 -0
- data/lib/blather/stanza/disco/disco_info.rb +176 -0
- data/lib/blather/stanza/disco/disco_items.rb +132 -0
- data/lib/blather/stanza/disco.rb +25 -0
- data/lib/blather/stanza/iq/query.rb +53 -0
- data/lib/blather/stanza/iq/roster.rb +179 -0
- data/lib/blather/stanza/iq.rb +138 -0
- data/lib/blather/stanza/message.rb +332 -0
- data/lib/blather/stanza/presence/status.rb +212 -0
- data/lib/blather/stanza/presence/subscription.rb +101 -0
- data/lib/blather/stanza/presence.rb +163 -0
- data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
- data/lib/blather/stanza/pubsub/create.rb +65 -0
- data/lib/blather/stanza/pubsub/errors.rb +18 -0
- data/lib/blather/stanza/pubsub/event.rb +123 -0
- data/lib/blather/stanza/pubsub/items.rb +103 -0
- data/lib/blather/stanza/pubsub/publish.rb +103 -0
- data/lib/blather/stanza/pubsub/retract.rb +92 -0
- data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
- data/lib/blather/stanza/pubsub/subscription.rb +134 -0
- data/lib/blather/stanza/pubsub/subscriptions.rb +81 -0
- data/lib/blather/stanza/pubsub/unsubscribe.rb +68 -0
- data/lib/blather/stanza/pubsub.rb +129 -0
- data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
- data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
- data/lib/blather/stanza/pubsub_owner.rb +51 -0
- data/lib/blather/stanza.rb +149 -0
- data/lib/blather/stream/client.rb +31 -0
- data/lib/blather/stream/component.rb +38 -0
- data/lib/blather/stream/features/resource.rb +63 -0
- data/lib/blather/stream/features/sasl.rb +187 -0
- data/lib/blather/stream/features/session.rb +44 -0
- data/lib/blather/stream/features/tls.rb +28 -0
- data/lib/blather/stream/features.rb +53 -0
- data/lib/blather/stream/parser.rb +102 -0
- data/lib/blather/stream.rb +231 -0
- data/lib/blather/xmpp_node.rb +218 -0
- data/lib/blather.rb +78 -0
- data/spec/blather/client/client_spec.rb +559 -0
- data/spec/blather/client/dsl/pubsub_spec.rb +462 -0
- data/spec/blather/client/dsl_spec.rb +143 -0
- data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
- data/spec/blather/errors/sasl_error_spec.rb +33 -0
- data/spec/blather/errors/stanza_error_spec.rb +129 -0
- data/spec/blather/errors/stream_error_spec.rb +108 -0
- data/spec/blather/errors_spec.rb +33 -0
- data/spec/blather/jid_spec.rb +87 -0
- data/spec/blather/roster_item_spec.rb +96 -0
- data/spec/blather/roster_spec.rb +103 -0
- data/spec/blather/stanza/discos/disco_info_spec.rb +226 -0
- data/spec/blather/stanza/discos/disco_items_spec.rb +148 -0
- data/spec/blather/stanza/iq/query_spec.rb +64 -0
- data/spec/blather/stanza/iq/roster_spec.rb +140 -0
- data/spec/blather/stanza/iq_spec.rb +45 -0
- data/spec/blather/stanza/message_spec.rb +132 -0
- data/spec/blather/stanza/presence/status_spec.rb +132 -0
- data/spec/blather/stanza/presence/subscription_spec.rb +105 -0
- data/spec/blather/stanza/presence_spec.rb +66 -0
- data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
- data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
- data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
- data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
- data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
- data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
- data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
- data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
- data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
- data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
- data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
- data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
- data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
- data/spec/blather/stanza/pubsub_spec.rb +67 -0
- data/spec/blather/stanza_spec.rb +116 -0
- data/spec/blather/stream/client_spec.rb +1011 -0
- data/spec/blather/stream/component_spec.rb +95 -0
- data/spec/blather/stream/parser_spec.rb +145 -0
- data/spec/blather/xmpp_node_spec.rb +231 -0
- data/spec/fixtures/pubsub.rb +311 -0
- data/spec/spec_helper.rb +43 -0
- metadata +249 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
|
|
2
|
+
|
|
3
|
+
def sasl_error_node(err_name = 'aborted')
|
|
4
|
+
node = Blather::XMPPNode.new 'failure'
|
|
5
|
+
node.namespace = Blather::SASLError::SASL_ERR_NS
|
|
6
|
+
|
|
7
|
+
node << Blather::XMPPNode.new(err_name, node.document)
|
|
8
|
+
node
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe Blather::SASLError do
|
|
12
|
+
it 'can import a node' do
|
|
13
|
+
Blather::SASLError.must_respond_to :import
|
|
14
|
+
e = Blather::SASLError.import sasl_error_node
|
|
15
|
+
e.must_be_kind_of Blather::SASLError
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe 'each XMPP SASL error type' do
|
|
19
|
+
%w[ aborted
|
|
20
|
+
incorrect-encoding
|
|
21
|
+
invalid-authzid
|
|
22
|
+
invalid-mechanism
|
|
23
|
+
mechanism-too-weak
|
|
24
|
+
not-authorized
|
|
25
|
+
temporary-auth-failure
|
|
26
|
+
].each do |error_type|
|
|
27
|
+
it "handles the name for #{error_type}" do
|
|
28
|
+
e = Blather::SASLError.import sasl_error_node(error_type)
|
|
29
|
+
e.name.must_equal error_type.gsub('-','_').to_sym
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
|
|
2
|
+
|
|
3
|
+
def stanza_error_node(type = 'cancel', error = 'internal-server-error', msg = nil)
|
|
4
|
+
node = Blather::Stanza::Message.new 'error@jabber.local', 'test message', :error
|
|
5
|
+
|
|
6
|
+
node << (error_node = Blather::XMPPNode.new('error'))
|
|
7
|
+
error_node['type'] = type.to_s
|
|
8
|
+
|
|
9
|
+
error_node << (err = Blather::XMPPNode.new(error, error_node.document))
|
|
10
|
+
err.namespace = 'urn:ietf:params:xml:ns:xmpp-stanzas'
|
|
11
|
+
|
|
12
|
+
if msg
|
|
13
|
+
error_node << (text = Blather::XMPPNode.new('text', error_node.document))
|
|
14
|
+
text.namespace = 'urn:ietf:params:xml:ns:xmpp-stanzas'
|
|
15
|
+
text.content = msg
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
error_node << (extra = Blather::XMPPNode.new('extra-error', error_node.document))
|
|
19
|
+
extra.namespace = 'blather:stanza:error'
|
|
20
|
+
extra.content = 'Blather Error'
|
|
21
|
+
|
|
22
|
+
node
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe Blather::StanzaError do
|
|
26
|
+
it 'can import a node' do
|
|
27
|
+
Blather::StanzaError.must_respond_to :import
|
|
28
|
+
e = Blather::StanzaError.import stanza_error_node
|
|
29
|
+
e.must_be_kind_of Blather::StanzaError
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe 'valid types' do
|
|
33
|
+
before { @original = Blather::Stanza::Message.new 'error@jabber.local', 'test message', :error }
|
|
34
|
+
|
|
35
|
+
it 'ensures type is one of Stanza::Message::VALID_TYPES' do
|
|
36
|
+
lambda { Blather::StanzaError.new @original, :gone, :invalid_type_name }.must_raise(Blather::ArgumentError)
|
|
37
|
+
|
|
38
|
+
Blather::StanzaError::VALID_TYPES.each do |valid_type|
|
|
39
|
+
msg = Blather::StanzaError.new @original, :gone, valid_type
|
|
40
|
+
msg.type.must_equal valid_type
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe 'when instantiated' do
|
|
46
|
+
before do
|
|
47
|
+
@type = 'cancel'
|
|
48
|
+
@err_name = 'internal-server-error'
|
|
49
|
+
@msg = 'the server has experienced a misconfiguration'
|
|
50
|
+
@err = Blather::StanzaError.import stanza_error_node(@type, @err_name, @msg)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'provides a type attribute' do
|
|
54
|
+
@err.must_respond_to :type
|
|
55
|
+
@err.type.must_equal @type.to_sym
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'provides a name attribute' do
|
|
59
|
+
@err.must_respond_to :name
|
|
60
|
+
@err.name.must_equal @err_name.gsub('-','_').to_sym
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'provides a text attribute' do
|
|
64
|
+
@err.must_respond_to :text
|
|
65
|
+
@err.text.must_equal @msg
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'provides a reader to the original node' do
|
|
69
|
+
@err.must_respond_to :original
|
|
70
|
+
@err.original.must_be_instance_of Blather::Stanza::Message
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'provides an extras attribute' do
|
|
74
|
+
@err.must_respond_to :extras
|
|
75
|
+
@err.extras.must_be_instance_of Array
|
|
76
|
+
@err.extras.first.element_name.must_equal 'extra-error'
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'describes itself' do
|
|
80
|
+
@err.to_s.must_match(/#{@err_name}/)
|
|
81
|
+
@err.to_s.must_match(/#{@msg}/)
|
|
82
|
+
|
|
83
|
+
@err.inspect.must_match(/#{@err_name}/)
|
|
84
|
+
@err.inspect.must_match(/#{@msg}/)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'can be turned into xml' do
|
|
88
|
+
@err.must_respond_to :to_xml
|
|
89
|
+
doc = parse_stanza @err.to_xml
|
|
90
|
+
|
|
91
|
+
doc.xpath("/message[@from='error@jabber.local' and @type='error']").wont_be_empty
|
|
92
|
+
doc.xpath("/message/error").wont_be_empty
|
|
93
|
+
doc.xpath("/message/error/err_ns:internal-server-error", :err_ns => Blather::StanzaError::STANZA_ERR_NS).wont_be_empty
|
|
94
|
+
doc.xpath("/message/error/err_ns:text[.='the server has experienced a misconfiguration']", :err_ns => Blather::StanzaError::STANZA_ERR_NS).wont_be_empty
|
|
95
|
+
doc.xpath("/message/error/extra_ns:extra-error[.='Blather Error']", :extra_ns => 'blather:stanza:error').wont_be_empty
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe 'each XMPP stanza error type' do
|
|
100
|
+
%w[ bad-request
|
|
101
|
+
conflict
|
|
102
|
+
feature-not-implemented
|
|
103
|
+
forbidden
|
|
104
|
+
gone
|
|
105
|
+
internal-server-error
|
|
106
|
+
item-not-found
|
|
107
|
+
jid-malformed
|
|
108
|
+
not-acceptable
|
|
109
|
+
not-allowed
|
|
110
|
+
not-authorized
|
|
111
|
+
payment-required
|
|
112
|
+
recipient-unavailable
|
|
113
|
+
redirect
|
|
114
|
+
registration-required
|
|
115
|
+
remote-server-not-found
|
|
116
|
+
remote-server-timeout
|
|
117
|
+
resource-constraint
|
|
118
|
+
service-unavailable
|
|
119
|
+
subscription-required
|
|
120
|
+
undefined-condition
|
|
121
|
+
unexpected-request
|
|
122
|
+
].each do |error_type|
|
|
123
|
+
it "handles the name for #{error_type}" do
|
|
124
|
+
e = Blather::StanzaError.import stanza_error_node(:cancel, error_type)
|
|
125
|
+
e.name.must_equal error_type.gsub('-','_').to_sym
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. .. spec_helper])
|
|
2
|
+
|
|
3
|
+
def stream_error_node(error = 'internal-server-error', msg = nil)
|
|
4
|
+
node = Blather::XMPPNode.new('error')
|
|
5
|
+
node.namespace = {'stream' => Blather::Stream::STREAM_NS}
|
|
6
|
+
|
|
7
|
+
node << (err = Blather::XMPPNode.new(error, node.document))
|
|
8
|
+
err.namespace = 'urn:ietf:params:xml:ns:xmpp-streams'
|
|
9
|
+
|
|
10
|
+
if msg
|
|
11
|
+
node << (text = Blather::XMPPNode.new('text', node.document))
|
|
12
|
+
text.namespace = 'urn:ietf:params:xml:ns:xmpp-streams'
|
|
13
|
+
text.content = msg
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
node << (extra = Blather::XMPPNode.new('extra-error', node.document))
|
|
17
|
+
extra.namespace = 'blather:stream:error'
|
|
18
|
+
extra.content = 'Blather Error'
|
|
19
|
+
|
|
20
|
+
node
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe 'Blather::StreamError' do
|
|
24
|
+
it 'can import a node' do
|
|
25
|
+
err = stream_error_node 'internal-server-error', 'the message'
|
|
26
|
+
Blather::StreamError.must_respond_to :import
|
|
27
|
+
e = Blather::StreamError.import err
|
|
28
|
+
e.must_be_kind_of Blather::StreamError
|
|
29
|
+
|
|
30
|
+
e.name.must_equal :internal_server_error
|
|
31
|
+
e.text.must_equal 'the message'
|
|
32
|
+
e.extras.must_equal err.find('descendant::*[name()="extra-error"]', 'blather:stream:error').map {|n|n}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe 'Blather::StreamError when instantiated' do
|
|
37
|
+
before do
|
|
38
|
+
@err_name = 'internal-server-error'
|
|
39
|
+
@msg = 'the server has experienced a misconfiguration'
|
|
40
|
+
@err = Blather::StreamError.import stream_error_node(@err_name, @msg)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'provides a err_name attribute' do
|
|
44
|
+
@err.must_respond_to :name
|
|
45
|
+
@err.name.must_equal @err_name.gsub('-','_').to_sym
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'provides a text attribute' do
|
|
49
|
+
@err.must_respond_to :text
|
|
50
|
+
@err.text.must_equal @msg
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'provides an extras attribute' do
|
|
54
|
+
@err.must_respond_to :extras
|
|
55
|
+
@err.extras.must_be_instance_of Array
|
|
56
|
+
@err.extras.size.must_equal 1
|
|
57
|
+
@err.extras.first.element_name.must_equal 'extra-error'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'describes itself' do
|
|
61
|
+
@err.to_s.must_match(/#{@type}/)
|
|
62
|
+
@err.to_s.must_match(/#{@msg}/)
|
|
63
|
+
|
|
64
|
+
@err.inspect.must_match(/#{@type}/)
|
|
65
|
+
@err.inspect.must_match(/#{@msg}/)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'can be turned into xml' do
|
|
69
|
+
@err.must_respond_to :to_xml
|
|
70
|
+
doc = parse_stanza @err.to_xml
|
|
71
|
+
doc.xpath("//err_ns:internal-server-error", :err_ns => Blather::StreamError::STREAM_ERR_NS).wont_be_empty
|
|
72
|
+
doc.xpath("//err_ns:text[.='the server has experienced a misconfiguration']", :err_ns => Blather::StreamError::STREAM_ERR_NS).wont_be_empty
|
|
73
|
+
doc.xpath("//err_ns:extra-error[.='Blather Error']", :err_ns => 'blather:stream:error').wont_be_empty
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe 'Each XMPP stream error type' do
|
|
78
|
+
%w[ bad-format
|
|
79
|
+
bad-namespace-prefix
|
|
80
|
+
conflict
|
|
81
|
+
connection-timeout
|
|
82
|
+
host-gone
|
|
83
|
+
host-unknown
|
|
84
|
+
improper-addressing
|
|
85
|
+
internal-server-error
|
|
86
|
+
invalid-from
|
|
87
|
+
invalid-id
|
|
88
|
+
invalid-namespace
|
|
89
|
+
invalid-xml
|
|
90
|
+
not-authorized
|
|
91
|
+
policy-violation
|
|
92
|
+
remote-connection-failed
|
|
93
|
+
resource-constraint
|
|
94
|
+
restricted-xml
|
|
95
|
+
see-other-host
|
|
96
|
+
system-shutdown
|
|
97
|
+
undefined-condition
|
|
98
|
+
unsupported-encoding
|
|
99
|
+
unsupported-stanza-type
|
|
100
|
+
unsupported-version
|
|
101
|
+
xml-not-well-formed
|
|
102
|
+
].each do |error_type|
|
|
103
|
+
it "handles the name for #{error_type}" do
|
|
104
|
+
e = Blather::StreamError.import stream_error_node(error_type)
|
|
105
|
+
e.name.must_equal error_type.gsub('-','_').to_sym
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
|
|
2
|
+
|
|
3
|
+
describe Blather::BlatherError do
|
|
4
|
+
it 'is handled by :error' do
|
|
5
|
+
Blather::BlatherError.new.handler_hierarchy.must_equal [:error]
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe 'Blather::ParseError' do
|
|
10
|
+
before { @error = Blather::ParseError.new('</generate-parse-error>"') }
|
|
11
|
+
|
|
12
|
+
it 'is registers with the handler hierarchy' do
|
|
13
|
+
@error.handler_hierarchy.must_equal [:parse_error, :error]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'contains the error message' do
|
|
17
|
+
@error.must_respond_to :message
|
|
18
|
+
@error.message.must_equal '</generate-parse-error>"'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe 'Blather::UnknownResponse' do
|
|
23
|
+
before { @error = Blather::UnknownResponse.new(Blather::XMPPNode.new('foo-bar')) }
|
|
24
|
+
|
|
25
|
+
it 'is registers with the handler hierarchy' do
|
|
26
|
+
@error.handler_hierarchy.must_equal [:unknown_response_error, :error]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'holds on to a copy of the failure node' do
|
|
30
|
+
@error.must_respond_to :node
|
|
31
|
+
@error.node.element_name.must_equal 'foo-bar'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
|
|
2
|
+
|
|
3
|
+
describe Blather::JID do
|
|
4
|
+
it 'does nothing if creaded from Blather::JID' do
|
|
5
|
+
jid = Blather::JID.new 'n@d/r'
|
|
6
|
+
Blather::JID.new(jid).object_id.must_equal jid.object_id
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'creates a new Blather::JID from (n,d,r)' do
|
|
10
|
+
jid = Blather::JID.new('n', 'd', 'r')
|
|
11
|
+
jid.node.must_equal 'n'
|
|
12
|
+
jid.domain.must_equal 'd'
|
|
13
|
+
jid.resource.must_equal 'r'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'creates a new Blather::JID from (n,d)' do
|
|
17
|
+
jid = Blather::JID.new('n', 'd')
|
|
18
|
+
jid.node.must_equal 'n'
|
|
19
|
+
jid.domain.must_equal 'd'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'creates a new Blather::JID from (n@d)' do
|
|
23
|
+
jid = Blather::JID.new('n@d')
|
|
24
|
+
jid.node.must_equal 'n'
|
|
25
|
+
jid.domain.must_equal 'd'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'creates a new Blather::JID from (n@d/r)' do
|
|
29
|
+
jid = Blather::JID.new('n@d/r')
|
|
30
|
+
jid.node.must_equal 'n'
|
|
31
|
+
jid.domain.must_equal 'd'
|
|
32
|
+
jid.resource.must_equal 'r'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'requires at least a node' do
|
|
36
|
+
proc { Blather::JID.new }.must_raise ::ArgumentError
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'ensures length of node is no more than 1023 characters' do
|
|
40
|
+
proc { Blather::JID.new('n'*1024) }.must_raise Blather::ArgumentError
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'ensures length of domain is no more than 1023 characters' do
|
|
44
|
+
proc { Blather::JID.new('n', 'd'*1024) }.must_raise Blather::ArgumentError
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'ensures length of resource is no more than 1023 characters' do
|
|
48
|
+
proc { Blather::JID.new('n', 'd', 'r'*1024) }.must_raise Blather::ArgumentError
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'compares Blather::JIDs' do
|
|
52
|
+
(Blather::JID.new('a@b/c') <=> Blather::JID.new('d@e/f')).must_equal -1
|
|
53
|
+
(Blather::JID.new('a@b/c') <=> Blather::JID.new('a@b/c')).must_equal 0
|
|
54
|
+
(Blather::JID.new('d@e/f') <=> Blather::JID.new('a@b/c')).must_equal 1
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'checks for equality' do
|
|
58
|
+
(Blather::JID.new('n@d/r') == Blather::JID.new('n@d/r')).must_equal true
|
|
59
|
+
Blather::JID.new('n@d/r').eql?(Blather::JID.new('n@d/r')).must_equal true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'will strip' do
|
|
63
|
+
jid = Blather::JID.new('n@d/r')
|
|
64
|
+
jid.stripped.must_equal Blather::JID.new('n@d')
|
|
65
|
+
jid.must_equal Blather::JID.new('n@d/r')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'will strip itself' do
|
|
69
|
+
jid = Blather::JID.new('n@d/r')
|
|
70
|
+
jid.strip!
|
|
71
|
+
jid.must_equal Blather::JID.new('n@d')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'has a string representation' do
|
|
75
|
+
Blather::JID.new('n@d/r').to_s.must_equal 'n@d/r'
|
|
76
|
+
Blather::JID.new('n', 'd', 'r').to_s.must_equal 'n@d/r'
|
|
77
|
+
Blather::JID.new('n', 'd').to_s.must_equal 'n@d'
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'provides a #stripped? helper' do
|
|
81
|
+
jid = Blather::JID.new 'a@b/c'
|
|
82
|
+
jid.must_respond_to :stripped?
|
|
83
|
+
jid.stripped?.wont_equal true
|
|
84
|
+
jid.strip!
|
|
85
|
+
jid.stripped?.must_equal true
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
|
|
2
|
+
|
|
3
|
+
describe Blather::RosterItem do
|
|
4
|
+
it 'can be initialized with Blather::JID' do
|
|
5
|
+
jid = Blather::JID.new(jid)
|
|
6
|
+
i = Blather::RosterItem.new jid
|
|
7
|
+
i.jid.must_equal jid
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'can be initialized with an Iq::RosterItem' do
|
|
11
|
+
jid = 'n@d/r'
|
|
12
|
+
i = Blather::RosterItem.new Blather::Stanza::Iq::Roster::RosterItem.new(jid)
|
|
13
|
+
i.jid.must_equal Blather::JID.new(jid).stripped
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'can be initialized with a string' do
|
|
17
|
+
jid = 'n@d/r'
|
|
18
|
+
i = Blather::RosterItem.new jid
|
|
19
|
+
i.jid.must_equal Blather::JID.new(jid).stripped
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'returns the same object when intialized with a Blather::RosterItem' do
|
|
23
|
+
control = Blather::RosterItem.new 'n@d/r'
|
|
24
|
+
Blather::RosterItem.new(control).must_be_same_as control
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'has a Blather::JID setter that strips the Blather::JID' do
|
|
28
|
+
jid = Blather::JID.new('n@d/r')
|
|
29
|
+
i = Blather::RosterItem.new nil
|
|
30
|
+
i.jid = jid
|
|
31
|
+
i.jid.must_equal jid.stripped
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'has a subscription setter that forces a symbol' do
|
|
35
|
+
i = Blather::RosterItem.new nil
|
|
36
|
+
i.subscription = 'remove'
|
|
37
|
+
i.subscription.must_equal :remove
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'forces the type of subscription' do
|
|
41
|
+
proc { Blather::RosterItem.new(nil).subscription = 'foo' }.must_raise Blather::ArgumentError
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'returns :none if the subscription field is blank' do
|
|
45
|
+
Blather::RosterItem.new(nil).subscription.must_equal :none
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'ensure #ask is a symbol' do
|
|
49
|
+
i = Blather::RosterItem.new(nil)
|
|
50
|
+
i.ask = 'subscribe'
|
|
51
|
+
i.ask.must_equal :subscribe
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'forces #ask to be :subscribe or nothing at all' do
|
|
55
|
+
proc { Blather::RosterItem.new(nil).ask = 'foo' }.must_raise Blather::ArgumentError
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'generates a stanza with #to_stanza' do
|
|
59
|
+
jid = Blather::JID.new('n@d/r')
|
|
60
|
+
i = Blather::RosterItem.new jid
|
|
61
|
+
s = i.to_stanza
|
|
62
|
+
s.must_be_kind_of Blather::Stanza::Iq::Roster
|
|
63
|
+
s.items.first.jid.must_equal jid.stripped
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'returns status based on priority' do
|
|
67
|
+
setup_item_with_presences
|
|
68
|
+
@i.status.must_equal @p2
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'returns status based on resource' do
|
|
72
|
+
setup_item_with_presences
|
|
73
|
+
@i.status('a').must_equal @p
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def setup_item_with_presences
|
|
77
|
+
@jid = Blather::JID.new('n@d/r')
|
|
78
|
+
@i = Blather::RosterItem.new @jid
|
|
79
|
+
|
|
80
|
+
@p = Blather::Stanza::Presence::Status.new(:away)
|
|
81
|
+
@p.from = 'n@d/a'
|
|
82
|
+
@p.priority = 0
|
|
83
|
+
|
|
84
|
+
@p2 = Blather::Stanza::Presence::Status.new(:dnd)
|
|
85
|
+
@p2.from = 'n@d/b'
|
|
86
|
+
@p2.priority = -1
|
|
87
|
+
|
|
88
|
+
@i.status = @p
|
|
89
|
+
@i.status = @p2
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'initializes groups to [nil] if the item is not part of a group' do
|
|
93
|
+
i = Blather::RosterItem.new 'n@d'
|
|
94
|
+
i.groups.must_equal [nil]
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. spec_helper])
|
|
2
|
+
|
|
3
|
+
describe Blather::Roster do
|
|
4
|
+
before do
|
|
5
|
+
@stream = mock()
|
|
6
|
+
@stream.stubs(:write)
|
|
7
|
+
|
|
8
|
+
@stanza = mock()
|
|
9
|
+
items = []; 4.times { |n| items << Blather::JID.new("n@d/#{n}r") }
|
|
10
|
+
@stanza.stubs(:items).returns(items)
|
|
11
|
+
|
|
12
|
+
@roster = Blather::Roster.new(@stream, @stanza)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'initializes with items' do
|
|
16
|
+
@roster.items.map { |_,i| i.jid.to_s }.must_equal(@stanza.items.map { |i| i.stripped.to_s }.uniq)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'processes @stanzas with remove requests' do
|
|
20
|
+
s = @roster['n@d/0r']
|
|
21
|
+
s.subscription = :remove
|
|
22
|
+
proc { @roster.process(s.to_stanza) }.must_change('@roster.items.length', :by => -1)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'processes @stanzas with add requests' do
|
|
26
|
+
s = Blather::Stanza::Iq::Roster::RosterItem.new('a@b/c').to_stanza
|
|
27
|
+
proc { @roster.process(s) }.must_change('@roster.items.length', :by => 1)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'allows a jid to be pushed' do
|
|
31
|
+
jid = 'a@b/c'
|
|
32
|
+
proc { @roster.push(jid) }.must_change('@roster.items.length', :by => 1)
|
|
33
|
+
@roster[jid].wont_be_nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'allows an item to be pushed' do
|
|
37
|
+
jid = 'a@b/c'
|
|
38
|
+
item = Blather::RosterItem.new(Blather::JID.new(jid))
|
|
39
|
+
proc { @roster.push(item) }.must_change('@roster.items.length', :by => 1)
|
|
40
|
+
@roster[jid].wont_be_nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'aliases #<< to #push and returns self to allow for chaining' do
|
|
44
|
+
jid = 'a@b/c'
|
|
45
|
+
item = Blather::RosterItem.new(Blather::JID.new(jid))
|
|
46
|
+
jid2 = 'd@e/f'
|
|
47
|
+
item2 = Blather::RosterItem.new(Blather::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
|
+
|
|
53
|
+
it 'sends a @roster addition over the wire' do
|
|
54
|
+
client = mock(:write => nil)
|
|
55
|
+
roster = Blather::Roster.new client, @stanza
|
|
56
|
+
roster.push('a@b/c')
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'removes a Blather::JID' do
|
|
60
|
+
proc { @roster.delete 'n@d' }.must_change('@roster.items.length', :by => -1)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'sends a @roster removal over the wire' do
|
|
64
|
+
client = mock(:write => nil)
|
|
65
|
+
roster = Blather::Roster.new client, @stanza
|
|
66
|
+
roster.delete('a@b/c')
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'returns an item through []' do
|
|
70
|
+
item = @roster['n@d']
|
|
71
|
+
item.must_be_kind_of Blather::RosterItem
|
|
72
|
+
item.jid.must_equal Blather::JID.new('n@d')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'responds to #each' do
|
|
76
|
+
@roster.must_respond_to :each
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'cycles through the items using #each' do
|
|
80
|
+
@roster.map { |i| i }.sort.must_equal(@roster.items.sort)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'returns a duplicate of items through #items' do
|
|
84
|
+
items = @roster.items
|
|
85
|
+
items.delete 'n@d'
|
|
86
|
+
items.wont_equal @roster.items
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'will group roster items' do
|
|
90
|
+
@roster.delete 'n@d'
|
|
91
|
+
item1 = Blather::RosterItem.new("n1@d")
|
|
92
|
+
item1.groups = ['group1', 'group2']
|
|
93
|
+
item2 = Blather::RosterItem.new("n2@d")
|
|
94
|
+
item2.groups = ['group1', 'group3']
|
|
95
|
+
@roster << item1 << item2
|
|
96
|
+
|
|
97
|
+
@roster.grouped.must_equal({
|
|
98
|
+
'group1' => [item1, item2],
|
|
99
|
+
'group2' => [item1],
|
|
100
|
+
'group3' => [item2]
|
|
101
|
+
})
|
|
102
|
+
end
|
|
103
|
+
end
|