diff --git a/tests/rest/client/test_relations.py b/tests/rest/client/test_relations.py
index c8db45719e..a087cd7b21 100644
--- a/tests/rest/client/test_relations.py
+++ b/tests/rest/client/test_relations.py
@@ -34,7 +34,7 @@ from tests.test_utils import make_awaitable
from tests.test_utils.event_injection import inject_event
-class RelationsTestCase(unittest.HomeserverTestCase):
+class BaseRelationsTestCase(unittest.HomeserverTestCase):
servlets = [
relations.register_servlets,
room.register_servlets,
@@ -48,7 +48,6 @@ class RelationsTestCase(unittest.HomeserverTestCase):
def default_config(self) -> dict:
# We need to enable msc1849 support for aggregations
config = super().default_config()
- config["experimental_msc1849_support_enabled"] = True
# We enable frozen dicts as relations/edits change event contents, so we
# want to test that we don't modify the events in the caches.
@@ -67,10 +66,62 @@ class RelationsTestCase(unittest.HomeserverTestCase):
res = self.helper.send(self.room, body="Hi!", tok=self.user_token)
self.parent_id = res["event_id"]
- def test_send_relation(self) -> None:
- """Tests that sending a relation using the new /send_relation works
- creates the right shape of event.
+ def _create_user(self, localpart: str) -> Tuple[str, str]:
+ user_id = self.register_user(localpart, "abc123")
+ access_token = self.login(localpart, "abc123")
+
+ return user_id, access_token
+
+ def _send_relation(
+ self,
+ relation_type: str,
+ event_type: str,
+ key: Optional[str] = None,
+ content: Optional[dict] = None,
+ access_token: Optional[str] = None,
+ parent_id: Optional[str] = None,
+ ) -> FakeChannel:
+ """Helper function to send a relation pointing at `self.parent_id`
+
+ Args:
+ relation_type: One of `RelationTypes`
+ event_type: The type of the event to create
+ key: The aggregation key used for m.annotation relation type.
+ content: The content of the created event. Will be modified to configure
+ the m.relates_to key based on the other provided parameters.
+ access_token: The access token used to send the relation, defaults
+ to `self.user_token`
+ parent_id: The event_id this relation relates to. If None, then self.parent_id
+
+ Returns:
+ FakeChannel
"""
+ if not access_token:
+ access_token = self.user_token
+
+ original_id = parent_id if parent_id else self.parent_id
+
+ if content is None:
+ content = {}
+ content["m.relates_to"] = {
+ "event_id": original_id,
+ "rel_type": relation_type,
+ }
+ if key is not None:
+ content["m.relates_to"]["key"] = key
+
+ channel = self.make_request(
+ "POST",
+ f"/_matrix/client/v3/rooms/{self.room}/send/{event_type}",
+ content,
+ access_token=access_token,
+ )
+ return channel
+
+
+class RelationsTestCase(BaseRelationsTestCase):
+ def test_send_relation(self) -> None:
+ """Tests that sending a relation works."""
channel = self._send_relation(RelationTypes.ANNOTATION, "m.reaction", key="👍")
self.assertEqual(200, channel.code, channel.json_body)
@@ -79,7 +130,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
channel = self.make_request(
"GET",
- "/rooms/%s/event/%s" % (self.room, event_id),
+ f"/rooms/{self.room}/event/{event_id}",
access_token=self.user_token,
)
self.assertEqual(200, channel.code, channel.json_body)
@@ -317,9 +368,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
# Request /sync, limiting it such that only the latest event is returned
# (and not the relation).
- filter = urllib.parse.quote_plus(
- '{"room": {"timeline": {"limit": 1}}}'.encode()
- )
+ filter = urllib.parse.quote_plus(b'{"room": {"timeline": {"limit": 1}}}')
channel = self.make_request(
"GET", f"/sync?filter={filter}", access_token=self.user_token
)
@@ -404,8 +453,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
channel = self.make_request(
"GET",
- "/_matrix/client/unstable/rooms/%s/aggregations/%s?limit=1%s"
- % (self.room, self.parent_id, from_token),
+ f"/_matrix/client/unstable/rooms/{self.room}/aggregations/{self.parent_id}?limit=1{from_token}",
access_token=self.user_token,
)
self.assertEqual(200, channel.code, channel.json_body)
@@ -544,8 +592,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
channel = self.make_request(
"GET",
- "/_matrix/client/unstable/rooms/%s/aggregations/%s"
- % (self.room, self.parent_id),
+ f"/_matrix/client/unstable/rooms/{self.room}/aggregations/{self.parent_id}",
access_token=self.user_token,
)
self.assertEqual(200, channel.code, channel.json_body)
@@ -560,47 +607,13 @@ class RelationsTestCase(unittest.HomeserverTestCase):
},
)
- def test_aggregation_redactions(self) -> None:
- """Test that annotations get correctly aggregated after a redaction."""
-
- channel = self._send_relation(RelationTypes.ANNOTATION, "m.reaction", "a")
- self.assertEqual(200, channel.code, channel.json_body)
- to_redact_event_id = channel.json_body["event_id"]
-
- channel = self._send_relation(
- RelationTypes.ANNOTATION, "m.reaction", "a", access_token=self.user2_token
- )
- self.assertEqual(200, channel.code, channel.json_body)
-
- # Now lets redact one of the 'a' reactions
- channel = self.make_request(
- "POST",
- "/_matrix/client/r0/rooms/%s/redact/%s" % (self.room, to_redact_event_id),
- access_token=self.user_token,
- content={},
- )
- self.assertEqual(200, channel.code, channel.json_body)
-
- channel = self.make_request(
- "GET",
- "/_matrix/client/unstable/rooms/%s/aggregations/%s"
- % (self.room, self.parent_id),
- access_token=self.user_token,
- )
- self.assertEqual(200, channel.code, channel.json_body)
-
- self.assertEqual(
- channel.json_body,
- {"chunk": [{"type": "m.reaction", "key": "a", "count": 1}]},
- )
-
def test_aggregation_must_be_annotation(self) -> None:
"""Test that aggregations must be annotations."""
channel = self.make_request(
"GET",
- "/_matrix/client/unstable/rooms/%s/aggregations/%s/%s?limit=1"
- % (self.room, self.parent_id, RelationTypes.REPLACE),
+ f"/_matrix/client/unstable/rooms/{self.room}/aggregations"
+ f"/{self.parent_id}/{RelationTypes.REPLACE}?limit=1",
access_token=self.user_token,
)
self.assertEqual(400, channel.code, channel.json_body)
@@ -986,9 +999,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
# Request sync, but limit the timeline so it becomes limited (and includes
# bundled aggregations).
- filter = urllib.parse.quote_plus(
- '{"room": {"timeline": {"limit": 2}}}'.encode()
- )
+ filter = urllib.parse.quote_plus(b'{"room": {"timeline": {"limit": 2}}}')
channel = self.make_request(
"GET", f"/sync?filter={filter}", access_token=self.user_token
)
@@ -1053,7 +1064,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
channel = self.make_request(
"GET",
- "/rooms/%s/event/%s" % (self.room, self.parent_id),
+ f"/rooms/{self.room}/event/{self.parent_id}",
access_token=self.user_token,
)
self.assertEqual(200, channel.code, channel.json_body)
@@ -1096,7 +1107,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
channel = self.make_request(
"GET",
- "/rooms/%s/event/%s" % (self.room, reply),
+ f"/rooms/{self.room}/event/{reply}",
access_token=self.user_token,
)
self.assertEqual(200, channel.code, channel.json_body)
@@ -1198,7 +1209,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
# Request the original event.
channel = self.make_request(
"GET",
- "/rooms/%s/event/%s" % (self.room, self.parent_id),
+ f"/rooms/{self.room}/event/{self.parent_id}",
access_token=self.user_token,
)
self.assertEqual(200, channel.code, channel.json_body)
@@ -1217,102 +1228,6 @@ class RelationsTestCase(unittest.HomeserverTestCase):
{"event_id": edit_event_id, "sender": self.user_id}, m_replace_dict
)
- def test_relations_redaction_redacts_edits(self) -> None:
- """Test that edits of an event are redacted when the original event
- is redacted.
- """
- # Send a new event
- res = self.helper.send(self.room, body="Heyo!", tok=self.user_token)
- original_event_id = res["event_id"]
-
- # Add a relation
- channel = self._send_relation(
- RelationTypes.REPLACE,
- "m.room.message",
- parent_id=original_event_id,
- content={
- "msgtype": "m.text",
- "body": "Wibble",
- "m.new_content": {"msgtype": "m.text", "body": "First edit"},
- },
- )
- self.assertEqual(200, channel.code, channel.json_body)
-
- # Check the relation is returned
- channel = self.make_request(
- "GET",
- "/_matrix/client/unstable/rooms/%s/relations/%s/m.replace/m.room.message"
- % (self.room, original_event_id),
- access_token=self.user_token,
- )
- self.assertEqual(200, channel.code, channel.json_body)
-
- self.assertIn("chunk", channel.json_body)
- self.assertEqual(len(channel.json_body["chunk"]), 1)
-
- # Redact the original event
- channel = self.make_request(
- "PUT",
- "/rooms/%s/redact/%s/%s"
- % (self.room, original_event_id, "test_relations_redaction_redacts_edits"),
- access_token=self.user_token,
- content="{}",
- )
- self.assertEqual(200, channel.code, channel.json_body)
-
- # Try to check for remaining m.replace relations
- channel = self.make_request(
- "GET",
- "/_matrix/client/unstable/rooms/%s/relations/%s/m.replace/m.room.message"
- % (self.room, original_event_id),
- access_token=self.user_token,
- )
- self.assertEqual(200, channel.code, channel.json_body)
-
- # Check that no relations are returned
- self.assertIn("chunk", channel.json_body)
- self.assertEqual(channel.json_body["chunk"], [])
-
- def test_aggregations_redaction_prevents_access_to_aggregations(self) -> None:
- """Test that annotations of an event are redacted when the original event
- is redacted.
- """
- # Send a new event
- res = self.helper.send(self.room, body="Hello!", tok=self.user_token)
- original_event_id = res["event_id"]
-
- # Add a relation
- channel = self._send_relation(
- RelationTypes.ANNOTATION, "m.reaction", key="👍", parent_id=original_event_id
- )
- self.assertEqual(200, channel.code, channel.json_body)
-
- # Redact the original
- channel = self.make_request(
- "PUT",
- "/rooms/%s/redact/%s/%s"
- % (
- self.room,
- original_event_id,
- "test_aggregations_redaction_prevents_access_to_aggregations",
- ),
- access_token=self.user_token,
- content="{}",
- )
- self.assertEqual(200, channel.code, channel.json_body)
-
- # Check that aggregations returns zero
- channel = self.make_request(
- "GET",
- "/_matrix/client/unstable/rooms/%s/aggregations/%s/m.annotation/m.reaction"
- % (self.room, original_event_id),
- access_token=self.user_token,
- )
- self.assertEqual(200, channel.code, channel.json_body)
-
- self.assertIn("chunk", channel.json_body)
- self.assertEqual(channel.json_body["chunk"], [])
-
def test_unknown_relations(self) -> None:
"""Unknown relations should be accepted."""
channel = self._send_relation("m.relation.test", "m.room.test")
@@ -1321,8 +1236,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
channel = self.make_request(
"GET",
- "/_matrix/client/unstable/rooms/%s/relations/%s?limit=1"
- % (self.room, self.parent_id),
+ f"/_matrix/client/unstable/rooms/{self.room}/relations/{self.parent_id}?limit=1",
access_token=self.user_token,
)
self.assertEqual(200, channel.code, channel.json_body)
@@ -1343,7 +1257,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
# When bundling the unknown relation is not included.
channel = self.make_request(
"GET",
- "/rooms/%s/event/%s" % (self.room, self.parent_id),
+ f"/rooms/{self.room}/event/{self.parent_id}",
access_token=self.user_token,
)
self.assertEqual(200, channel.code, channel.json_body)
@@ -1352,8 +1266,7 @@ class RelationsTestCase(unittest.HomeserverTestCase):
# But unknown relations can be directly queried.
channel = self.make_request(
"GET",
- "/_matrix/client/unstable/rooms/%s/aggregations/%s?limit=1"
- % (self.room, self.parent_id),
+ f"/_matrix/client/unstable/rooms/{self.room}/aggregations/{self.parent_id}?limit=1",
access_token=self.user_token,
)
self.assertEqual(200, channel.code, channel.json_body)
@@ -1369,58 +1282,6 @@ class RelationsTestCase(unittest.HomeserverTestCase):
raise AssertionError(f"Event {self.parent_id} not found in chunk")
- def _send_relation(
- self,
- relation_type: str,
- event_type: str,
- key: Optional[str] = None,
- content: Optional[dict] = None,
- access_token: Optional[str] = None,
- parent_id: Optional[str] = None,
- ) -> FakeChannel:
- """Helper function to send a relation pointing at `self.parent_id`
-
- Args:
- relation_type: One of `RelationTypes`
- event_type: The type of the event to create
- key: The aggregation key used for m.annotation relation type.
- content: The content of the created event. Will be modified to configure
- the m.relates_to key based on the other provided parameters.
- access_token: The access token used to send the relation, defaults
- to `self.user_token`
- parent_id: The event_id this relation relates to. If None, then self.parent_id
-
- Returns:
- FakeChannel
- """
- if not access_token:
- access_token = self.user_token
-
- original_id = parent_id if parent_id else self.parent_id
-
- if content is None:
- content = {}
- content["m.relates_to"] = {
- "event_id": original_id,
- "rel_type": relation_type,
- }
- if key is not None:
- content["m.relates_to"]["key"] = key
-
- channel = self.make_request(
- "POST",
- f"/_matrix/client/v3/rooms/{self.room}/send/{event_type}",
- content,
- access_token=access_token,
- )
- return channel
-
- def _create_user(self, localpart: str) -> Tuple[str, str]:
- user_id = self.register_user(localpart, "abc123")
- access_token = self.login(localpart, "abc123")
-
- return user_id, access_token
-
def test_background_update(self) -> None:
"""Test the event_arbitrary_relations background update."""
channel = self._send_relation(RelationTypes.ANNOTATION, "m.reaction", key="👍")
@@ -1482,3 +1343,112 @@ class RelationsTestCase(unittest.HomeserverTestCase):
[ev["event_id"] for ev in channel.json_body["chunk"]],
[annotation_event_id_good, thread_event_id],
)
+
+
+class RelationRedactionTestCase(BaseRelationsTestCase):
+ """Test the behaviour of relations when the parent or child event is redacted."""
+
+ def _redact(self, event_id: str) -> None:
+ channel = self.make_request(
+ "POST",
+ f"/_matrix/client/r0/rooms/{self.room}/redact/{event_id}",
+ access_token=self.user_token,
+ content={},
+ )
+ self.assertEqual(200, channel.code, channel.json_body)
+
+ def test_redact_relation_annotation(self) -> None:
+ """Test that annotations of an event are properly handled after the
+ annotation is redacted.
+ """
+ channel = self._send_relation(RelationTypes.ANNOTATION, "m.reaction", "a")
+ self.assertEqual(200, channel.code, channel.json_body)
+ to_redact_event_id = channel.json_body["event_id"]
+
+ channel = self._send_relation(
+ RelationTypes.ANNOTATION, "m.reaction", "a", access_token=self.user2_token
+ )
+ self.assertEqual(200, channel.code, channel.json_body)
+
+ # Redact one of the reactions.
+ self._redact(to_redact_event_id)
+
+ # Ensure that the aggregations are correct.
+ channel = self.make_request(
+ "GET",
+ f"/_matrix/client/unstable/rooms/{self.room}/aggregations/{self.parent_id}",
+ access_token=self.user_token,
+ )
+ self.assertEqual(200, channel.code, channel.json_body)
+
+ self.assertEqual(
+ channel.json_body,
+ {"chunk": [{"type": "m.reaction", "key": "a", "count": 1}]},
+ )
+
+ def test_redact_relation_edit(self) -> None:
+ """Test that edits of an event are redacted when the original event
+ is redacted.
+ """
+ # Add a relation
+ channel = self._send_relation(
+ RelationTypes.REPLACE,
+ "m.room.message",
+ parent_id=self.parent_id,
+ content={
+ "msgtype": "m.text",
+ "body": "Wibble",
+ "m.new_content": {"msgtype": "m.text", "body": "First edit"},
+ },
+ )
+ self.assertEqual(200, channel.code, channel.json_body)
+
+ # Check the relation is returned
+ channel = self.make_request(
+ "GET",
+ f"/_matrix/client/unstable/rooms/{self.room}/relations"
+ f"/{self.parent_id}/m.replace/m.room.message",
+ access_token=self.user_token,
+ )
+ self.assertEqual(200, channel.code, channel.json_body)
+
+ self.assertIn("chunk", channel.json_body)
+ self.assertEqual(len(channel.json_body["chunk"]), 1)
+
+ # Redact the original event
+ self._redact(self.parent_id)
+
+ # Try to check for remaining m.replace relations
+ channel = self.make_request(
+ "GET",
+ f"/_matrix/client/unstable/rooms/{self.room}/relations"
+ f"/{self.parent_id}/m.replace/m.room.message",
+ access_token=self.user_token,
+ )
+ self.assertEqual(200, channel.code, channel.json_body)
+
+ # Check that no relations are returned
+ self.assertIn("chunk", channel.json_body)
+ self.assertEqual(channel.json_body["chunk"], [])
+
+ def test_redact_parent(self) -> None:
+ """Test that annotations of an event are redacted when the original event
+ is redacted.
+ """
+ # Add a relation
+ channel = self._send_relation(RelationTypes.ANNOTATION, "m.reaction", key="👍")
+ self.assertEqual(200, channel.code, channel.json_body)
+
+ # Redact the original event.
+ self._redact(self.parent_id)
+
+ # Check that aggregations returns zero
+ channel = self.make_request(
+ "GET",
+ f"/_matrix/client/unstable/rooms/{self.room}/aggregations/{self.parent_id}/m.annotation/m.reaction",
+ access_token=self.user_token,
+ )
+ self.assertEqual(200, channel.code, channel.json_body)
+
+ self.assertIn("chunk", channel.json_body)
+ self.assertEqual(channel.json_body["chunk"], [])
|