Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support testing direct messages (via @mention) in Mastodon #354

Merged
merged 17 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions src/feditest/nodedrivers/mastodon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import sys
import time
from typing import Any, Callable, cast
from urllib.parse import urlparse

from feditest import AssertionFailure, InteropLevel, SpecLevel
from feditest.protocols import (
Expand Down Expand Up @@ -306,11 +305,10 @@ def make_create_note(self, actor_uri: str, content: str, deliver_to: list[str] |
trace('make_create_note:')
mastodon_client = self._get_mastodon_client_by_actor_uri(actor_uri)

if deliver_to:
if deliver_to: # The only way we can address specific accounts in Mastodon
for to in deliver_to:
if to_account := self._get_account_dict_by_other_actor_uri(mastodon_client, to):
to_url = urlparse(to_account.uri)
to_handle = f"@{to_account.acct}@{to_url.netloc}"
to_handle = f"@{to_account.acct}"
content += f" {to_handle}"
else:
raise ValueError(f'Cannot find account for Actor { to }')
Expand Down Expand Up @@ -382,17 +380,31 @@ def make_follow_undo(self, actor_uri: str, follower_actor_uri: str) -> None:


# Python 3.12 @override
def wait_until_actor_has_received_note(self, actor_uri: str, object_uri: str, max_wait: float = 5.) -> None:
def wait_until_actor_has_received_note(self, actor_uri: str, object_uri: str, max_wait: float = 5.) -> str:
trace('wait_until_actor_has_received_note:')
mastodon_client = self._get_mastodon_client_by_actor_uri(actor_uri)

def find_note():
"""
Depending on how the Note is addressed and follow status, Mastodon puts it into the Home timeline or only
into notifications.
"""
elements = mastodon_client.timeline_home(local=True, remote=True)
ret = find_first_in_array( elements, lambda s: s.uri == object_uri)
if not ret:
elements = mastodon_client.notifications()
parent_ret = find_first_in_array( elements, lambda s: s.status.uri == object_uri)
ret = parent_ret.status if parent_ret else None
return ret

response = self._poll_until_result( # may throw
lambda: any( s.uri == object_uri for s in mastodon_client.timeline_home(local=True, remote=True)),
find_note,
int(max_wait),
1.0,
f'Expected object { object_uri } has not arrived in inbox of actor { actor_uri }'
)
trace(f'wait_for_object_in_inbox returns with { response }')
return response.content


# Python 3.12 @override
Expand Down Expand Up @@ -424,7 +436,6 @@ def wait_until_actor_is_followed_by_actor(self, actor_uri: str, to_be_following_
return
raise ValueError(f'Account not found with Actor URI: { to_be_following_uri }')


# From ActivityPubNode

# Python 3.12 @override
Expand Down
3 changes: 2 additions & 1 deletion src/feditest/protocols/fediverse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,13 @@ def make_follow_undo(self, actor_uri: str, follower_actor_uri: str) -> None:
raise NotImplementedByNodeError(self, FediverseNode.make_follow_undo)


def wait_until_actor_has_received_note(self, actor_uri: str, object_uri: str, max_wait: float = 5.) -> None:
def wait_until_actor_has_received_note(self, actor_uri: str, object_uri: str, max_wait: float = 5.) -> str:
"""
Wait until the object at object_uri has arrived with the Actor at actor_uri.
This method does not state that the object needs to have arrived in the Actor's, inbox,
as Nodes might implement different routing strategies (including antispam).
If the condition has not arrived by the time max_wait seconds have passed, throw
Return value: the content of the Note
a TimeoutException.
"""
raise NotImplementedByNodeError(self, FediverseNode.wait_until_actor_has_received_note)
Expand Down
2 changes: 1 addition & 1 deletion src/feditest/testrun.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def run(self, test_instance: object, controller: feditest.testruncontroller.Test
info(f'Started step { self.str_in_session() }')

try:
self.test_step.test_step_function(test_instance) # what an object-oriented language this is
self.test_step.test_step_function(test_instance)

except Exception as e:
self.exception = e
Expand Down
Loading