5 from slixmpp
.test
import SlixTest
6 from slixmpp
.xmlstream
import ElementBase
, register_stanza_plugin
9 class TestAdHocCommands(SlixTest
):
12 self
.stream_start(mode
='client',
13 plugins
=['xep_0030', 'xep_0004', 'xep_0050'])
15 # Real session IDs don't make for nice tests, so use
17 self
.xmpp
['xep_0050'].new_session
= lambda: '_sessionid_'
22 def testInitialPayloadCommand(self
):
23 """Test a command with an initial payload."""
25 class TestPayload(ElementBase
):
28 interfaces
= set(['bar'])
31 Command
= self
.xmpp
['xep_0050'].stanza
.Command
32 register_stanza_plugin(Command
, TestPayload
, iterable
=True)
34 def handle_command(iq
, session
):
35 initial
= session
['payload']
36 logging
.debug(initial
)
37 new_payload
= TestPayload()
39 new_payload
['bar'] = 'Received: %s' % initial
['bar']
41 new_payload
['bar'] = 'Failed'
43 logging
.debug(initial
)
45 session
['payload'] = new_payload
46 session
['next'] = None
47 session
['has_next'] = False
51 self
.xmpp
['xep_0050'].add_command('tester@localhost', 'foo',
52 'Do Foo', handle_command
)
55 <iq id="11" type="set" to="tester@localhost" from="foo@bar">
56 <command xmlns="http://jabber.org/protocol/commands"
59 <foo xmlns="test" bar="baz" />
65 <iq id="11" type="result" to="foo@bar">
66 <command xmlns="http://jabber.org/protocol/commands"
69 sessionid="_sessionid_">
70 <foo xmlns="test" bar="Received: baz" />
75 def testZeroStepCommand(self
):
76 """Test running a command with no steps."""
78 def handle_command(iq
, session
):
79 form
= self
.xmpp
['xep_0004'].makeForm(ftype
='result')
80 form
.addField(var
='foo', ftype
='text-single',
81 label
='Foo', value
='bar')
83 session
['payload'] = form
84 session
['next'] = None
85 session
['has_next'] = False
89 self
.xmpp
['xep_0050'].add_command('tester@localhost', 'foo',
90 'Do Foo', handle_command
)
93 <iq id="11" type="set" to="tester@localhost" from="foo@bar">
94 <command xmlns="http://jabber.org/protocol/commands"
101 <iq id="11" type="result" to="foo@bar">
102 <command xmlns="http://jabber.org/protocol/commands"
105 sessionid="_sessionid_">
106 <x xmlns="jabber:x:data" type="result">
107 <field var="foo" label="Foo" type="text-single">
115 def testOneStepCommand(self
):
116 """Test running a single step command."""
119 def handle_command(iq
, session
):
121 def handle_form(form
, session
):
122 results
.append(form
['values']['foo'])
124 form
= self
.xmpp
['xep_0004'].makeForm('form')
125 form
.addField(var
='foo', ftype
='text-single', label
='Foo')
127 session
['payload'] = form
128 session
['next'] = handle_form
129 session
['has_next'] = False
133 self
.xmpp
['xep_0050'].add_command('tester@localhost', 'foo',
134 'Do Foo', handle_command
)
137 <iq id="11" type="set" to="tester@localhost" from="foo@bar">
138 <command xmlns="http://jabber.org/protocol/commands"
145 <iq id="11" type="result" to="foo@bar">
146 <command xmlns="http://jabber.org/protocol/commands"
149 sessionid="_sessionid_">
153 <x xmlns="jabber:x:data" type="form">
154 <field var="foo" label="Foo" type="text-single" />
161 <iq id="12" type="set" to="tester@localhost" from="foo@bar">
162 <command xmlns="http://jabber.org/protocol/commands"
165 sessionid="_sessionid_">
166 <x xmlns="jabber:x:data" type="submit">
167 <field var="foo" label="Foo" type="text-single">
176 <iq id="12" type="result" to="foo@bar">
177 <command xmlns="http://jabber.org/protocol/commands"
180 sessionid="_sessionid_" />
184 self
.assertEqual(results
, ['blah'],
185 "Command handler was not executed: %s" % results
)
187 def testTwoStepCommand(self
):
188 """Test using a two-stage command."""
191 def handle_command(iq
, session
):
193 def handle_step2(form
, session
):
194 results
.append(form
['values']['bar'])
196 def handle_step1(form
, session
):
197 results
.append(form
['values']['foo'])
199 form
= self
.xmpp
['xep_0004'].makeForm('form')
200 form
.addField(var
='bar', ftype
='text-single', label
='Bar')
202 session
['payload'] = form
203 session
['next'] = handle_step2
204 session
['has_next'] = False
208 form
= self
.xmpp
['xep_0004'].makeForm('form')
209 form
.addField(var
='foo', ftype
='text-single', label
='Foo')
211 session
['payload'] = form
212 session
['next'] = handle_step1
213 session
['has_next'] = True
217 self
.xmpp
['xep_0050'].add_command('tester@localhost', 'foo',
218 'Do Foo', handle_command
)
221 <iq id="11" type="set" to="tester@localhost" from="foo@bar">
222 <command xmlns="http://jabber.org/protocol/commands"
229 <iq id="11" type="result" to="foo@bar">
230 <command xmlns="http://jabber.org/protocol/commands"
233 sessionid="_sessionid_">
237 <x xmlns="jabber:x:data" type="form">
238 <field var="foo" label="Foo" type="text-single" />
245 <iq id="12" type="set" to="tester@localhost" from="foo@bar">
246 <command xmlns="http://jabber.org/protocol/commands"
249 sessionid="_sessionid_">
250 <x xmlns="jabber:x:data" type="submit">
251 <field var="foo" label="Foo" type="text-single">
260 <iq id="12" type="result" to="foo@bar">
261 <command xmlns="http://jabber.org/protocol/commands"
264 sessionid="_sessionid_">
268 <x xmlns="jabber:x:data" type="form">
269 <field var="bar" label="Bar" type="text-single" />
276 <iq id="13" type="set" to="tester@localhost" from="foo@bar">
277 <command xmlns="http://jabber.org/protocol/commands"
280 sessionid="_sessionid_">
281 <x xmlns="jabber:x:data" type="submit">
282 <field var="bar" label="Bar" type="text-single">
290 <iq id="13" type="result" to="foo@bar">
291 <command xmlns="http://jabber.org/protocol/commands"
294 sessionid="_sessionid_" />
298 self
.assertEqual(results
, ['blah', 'meh'],
299 "Command handler was not executed: %s" % results
)
301 def testCancelCommand(self
):
302 """Test canceling command."""
305 def handle_command(iq
, session
):
307 def handle_form(form
, session
):
308 results
.append(form
['values']['foo'])
310 def handle_cancel(iq
, session
):
311 results
.append('canceled')
313 form
= self
.xmpp
['xep_0004'].makeForm('form')
314 form
.addField(var
='foo', ftype
='text-single', label
='Foo')
316 session
['payload'] = form
317 session
['next'] = handle_form
318 session
['cancel'] = handle_cancel
319 session
['has_next'] = False
323 self
.xmpp
['xep_0050'].add_command('tester@localhost', 'foo',
324 'Do Foo', handle_command
)
327 <iq id="11" type="set" to="tester@localhost" from="foo@bar">
328 <command xmlns="http://jabber.org/protocol/commands"
335 <iq id="11" type="result" to="foo@bar">
336 <command xmlns="http://jabber.org/protocol/commands"
339 sessionid="_sessionid_">
343 <x xmlns="jabber:x:data" type="form">
344 <field var="foo" label="Foo" type="text-single" />
351 <iq id="12" type="set" to="tester@localhost" from="foo@bar">
352 <command xmlns="http://jabber.org/protocol/commands"
355 sessionid="_sessionid_">
356 <x xmlns="jabber:x:data" type="submit">
357 <field var="foo" label="Foo" type="text-single">
366 <iq id="12" type="result" to="foo@bar">
367 <command xmlns="http://jabber.org/protocol/commands"
370 sessionid="_sessionid_" />
374 self
.assertEqual(results
, ['canceled'],
375 "Cancelation handler not executed: %s" % results
)
377 def testCommandNote(self
):
378 """Test adding notes to commands."""
380 def handle_command(iq
, session
):
381 form
= self
.xmpp
['xep_0004'].makeForm(ftype
='result')
382 form
.addField(var
='foo', ftype
='text-single',
383 label
='Foo', value
='bar')
385 session
['payload'] = form
386 session
['next'] = None
387 session
['has_next'] = False
388 session
['notes'] = [('info', 'testing notes')]
392 self
.xmpp
['xep_0050'].add_command('tester@localhost', 'foo',
393 'Do Foo', handle_command
)
396 <iq id="11" type="set" to="tester@localhost" from="foo@bar">
397 <command xmlns="http://jabber.org/protocol/commands"
404 <iq id="11" type="result" to="foo@bar">
405 <command xmlns="http://jabber.org/protocol/commands"
408 sessionid="_sessionid_">
409 <note type="info">testing notes</note>
410 <x xmlns="jabber:x:data" type="result">
411 <field var="foo" label="Foo" type="text-single">
421 def testMultiPayloads(self
):
422 """Test using commands with multiple payloads."""
425 def handle_command(iq
, session
):
427 def handle_form(forms
, session
):
429 results
.append(form
['values']['FORM_TYPE'])
431 form1
= self
.xmpp
['xep_0004'].makeForm('form')
432 form1
.addField(var
='FORM_TYPE', ftype
='hidden', value
='form_1')
433 form1
.addField(var
='foo', ftype
='text-single', label
='Foo')
435 form2
= self
.xmpp
['xep_0004'].makeForm('form')
436 form2
.addField(var
='FORM_TYPE', ftype
='hidden', value
='form_2')
437 form2
.addField(var
='foo', ftype
='text-single', label
='Foo')
439 session
['payload'] = [form1
, form2
]
440 session
['next'] = handle_form
441 session
['has_next'] = False
445 self
.xmpp
['xep_0050'].add_command('tester@localhost', 'foo',
446 'Do Foo', handle_command
)
449 <iq id="11" type="set" to="tester@localhost" from="foo@bar">
450 <command xmlns="http://jabber.org/protocol/commands"
457 <iq id="11" type="result" to="foo@bar">
458 <command xmlns="http://jabber.org/protocol/commands"
461 sessionid="_sessionid_">
465 <x xmlns="jabber:x:data" type="form">
466 <field var="FORM_TYPE" type="hidden">
467 <value>form_1</value>
469 <field var="foo" label="Foo" type="text-single" />
471 <x xmlns="jabber:x:data" type="form">
472 <field var="FORM_TYPE" type="hidden">
473 <value>form_2</value>
475 <field var="foo" label="Foo" type="text-single" />
482 <iq id="12" type="set" to="tester@localhost" from="foo@bar">
483 <command xmlns="http://jabber.org/protocol/commands"
486 sessionid="_sessionid_">
487 <x xmlns="jabber:x:data" type="submit">
488 <field var="FORM_TYPE" type="hidden">
489 <value>form_1</value>
491 <field var="foo" type="text-single">
495 <x xmlns="jabber:x:data" type="submit">
496 <field var="FORM_TYPE" type="hidden">
497 <value>form_2</value>
499 <field var="foo" type="text-single">
508 <iq id="12" type="result" to="foo@bar">
509 <command xmlns="http://jabber.org/protocol/commands"
512 sessionid="_sessionid_" />
516 self
.assertEqual(results
, [['form_1'], ['form_2']],
517 "Command handler was not executed: %s" % results
)
519 def testClientAPI(self
):
520 """Test using client-side API for commands."""
523 def handle_complete(iq
, session
):
524 for item
in session
['custom_data']:
527 def handle_step2(iq
, session
):
528 form
= self
.xmpp
['xep_0004'].makeForm(ftype
='submit')
529 form
.addField(var
='bar', value
='123')
531 session
['custom_data'].append('baz')
532 session
['payload'] = form
533 session
['next'] = handle_complete
534 self
.xmpp
['xep_0050'].complete_command(session
)
536 def handle_step1(iq
, session
):
537 form
= self
.xmpp
['xep_0004'].makeForm(ftype
='submit')
538 form
.addField(var
='foo', value
='42')
540 session
['custom_data'].append('bar')
541 session
['payload'] = form
542 session
['next'] = handle_step2
543 self
.xmpp
['xep_0050'].continue_command(session
)
545 session
= {'custom_data': ['foo'],
546 'next': handle_step1
}
548 self
.xmpp
['xep_0050'].start_command(
554 <iq id="1" to="foo@example.com" type="set">
555 <command xmlns="http://jabber.org/protocol/commands"
562 <iq id="1" from="foo@example.com" type="result">
563 <command xmlns="http://jabber.org/protocol/commands"
565 sessionid="_sessionid_"
567 <x xmlns="jabber:x:data" type="form">
568 <field var="foo" type="text-single" />
575 <iq id="2" to="foo@example.com" type="set">
576 <command xmlns="http://jabber.org/protocol/commands"
578 sessionid="_sessionid_"
580 <x xmlns="jabber:x:data" type="submit">
590 <iq id="2" from="foo@example.com" type="result">
591 <command xmlns="http://jabber.org/protocol/commands"
593 sessionid="_sessionid_"
595 <x xmlns="jabber:x:data" type="form">
596 <field var="bar" type="text-single" />
603 <iq id="3" to="foo@example.com" type="set">
604 <command xmlns="http://jabber.org/protocol/commands"
606 sessionid="_sessionid_"
608 <x xmlns="jabber:x:data" type="submit">
618 <iq id="3" from="foo@example.com" type="result">
619 <command xmlns="http://jabber.org/protocol/commands"
621 sessionid="_sessionid_"
622 status="completed" />
626 # Give the event queue time to process
629 self
.failUnless(results
== ['foo', 'bar', 'baz'],
630 'Incomplete command workflow: %s' % results
)
632 def testClientAPICancel(self
):
633 """Test using client-side cancel API for commands."""
636 def handle_canceled(iq
, session
):
637 for item
in session
['custom_data']:
640 def handle_step1(iq
, session
):
641 session
['custom_data'].append('bar')
642 session
['next'] = handle_canceled
643 self
.xmpp
['xep_0050'].cancel_command(session
)
645 session
= {'custom_data': ['foo'],
646 'next': handle_step1
}
648 self
.xmpp
['xep_0050'].start_command(
654 <iq id="1" to="foo@example.com" type="set">
655 <command xmlns="http://jabber.org/protocol/commands"
662 <iq id="1" to="foo@example.com" type="result">
663 <command xmlns="http://jabber.org/protocol/commands"
665 sessionid="_sessionid_"
667 <x xmlns="jabber:x:data" type="form">
668 <field var="foo" type="text-single" />
675 <iq id="2" to="foo@example.com" type="set">
676 <command xmlns="http://jabber.org/protocol/commands"
678 sessionid="_sessionid_"
684 <iq id="2" to="foo@example.com" type="result">
685 <command xmlns="http://jabber.org/protocol/commands"
687 sessionid="_sessionid_"
692 # Give the event queue time to process
695 self
.failUnless(results
== ['foo', 'bar'],
696 'Incomplete command workflow: %s' % results
)
698 def testClientAPIError(self
):
699 """Test using client-side error API for commands."""
702 def handle_error(iq
, session
):
703 for item
in session
['custom_data']:
706 session
= {'custom_data': ['foo'],
707 'error': handle_error
}
709 self
.xmpp
['xep_0050'].start_command(
715 <iq id="1" to="foo@example.com" type="set">
716 <command xmlns="http://jabber.org/protocol/commands"
723 <iq id="1" to="foo@example.com" type="error">
724 <command xmlns="http://jabber.org/protocol/commands"
727 <error type='cancel'>
728 <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
733 # Give the event queue time to process
736 self
.failUnless(results
== ['foo'],
737 'Incomplete command workflow: %s' % results
)
739 def testClientAPIErrorStrippedResponse(self
):
740 """Test errors that don't include the command substanza."""
743 def handle_error(iq
, session
):
744 for item
in session
['custom_data']:
747 session
= {'custom_data': ['foo'],
748 'error': handle_error
}
750 self
.xmpp
['xep_0050'].start_command(
756 <iq id="1" to="foo@example.com" type="set">
757 <command xmlns="http://jabber.org/protocol/commands"
764 <iq id="1" to="foo@example.com" type="error">
765 <error type='cancel'>
766 <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' />
771 # Give the event queue time to process
774 self
.failUnless(results
== ['foo'],
775 'Incomplete command workflow: %s' % results
)
781 suite
= unittest
.TestLoader().loadTestsFromTestCase(TestAdHocCommands
)