Begin reimplementing compose

This commit is contained in:
2026-03-12 00:12:57 +00:00
parent 1570f79b62
commit 79766d279d
56 changed files with 2726 additions and 6271 deletions

View File

@@ -219,12 +219,24 @@ class ComposeReactTests(TestCase):
)
mocked_send_reaction.assert_not_awaited()
def test_compose_page_renders_reaction_actions_for_signal(self):
person, _, _ = self._build_message(
def test_compose_page_hides_reaction_actions_for_signal_but_keeps_reaction_chips(
self,
):
person, _, message = self._build_message(
service="signal",
identifier="+15551230000",
source_message_id="1771234567000",
)
message.receipt_payload = {
"reactions": [
{
"emoji": "👍",
"actor": "remote:signal",
"source_service": "signal",
}
]
}
message.save(update_fields=["receipt_payload"])
response = self.client.get(
reverse("compose_page"),
{
@@ -235,8 +247,10 @@ class ComposeReactTests(TestCase):
)
self.assertEqual(200, response.status_code)
content = response.content.decode("utf-8")
self.assertIn("data-react-url=", content)
self.assertIn("compose-reaction-actions", content)
self.assertNotIn("data-react-url=", content)
self.assertNotIn("compose-reaction-actions", content)
self.assertIn("compose-reaction-chip", content)
self.assertIn("👍", content)
def test_compose_page_hides_reaction_actions_for_unsupported_service(self):
person, _, _ = self._build_message(
@@ -253,7 +267,9 @@ class ComposeReactTests(TestCase):
},
)
self.assertEqual(200, response.status_code)
content = response.content.decode("utf-8")
self.assertNotIn("data-react-url=", content)
self.assertNotIn(
'class="compose-reaction-actions"',
response.content.decode("utf-8"),
content,
)

View File

@@ -65,3 +65,70 @@ class ComposeSendCapabilityTests(TestCase):
self.assertEqual(200, response.status_code)
self.assertContains(response, "<title>Compose Page · GIA</title>", html=False)
def test_compose_page_uses_external_compose_assets(self):
response = self.client.get(
reverse("compose_page"),
{
"service": "signal",
"identifier": "+15551230000",
},
)
self.assertEqual(200, response.status_code)
content = response.content.decode("utf-8")
self.assertIn("compose-panel.css", content)
self.assertIn("compose-panel.js", content)
self.assertNotIn("const initialTyping = JSON.parse(", content)
self.assertNotIn("data-drafts-url=", content)
self.assertNotIn("data-summary-url=", content)
self.assertNotIn("data-quick-insights-url=", content)
self.assertNotIn("data-toggle-command-url=", content)
self.assertNotIn("data-engage-preview-url=", content)
self.assertNotIn("data-engage-send-url=", content)
self.assertNotIn("compose-ticks", content)
self.assertNotIn("compose-receipt-modal", content)
@patch("core.views.compose._recent_manual_contacts")
def test_compose_contact_options_use_compact_service_map(self, mocked_recent_contacts):
mocked_recent_contacts.return_value = [
{
"person_name": "Compact Contact",
"service": "whatsapp",
"identifier": "447777695114",
"person_id": "53707cb8-5680-450f-94e2-a515f455c01e",
"service_identifiers_json": '{"whatsapp":"447777695114"}',
"is_active": True,
}
]
response = self.client.get(
reverse("compose_page"),
{
"service": "whatsapp",
"identifier": "447777695114",
},
)
self.assertEqual(200, response.status_code)
content = response.content.decode("utf-8")
self.assertIn("data-service-map=", content)
self.assertNotIn("data-signal-identifier=", content)
self.assertNotIn("data-whatsapp-page-url=", content)
self.assertNotIn("data-signal-widget-url=", content)
def test_compose_thread_payload_omits_removed_availability_payload(self):
response = self.client.get(
reverse("compose_thread"),
{
"service": "signal",
"identifier": "+15551230000",
},
)
self.assertEqual(200, response.status_code)
payload = response.json()
self.assertIn("messages", payload)
self.assertIn("typing", payload)
self.assertNotIn("availability_slices", payload)
self.assertNotIn("availability_summary", payload)

View File

@@ -1,5 +1,7 @@
from __future__ import annotations
import json
from django.test import TestCase
from unittest.mock import patch
@@ -11,6 +13,7 @@ from core.views.compose import (
_compose_availability_payload,
_context_base,
_manual_contact_rows,
_recent_manual_contacts,
)
@@ -75,6 +78,55 @@ class PresenceQueryAndComposeContextTests(TestCase):
self.assertIsNotNone(base["person_identifier"])
self.assertEqual(str(self.person.id), str(base["person"].id))
@patch("core.views.compose._manual_contact_rows")
def test_recent_manual_contacts_keeps_current_person_name_for_signal_alias(
self, mocked_manual_contact_rows
):
current_identifier = "d3198cce-f003-4290-a016-eaaa1a11c392"
PersonIdentifier.objects.create(
user=self.user,
person=self.person,
service="signal",
identifier=current_identifier,
)
mocked_manual_contact_rows.return_value = [
{
"person_name": self.person.name,
"linked_person_name": self.person.name,
"person_id": str(self.person.id),
"detected_name": "",
"service": "signal",
"service_icon_class": "fa-solid fa-signal",
"identifier": "+15551234567",
"compose_url": "/compose/page/?service=signal&identifier=%2B15551234567",
"compose_widget_url": "/compose/widget/?service=signal&identifier=%2B15551234567",
"linked_person": True,
"source": "linked",
}
]
rows = _recent_manual_contacts(
self.user,
current_service="signal",
current_identifier=current_identifier,
current_person=self.person,
limit=12,
)
self.assertGreaterEqual(len(rows), 1)
self.assertEqual(self.person.name, rows[0]["person_name"])
self.assertEqual(str(self.person.id), rows[0]["person_id"])
self.assertEqual(current_identifier, rows[0]["identifier"])
self.assertEqual(
{"signal": current_identifier},
rows[0]["service_identifiers"],
)
self.assertEqual(
{"signal": current_identifier},
json.loads(rows[0]["service_identifiers_json"]),
)
self.assertTrue(bool(rows[0]["is_active"]))
@patch("core.presence.query.get_behavioral_latest_states")
@patch("core.presence.query.get_behavioral_events_for_range")
def test_compose_availability_payload_falls_back_to_cross_service(
@@ -344,3 +396,40 @@ class PresenceQueryAndComposeContextTests(TestCase):
["sEGA9F0HQ/eyLgmvKx23hha9Vp7mDRhpq23/roVSZbI="],
rows[0].get("identifier_aliases"),
)
def test_manual_contact_rows_fill_whatsapp_detected_name_for_linked_jid(self):
transport.update_runtime_state("whatsapp", accounts=[], contacts=[])
whatsapp_person = Person.objects.create(
user=self.user,
name="Mapped Contact",
)
PersonIdentifier.objects.create(
user=self.user,
person=whatsapp_person,
service="whatsapp",
identifier="962799299627@s.whatsapp.net",
)
transport.update_runtime_state(
"whatsapp",
accounts=["155500000000@s.whatsapp.net"],
contacts=[
{
"identifier": "962799299627",
"jid": "962799299627@s.whatsapp.net",
"name": "Detected Contact",
"chat": "",
}
],
)
rows = [
row
for row in _manual_contact_rows(self.user)
if str(row.get("service")) == "whatsapp"
and str(row.get("identifier")) == "962799299627@s.whatsapp.net"
]
self.assertEqual(1, len(rows))
self.assertTrue(bool(rows[0].get("linked_person")))
self.assertEqual("Mapped Contact", str(rows[0].get("linked_person_name") or ""))
self.assertEqual("Detected Contact", str(rows[0].get("detected_name") or ""))