def test_ignore_form_without_type(self): forms = [ forms_xso.Data(type_=forms_xso.DataType.FORM), forms_xso.Data(type_=forms_xso.DataType.FORM) ] forms[0].fields.extend([ forms_xso.Field(var="FORM_TYPE", values=[]), forms_xso.Field(var="os_version", values=[ "10.5.1", ]), ]) forms[1].fields.extend([ forms_xso.Field(var="FORM_TYPE", values=[ "urn:xmpp:dataforms:softwareinfo", ]), forms_xso.Field(var="os_version", values=[ "10.5.1", ]), forms_xso.Field(var="os", values=[ "Mac", ]), ]) self.assertEqual( b"urn:xmpp:dataforms:softwareinfo<" b"os<Mac<" b"os_version<10.5.1<", caps115.build_forms_string(forms))
def test_validate_reject_empty_reported(self): obj = forms_xso.Data() obj.type_ = "result" obj.reported = forms_xso.Reported() with self.assertRaisesRegex(ValueError, "empty report header"): obj.validate()
def prepare(self): """ Returns an aioxmpp.stanza.Message built from the Message and prepared to be sent. Returns: aioxmpp.stanza.Message: the message prepared to be sent """ msg = aioxmpp.stanza.Message( to=self.to, from_=self.sender, type_=aioxmpp.MessageType.CHAT, ) msg.body[None] = self.body msg.thread = self.thread # Send metadata using xep-0004: Data Forms (https://xmpp.org/extensions/xep-0004.html) if len(self.metadata): data = forms_xso.Data(type_=forms_xso.DataType.FORM) for name, value in self.metadata.items(): data.fields.append( forms_xso.Field( var=name, type_=forms_xso.FieldType.TEXT_SINGLE, values=[value], )) data.title = SPADE_X_METADATA msg.xep0004_data = [data] return msg
def test_validate_accepts_fields_for_results_without_report(self): field = forms_xso.Field() field.type_ = forms_xso.FieldType.FIXED obj = forms_xso.Data(type_=forms_xso.DataType.RESULT) obj.fields.append(field) obj.validate()
def test_from_xso_complex(self): data = forms_xso.Data(type_=forms_xso.DataType.FORM) data.fields.append( forms_xso.Field( var="FORM_TYPE", type_=forms_xso.FieldType.HIDDEN, values=["some-uri"], )) data.fields.append( forms_xso.Field( type_=forms_xso.FieldType.FIXED, values=["This is some heading."], )) data.fields.append( forms_xso.Field( var="jid", type_=forms_xso.FieldType.JID_SINGLE, values=[], desc="some description", label="some label", )) class F(form.Form): jid = fields.JIDSingle(var="jid", ) f = F.from_xso(data) self.assertIsNone(f.jid.value) self.assertIs(f._recv_xso, data)
def test_from_xso_rejects_mismatching_type(self): data = forms_xso.Data(type_=forms_xso.DataType.FORM) data.fields.append( forms_xso.Field( var="FORM_TYPE", type_=forms_xso.FieldType.HIDDEN, values=["some-uri"], )) data.fields.append( forms_xso.Field( type_=forms_xso.FieldType.FIXED, values=["This is some heading."], )) data.fields.append( forms_xso.Field( var="jid", type_=forms_xso.FieldType.JID_SINGLE, values=[], desc="some description", label="some label", )) class F(form.Form): jid = fields.TextSingle(var="jid", ) with self.assertRaisesRegex( ValueError, r"mismatching type (.+ != .+) on field .+"): F.from_xso(data)
def test_from_xso_allows_upcast(self): data = forms_xso.Data(type_=forms_xso.DataType.FORM) data.fields.append( forms_xso.Field( var="FORM_TYPE", type_=forms_xso.FieldType.HIDDEN, values=["some-uri"], )) data.fields.append( forms_xso.Field( type_=forms_xso.FieldType.FIXED, values=["This is some heading."], )) data.fields.append( forms_xso.Field( var="jid", type_=forms_xso.FieldType.TEXT_SINGLE, values=[], desc="some description", label="some label", )) class F(form.Form): jid = fields.TextPrivate(var="jid", ) F.from_xso(data)
def test_message_from_node(): aiomsg = aioxmpp.Message(type_=aioxmpp.MessageType.CHAT) data = forms_xso.Data(type_=forms_xso.DataType.FORM) data.fields.append( forms_xso.Field( var="performative", type_=forms_xso.FieldType.TEXT_SINGLE, values=["request"], ) ) data.fields.append( forms_xso.Field( var="_thread_node", type_=forms_xso.FieldType.TEXT_SINGLE, values=["thread-id"], ) ) data.title = SPADE_X_METADATA aiomsg.xep0004_data = [data] msg = Message.from_node(aiomsg) assert msg.thread == "thread-id" assert msg.get_metadata("performative") == "request" assert msg.metadata == {"performative": "request"}
def test_xep_form(self): forms = [forms_xso.Data(type_=forms_xso.DataType.FORM)] forms[0].fields.extend([ forms_xso.Field(var="FORM_TYPE", values=[ "urn:xmpp:dataforms:softwareinfo", ]), forms_xso.Field(var="os_version", values=[ "10.5.1", ]), forms_xso.Field(var="os", values=[ "Mac", ]), forms_xso.Field(var="ip_version", values=[ "ipv4", "ipv6", ]), forms_xso.Field(var="software", values=[ "Psi", ]), forms_xso.Field(var="software_version", values=[ "0.11", ]), ]) self.assertEqual( b"urn:xmpp:dataforms:softwareinfo<" b"ip_version<ipv4<ipv6<" b"os<Mac<" b"os_version<10.5.1<" b"software<Psi<" b"software_version<0.11<", caps115.build_forms_string(forms))
def test_validate_accepts_fields_for_results_without_report(self): field = forms_xso.Field() field.type_ = "fixed" obj = forms_xso.Data() obj.type_ = "result" obj.fields.append(field) obj.validate()
def test_render_reply_includes_unknown_field(self): data = forms_xso.Data(type_=forms_xso.DataType.FORM) data.fields.append( forms_xso.Field( var="jid", type_=forms_xso.FieldType.JID_SINGLE, values=[], desc="some description", ) ) data.fields.append( forms_xso.Field( var="foo", type_=forms_xso.FieldType.TEXT_SINGLE, values=[], ) ) class F(form.Form): jid = fields.JIDSingle( var="jid", label="Foobar" ) f = F.from_xso(data) f.jid.value = aioxmpp.JID.fromstr("*****@*****.**") result = f.render_reply() self.assertIsInstance(result, forms_xso.Data) self.assertEqual( len(result.fields), 2 ) self.assertIs( data.fields[1], result.fields[1] ) self.assertIsNot( data.fields[0], result.fields[0], ) jid_field = result.fields[0] self.assertSequenceEqual( jid_field.values, ["*****@*****.**"] ) self.assertEqual( jid_field.desc, "some description", ) self.assertIsNone( jid_field.label )
def test_render_reply(self): data = forms_xso.Data(type_=forms_xso.DataType.FORM) data.fields.append( forms_xso.Field( var="FORM_TYPE", type_=forms_xso.FieldType.HIDDEN, values=["some-uri"], )) data.fields.append( forms_xso.Field( type_=forms_xso.FieldType.FIXED, values=["This is some heading."], )) data.fields.append( forms_xso.Field( var="jid", type_=forms_xso.FieldType.JID_SINGLE, values=[], desc="some description", )) class F(form.Form): jid = fields.JIDSingle(var="jid", label="Foobar") other = fields.TextSingle(var="foo", ) f = F.from_xso(data) f.jid.value = aioxmpp.JID.fromstr("*****@*****.**") result = f.render_reply() self.assertIsInstance(result, forms_xso.Data) self.assertEqual( result.type_, forms_xso.DataType.SUBMIT, ) self.assertEqual(len(result.fields), 3) self.assertIs(data.fields[0], result.fields[0]) self.assertIs( data.fields[1], result.fields[1], ) self.assertIsNot( data.fields[2], result.fields[2], ) jid_field = result.fields[2] self.assertSequenceEqual(jid_field.values, ["*****@*****.**"]) self.assertEqual( jid_field.desc, "some description", ) self.assertIsNone(jid_field.label)
def test_get_form_type_copes_with_too_many_values(self): d = forms_xso.Data(type_=forms_xso.DataType.FORM) d.fields.append(forms_xso.Field(), ) d.fields.append( forms_xso.Field(type_=forms_xso.FieldType.HIDDEN, var="FORM_TYPE", values=["foo", "bar"]), ) d.fields.append(forms_xso.Field(), ) self.assertIsNone(d.get_form_type(), )
def test_get_form_type_copes_with_malformed_FORM_TYPE(self): d = forms_xso.Data(type_=forms_xso.DataType.FORM) d.fields.append(forms_xso.Field(), ) d.fields.append( forms_xso.Field(type_=forms_xso.FieldType.HIDDEN, var="FORM_TYPE", values=[]), ) d.fields.append(forms_xso.Field(), ) self.assertIsNone(d.get_form_type(), )
def test_get_form_type_detects_incorrect_FORM_TYPE(self): d = forms_xso.Data(type_=forms_xso.DataType.FORM) d.fields.append(forms_xso.Field(), ) d.fields.append( forms_xso.Field(type_=forms_xso.FieldType.TEXT_SINGLE, var="FORM_TYPE", values=[unittest.mock.sentinel.form_type]), ) d.fields.append(forms_xso.Field(), ) self.assertIsNone(d.get_form_type(), )
def test_multiple(self): forms = [ forms_xso.Data(type_=forms_xso.DataType.FORM), forms_xso.Data(type_=forms_xso.DataType.FORM) ] forms[0].fields.extend([ forms_xso.Field(var="FORM_TYPE", values=[ "uri:foo", ]), ]) forms[1].fields.extend([ forms_xso.Field(var="FORM_TYPE", values=[ "uri:bar", ]), ]) self.assertEqual(b"uri:bar<uri:foo<", caps115.build_forms_string(forms))
def test_from_xso_checks_FORM_TYPE(self): class F(form.Form): FORM_TYPE = "foo" tree = forms_xso.Data(type_=forms_xso.DataType.FORM) tree.fields.append( forms_xso.Field(type_=forms_xso.FieldType.HIDDEN, values=["bar"], var="FORM_TYPE")) with self.assertRaisesRegex(ValueError, "mismatching FORM_TYPE"): F.from_xso(tree)
def test_get_form_type_returns_none_without_FORM_TYPE(self): d = forms_xso.Data(type_=forms_xso.DataType.FORM) d.fields.append( forms_xso.Field(), ) d.fields.append( forms_xso.Field(), ) self.assertIsNone( d.get_form_type(), )
def test_from_xso_single_field(self): class F(form.Form): field = fields.TextSingle("foobar", ) tree = forms_xso.Data(type_=forms_xso.DataType.FORM) tree.fields.append(forms_xso.Field(values=["value"], var="foobar")) f = F.from_xso(tree) self.assertIsInstance(f, F) self.assertEqual( f.field.value, "value", )
def test_validate_reject_empty_items(self): f = forms_xso.Field() f.var = "foobar" obj = forms_xso.Data(forms_xso.DataType.RESULT) obj.reported = forms_xso.Reported() obj.reported.fields.append(f) obj.items.append(forms_xso.Item()) with self.assertRaisesRegex(ValueError, "field mismatch between row and header"): obj.validate()
def test_get_form_type(self): d = forms_xso.Data(type_=forms_xso.DataType.FORM) d.fields.append(forms_xso.Field(), ) d.fields.append( forms_xso.Field(type_=forms_xso.FieldType.HIDDEN, var="FORM_TYPE", values=[unittest.mock.sentinel.form_type]), ) d.fields.append(forms_xso.Field(), ) self.assertEqual( d.get_form_type(), unittest.mock.sentinel.form_type, )
def test_form_xso_allows_all_data_types(self): allow = [ forms_xso.DataType.CANCEL, forms_xso.DataType.FORM, forms_xso.DataType.SUBMIT, forms_xso.DataType.RESULT, ] class F(form.Form): pass for t in forms_xso.DataType: tree = forms_xso.Data(type_=t) F.from_xso(tree)
def test_accept_form_with_multiple_identical_types(self): forms = [forms_xso.Data(type_=forms_xso.DataType.FORM)] forms[0].fields.extend([ forms_xso.Field(var="FORM_TYPE", values=[ "urn:xmpp:dataforms:softwareinfo", "urn:xmpp:dataforms:softwareinfo", ]), forms_xso.Field(var="os_version", values=[ "10.5.1", ]), ]) caps115.build_forms_string(forms)
def test_validate_rejects_fields_for_results_if_report(self): field = forms_xso.Field() field.type_ = forms_xso.FieldType.FIXED obj = forms_xso.Data(type_=forms_xso.DataType.RESULT) obj.fields.append(field) obj.reported = forms_xso.Reported() with self.assertRaisesRegex(ValueError, "field in report result"): obj.validate() obj.reported = None obj.items.append(forms_xso.Item()) with self.assertRaisesRegex(ValueError, "field in report result"): obj.validate()
def test_reject_multiple_identical_form_types(self): forms = [ forms_xso.Data(type_=forms_xso.DataType.FORM), forms_xso.Data(type_=forms_xso.DataType.FORM) ] forms[0].fields.extend([ forms_xso.Field(var="FORM_TYPE", values=[ "urn:xmpp:dataforms:softwareinfo", ]), forms_xso.Field(var="os_version", values=[ "10.5.1", ]), forms_xso.Field(var="os", values=[ "Mac", ]), ]) forms[1].fields.extend([ forms_xso.Field(var="FORM_TYPE", values=[ "urn:xmpp:dataforms:softwareinfo", ]), forms_xso.Field(var="os_version", values=[ "10.5.1", ]), forms_xso.Field(var="os", values=[ "Mac", ]), ]) with self.assertRaisesRegex( ValueError, "multiple forms of type b'urn:xmpp:dataforms:softwareinfo'"): caps115.build_forms_string(forms)
def test_validate_rejects_reported_or_items_if_type_is_not_result(self): types = ["form", "submit", "cancel"] rep = forms_xso.Reported() item = forms_xso.Item() for type_ in types: obj = forms_xso.Data() obj.type_ = type_ obj.reported = rep with self.assertRaisesRegex(ValueError, "report in non-result"): obj.validate() obj.reported = None obj.items.append(item) with self.assertRaisesRegex(ValueError, "report in non-result"): obj.validate() obj.items.clear()
def test_from_xso_checks_data_type(self): reject = [ forms_xso.DataType.RESULT, forms_xso.DataType.CANCEL, ] class F(form.Form): pass for t in forms_xso.DataType: tree = forms_xso.Data(type_=t) if t in reject: with self.assertRaisesRegex(ValueError, r"unexpected form type", msg="for {}".format(t)): F.from_xso(tree) else: F.from_xso(tree)
def test_value_and_var_escaping(self): forms = [forms_xso.Data(type_=forms_xso.DataType.FORM)] forms[0].fields.extend([ forms_xso.Field(var="FORM_TYPE", values=[ "urn:xmpp:<dataforms:softwareinfo", ]), forms_xso.Field(var="os_version", values=[ "10.&5.1", ]), forms_xso.Field(var="os>", values=[ "Mac", ]), ]) self.assertEqual( b"urn:xmpp:<dataforms:softwareinfo<" b"os><Mac<" b"os_version<10.&5.1<", caps115.build_forms_string(forms))
def test_complex_xep_data(self): info = disco.xso.InfoQuery() info.identities.extend([ disco.xso.Identity(category="client", name="Psi 0.11", type_="pc", lang=structs.LanguageTag.fromstr("en")), disco.xso.Identity(category="client", name="Ψ 0.11", type_="pc", lang=structs.LanguageTag.fromstr("el")), ]) info.features.update({ "http://jabber.org/protocol/caps", "http://jabber.org/protocol/disco#info", "http://jabber.org/protocol/disco#items", "http://jabber.org/protocol/muc", }) ext_form = forms_xso.Data(type_=forms_xso.DataType.FORM) ext_form.fields.extend([ forms_xso.Field(var="FORM_TYPE", values=["urn:xmpp:dataforms:softwareinfo"]), forms_xso.Field(var="ip_version", values=[ "ipv6", "ipv4", ]), forms_xso.Field(var="os", values=["Mac"]), forms_xso.Field(var="os_version", values=[ "10.5.1", ]), forms_xso.Field(var="software", values=[ "Psi", ]), forms_xso.Field(var="software_version", values=["0.11"]), ]) info.exts.append(ext_form) self.assertEqual("q07IKJEyjvHSyhy//CH0CxmKi8w=", caps115.hash_query(info, "sha1"))
def test_validate_reject_mismatching_items(self): f = forms_xso.Field() f.var = "foobar" obj = forms_xso.Data() obj.type_ = "result" obj.reported = forms_xso.Reported() obj.reported.fields.append(f) f2 = forms_xso.Field() f2.var = "fnord" item = forms_xso.Item() item.fields.append(f2) obj.items.append(item) with self.assertRaisesRegex(ValueError, "field mismatch between row and header"): obj.validate()