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
This commit is contained in:
Goffi 2022-07-10 16:15:09 +02:00
commit 68d7c9257b

View file

@ -20,6 +20,7 @@ from copy import deepcopy
from unittest.mock import MagicMock, AsyncMock, patch, DEFAULT
from urllib import parse
from functools import partial
from typing import Dict, Union
import pytest
from pytest_twisted import ensureDeferred as ed
@ -42,6 +43,7 @@ from sat.plugins.plugin_xep_0424 import NS_MESSAGE_RETRACT
from sat.plugins.plugin_xep_0465 import NS_PPS
from sat.tools.utils import xmpp_date
from sat.tools import xml_tools
from sat.tools.common import uri as xmpp_uri
from sat.plugins.plugin_comp_ap_gateway import TYPE_ACTOR
from sat.memory.sqla_mapping import SubscriptionState
@ -391,6 +393,16 @@ async def mock_getItems(client, service, node, *args, **kwargs):
return ret_items, {"rsm": rsm_resp.toDict(), "complete": True}
async def mock_getPubsubNode(client, service, node, with_subscriptions=False, **kwargs):
"""Mock storage's getPubsubNode
return an MagicMock with subscription attribute set to empty list
"""
fake_cached_node = MagicMock()
fake_cached_node.subscriptions = []
return fake_cached_node
def getVirtualClient(jid):
client = MagicMock()
client.jid = jid
@ -415,6 +427,7 @@ def ap_gateway(host):
gateway.local_only = True
gateway.public_url = PUBLIC_URL
gateway.ap_path = '_ap'
gateway.auto_mentions = True
gateway.base_ap_url = parse.urljoin(
f"https://{gateway.public_url}",
f"{gateway.ap_path}/"
@ -1142,3 +1155,198 @@ class TestActivityPubGateway:
# only the first nickname should be used
assert actor_data["name"] == "nick1"
assert actor_data["summary"] == "test description"
@ed
async def test_direct_addressing_mention_to_reference(self, ap_gateway, monkeypatch):
"""AP mentions by direct addressing are converted to XEP-0372 references"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get)
xmpp_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost())
direct_addr_mention = {
'attributedTo': TEST_AP_ACTOR_ID,
'cc': [],
'content': '<p>test mention by direct addressing</p>',
'id': f'{TEST_AP_ACTOR_ID}/statuses/direct_addr_123',
'published': '2022-05-20T08:14:39Z',
'to': [ap_const.NS_AP_PUBLIC, xmpp_actor_id],
'type': 'Note'
}
client = ap_gateway.client.getVirtualClient(
ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT)
)
monkeypatch.setattr(client, "sendMessage", MagicMock())
with patch.object(ap_gateway._refs, "sendReference") as sendReference:
await ap_gateway.newAPItem(
client, None, ap_gateway._m.namespace, direct_addr_mention
)
assert sendReference.call_count == 1
assert sendReference.call_args.kwargs["to_jid"] == TEST_JID
local_actor_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT)
expected_anchor = xmpp_uri.buildXMPPUri(
"pubsub",
path=local_actor_jid.full(),
node=ap_gateway._m.namespace,
item=direct_addr_mention["id"]
)
assert sendReference.call_args.kwargs["anchor"] == expected_anchor
@ed
async def test_tag_mention_to_reference(self, ap_gateway, monkeypatch):
"""AP mentions in "tag" field are converted to XEP-0372 references"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get)
xmpp_actor_id = ap_gateway.buildAPURL(ap_const.TYPE_ACTOR, TEST_JID.userhost())
direct_addr_mention = {
'attributedTo': TEST_AP_ACTOR_ID,
'cc': [],
'content': '<p>test mention by tag</p>',
'id': f'{TEST_AP_ACTOR_ID}/statuses/tag_123',
'published': '2022-05-20T08:14:39Z',
'to': [ap_const.NS_AP_PUBLIC],
"tag": [
{
"type": "Mention",
"href": xmpp_actor_id,
"name": f"@{TEST_JID}'"
}
],
'type': 'Note'
}
client = ap_gateway.client.getVirtualClient(
ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT)
)
monkeypatch.setattr(client, "sendMessage", MagicMock())
with patch.object(ap_gateway._refs, "sendReference") as sendReference:
await ap_gateway.newAPItem(
client, None, ap_gateway._m.namespace, direct_addr_mention
)
assert sendReference.call_count == 1
assert sendReference.call_args.kwargs["to_jid"] == TEST_JID
local_actor_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT)
expected_anchor = xmpp_uri.buildXMPPUri(
"pubsub",
path=local_actor_jid.full(),
node=ap_gateway._m.namespace,
item=direct_addr_mention["id"]
)
assert sendReference.call_args.kwargs["anchor"] == expected_anchor
@ed
async def test_auto_mentions(self, ap_gateway, monkeypatch):
"""Check that mentions in body are converted to AP mentions"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get)
mb_data = {
"author_jid": TEST_JID.full(),
"content": f"mention of @{TEST_AP_ACCOUNT}",
"service": TEST_JID.full(),
"node": ap_gateway._m.namespace
}
ap_item = await ap_gateway.mbdata2APitem(ap_gateway.client, mb_data, public=True)
ap_object = ap_item["object"]
assert TEST_AP_ACTOR_ID in ap_object["to"]
expected_mention = {
"type": ap_const.TYPE_MENTION,
"href": TEST_AP_ACTOR_ID,
"name": f"@{TEST_AP_ACCOUNT}"
}
assert expected_mention in ap_object["tag"]
@ed
async def test_no_auto_mentions_when_not_public(self, ap_gateway, monkeypatch):
"""Check that no mention is send when the message is not public"""
# this is the same test as test_auto_mentions above, except that public is not set
# in mbdata2APitem
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get)
mb_data = {
"author_jid": TEST_JID.full(),
"content": f"mention of @{TEST_AP_ACCOUNT}",
"service": TEST_JID.full(),
"node": ap_gateway._m.namespace
}
ap_item = await ap_gateway.mbdata2APitem(ap_gateway.client, mb_data, public=False)
ap_object = ap_item["object"]
assert "to" not in ap_object
assert "tag" not in ap_object
@ed
async def test_xmpp_reference_to_ap_mention(self, ap_gateway, monkeypatch):
"""Check that XEP-0372 references are converted to AP mention"""
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "get", mock_ap_get)
monkeypatch.setattr(plugin_comp_ap_gateway.treq, "json_content", mock_treq_json)
monkeypatch.setattr(ap_gateway, "apGet", mock_ap_get)
local_actor_jid = ap_gateway.getLocalJIDFromAccount(TEST_AP_ACCOUNT)
item_elt = XMPP_ITEMS[0]
anchor = xmpp_uri.buildXMPPUri(
"pubsub",
path=TEST_JID.full(),
node=ap_gateway._m.namespace,
item=item_elt["id"]
)
ref_data: Dict[str, Union[str, int, dict]] = {
"uri": xmpp_uri.buildXMPPUri(None, path=local_actor_jid.full()),
"type_": "mention",
"anchor": anchor
}
reference_elt = ap_gateway._refs.buildRefElement(**ref_data)
# we now update ref_data to look like what is received in the trigger
ref_data["parsed_uri"] = xmpp_uri.parseXMPPUri(ref_data["uri"])
ref_data["parsed_anchor"] = xmpp_uri.parseXMPPUri(ref_data["anchor"])
# "type" is a builtin function, thus "type_" is used in buildRefElement, but in
# ref_data is "type" without underscore
ref_data["type"] = ref_data["type_"]
del ref_data["type_"]
message_elt = domish.Element((None, "message"))
message_elt.addChild(reference_elt)
with patch.object(ap_gateway.host.memory.storage, "getItems") as getItems:
# getItems returns a sqla_mapping.PubsubItem, thus we need to fake it and set
# the item_elt we want to use in its "data" attribute
mock_pubsub_item = MagicMock
mock_pubsub_item.data = item_elt
getItems.return_value = ([mock_pubsub_item], {})
with patch.object(ap_gateway, "signAndPost") as signAndPost:
signAndPost.return_value.code = 202
await ap_gateway._onReferenceReceived(ap_gateway.client, message_elt, ref_data)
# when reference is received, the referencing item must be sent to referenced
# actor, and they must be in "to" field and in "tag"
assert signAndPost.call_count == 1
send_ap_item = signAndPost.call_args.args[-1]
ap_object = send_ap_item["object"]
assert TEST_AP_ACTOR_ID in ap_object["to"]
expected_mention = {
"type": ap_const.TYPE_MENTION,
"href": TEST_AP_ACTOR_ID,
# we don't have a prefixing "@" here, because it's not needed in referencing
# item with XMPP
"name": f"{TEST_AP_ACCOUNT}"
}
assert expected_mention in ap_object["tag"]