Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2023-10-17 16:41:31 +02:00
parent 0613f7f736
commit b5672cee7e
108 changed files with 5221 additions and 1318 deletions

View File

@@ -0,0 +1,107 @@
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CreateTest do
use Mobilizon.DataCase
import Mobilizon.Factory
import Mox
alias Mobilizon.Actors.Actor
alias Mobilizon.Conversations.Conversation
alias Mobilizon.Discussions.Comment
alias Mobilizon.Federation.ActivityPub.Transmogrifier
alias Mobilizon.Service.HTTP.ActivityPub.Mock
describe "Receive Create Notes" do
test "it creates conversations for received comments in reply to events" do
actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
Mock
|> expect(:call, 2, fn
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/admin")
|> Map.put("preferredUsername", "admin")
}}
%{method: :get, url: "https://framapiaf.org/users/tcit"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/tcit")
|> Map.put("preferredUsername", "tcit")
}}
end)
data = File.read!("test/fixtures/mastodon-post-activity-private.json") |> Jason.decode!()
event = insert(:event)
object = data["object"]
object = Map.put(object, "inReplyTo", event.url)
data = Map.put(data, "object", object)
{:ok, _activity,
%Conversation{
origin_comment: %Comment{visibility: :private, id: origin_comment_id},
last_comment: %Comment{visibility: :private, id: last_comment_id},
participants: participants,
event: matched_event
}} = Transmogrifier.handle_incoming(data)
assert origin_comment_id == last_comment_id
assert event.id == matched_event.id
participant_ids = participants |> Enum.map(& &1.id) |> MapSet.new()
{:ok, tcit} = Mobilizon.Actors.get_actor_by_url("https://framapiaf.org/users/tcit")
{:ok, admin} = Mobilizon.Actors.get_actor_by_url("https://framapiaf.org/users/admin")
assert participant_ids == MapSet.new([event.organizer_actor_id, tcit.id, admin.id])
end
test "it creates conversations for received comments if we're concerned" do
actor_data = File.read!("test/fixtures/mastodon-actor.json") |> Jason.decode!()
Mock
|> expect(:call, 1, fn
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
{:ok,
%Tesla.Env{
status: 200,
body:
actor_data
|> Map.put("id", "https://framapiaf.org/users/admin")
|> Map.put("preferredUsername", "admin")
}}
end)
actor = insert(:actor)
data = File.read!("test/fixtures/mastodon-post-activity-private.json") |> Jason.decode!()
data = Map.put(data, "to", [actor.url])
object =
data["object"]
|> Map.put("to", [actor.url])
|> Map.put("tag", [
data["object"]["tag"]
|> hd()
|> Map.put("href", actor.url)
|> Map.put("name", Actor.preferred_username_and_domain(actor))
])
data = Map.put(data, "object", object)
{:ok, _activity,
%Conversation{
origin_comment: %Comment{visibility: :private, id: origin_comment_id},
last_comment: %Comment{visibility: :private, id: last_comment_id},
participants: participants,
event: nil
}} = Transmogrifier.handle_incoming(data)
assert origin_comment_id == last_comment_id
participant_ids = participants |> Enum.map(& &1.id) |> MapSet.new()
{:ok, admin} = Mobilizon.Actors.get_actor_by_url("https://framapiaf.org/users/admin")
assert participant_ids == MapSet.new([actor.id, admin.id])
end
end
end

View File

@@ -0,0 +1,78 @@
defmodule Mobilizon.GraphQL.Resolvers.ConversationTest do
use Mobilizon.Web.ConnCase
alias Mobilizon.Actors
alias Mobilizon.Actors.Actor
alias Mobilizon.GraphQL.AbsintheHelpers
import Mobilizon.Factory
setup %{conn: conn} do
user = insert(:user)
actor = insert(:actor, user: user, preferred_username: "test")
{:ok, conn: conn, user: user, actor: actor}
end
@event_conversations_query """
query Event($uuid: UUID!) {
event(uuid: $uuid) {
id
uuid
conversations {
total
elements {
id
lastComment {
id
text
}
comments {
total
elements {
id
text
}
}
actor {
id
preferredUsername
}
}
}
}
}
"""
describe "Find conversations for event" do
test "for a given event", %{conn: conn, user: user, actor: actor} do
event = insert(:event, organizer_actor: actor)
conversation = insert(:conversation, event: event)
another_comment = build(:comment, origin_comment: conversation.origin_comment)
conversation_participant =
insert(:conversation_participant, actor: actor, conversation: conversation)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @event_conversations_query,
variables: %{uuid: conversation.event.uuid}
)
assert res["errors"] == nil
assert res["data"]["event"]["uuid"] == to_string(conversation.event.uuid)
assert res["data"]["event"]["conversations"]["total"] == 1
conversation_data = hd(res["data"]["event"]["conversations"]["elements"])
assert conversation_data["id"] == to_string(conversation.id)
assert conversation_data["lastComment"]["text"] == conversation.last_comment.text
assert conversation_data["comments"]["total"] == 2
assert conversation_data["comments"]["elements"]
|> Enum.any?(fn comment -> comment.text == conversation.origin_comment.text end)
assert conversation_data["actor"]["preferredUsername"] ==
conversation_participant.actor.preferred_username
end
end
end

View File

@@ -0,0 +1,86 @@
defmodule Mobilizon.DiscussionsTest do
use Mobilizon.DataCase
import Mobilizon.Factory
alias Mobilizon.Conversations
alias Mobilizon.Conversations.{Conversation, ConversationParticipant}
describe "create_conversation/1" do
@conversation_attrs %{
text: "A conversation comment",
published_at: NaiveDateTime.utc_now()
}
test "creates a conversation" do
actor = insert(:actor)
actor_participant1 = insert(:actor)
actor_participant2 = insert(:actor)
participants = [actor, actor_participant1, actor_participant2]
assert {:ok, %Conversation{} = conversation} =
Conversations.create_conversation(
Map.merge(@conversation_attrs, %{
actor_id: actor.id,
participants: participants
})
)
participants =
Conversations.list_conversation_participants_for_conversation(conversation.id)
assert length(participants) == 3
assert %ConversationParticipant{unread: false} =
Enum.find(participants, &(&1.actor_id == actor.id))
assert %ConversationParticipant{unread: true} =
Enum.find(participants, &(&1.actor_id == actor_participant1.id))
assert %ConversationParticipant{unread: true} =
Enum.find(participants, &(&1.actor_id == actor_participant2.id))
end
end
describe "reply_to_conversation/2" do
@conversation_attrs %{
text: "A conversation reply",
published_at: NaiveDateTime.utc_now()
}
test "creates a reply" do
conversation = insert(:conversation)
actor = insert(:actor)
actor_participant1 = insert(:actor)
actor_participant2 = insert(:actor)
insert(:conversation_participant, conversation: conversation, actor: actor)
insert(:conversation_participant, conversation: conversation, actor: actor_participant1)
insert(:conversation_participant, conversation: conversation, actor: actor_participant2)
participants = [actor, actor_participant1, actor_participant2]
assert {:ok, %Conversation{} = conversation} =
Conversations.reply_to_conversation(
conversation,
Map.merge(@conversation_attrs, %{
actor_id: actor.id,
participants: participants
})
)
participants =
Conversations.list_conversation_participants_for_conversation(conversation.id)
assert length(participants) == 3
assert %ConversationParticipant{unread: false} =
Enum.find(participants, &(&1.actor_id == actor.id))
assert %ConversationParticipant{unread: true} =
Enum.find(participants, &(&1.actor_id == actor_participant1.id))
assert %ConversationParticipant{unread: true} =
Enum.find(participants, &(&1.actor_id == actor_participant2.id))
end
end
end

View File

@@ -0,0 +1,70 @@
defmodule Mobilizon.Service.Activity.ConversationTest do
@moduledoc """
Test the Comment activity provider module
"""
alias Mobilizon.Actors.Actor
alias Mobilizon.Conversations
alias Mobilizon.Conversations.Conversation
alias Mobilizon.Discussions.Comment
alias Mobilizon.Service.Activity.Conversation, as: ConversationActivity
alias Mobilizon.Service.Workers.LegacyNotifierBuilder
alias Mobilizon.Users.User
use Mobilizon.DataCase
use Oban.Testing, repo: Mobilizon.Storage.Repo
import Mobilizon.Factory
describe "handle conversation" do
test "with participants" do
%User{} = user = insert(:user)
%Actor{id: actor_id} = actor = insert(:actor, user: user)
%Conversation{id: conversation_id, last_comment: %Comment{actor_id: last_comment_actor_id}} =
conversation = insert(:conversation)
insert(:conversation_participant, actor: actor, conversation: conversation)
insert(:conversation_participant, conversation: conversation)
conversation = Conversations.get_conversation(conversation_id)
assert {:ok, _} =
ConversationActivity.insert_activity(conversation, subject: "conversation_created")
assert_enqueued(
worker: LegacyNotifierBuilder,
args: %{
"author_id" => last_comment_actor_id,
"participants" => [actor_id],
"object_id" => to_string(conversation_id),
"object_type" => "conversation",
"op" => "legacy_notify",
"subject" => "conversation_created",
"subject_params" => %{
"conversation_id" => conversation_id
},
"type" => "conversation"
}
)
assert_enqueued(
worker: LegacyNotifierBuilder,
args: %{
"author_id" => author_id,
"object_id" => to_string(comment_id),
"object_type" => "comment",
"op" => "legacy_notify",
"subject" => "event_new_comment",
"subject_params" => %{
"comment_reply_to_uuid" => nil,
"event_title" => event_title,
"event_uuid" => event_uuid,
"comment_reply_to" => false,
"comment_uuid" => comment_uuid
},
"type" => "comment"
}
)
end
end
end

View File

@@ -536,4 +536,20 @@ defmodule Mobilizon.Factory do
application: build(:auth_application)
}
end
def conversation_factory do
%Mobilizon.Conversations.Conversation{
event: build(:event),
origin_comment: build(:comment),
last_comment: build(:comment)
}
end
def conversation_participant_factory do
%Mobilizon.Conversations.ConversationParticipant{
conversation: build(:conversation),
actor: build(:actor),
unread: true
}
end
end