Mercurial > libervia-backend
comparison tests/unit/test_ap-gateway.py @ 3837:56720561f45f
test (unit/AP gateway): tests for XMPP reference/mention <=> AP mention conversion:
this patch add 5 tests:
- 2 to mention AP mention to XMPP conversion, with direct addressing or using "tag" field
- 2 to test automatic mention parsing of body
- 1 to test XEP-0372 Reference to AP mention conversion
rel 369
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 10 Jul 2022 16:15:09 +0200 |
parents | 81c79b7cafa7 |
children | 8c01d8ab9447 |
comparison
equal
deleted
inserted
replaced
3836:e183f1fbfa8d | 3837:56720561f45f |
---|---|
18 | 18 |
19 from copy import deepcopy | 19 from copy import deepcopy |
20 from unittest.mock import MagicMock, AsyncMock, patch, DEFAULT | 20 from unittest.mock import MagicMock, AsyncMock, patch, DEFAULT |
21 from urllib import parse | 21 from urllib import parse |
22 from functools import partial | 22 from functools import partial |
23 from typing import Dict, Union | |
23 | 24 |
24 import pytest | 25 import pytest |
25 from pytest_twisted import ensureDeferred as ed | 26 from pytest_twisted import ensureDeferred as ed |
26 from twisted.internet import defer | 27 from twisted.internet import defer |
27 from twisted.words.protocols.jabber import jid | 28 from twisted.words.protocols.jabber import jid |
40 from sat.plugins.plugin_xep_0422 import NS_FASTEN | 41 from sat.plugins.plugin_xep_0422 import NS_FASTEN |
41 from sat.plugins.plugin_xep_0424 import NS_MESSAGE_RETRACT | 42 from sat.plugins.plugin_xep_0424 import NS_MESSAGE_RETRACT |
42 from sat.plugins.plugin_xep_0465 import NS_PPS | 43 from sat.plugins.plugin_xep_0465 import NS_PPS |
43 from sat.tools.utils import xmpp_date | 44 from sat.tools.utils import xmpp_date |
44 from sat.tools import xml_tools | 45 from sat.tools import xml_tools |
46 from sat.tools.common import uri as xmpp_uri | |
45 from sat.plugins.plugin_comp_ap_gateway import TYPE_ACTOR | 47 from sat.plugins.plugin_comp_ap_gateway import TYPE_ACTOR |
46 from sat.memory.sqla_mapping import SubscriptionState | 48 from sat.memory.sqla_mapping import SubscriptionState |
47 | 49 |
48 | 50 |
49 TEST_BASE_URL = "https://example.org" | 51 TEST_BASE_URL = "https://example.org" |
389 count=len(ret_items) | 391 count=len(ret_items) |
390 ) | 392 ) |
391 return ret_items, {"rsm": rsm_resp.toDict(), "complete": True} | 393 return ret_items, {"rsm": rsm_resp.toDict(), "complete": True} |
392 | 394 |
393 | 395 |
396 async def mock_getPubsubNode(client, service, node, with_subscriptions=False, **kwargs): | |
397 """Mock storage's getPubsubNode | |
398 | |
399 return an MagicMock with subscription attribute set to empty list | |
400 """ | |
401 fake_cached_node = MagicMock() | |
402 fake_cached_node.subscriptions = [] | |
403 return fake_cached_node | |
404 | |
405 | |
394 def getVirtualClient(jid): | 406 def getVirtualClient(jid): |
395 client = MagicMock() | 407 client = MagicMock() |
396 client.jid = jid | 408 client.jid = jid |
397 return client | 409 return client |
398 | 410 |
413 client.getVirtualClient = getVirtualClient | 425 client.getVirtualClient = getVirtualClient |
414 gateway.client = client | 426 gateway.client = client |
415 gateway.local_only = True | 427 gateway.local_only = True |
416 gateway.public_url = PUBLIC_URL | 428 gateway.public_url = PUBLIC_URL |
417 gateway.ap_path = '_ap' | 429 gateway.ap_path = '_ap' |
430 gateway.auto_mentions = True | |
418 gateway.base_ap_url = parse.urljoin( | 431 gateway.base_ap_url = parse.urljoin( |
419 f"https://{gateway.public_url}", | 432 f"https://{gateway.public_url}", |
420 f"{gateway.ap_path}/" | 433 f"{gateway.ap_path}/" |
421 ) | 434 ) |
422 gateway.server = HTTPServer(gateway) | 435 gateway.server = HTTPServer(gateway) |
1140 ) | 1153 ) |
1141 | 1154 |
1142 # only the first nickname should be used | 1155 # only the first nickname should be used |
1143 assert actor_data["name"] == "nick1" | 1156 assert actor_data["name"] == "nick1" |
1144 assert actor_data["summary"] == "test description" | 1157 assert actor_data["summary"] == "test description" |
1158 | |
1159 @ed | |
1160 async def test_direct_addressing_mention_to_reference(self, ap_gateway, monkeypatch): | |
1161 """AP mentions by direct addressing are converted to XEP-0372 references""" | |
1162 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) | |
1163 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) | |
1164 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) | |
1165 | |
1166 xmpp_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost()) | |
1167 | |
1168 direct_addr_mention = { | |
1169 'attributedTo': TEST_AP_ACTOR_ID, | |
1170 'cc': [], | |
1171 'content': '<p>test mention by direct addressing</p>', | |
1172 'id': f'{TEST_AP_ACTOR_ID}/statuses/direct_addr_123', | |
1173 'published': '2022-05-20T08:14:39Z', | |
1174 'to': [ap_const.NS_AP_PUBLIC, xmpp_actor_id], | |
1175 'type': 'Note' | |
1176 } | |
1177 client = ap_gateway.client.getVirtualClient( | |
1178 ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) | |
1179 ) | |
1180 monkeypatch.setattr(client, "sendMessage", MagicMock()) | |
1181 | |
1182 with patch.object(ap_gateway._refs, "sendReference") as sendReference: | |
1183 await ap_gateway.newAPItem( | |
1184 client, None, ap_gateway._m.namespace, direct_addr_mention | |
1185 ) | |
1186 | |
1187 assert sendReference.call_count == 1 | |
1188 assert sendReference.call_args.kwargs["to_jid"] == TEST_JID | |
1189 | |
1190 local_actor_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) | |
1191 expected_anchor = xmpp_uri.buildXMPPUri( | |
1192 "pubsub", | |
1193 path=local_actor_jid.full(), | |
1194 node=ap_gateway._m.namespace, | |
1195 item=direct_addr_mention["id"] | |
1196 ) | |
1197 | |
1198 assert sendReference.call_args.kwargs["anchor"] == expected_anchor | |
1199 | |
1200 @ed | |
1201 async def test_tag_mention_to_reference(self, ap_gateway, monkeypatch): | |
1202 """AP mentions in "tag" field are converted to XEP-0372 references""" | |
1203 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) | |
1204 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) | |
1205 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) | |
1206 | |
1207 xmpp_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost()) | |
1208 | |
1209 direct_addr_mention = { | |
1210 'attributedTo': TEST_AP_ACTOR_ID, | |
1211 'cc': [], | |
1212 'content': '<p>test mention by tag</p>', | |
1213 'id': f'{TEST_AP_ACTOR_ID}/statuses/tag_123', | |
1214 'published': '2022-05-20T08:14:39Z', | |
1215 'to': [ap_const.NS_AP_PUBLIC], | |
1216 "tag": [ | |
1217 { | |
1218 "type": "Mention", | |
1219 "href": xmpp_actor_id, | |
1220 "name": f"@{TEST_JID}'" | |
1221 } | |
1222 ], | |
1223 'type': 'Note' | |
1224 } | |
1225 client = ap_gateway.client.getVirtualClient( | |
1226 ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) | |
1227 ) | |
1228 monkeypatch.setattr(client, "sendMessage", MagicMock()) | |
1229 | |
1230 with patch.object(ap_gateway._refs, "sendReference") as sendReference: | |
1231 await ap_gateway.newAPItem( | |
1232 client, None, ap_gateway._m.namespace, direct_addr_mention | |
1233 ) | |
1234 | |
1235 assert sendReference.call_count == 1 | |
1236 assert sendReference.call_args.kwargs["to_jid"] == TEST_JID | |
1237 | |
1238 local_actor_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) | |
1239 expected_anchor = xmpp_uri.buildXMPPUri( | |
1240 "pubsub", | |
1241 path=local_actor_jid.full(), | |
1242 node=ap_gateway._m.namespace, | |
1243 item=direct_addr_mention["id"] | |
1244 ) | |
1245 | |
1246 assert sendReference.call_args.kwargs["anchor"] == expected_anchor | |
1247 | |
1248 @ed | |
1249 async def test_auto_mentions(self, ap_gateway, monkeypatch): | |
1250 """Check that mentions in body are converted to AP mentions""" | |
1251 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) | |
1252 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) | |
1253 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) | |
1254 | |
1255 mb_data = { | |
1256 "author_jid": TEST_JID.full(), | |
1257 "content": f"mention of @{TEST_AP_ACCOUNT}", | |
1258 "service": TEST_JID.full(), | |
1259 "node": ap_gateway._m.namespace | |
1260 } | |
1261 ap_item = await ap_gateway.mbdata2APitem(ap_gateway.client, mb_data, public=True) | |
1262 | |
1263 ap_object = ap_item["object"] | |
1264 assert TEST_AP_ACTOR_ID in ap_object["to"] | |
1265 expected_mention = { | |
1266 "type": ap_const.TYPE_MENTION, | |
1267 "href": TEST_AP_ACTOR_ID, | |
1268 "name": f"@{TEST_AP_ACCOUNT}" | |
1269 } | |
1270 assert expected_mention in ap_object["tag"] | |
1271 | |
1272 @ed | |
1273 async def test_no_auto_mentions_when_not_public(self, ap_gateway, monkeypatch): | |
1274 """Check that no mention is send when the message is not public""" | |
1275 # this is the same test as test_auto_mentions above, except that public is not set | |
1276 # in mbdata2APitem | |
1277 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) | |
1278 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) | |
1279 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) | |
1280 | |
1281 mb_data = { | |
1282 "author_jid": TEST_JID.full(), | |
1283 "content": f"mention of @{TEST_AP_ACCOUNT}", | |
1284 "service": TEST_JID.full(), | |
1285 "node": ap_gateway._m.namespace | |
1286 } | |
1287 ap_item = await ap_gateway.mbdata2APitem(ap_gateway.client, mb_data, public=False) | |
1288 | |
1289 ap_object = ap_item["object"] | |
1290 assert "to" not in ap_object | |
1291 assert "tag" not in ap_object | |
1292 | |
1293 @ed | |
1294 async def test_xmpp_reference_to_ap_mention(self, ap_gateway, monkeypatch): | |
1295 """Check that XEP-0372 references are converted to AP mention""" | |
1296 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get) | |
1297 monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json) | |
1298 monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get) | |
1299 | |
1300 local_actor_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT) | |
1301 item_elt = XMPP_ITEMS[0] | |
1302 anchor = xmpp_uri.buildXMPPUri( | |
1303 "pubsub", | |
1304 path=TEST_JID.full(), | |
1305 node=ap_gateway._m.namespace, | |
1306 item=item_elt["id"] | |
1307 ) | |
1308 | |
1309 ref_data: Dict[str, Union[str, int, dict]] = { | |
1310 "uri": xmpp_uri.buildXMPPUri(None, path=local_actor_jid.full()), | |
1311 "type_": "mention", | |
1312 "anchor": anchor | |
1313 } | |
1314 reference_elt = ap_gateway._refs.buildRefElement(**ref_data) | |
1315 | |
1316 # we now update ref_data to look like what is received in the trigger | |
1317 | |
1318 ref_data["parsed_uri"] = xmpp_uri.parseXMPPUri(ref_data["uri"]) | |
1319 ref_data["parsed_anchor"] = xmpp_uri.parseXMPPUri(ref_data["anchor"]) | |
1320 | |
1321 # "type" is a builtin function, thus "type_" is used in buildRefElement, but in | |
1322 # ref_data is "type" without underscore | |
1323 ref_data["type"] = ref_data["type_"] | |
1324 del ref_data["type_"] | |
1325 | |
1326 message_elt = domish.Element((None, "message")) | |
1327 message_elt.addChild(reference_elt) | |
1328 | |
1329 with patch.object(ap_gateway.host.memory.storage, "getItems") as getItems: | |
1330 # getItems returns a sqla_mapping.PubsubItem, thus we need to fake it and set | |
1331 # the item_elt we want to use in its "data" attribute | |
1332 mock_pubsub_item = MagicMock | |
1333 mock_pubsub_item.data = item_elt | |
1334 getItems.return_value = ([mock_pubsub_item], {}) | |
1335 with patch.object(ap_gateway, "signAndPost") as signAndPost: | |
1336 signAndPost.return_value.code = 202 | |
1337 await ap_gateway._onReferenceReceived(ap_gateway.client, message_elt, ref_data) | |
1338 | |
1339 # when reference is received, the referencing item must be sent to referenced | |
1340 # actor, and they must be in "to" field and in "tag" | |
1341 assert signAndPost.call_count == 1 | |
1342 send_ap_item = signAndPost.call_args.args[-1] | |
1343 ap_object = send_ap_item["object"] | |
1344 assert TEST_AP_ACTOR_ID in ap_object["to"] | |
1345 expected_mention = { | |
1346 "type": ap_const.TYPE_MENTION, | |
1347 "href": TEST_AP_ACTOR_ID, | |
1348 # we don't have a prefixing "@" here, because it's not needed in referencing | |
1349 # item with XMPP | |
1350 "name": f"{TEST_AP_ACCOUNT}" | |
1351 } | |
1352 assert expected_mention in ap_object["tag"] |