blather 0.4.10 → 0.4.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,8 +22,8 @@ class Stanza
22
22
  def self.new(type = nil, node = nil, identities = [], features = [])
23
23
  new_node = super type
24
24
  new_node.node = node
25
- [identities].flatten.each { |i| new_node.query << Identity.new(i) }
26
- [features].flatten.each { |f| new_node.query << Feature.new(f) }
25
+ new_node.identities = [identities]
26
+ new_node.features = [features]
27
27
  new_node
28
28
  end
29
29
 
@@ -34,6 +34,15 @@ class Stanza
34
34
  end
35
35
  end
36
36
 
37
+ # Add an array of identities
38
+ # @param identities the array of identities, passed directly to Identity.new
39
+ def identities=(identities)
40
+ query.find('//ns:identity', :ns => self.class.registered_ns).each &:remove
41
+ if identities
42
+ [identities].flatten.each { |i| self.query << Identity.new(i) }
43
+ end
44
+ end
45
+
37
46
  # List of feature objects
38
47
  def features
39
48
  query.find('//ns:feature', :ns => self.class.registered_ns).map do |f|
@@ -41,6 +50,15 @@ class Stanza
41
50
  end
42
51
  end
43
52
 
53
+ # Add an array of features
54
+ # @param features the array of features, passed directly to Feature.new
55
+ def features=(features)
56
+ query.find('//ns:feature', :ns => self.class.registered_ns).each &:remove
57
+ if features
58
+ [features].flatten.each { |f| self.query << Feature.new(f) }
59
+ end
60
+ end
61
+
44
62
  class Identity < XMPPNode
45
63
  # Create a new DiscoInfo Identity
46
64
  # @overload new(node)
@@ -21,7 +21,7 @@ class Stanza
21
21
  def self.new(type = nil, node = nil, items = [])
22
22
  new_node = super type
23
23
  new_node.node = node
24
- [items].flatten.each { |item| new_node.query << Item.new(item) }
24
+ new_node.items = [items]
25
25
  new_node
26
26
  end
27
27
 
@@ -34,6 +34,15 @@ class Stanza
34
34
  end
35
35
  end
36
36
 
37
+ # Add an array of items
38
+ # @param items the array of items, passed directly to Item.new
39
+ def items=(items)
40
+ query.find('//ns:item', :ns => self.class.registered_ns).each &:remove
41
+ if items
42
+ [items].flatten.each { |i| self.query << Item.new(i) }
43
+ end
44
+ end
45
+
37
46
  # An individual Disco Item
38
47
  class Item < XMPPNode
39
48
  # Create a new Blather::Stanza::DiscoItems::Item
@@ -28,16 +28,27 @@ class Iq
28
28
  new_node.command
29
29
  new_node.node = node
30
30
  new_node.action = action
31
- new_node.new_sessionid!
32
31
  new_node
33
32
  end
34
33
 
35
34
  # Overrides the parent method to ensure the current command node is destroyed
35
+ # and the action is set to execute if no action provided
36
36
  #
37
37
  # @see Blather::Stanza::Iq#inherit
38
38
  def inherit(node)
39
39
  command.remove
40
40
  super
41
+ self.action = :execute unless self.action
42
+ self
43
+ end
44
+
45
+ # Overrides the parent method to ensure the reply has no action
46
+ #
47
+ # @return [self]
48
+ def reply!
49
+ super
50
+ self.action = nil
51
+ self
41
52
  end
42
53
 
43
54
  # Command node accessor
@@ -47,7 +58,7 @@ class Iq
47
58
  # @return [Blather::XMPPNode]
48
59
  def command
49
60
  c = if self.class.registered_ns
50
- find_first('command_ns:command', :command_ns => self.class.registered_ns)
61
+ find_first('ns:command', :ns => self.class.registered_ns)
51
62
  else
52
63
  find_first('command')
53
64
  end
@@ -80,6 +91,13 @@ class Iq
80
91
  command[:sessionid]
81
92
  end
82
93
 
94
+ # Check if there is a sessionid set
95
+ #
96
+ # @return [true, false]
97
+ def sessionid?
98
+ !sessionid.nil?
99
+ end
100
+
83
101
  # Set the sessionid of the command
84
102
  #
85
103
  # @param [String, nil] sessionid the new sessionid
@@ -89,14 +107,14 @@ class Iq
89
107
 
90
108
  # Generate a new session ID (SHA-1 hash)
91
109
  def new_sessionid!
92
- self.sessionid = "commandsession-"+id
110
+ self.sessionid = "commandsession-#{id}"
93
111
  end
94
112
 
95
113
  # Get the action of the command
96
114
  #
97
115
  # @return [Symbol, nil]
98
116
  def action
99
- command.read_attr :action, :to_sym
117
+ (val = command[:action]) && val.to_sym
100
118
  end
101
119
 
102
120
  # Check if the command action is :cancel
@@ -148,7 +166,7 @@ class Iq
148
166
  #
149
167
  # @return [Symbol, nil]
150
168
  def status
151
- command.read_attr :status, :to_sym
169
+ ((val = command[:status]) && val.to_sym) || :executing
152
170
  end
153
171
 
154
172
  # Check if the command status is :executing
@@ -177,7 +195,7 @@ class Iq
177
195
  # @param [:executing, :completed, :canceled] status the new status
178
196
  def status=(status)
179
197
  if status && !VALID_STATUS.include?(status.to_sym)
180
- raise ArgumentError, "Invalid Action (#{statusn}), use: #{VALID_STATUS*' '}"
198
+ raise ArgumentError, "Invalid Action (#{status}), use: #{VALID_STATUS*' '}"
181
199
  end
182
200
  command[:status] = status
183
201
  end
@@ -188,10 +206,9 @@ class Iq
188
206
  #
189
207
  # @return [Blather::XMPPNode]
190
208
  def actions
191
- a = find_first('actions')
192
-
193
- unless a
194
- (self << (a = XMPPNode.new('actions', self.document)))
209
+ unless a = self.command.find_first('ns:actions', :ns => self.class.registered_ns)
210
+ (self.command << (a = XMPPNode.new('actions', self.document)))
211
+ a.namespace = self.command.namespace
195
212
  end
196
213
  a
197
214
  end
@@ -200,33 +217,37 @@ class Iq
200
217
  #
201
218
  # @return [[Symbol]]
202
219
  def allowed_actions
203
- a = []
204
- a << :execute
205
- actions.children.each do |action|
206
- a << action.name.to_sym
220
+ ([:execute] + actions.children.map { |action| action.name.to_sym }).uniq
221
+ end
222
+
223
+ def primary_allowed_action
224
+ (actions[:execute] || :execute).to_sym
225
+ end
226
+
227
+ def primary_allowed_action=(a)
228
+ if a && ![:prev, :next, :complete, :execute].include?(a.to_sym)
229
+ raise ArgumentError, "Invalid Action (#{a}), use: #{[:prev, :next, :complete, :execute]*' '}"
207
230
  end
208
- a
231
+ actions[:execute] = a
209
232
  end
210
233
 
211
234
  # Add allowed actions to the command
212
235
  #
213
236
  # @param [[:prev, :next, :complete]] allowed_actions the new allowed actions
214
- def add_allowed_actions(allowed_actions)
215
- [allowed_actions].flatten.each do |action|
216
- if action && !VALID_ACTIONS.include?(action.to_sym)
217
- raise ArgumentError, "Invalid Action (#{action}), use: #{VALID_ACTIONS*' '}"
218
- end
219
- actions << "<#{action.to_s}/>"
237
+ def allowed_actions=(allowed_actions)
238
+ allowed_actions = ([allowed_actions].flatten.map(&:to_sym) + [:execute]).uniq
239
+ if (invalid_actions = allowed_actions - VALID_ACTIONS).size > 0
240
+ raise ArgumentError, "Invalid Action(s) (#{invalid_actions*' '}), use: #{VALID_ACTIONS*' '}"
220
241
  end
242
+ actions.children.map(&:remove)
243
+ allowed_actions.each { |action| actions << XMPPNode.new(action.to_s) }
221
244
  end
222
245
 
223
246
  # Remove allowed actions from the command
224
247
  #
225
248
  # @param [[:prev, :next, :complete]] disallowed_actions the allowed actions to remove
226
- def remove_allowed_actions(disallowed_actions)
227
- [disallowed_actions].flatten.each do |action|
228
- actions.remove_children action.to_sym
229
- end
249
+ def remove_allowed_actions!
250
+ actions.remove
230
251
  end
231
252
 
232
253
  # Command note accessor
@@ -235,10 +256,9 @@ class Iq
235
256
  #
236
257
  # @return [Blather::XMPPNode]
237
258
  def note
238
- n = find_first('note')
239
-
240
- unless n
241
- (self << (n = XMPPNode.new('note', self.document)))
259
+ unless n = self.command.find_first('ns:note', :ns => self.class.registered_ns)
260
+ (self.command << (n = XMPPNode.new('note', self.document)))
261
+ n.namespace = self.command.namespace
242
262
  end
243
263
  n
244
264
  end
@@ -247,7 +267,7 @@ class Iq
247
267
  #
248
268
  # @return [Symbol, nil]
249
269
  def note_type
250
- note.read_attr :type, :to_sym
270
+ (val = note[:type]) && val.to_sym
251
271
  end
252
272
 
253
273
  # Check if the command status is :info
@@ -283,23 +303,29 @@ class Iq
283
303
 
284
304
  # Get the text of the command's note
285
305
  def note_text
286
- content_from "note"
306
+ content_from :note
287
307
  end
288
308
 
289
309
  # Set the command's note text
290
310
  #
291
311
  # @param [String] note_text the command's new note text
292
312
  def note_text=(note_text)
293
- set_content_for "note", note_text
313
+ set_content_for :note, note_text
294
314
  end
295
315
 
296
316
  # Returns the command's x:data form child
297
317
  def form
298
- X.new command.find_first('//ns:x', :ns => X.registered_ns)
318
+ if found_x = command.find_first('ns:x', :ns => X.registered_ns)
319
+ x = X.new found_x
320
+ found_x.remove
321
+ else
322
+ x = X.new
323
+ end
324
+ self.command << x
325
+ x
299
326
  end
300
-
301
327
  end #Command
302
328
 
303
329
  end #Iq
304
330
  end #Stanza
305
- end
331
+ end #Blather
@@ -25,10 +25,10 @@ class Stanza
25
25
  new_node.inherit type
26
26
  when Hash
27
27
  new_node.type = type[:type]
28
- new_node.add_fields([type[:fields]])
28
+ new_node.fields = type[:fields]
29
29
  else
30
30
  new_node.type = type
31
- new_node.add_fields([fields])
31
+ new_node.fields = fields
32
32
  end
33
33
  new_node
34
34
  end
@@ -51,15 +51,25 @@ class Stanza
51
51
  # List of field objects
52
52
  # @return [Blather::Stanza::X::Field]
53
53
  def fields
54
- self.find('ns:field', :ns => self.class.registered_ns).map do |f|
55
- Field.new f
54
+ self.find('ns:field', :ns => self.class.registered_ns).map do |field|
55
+ Field.new(field)
56
56
  end
57
57
  end
58
58
 
59
+ # Find a field by var
60
+ # @param var the var for the field you wish to find
61
+ def field(var)
62
+ fields.detect { |f| f.var == var }
63
+ end
64
+
59
65
  # Add an array of fields to form
60
66
  # @param fields the array of fields, passed directly to Field.new
61
- def add_fields(fields = [])
62
- [fields].flatten.each { |f| self << Field.new(f) }
67
+ def fields=(fields)
68
+ remove_children :field
69
+ [fields].flatten.each do |field|
70
+ self << (f = Field.new(field))
71
+ f.namespace = self.namespace
72
+ end
63
73
  end
64
74
 
65
75
  # Check if the x is of type :cancel
@@ -94,9 +104,7 @@ class Stanza
94
104
  #
95
105
  # @return [String]
96
106
  def instructions
97
- if i = self.find_first('ns:instructions', :ns => self.class.registered_ns)
98
- i.children.inner_text
99
- end
107
+ content_from 'ns:instructions', :ns => self.registered_ns
100
108
  end
101
109
 
102
110
  # Set the form's instructions
@@ -104,16 +112,18 @@ class Stanza
104
112
  # @param [String] instructions the form's instructions
105
113
  def instructions=(instructions)
106
114
  self.remove_children :instructions
107
- self << "<instructions>#{instructions}</instructions>"
115
+ if instructions
116
+ self << (i = XMPPNode.new(:instructions, self.document))
117
+ i.namespace = self.namespace
118
+ i << instructions
119
+ end
108
120
  end
109
121
 
110
122
  # Retrieve the form's title
111
123
  #
112
124
  # @return [String]
113
125
  def title
114
- if t = self.find_first('ns:title', :ns => self.class.registered_ns)
115
- t.children.inner_text
116
- end
126
+ content_from 'ns:title', :ns => self.registered_ns
117
127
  end
118
128
 
119
129
  # Set the form's title
@@ -121,7 +131,11 @@ class Stanza
121
131
  # @param [String] title the form's title
122
132
  def title=(title)
123
133
  self.remove_children :title
124
- self << "<title>#{title}</title>"
134
+ if title
135
+ self << (t = XMPPNode.new(:title))
136
+ t.namespace = self.namespace
137
+ t << title
138
+ end
125
139
  end
126
140
 
127
141
  class Field < XMPPNode
@@ -137,12 +151,22 @@ class Stanza
137
151
  # @option opts [:boolean, :fixed, :hidden, :"jid-multi", :"jid-single", :"list-multi", :"list-single", :"text-multi", :"text-private", :"text-single"] :type the type of the field
138
152
  # @option opts [String] :var the variable for the field
139
153
  # @option opts [String] :label the label for the field
154
+ # @option [String, nil] :value the value for the field
155
+ # @option [String, nil] :description the description for the field
156
+ # @option [true, false, nil] :required the required flag for the field
157
+ # @param [Array<Array, X::Field::Option>, nil] :options a list of field options.
158
+ # These are passed directly to X::Field::Option.new
140
159
  # @overload new(type, var = nil, label = nil)
141
160
  # Create a new Field by name
142
161
  # @param [:boolean, :fixed, :hidden, :"jid-multi", :"jid-single", :"list-multi", :"list-single", :"text-multi", :"text-private", :"text-single"] type the type of the field
143
162
  # @param [String, nil] var the variable for the field
144
163
  # @param [String, nil] label the label for the field
145
- def self.new(type, var = nil, label = nil)
164
+ # @param [String, nil] value the value for the field
165
+ # @param [String, nil] description the description for the field
166
+ # @param [true, false, nil] required the required flag for the field
167
+ # @param [Array<Array, X::Field::Option>, nil] options a list of field options.
168
+ # These are passed directly to X::Field::Option.new
169
+ def self.new(type, var = nil, label = nil, value = nil, description = nil, required = false, options = [])
146
170
  new_node = super :field
147
171
 
148
172
  case type
@@ -152,10 +176,18 @@ class Stanza
152
176
  new_node.type = type[:type]
153
177
  new_node.var = type[:var]
154
178
  new_node.label = type[:label]
179
+ new_node.value = type[:value]
180
+ new_node.desc = type[:description]
181
+ new_node.required = type[:required]
182
+ new_node.options = type[:options]
155
183
  else
156
184
  new_node.type = type
157
185
  new_node.var = var
158
186
  new_node.label = label
187
+ new_node.value = value
188
+ new_node.desc = description
189
+ new_node.required = required
190
+ new_node.options = options
159
191
  end
160
192
  new_node
161
193
  end
@@ -203,8 +235,10 @@ class Stanza
203
235
  #
204
236
  # @param [String]
205
237
  def value
206
- if v = self.find_first('value')
207
- v.children.inner_text
238
+ if self.namespace
239
+ content_from 'ns:value', :ns => self.namespace.href
240
+ else
241
+ content_from :value
208
242
  end
209
243
  end
210
244
 
@@ -213,15 +247,21 @@ class Stanza
213
247
  # @param [String] value the field's value
214
248
  def value=(value)
215
249
  self.remove_children :value
216
- self << "<value>#{value}</value>"
250
+ if value
251
+ self << (v = XMPPNode.new(:value))
252
+ v.namespace = self.namespace
253
+ v << value
254
+ end
217
255
  end
218
256
 
219
257
  # Get the field's description
220
258
  #
221
259
  # @param [String]
222
260
  def desc
223
- if d = self.find_first('desc')
224
- d.children.inner_text
261
+ if self.namespace
262
+ content_from 'ns:desc', :ns => self.namespace.href
263
+ else
264
+ content_from :desc
225
265
  end
226
266
  end
227
267
 
@@ -230,60 +270,50 @@ class Stanza
230
270
  # @param [String] description the field's description
231
271
  def desc=(description)
232
272
  self.remove_children :desc
233
- self << "<desc>#{description}</desc>"
273
+ if description
274
+ self << (d = XMPPNode.new(:desc))
275
+ d.namespace = self.namespace
276
+ d << description
277
+ end
234
278
  end
235
279
 
236
280
  # Get the field's required flag
237
281
  #
238
282
  # @param [true, false]
239
283
  def required?
240
- self.find_first('required') ? true : false
284
+ !self.find_first('required').nil?
241
285
  end
242
286
 
243
287
  # Set the field's required flag
244
288
  #
245
289
  # @param [true, false] required the field's required flag
246
- def required!(required = true)
247
- if self.find_first('required')
248
- if required==false
249
- self.remove_children :required
250
- end
251
- else
252
- if required==true
253
- self << "<required/>"
254
- end
255
- end
290
+ def required=(required)
291
+ self.remove_children(:required) unless required
292
+ self << XMPPNode.new(:required) if required
256
293
  end
257
294
 
258
295
  # Extract list of option objects
259
296
  #
260
297
  # @return [Blather::Stanza::X::Field::Option]
261
298
  def options
262
- self.find('option').map do |f|
263
- Option.new f
264
- end
299
+ self.find(:option).map { |f| Option.new(f) }
265
300
  end
266
301
 
267
302
  # Add an array of options to field
268
303
  # @param options the array of options, passed directly to Option.new
269
- def add_options(options = [])
270
- [options].flatten.each { |o| self << Option.new(o) }
304
+ def options=(options)
305
+ remove_children :option
306
+ if options
307
+ [options].flatten.each { |o| self << Option.new(o) }
308
+ end
271
309
  end
272
310
 
273
311
  # Compare two Field objects by type, var and label
274
312
  # @param [X::Field] o the Field object to compare against
275
313
  # @return [true, false]
276
314
  def eql?(o)
277
- unless o.is_a?(self.class)
278
- raise "Cannot compare #{self.class} with #{o.class}"
279
- end
280
-
281
- o.type == self.type &&
282
- o.var == self.var &&
283
- o.label == self.label &&
284
- o.desc == self.desc &&
285
- o.required? == self.required? &&
286
- o.value == self.value
315
+ raise "Cannot compare #{self.class} with #{o.class}" unless o.is_a?(self.class)
316
+ ![:type, :var, :label, :desc, :required?, :value].detect { |m| o.send(m) != self.send(m) }
287
317
  end
288
318
  alias_method :==, :eql?
289
319
 
@@ -320,16 +350,22 @@ class Stanza
320
350
  # The Field Option's value
321
351
  # @return [String]
322
352
  def value
323
- if v = self.find_first('value')
324
- v.children.inner_text
353
+ if self.namespace
354
+ content_from 'ns:value', :ns => self.namespace.href
355
+ else
356
+ content_from :value
325
357
  end
326
358
  end
327
359
 
328
360
  # Set the Field Option's value
329
361
  # @param [String] value the new value for the field option
330
- def value=(v)
362
+ def value=(value)
331
363
  self.remove_children :value
332
- self << "<value>#{v}</value>"
364
+ if value
365
+ self << (v = XMPPNode.new(:value))
366
+ v.namespace = self.namespace
367
+ v << value
368
+ end
333
369
  end
334
370
 
335
371
  # The Field Option's label
@@ -54,6 +54,29 @@ describe Blather::Stanza::Iq::DiscoInfo do
54
54
  n.to = 'to@jid.com'
55
55
  n.find("/iq[@to='to@jid.com' and @type='get' and @id='#{n.id}']/ns:query[@node='/path/to/node']", :ns => Blather::Stanza::Iq::DiscoInfo.registered_ns).wont_be_empty
56
56
  end
57
+
58
+ it 'allows adding of identities' do
59
+ di = Blather::Stanza::Iq::DiscoInfo.new
60
+ di.identities.size.must_equal 0
61
+ di.identities = [{:name => 'name', :type => 'type', :category => 'category'}]
62
+ di.identities.size.must_equal 1
63
+ di.identities += [Blather::Stanza::Iq::DiscoInfo::Identity.new(*%w[name type category])]
64
+ di.identities.size.must_equal 2
65
+ di.identities = nil
66
+ di.identities.size.must_equal 0
67
+ end
68
+
69
+ it 'allows adding of features' do
70
+ di = Blather::Stanza::Iq::DiscoInfo.new
71
+ di.features.size.must_equal 0
72
+ di.features = ["feature1"]
73
+ di.features.size.must_equal 1
74
+ di.features += [Blather::Stanza::Iq::DiscoInfo::Feature.new "feature2"]
75
+ di.features.size.must_equal 2
76
+ di.features = nil
77
+ di.features.size.must_equal 0
78
+ end
79
+
57
80
  end
58
81
 
59
82
  describe 'Blather::Stanza::Iq::DiscoInfo identities' do
@@ -102,6 +102,17 @@ describe Blather::Stanza::Iq::DiscoItems do
102
102
  di.items.size.must_equal 2
103
103
  di.items.each { |i| control.include?(i).must_equal true }
104
104
  end
105
+
106
+ it 'allows adding of items' do
107
+ di = Blather::Stanza::Iq::DiscoItems.new
108
+ di.items.size.must_equal 0
109
+ di.items = [{:jid => 'foo@bar/baz', :node => 'node', :name => 'name'}]
110
+ di.items.size.must_equal 1
111
+ di.items += [Blather::Stanza::Iq::DiscoItems::Item.new(*%w[foo@bar/baz node name])]
112
+ di.items.size.must_equal 2
113
+ di.items = nil
114
+ di.items.size.must_equal 0
115
+ end
105
116
  end
106
117
 
107
118
  describe Blather::Stanza::Iq::DiscoItems::Item do
@@ -8,7 +8,6 @@ def command_xml
8
8
  id='form2'>
9
9
  <command xmlns='http://jabber.org/protocol/commands'
10
10
  node='node1'
11
- action='execute'
12
11
  sessionid='dqjiodmqlmakm'>
13
12
  <x xmlns='jabber:x:data' type='form'>
14
13
  <field var='field-name' type='text-single' label='description' />
@@ -86,7 +85,18 @@ describe Blather::Stanza::Iq::Command do
86
85
  c.type.must_equal :result
87
86
  end
88
87
 
89
- # TODO: Deal with #reply/#reply! better?
88
+ it 'removes action on reply' do
89
+ c = Blather::XMPPNode.import parse_stanza(command_xml).root
90
+ c.action.must_equal :execute
91
+ c.reply.action.must_equal nil
92
+ end
93
+
94
+ it 'removes action on reply!' do
95
+ c = Blather::XMPPNode.import parse_stanza(command_xml).root
96
+ c.action.must_equal :execute
97
+ c.reply!
98
+ c.action.must_equal nil
99
+ end
90
100
 
91
101
  it 'can be registered under a namespace' do
92
102
  class CommandNs < Blather::Stanza::Iq::Command; register :command_ns, nil, 'command:ns'; end
@@ -113,27 +123,53 @@ describe Blather::Stanza::Iq::Command do
113
123
  n.action.must_equal :cancel
114
124
  end
115
125
 
126
+ it 'must default action to :execute on import' do
127
+ n = Blather::XMPPNode.import(parse_stanza(command_xml).root)
128
+ n.action.must_equal :execute
129
+ end
130
+
116
131
  it 'has a status attribute' do
117
132
  n = Blather::Stanza::Iq::Command.new
118
- n.status.must_equal nil
119
- n.status = :executing
120
133
  n.status.must_equal :executing
134
+ n.status = :completed
135
+ n.status.must_equal :completed
121
136
  end
122
137
 
123
138
  it 'has a sessionid attribute' do
124
139
  n = Blather::Stanza::Iq::Command.new
125
- n.sessionid.wont_be_nil
140
+ n.sessionid.must_equal nil
126
141
  n.sessionid = "somerandomstring"
127
142
  n.sessionid.must_equal Digest::SHA1.hexdigest("somerandomstring")
128
143
  end
129
144
 
130
- it 'has an allowed_actions attribute' do
145
+ it 'has a sessionid? attribute' do
131
146
  n = Blather::Stanza::Iq::Command.new
147
+ n.sessionid?.must_equal false
148
+ n.new_sessionid!
149
+ n.sessionid?.must_equal true
150
+ end
151
+
152
+ it 'has an allowed_actions attribute' do
153
+ n = Blather::XMPPNode.import parse_stanza(command_xml).root
154
+ n.allowed_actions.must_equal [:execute]
155
+ n.allowed_actions = [:next, :prev]
156
+ (n.allowed_actions - [:next, :prev, :execute]).must_be_empty
157
+ n.remove_allowed_actions!
132
158
  n.allowed_actions.must_equal [:execute]
133
- n.add_allowed_actions [:prev, :next]
134
- n.allowed_actions.must_equal [:execute, :prev, :next]
135
- n.remove_allowed_actions :prev
136
- n.allowed_actions.must_equal [:execute, :next]
159
+ n.allowed_actions += [:next]
160
+ (n.allowed_actions - [:next, :execute]).must_be_empty
161
+
162
+ r = Blather::Stanza::Iq::Command.new
163
+ r.allowed_actions.must_equal [:execute]
164
+ r.allowed_actions += [:prev]
165
+ (r.allowed_actions - [:prev, :execute]).must_be_empty
166
+ end
167
+
168
+ it 'has a primary_allowed_action attribute' do
169
+ n = Blather::XMPPNode.import parse_stanza(command_xml).root
170
+ n.primary_allowed_action.must_equal :execute
171
+ n.primary_allowed_action = :next
172
+ n.primary_allowed_action.must_equal :next
137
173
  end
138
174
 
139
175
  it 'has a note_type attribute' do
@@ -155,5 +191,9 @@ describe Blather::Stanza::Iq::Command do
155
191
  n.form.fields.size.must_equal 1
156
192
  n.form.fields.map { |f| f.class }.uniq.must_equal [Blather::Stanza::X::Field]
157
193
  n.form.must_be_instance_of Blather::Stanza::X
194
+
195
+ r = Blather::Stanza::Iq::Command.new
196
+ r.form.type = :form
197
+ r.form.type.must_equal :form
158
198
  end
159
199
  end
@@ -15,12 +15,12 @@ def x_xml
15
15
  <field var='field-name3'
16
16
  type='text-single'
17
17
  label='description' />
18
- <field var='field-name'
19
- type='{field-type}'
18
+ <field var='field-name4'
19
+ type='list-multi'
20
20
  label='description'>
21
21
  <desc/>
22
22
  <required/>
23
- <value>field-value</value>
23
+ <value>field-value4</value>
24
24
  <option label='option-label'><value>option-value</value></option>
25
25
  <option label='option-label'><value>option-value</value></option>
26
26
  </field>
@@ -81,6 +81,13 @@ describe Blather::Stanza::X do
81
81
  r.fields.map { |f| f.class }.uniq.must_equal [Blather::Stanza::X::Field]
82
82
  end
83
83
 
84
+ it 'returns a field object for a particular var' do
85
+ x = Blather::Stanza::X.new parse_stanza(x_xml).root
86
+ f = x.field 'field-name4'
87
+ f.must_be_instance_of Blather::Stanza::X::Field
88
+ f.value.must_equal 'field-value4'
89
+ end
90
+
84
91
  it 'takes a list of hashes for fields' do
85
92
  fields = [
86
93
  {:label => 'label', :type => 'text-single', :var => 'var'},
@@ -121,9 +128,9 @@ describe Blather::Stanza::X do
121
128
  it 'allows adding of fields' do
122
129
  di = Blather::Stanza::X.new nil
123
130
  di.fields.size.must_equal 0
124
- di.add_fields [{:label => 'label', :type => 'text-single', :var => 'var'}]
131
+ di.fields = [{:label => 'label', :type => 'text-single', :var => 'var', :required => true}]
125
132
  di.fields.size.must_equal 1
126
- di.add_fields [Blather::Stanza::X::Field.new(*%w[text-single var1 label1])]
133
+ di.fields += [Blather::Stanza::X::Field.new(*%w[text-single var1 label1])]
127
134
  di.fields.size.must_equal 2
128
135
  end
129
136
 
@@ -171,9 +178,9 @@ describe Blather::Stanza::X::Field do
171
178
  it 'has a required? attribute' do
172
179
  n = Blather::Stanza::X::Field.new 'text-single', 'subject', 'Music from the time of Shakespeare'
173
180
  n.required?.must_equal false
174
- n.required!
181
+ n.required = true
175
182
  n.required?.must_equal true
176
- n.required! false
183
+ n.required = false
177
184
  n.required?.must_equal false
178
185
  end
179
186
 
@@ -190,9 +197,9 @@ describe Blather::Stanza::X::Field do
190
197
  it 'allows adding of options' do
191
198
  di = Blather::Stanza::X::Field.new nil
192
199
  di.options.size.must_equal 0
193
- di.add_options [{:label => 'Person', :value => 'person'}]
200
+ di.options += [{:label => 'Person', :value => 'person'}]
194
201
  di.options.size.must_equal 1
195
- di.add_options [Blather::Stanza::X::Field::Option.new(*%w[person1 Person1])]
202
+ di.options += [Blather::Stanza::X::Field::Option.new(*%w[person1 Person1])]
196
203
  di.options.size.must_equal 2
197
204
  end
198
205
 
@@ -225,4 +232,4 @@ describe Blather::Stanza::X::Field::Option do
225
232
  n.label = 'Book 2'
226
233
  n.label.must_equal 'Book 2'
227
234
  end
228
- end
235
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blather
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 4
9
- - 10
10
- version: 0.4.10
9
+ - 11
10
+ version: 0.4.11
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jeff Smick
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-19 00:00:00 -07:00
18
+ date: 2010-07-29 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency