diff --git a/slixmpp/plugins/xep_0405/mix_pam.py b/slixmpp/plugins/xep_0405/mix_pam.py
index 2b132526..7d87158e 100644
--- a/slixmpp/plugins/xep_0405/mix_pam.py
+++ b/slixmpp/plugins/xep_0405/mix_pam.py
@@ -70,7 +70,7 @@ class XEP_0405(BasePlugin):
iq['client_join']['mix_join'].append(sub)
result = await iq.send(**iqkwargs)
result_nodes = {sub['node'] for sub in result['client_join']['mix_join']}
- return result_nodes.difference(subscribe)
+ return subscribe.difference(result_nodes)
async def leave_channel(self, room: JID, *,
ito: Optional[JID] = None,
diff --git a/tests/test_stanza_xep_0403.py b/tests/test_stanza_xep_0403.py
new file mode 100644
index 00000000..7d7a5daa
--- /dev/null
+++ b/tests/test_stanza_xep_0403.py
@@ -0,0 +1,32 @@
+import unittest
+from slixmpp import Presence, JID
+from slixmpp.test import SlixTest
+from slixmpp.plugins.xep_0403 import stanza
+
+
+class TestMIXPresenceStanza(SlixTest):
+
+ def setUp(self):
+ stanza.register_plugins()
+
+ def testMIXPresence(self):
+ """Test that data is converted to base64"""
+ pres = Presence()
+ pres['show'] = 'dnd'
+ pres['status'] = 'Hey there!'
+ pres['mix']['jid'] = JID('toto@example.com')
+ pres['mix']['nick'] = 'Toto toto'
+
+ self.check(pres, """
+
+ dnd
+ Hey there!
+
+ toto@example.com
+ Toto toto
+
+
+ """)
+
+
+suite = unittest.TestLoader().loadTestsFromTestCase(TestMIXPresenceStanza)
diff --git a/tests/test_stream_xep_0405.py b/tests/test_stream_xep_0405.py
new file mode 100644
index 00000000..9bc01601
--- /dev/null
+++ b/tests/test_stream_xep_0405.py
@@ -0,0 +1,181 @@
+import unittest
+from slixmpp.test import SlixTest
+from slixmpp import JID
+
+
+class TestMIXPAM(SlixTest):
+
+ def setUp(self):
+ self.stream_start(plugins=['xep_0405'])
+
+ def tearDown(self):
+ self.stream_close()
+
+ def testGetRosterEmpty(self):
+ """Test requesting an empty annotated roster"""
+
+ fut = self.xmpp.wrap(self.xmpp['xep_0405'].get_mix_roster())
+
+ self.wait_()
+ self.send("""
+
+
+
+
+
+ """)
+
+ self.recv("""
+
+ """)
+
+ result = self.run_coro(fut)
+
+ def testGetRoster(self):
+ """Test requesting an annotated roster"""
+
+ fut = self.xmpp.wrap(self.xmpp['xep_0405'].get_mix_roster())
+
+ self.wait_()
+ self.send("""
+
+
+
+
+
+ """)
+
+ self.recv("""
+
+
+
+
+ -
+
+
+
+
+ """)
+
+ self.wait_()
+ contacts, channels = fut.result()
+ self.assertEqual(len(contacts), 2)
+ self.assertEqual(contacts[0]['jid'], 'romeo@example.net')
+ self.assertEqual(contacts[1]['jid'], 'juliet@example.net')
+ self.assertEqual(len(channels), 1)
+ self.assertEqual(channels[0]['jid'], 'balcony@example.net')
+ self.assertEqual(
+ channels[0]['channel']['participant-id'],
+ '123456'
+ )
+
+ def testClientJoin(self):
+ """Test a client join"""
+
+ fut = self.xmpp.wrap(self.xmpp['xep_0405'].join_channel(
+ JID('coven@mix.shakespeare.example'),
+ 'toto',
+ ))
+ self.send("""
+
+
+
+ toto
+
+
+
+
+
+
+ """)
+ self.recv("""
+
+
+
+
+
+
+
+
+
+ """)
+ self.wait_()
+ self.assertEqual(fut.result(), set())
+
+ def testClientJoinNotAllNodes(self):
+ """Test a client join where one of the nodes is rejected"""
+
+ fut = self.xmpp.wrap(self.xmpp['xep_0405'].join_channel(
+ JID('coven@mix.shakespeare.example'),
+ 'toto',
+ ))
+ self.send("""
+
+
+
+ toto
+
+
+
+
+
+
+ """)
+ self.recv("""
+
+
+
+
+
+
+
+
+ """)
+ self.wait_()
+ self.assertEqual(fut.result(), {'urn:xmpp:mix:nodes:info'})
+
+ def testClientLeave(self):
+ """Test a client leave"""
+
+ fut = self.xmpp.wrap(self.xmpp['xep_0405'].leave_channel(
+ JID('coven@mix.shakespeare.example'),
+ ))
+ self.send("""
+
+
+
+
+
+ """)
+ self.recv("""
+
+
+
+
+
+ """)
+
+ self.assertEqual(fut.done(), True)
+ self.assertEqual(fut.exception(), None)
+
+
+suite = unittest.TestLoader().loadTestsFromTestCase(TestMIXPAM)