diff options
author | Michael Manfre | 2022-12-05 23:44:26 -0500 |
---|---|---|
committer | GitHub | 2022-12-05 21:44:26 -0700 |
commit | 64cea557bebdb0a5b4f17362d8e66845b0a77113 (patch) | |
tree | 7f5ff24cfa18f3aebf8c8ef91b79465363953be1 | |
parent | 5b82c76defd8016df137087e5ce55b44cf017399 (diff) | |
download | takahe-64cea557bebdb0a5b4f17362d8e66845b0a77113.tar.gz takahe-64cea557bebdb0a5b4f17362d8e66845b0a77113.tar.bz2 takahe-64cea557bebdb0a5b4f17362d8e66845b0a77113.zip |
Collapse linkify mentions (#123)
-rw-r--r-- | activities/models/post.py | 6 | ||||
-rw-r--r-- | tests/activities/models/test_post.py | 35 | ||||
-rw-r--r-- | tests/conftest.py | 40 |
3 files changed, 75 insertions, 6 deletions
diff --git a/activities/models/post.py b/activities/models/post.py index daf61e8..55d2f65 100644 --- a/activities/models/post.py +++ b/activities/models/post.py @@ -276,6 +276,8 @@ class Post(StatorModel): possible_matches[mention.username] = url possible_matches[f"{mention.username}@{mention.domain_id}"] = url + collapse_name: dict[str, str] = {} + def replacer(match): precursor = match.group(1) handle = match.group(2).lower() @@ -284,6 +286,10 @@ class Post(StatorModel): else: short_handle = handle if handle in possible_matches: + if short_handle not in collapse_name: + collapse_name[short_handle] = handle + elif collapse_name.get(short_handle) != handle: + short_handle = handle return f'{precursor}<a href="{possible_matches[handle]}">@{short_handle}</a>' else: return match.group() diff --git a/tests/activities/models/test_post.py b/tests/activities/models/test_post.py index 06d26ed..a5f2f79 100644 --- a/tests/activities/models/test_post.py +++ b/tests/activities/models/test_post.py @@ -32,7 +32,9 @@ def test_fetch_post(httpx_mock: HTTPXMock, config_system): @pytest.mark.django_db -def test_linkify_mentions_remote(identity, remote_identity): +def test_linkify_mentions_remote( + identity, identity2, remote_identity, remote_identity2 +): """ Tests that we can linkify post mentions properly for remote use """ @@ -77,9 +79,28 @@ def test_linkify_mentions_remote(identity, remote_identity): == '<p>Hey <a href="https://remote.test/@test/">@test</a></p>' ) + # Test that collapsing only applies to the first unique, short username + post = Post.objects.create( + content="<p>Hey @TeSt@remote.test and @test@remote2.test</p>", + author=identity, + local=True, + ) + post.mentions.set([remote_identity, remote_identity2]) + assert post.safe_content_remote() == ( + '<p>Hey <a href="https://remote.test/@test/">@test</a> ' + 'and <a href="https://remote2.test/@test/">@test@remote2.test</a></p>' + ) + + post.content = "<p>Hey @TeSt, @Test@remote.test and @test</p>" + assert post.safe_content_remote() == ( + '<p>Hey <a href="https://remote2.test/@test/">@test</a>, ' + '<a href="https://remote.test/@test/">@test@remote.test</a> ' + 'and <a href="https://remote2.test/@test/">@test</a></p>' + ) + @pytest.mark.django_db -def test_linkify_mentions_local(identity, remote_identity): +def test_linkify_mentions_local(identity, identity2, remote_identity): """ Tests that we can linkify post mentions properly for local use """ @@ -96,14 +117,16 @@ def test_linkify_mentions_local(identity, remote_identity): ) # Test a full username (local) post = Post.objects.create( - content="<p>@test@example.com, welcome!</p>", + content="<p>@test@example.com, welcome! @test@example2.com @test@example.com</p>", author=identity, local=True, ) post.mentions.add(identity) - assert ( - post.safe_content_local() - == '<p><a href="/@test@example.com/">@test</a>, welcome!</p>' + post.mentions.add(identity2) + assert post.safe_content_local() == ( + '<p><a href="/@test@example.com/">@test</a>, welcome!' + ' <a href="/@test@example2.com/">@test@example2.com</a>' + ' <a href="/@test@example.com/">@test</a></p>' ) # Test a full username (remote) with no <p> post = Post.objects.create( diff --git a/tests/conftest.py b/tests/conftest.py index 80622f0..c67717c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -80,6 +80,12 @@ def domain() -> Domain: @pytest.fixture @pytest.mark.django_db +def domain2() -> Domain: + return Domain.objects.create(domain="example2.com", local=True, public=True) + + +@pytest.fixture +@pytest.mark.django_db def identity(user, domain) -> Identity: """ Creates a basic test identity with a user and domain. @@ -96,6 +102,23 @@ def identity(user, domain) -> Identity: @pytest.fixture +@pytest.mark.django_db +def identity2(user, domain2) -> Identity: + """ + Creates a basic test identity with a user and domain. + """ + identity = Identity.objects.create( + actor_uri="https://example2.com/@test@example2.com/", + username="test", + domain=domain2, + name="Test User Domain2", + local=True, + ) + identity.users.set([user]) + return identity + + +@pytest.fixture def other_identity(user, domain) -> Identity: """ Creates a different basic test identity with a user and domain. @@ -129,6 +152,23 @@ def remote_identity() -> Identity: @pytest.fixture +@pytest.mark.django_db +def remote_identity2() -> Identity: + """ + Creates a basic remote test identity with a domain. + """ + domain = Domain.objects.create(domain="remote2.test", local=False) + return Identity.objects.create( + actor_uri="https://remote2.test/test-actor/", + profile_uri="https://remote2.test/@test/", + username="test", + domain=domain, + name="Test2 Remote User", + local=False, + ) + + +@pytest.fixture def stator(config_system) -> StatorRunner: """ Return an initialized StatorRunner for tests that need state transitioning |