Merge branch 'conversations_three' into 'develop'
Conversations once more. See merge request pleroma/pleroma!1119
This commit is contained in:
commit
238dd72fad
16 changed files with 710 additions and 34 deletions
89
test/conversation/participation_test.exs
Normal file
89
test/conversation/participation_test.exs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Conversation.ParticipationTest do
|
||||
use Pleroma.DataCase
|
||||
import Pleroma.Factory
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
test "it creates a participation for a conversation and a user" do
|
||||
user = insert(:user)
|
||||
conversation = insert(:conversation)
|
||||
|
||||
{:ok, %Participation{} = participation} =
|
||||
Participation.create_for_user_and_conversation(user, conversation)
|
||||
|
||||
assert participation.user_id == user.id
|
||||
assert participation.conversation_id == conversation.id
|
||||
|
||||
:timer.sleep(1000)
|
||||
# Creating again returns the same participation
|
||||
{:ok, %Participation{} = participation_two} =
|
||||
Participation.create_for_user_and_conversation(user, conversation)
|
||||
|
||||
assert participation.id == participation_two.id
|
||||
refute participation.updated_at == participation_two.updated_at
|
||||
end
|
||||
|
||||
test "recreating an existing participations sets it to unread" do
|
||||
participation = insert(:participation, %{read: true})
|
||||
|
||||
{:ok, participation} =
|
||||
Participation.create_for_user_and_conversation(
|
||||
participation.user,
|
||||
participation.conversation
|
||||
)
|
||||
|
||||
refute participation.read
|
||||
end
|
||||
|
||||
test "it marks a participation as read" do
|
||||
participation = insert(:participation, %{read: false})
|
||||
{:ok, participation} = Participation.mark_as_read(participation)
|
||||
|
||||
assert participation.read
|
||||
end
|
||||
|
||||
test "it marks a participation as unread" do
|
||||
participation = insert(:participation, %{read: true})
|
||||
{:ok, participation} = Participation.mark_as_unread(participation)
|
||||
|
||||
refute participation.read
|
||||
end
|
||||
|
||||
test "gets all the participations for a user, ordered by updated at descending" do
|
||||
user = insert(:user)
|
||||
{:ok, activity_one} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
|
||||
:timer.sleep(1000)
|
||||
{:ok, activity_two} = CommonAPI.post(user, %{"status" => "x", "visibility" => "direct"})
|
||||
:timer.sleep(1000)
|
||||
|
||||
{:ok, activity_three} =
|
||||
CommonAPI.post(user, %{
|
||||
"status" => "x",
|
||||
"visibility" => "direct",
|
||||
"in_reply_to_status_id" => activity_one.id
|
||||
})
|
||||
|
||||
assert [participation_one, participation_two] = Participation.for_user(user)
|
||||
|
||||
object2 = Pleroma.Object.normalize(activity_two)
|
||||
object3 = Pleroma.Object.normalize(activity_three)
|
||||
|
||||
assert participation_one.conversation.ap_id == object3.data["context"]
|
||||
assert participation_two.conversation.ap_id == object2.data["context"]
|
||||
|
||||
# Pagination
|
||||
assert [participation_one] = Participation.for_user(user, %{"limit" => 1})
|
||||
|
||||
assert participation_one.conversation.ap_id == object3.data["context"]
|
||||
|
||||
# With last_activity_id
|
||||
assert [participation_one] =
|
||||
Participation.for_user_with_last_activity_id(user, %{"limit" => 1})
|
||||
|
||||
assert participation_one.last_activity_id == activity_three.id
|
||||
end
|
||||
end
|
||||
137
test/conversation_test.exs
Normal file
137
test/conversation_test.exs
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ConversationTest do
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Conversation
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
test "it creates a conversation for given ap_id" do
|
||||
assert {:ok, %Conversation{} = conversation} =
|
||||
Conversation.create_for_ap_id("https://some_ap_id")
|
||||
|
||||
# Inserting again returns the same
|
||||
assert {:ok, conversation_two} = Conversation.create_for_ap_id("https://some_ap_id")
|
||||
assert conversation_two.id == conversation.id
|
||||
end
|
||||
|
||||
test "public posts don't create conversations" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey"})
|
||||
|
||||
object = Pleroma.Object.normalize(activity)
|
||||
context = object.data["context"]
|
||||
|
||||
conversation = Conversation.get_for_ap_id(context)
|
||||
|
||||
refute conversation
|
||||
end
|
||||
|
||||
test "it creates or updates a conversation and participations for a given DM" do
|
||||
har = insert(:user)
|
||||
jafnhar = insert(:user, local: false)
|
||||
tridi = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(har, %{"status" => "Hey @#{jafnhar.nickname}", "visibility" => "direct"})
|
||||
|
||||
object = Pleroma.Object.normalize(activity)
|
||||
context = object.data["context"]
|
||||
|
||||
conversation =
|
||||
Conversation.get_for_ap_id(context)
|
||||
|> Repo.preload(:participations)
|
||||
|
||||
assert conversation
|
||||
|
||||
assert Enum.find(conversation.participations, fn %{user_id: user_id} -> har.id == user_id end)
|
||||
|
||||
assert Enum.find(conversation.participations, fn %{user_id: user_id} ->
|
||||
jafnhar.id == user_id
|
||||
end)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(jafnhar, %{
|
||||
"status" => "Hey @#{har.nickname}",
|
||||
"visibility" => "direct",
|
||||
"in_reply_to_status_id" => activity.id
|
||||
})
|
||||
|
||||
object = Pleroma.Object.normalize(activity)
|
||||
context = object.data["context"]
|
||||
|
||||
conversation_two =
|
||||
Conversation.get_for_ap_id(context)
|
||||
|> Repo.preload(:participations)
|
||||
|
||||
assert conversation_two.id == conversation.id
|
||||
|
||||
assert Enum.find(conversation_two.participations, fn %{user_id: user_id} ->
|
||||
har.id == user_id
|
||||
end)
|
||||
|
||||
assert Enum.find(conversation_two.participations, fn %{user_id: user_id} ->
|
||||
jafnhar.id == user_id
|
||||
end)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(tridi, %{
|
||||
"status" => "Hey @#{har.nickname}",
|
||||
"visibility" => "direct",
|
||||
"in_reply_to_status_id" => activity.id
|
||||
})
|
||||
|
||||
object = Pleroma.Object.normalize(activity)
|
||||
context = object.data["context"]
|
||||
|
||||
conversation_three =
|
||||
Conversation.get_for_ap_id(context)
|
||||
|> Repo.preload([:participations, :users])
|
||||
|
||||
assert conversation_three.id == conversation.id
|
||||
|
||||
assert Enum.find(conversation_three.participations, fn %{user_id: user_id} ->
|
||||
har.id == user_id
|
||||
end)
|
||||
|
||||
assert Enum.find(conversation_three.participations, fn %{user_id: user_id} ->
|
||||
jafnhar.id == user_id
|
||||
end)
|
||||
|
||||
assert Enum.find(conversation_three.participations, fn %{user_id: user_id} ->
|
||||
tridi.id == user_id
|
||||
end)
|
||||
|
||||
assert Enum.find(conversation_three.users, fn %{id: user_id} ->
|
||||
har.id == user_id
|
||||
end)
|
||||
|
||||
assert Enum.find(conversation_three.users, fn %{id: user_id} ->
|
||||
jafnhar.id == user_id
|
||||
end)
|
||||
|
||||
assert Enum.find(conversation_three.users, fn %{id: user_id} ->
|
||||
tridi.id == user_id
|
||||
end)
|
||||
end
|
||||
|
||||
test "create_or_bump_for returns the conversation with participations" do
|
||||
har = insert(:user)
|
||||
jafnhar = insert(:user, local: false)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(har, %{"status" => "Hey @#{jafnhar.nickname}", "visibility" => "direct"})
|
||||
|
||||
{:ok, conversation} = Conversation.create_or_bump_for(activity)
|
||||
|
||||
assert length(conversation.participations) == 2
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(har, %{"status" => "Hey @#{jafnhar.nickname}", "visibility" => "public"})
|
||||
|
||||
assert {:error, _} = Conversation.create_or_bump_for(activity)
|
||||
end
|
||||
end
|
||||
|
|
@ -5,6 +5,23 @@
|
|||
defmodule Pleroma.Factory do
|
||||
use ExMachina.Ecto, repo: Pleroma.Repo
|
||||
|
||||
def participation_factory do
|
||||
conversation = insert(:conversation)
|
||||
user = insert(:user)
|
||||
|
||||
%Pleroma.Conversation.Participation{
|
||||
conversation: conversation,
|
||||
user: user,
|
||||
read: false
|
||||
}
|
||||
end
|
||||
|
||||
def conversation_factory do
|
||||
%Pleroma.Conversation{
|
||||
ap_id: sequence(:ap_id, &"https://some_conversation/#{&1}")
|
||||
}
|
||||
end
|
||||
|
||||
def user_factory do
|
||||
user = %Pleroma.User{
|
||||
name: sequence(:name, &"Test テスト User #{&1}"),
|
||||
|
|
|
|||
|
|
@ -22,6 +22,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
:ok
|
||||
end
|
||||
|
||||
describe "streaming out participations" do
|
||||
test "it streams them out" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
|
||||
|
||||
{:ok, conversation} = Pleroma.Conversation.create_or_bump_for(activity)
|
||||
|
||||
participations =
|
||||
conversation.participations
|
||||
|> Repo.preload(:user)
|
||||
|
||||
with_mock Pleroma.Web.Streamer,
|
||||
stream: fn _, _ -> nil end do
|
||||
ActivityPub.stream_out_participations(conversation.participations)
|
||||
|
||||
Enum.each(participations, fn participation ->
|
||||
assert called(Pleroma.Web.Streamer.stream("participation", participation))
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetching restricted by visibility" do
|
||||
test "it restricts by the appropriate visibility" do
|
||||
user = insert(:user)
|
||||
|
|
@ -130,9 +152,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end
|
||||
|
||||
test "doesn't drop activities with content being null" do
|
||||
user = insert(:user)
|
||||
|
||||
data = %{
|
||||
"ok" => true,
|
||||
"actor" => user.ap_id,
|
||||
"to" => [],
|
||||
"object" => %{
|
||||
"actor" => user.ap_id,
|
||||
"to" => [],
|
||||
"type" => "Note",
|
||||
"content" => nil
|
||||
}
|
||||
}
|
||||
|
|
@ -148,8 +176,17 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end
|
||||
|
||||
test "inserts a given map into the activity database, giving it an id if it has none." do
|
||||
user = insert(:user)
|
||||
|
||||
data = %{
|
||||
"ok" => true
|
||||
"actor" => user.ap_id,
|
||||
"to" => [],
|
||||
"object" => %{
|
||||
"actor" => user.ap_id,
|
||||
"to" => [],
|
||||
"type" => "Note",
|
||||
"content" => "hey"
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, %Activity{} = activity} = ActivityPub.insert(data)
|
||||
|
|
@ -159,9 +196,16 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
given_id = "bla"
|
||||
|
||||
data = %{
|
||||
"ok" => true,
|
||||
"id" => given_id,
|
||||
"context" => "blabla"
|
||||
"actor" => user.ap_id,
|
||||
"to" => [],
|
||||
"context" => "blabla",
|
||||
"object" => %{
|
||||
"actor" => user.ap_id,
|
||||
"to" => [],
|
||||
"type" => "Note",
|
||||
"content" => "hey"
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, %Activity{} = activity} = ActivityPub.insert(data)
|
||||
|
|
@ -172,26 +216,39 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
end
|
||||
|
||||
test "adds a context when none is there" do
|
||||
user = insert(:user)
|
||||
|
||||
data = %{
|
||||
"id" => "some_id",
|
||||
"actor" => user.ap_id,
|
||||
"to" => [],
|
||||
"object" => %{
|
||||
"id" => "object_id"
|
||||
"actor" => user.ap_id,
|
||||
"to" => [],
|
||||
"type" => "Note",
|
||||
"content" => "hey"
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, %Activity{} = activity} = ActivityPub.insert(data)
|
||||
object = Pleroma.Object.normalize(activity)
|
||||
|
||||
assert is_binary(activity.data["context"])
|
||||
assert is_binary(activity.data["object"]["context"])
|
||||
assert is_binary(object.data["context"])
|
||||
assert activity.data["context_id"]
|
||||
assert activity.data["object"]["context_id"]
|
||||
assert object.data["context_id"]
|
||||
end
|
||||
|
||||
test "adds an id to a given object if it lacks one and is a note and inserts it to the object database" do
|
||||
user = insert(:user)
|
||||
|
||||
data = %{
|
||||
"actor" => user.ap_id,
|
||||
"to" => [],
|
||||
"object" => %{
|
||||
"actor" => user.ap_id,
|
||||
"to" => [],
|
||||
"type" => "Note",
|
||||
"ok" => true
|
||||
"content" => "hey"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -300,6 +300,65 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|
|||
assert status["url"] != direct.data["id"]
|
||||
end
|
||||
|
||||
test "Conversations", %{conn: conn} do
|
||||
user_one = insert(:user)
|
||||
user_two = insert(:user)
|
||||
|
||||
{:ok, user_two} = User.follow(user_two, user_one)
|
||||
|
||||
{:ok, direct} =
|
||||
CommonAPI.post(user_one, %{
|
||||
"status" => "Hi @#{user_two.nickname}!",
|
||||
"visibility" => "direct"
|
||||
})
|
||||
|
||||
{:ok, _follower_only} =
|
||||
CommonAPI.post(user_one, %{
|
||||
"status" => "Hi @#{user_two.nickname}!",
|
||||
"visibility" => "private"
|
||||
})
|
||||
|
||||
res_conn =
|
||||
conn
|
||||
|> assign(:user, user_one)
|
||||
|> get("/api/v1/conversations")
|
||||
|
||||
assert response = json_response(res_conn, 200)
|
||||
|
||||
assert [
|
||||
%{
|
||||
"id" => res_id,
|
||||
"accounts" => res_accounts,
|
||||
"last_status" => res_last_status,
|
||||
"unread" => unread
|
||||
}
|
||||
] = response
|
||||
|
||||
assert length(res_accounts) == 2
|
||||
assert is_binary(res_id)
|
||||
assert unread == true
|
||||
assert res_last_status["id"] == direct.id
|
||||
|
||||
# Apparently undocumented API endpoint
|
||||
res_conn =
|
||||
conn
|
||||
|> assign(:user, user_one)
|
||||
|> post("/api/v1/conversations/#{res_id}/read")
|
||||
|
||||
assert response = json_response(res_conn, 200)
|
||||
assert length(response["accounts"]) == 2
|
||||
assert response["last_status"]["id"] == direct.id
|
||||
assert response["unread"] == false
|
||||
|
||||
# (vanilla) Mastodon frontend behaviour
|
||||
res_conn =
|
||||
conn
|
||||
|> assign(:user, user_one)
|
||||
|> get("/api/v1/statuses/#{res_last_status["id"]}/context")
|
||||
|
||||
assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
|
||||
end
|
||||
|
||||
test "doesn't include DMs from blocked users", %{conn: conn} do
|
||||
blocker = insert(:user)
|
||||
blocked = insert(:user)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue