Introduce group basic federation, event new page and notifications
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -10,11 +10,13 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
import Mock
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.{Actors, Conversations, Events}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Resources.Resource
|
||||
alias Mobilizon.Todos.{Todo, TodoList}
|
||||
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Utils
|
||||
alias Mobilizon.Federation.HTTPSignatures.Signature
|
||||
|
||||
@activity_pub_public_audience "https://www.w3.org/ns/activitystreams#Public"
|
||||
@@ -189,7 +191,7 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
end
|
||||
|
||||
test "it deletes the original event but only locally if needed" do
|
||||
with_mock ActivityPub.Utils,
|
||||
with_mock Utils,
|
||||
maybe_federate: fn _ -> :ok end,
|
||||
lazy_put_activity_defaults: fn args -> args end do
|
||||
event = insert(:event)
|
||||
@@ -203,21 +205,21 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
|
||||
assert Events.get_event_by_url(event.url) == nil
|
||||
|
||||
assert_called(ActivityPub.Utils.maybe_federate(delete))
|
||||
assert_called(Utils.maybe_federate(delete))
|
||||
end
|
||||
end
|
||||
|
||||
test "it creates a delete activity and deletes the original comment" do
|
||||
comment = insert(:comment)
|
||||
comment = Events.get_comment_from_url_with_preload!(comment.url)
|
||||
assert is_nil(Events.get_comment_from_url(comment.url).deleted_at)
|
||||
comment = Conversations.get_comment_from_url_with_preload!(comment.url)
|
||||
assert is_nil(Conversations.get_comment_from_url(comment.url).deleted_at)
|
||||
{:ok, delete, _} = ActivityPub.delete(comment)
|
||||
|
||||
assert delete.data["type"] == "Delete"
|
||||
assert delete.data["actor"] == comment.actor.url
|
||||
assert delete.data["object"] == comment.url
|
||||
|
||||
refute is_nil(Events.get_comment_from_url(comment.url).deleted_at)
|
||||
refute is_nil(Conversations.get_comment_from_url(comment.url).deleted_at)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -253,4 +255,288 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
assert update.data["object"]["startTime"] == DateTime.to_iso8601(@updated_start_time)
|
||||
end
|
||||
end
|
||||
|
||||
describe "create a todo list" do
|
||||
@todo_list_title "My TODO-list"
|
||||
|
||||
test "it creates a todo list" do
|
||||
with_mock Utils, [:passthrough], maybe_federate: fn _ -> :ok end do
|
||||
actor = insert(:actor)
|
||||
group = insert(:group)
|
||||
|
||||
{:ok, create_data, %TodoList{url: todo_list_url}} =
|
||||
ActivityPub.create(:todo_list, %{title: @todo_list_title, actor_id: group.id}, true, %{
|
||||
"actor" => actor.url
|
||||
})
|
||||
|
||||
assert create_data.local
|
||||
assert create_data.data["object"]["id"] == todo_list_url
|
||||
assert create_data.data["object"]["type"] == "TodoList"
|
||||
assert create_data.data["object"]["title"] == @todo_list_title
|
||||
assert create_data.data["to"] == [group.url]
|
||||
assert create_data.data["actor"] == actor.url
|
||||
|
||||
assert_called(Utils.maybe_federate(create_data))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "create a todo" do
|
||||
@todo_title "Finish this thing"
|
||||
|
||||
test "it creates a todo" do
|
||||
with_mock Utils, [:passthrough], maybe_federate: fn _ -> :ok end do
|
||||
actor = insert(:actor)
|
||||
todo_list = insert(:todo_list)
|
||||
|
||||
{:ok, create_data, %Todo{url: todo_url}} =
|
||||
ActivityPub.create(
|
||||
:todo,
|
||||
%{title: @todo_title, todo_list_id: todo_list.id, creator_id: actor.id},
|
||||
true,
|
||||
%{"actor" => actor.url}
|
||||
)
|
||||
|
||||
assert create_data.local
|
||||
assert create_data.data["object"]["id"] == todo_url
|
||||
assert create_data.data["object"]["type"] == "Todo"
|
||||
assert create_data.data["object"]["name"] == @todo_title
|
||||
assert create_data.data["to"] == [todo_list.actor.url]
|
||||
assert create_data.data["actor"] == actor.url
|
||||
|
||||
assert_called(Utils.maybe_federate(create_data))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@resource_url "https://framasoft.org/fr/full"
|
||||
@resource_title "my resource"
|
||||
@updated_resource_title "my updated resource"
|
||||
@folder_title "my folder"
|
||||
describe "create resources" do
|
||||
test "it creates a resource" do
|
||||
with_mock Utils, [:passthrough], maybe_federate: fn _ -> :ok end do
|
||||
actor = insert(:actor)
|
||||
group = insert(:group)
|
||||
|
||||
{:ok, create_data, %Resource{url: url}} =
|
||||
ActivityPub.create(
|
||||
:resource,
|
||||
%{
|
||||
title: @resource_title,
|
||||
creator_id: actor.id,
|
||||
actor_id: group.id,
|
||||
parent_id: nil,
|
||||
resource_url: @resource_url,
|
||||
type: :link
|
||||
},
|
||||
true
|
||||
)
|
||||
|
||||
assert create_data.local
|
||||
assert create_data.data["type"] == "Create"
|
||||
assert create_data.data["object"]["id"] == url
|
||||
assert create_data.data["object"]["type"] == "Document"
|
||||
assert create_data.data["object"]["name"] == @resource_title
|
||||
|
||||
assert create_data.data["object"]["url"] == @resource_url
|
||||
|
||||
assert create_data.data["to"] == [group.url]
|
||||
assert create_data.data["actor"] == actor.url
|
||||
assert create_data.data["attributedTo"] == [actor.url]
|
||||
|
||||
assert_called(Utils.maybe_federate(create_data))
|
||||
end
|
||||
end
|
||||
|
||||
test "it creates a folder" do
|
||||
with_mock Utils, [:passthrough], maybe_federate: fn _ -> :ok end do
|
||||
actor = insert(:actor)
|
||||
group = insert(:group)
|
||||
|
||||
{:ok, create_data, %Resource{url: url}} =
|
||||
ActivityPub.create(
|
||||
:resource,
|
||||
%{
|
||||
title: @folder_title,
|
||||
creator_id: actor.id,
|
||||
actor_id: group.id,
|
||||
parent_id: nil,
|
||||
type: :folder
|
||||
},
|
||||
true
|
||||
)
|
||||
|
||||
assert create_data.local
|
||||
assert create_data.data["type"] == "Create"
|
||||
assert create_data.data["object"]["id"] == url
|
||||
assert create_data.data["object"]["type"] == "ResourceCollection"
|
||||
assert create_data.data["object"]["name"] == @folder_title
|
||||
assert create_data.data["to"] == [group.url]
|
||||
assert create_data.data["actor"] == actor.url
|
||||
assert create_data.data["attributedTo"] == [actor.url]
|
||||
|
||||
assert_called(Utils.maybe_federate(create_data))
|
||||
end
|
||||
end
|
||||
|
||||
test "it creates a resource in a folder" do
|
||||
with_mock Utils, [:passthrough], maybe_federate: fn _ -> :ok end do
|
||||
actor = insert(:actor)
|
||||
group = insert(:group)
|
||||
|
||||
%Resource{id: parent_id, url: parent_url} =
|
||||
insert(:resource, type: :folder, resource_url: nil, actor: group)
|
||||
|
||||
{:ok, create_data, %Resource{url: url}} =
|
||||
ActivityPub.create(
|
||||
:resource,
|
||||
%{
|
||||
title: @resource_title,
|
||||
creator_id: actor.id,
|
||||
actor_id: group.id,
|
||||
parent_id: parent_id,
|
||||
resource_url: @resource_url,
|
||||
type: :link
|
||||
},
|
||||
true
|
||||
)
|
||||
|
||||
assert create_data.local
|
||||
assert create_data.data["type"] == "Add"
|
||||
assert create_data.data["target"] == parent_url
|
||||
assert create_data.data["object"]["id"] == url
|
||||
assert create_data.data["object"]["type"] == "Document"
|
||||
assert create_data.data["object"]["name"] == @resource_title
|
||||
|
||||
assert create_data.data["object"]["url"] == @resource_url
|
||||
|
||||
assert create_data.data["to"] == [group.url]
|
||||
assert create_data.data["actor"] == actor.url
|
||||
assert create_data.data["attributedTo"] == [actor.url]
|
||||
|
||||
assert_called(Utils.maybe_federate(create_data))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "move resources" do
|
||||
test "rename resource" do
|
||||
with_mock Utils, [:passthrough], maybe_federate: fn _ -> :ok end do
|
||||
actor = insert(:actor)
|
||||
group = insert(:group)
|
||||
|
||||
%Resource{} =
|
||||
resource =
|
||||
insert(:resource,
|
||||
resource_url: @resource_url,
|
||||
actor: group,
|
||||
creator: actor,
|
||||
title: @resource_title
|
||||
)
|
||||
|
||||
{:ok, update_data, %Resource{url: url}} =
|
||||
ActivityPub.update(
|
||||
:resource,
|
||||
resource,
|
||||
%{
|
||||
title: @updated_resource_title
|
||||
},
|
||||
true
|
||||
)
|
||||
|
||||
assert update_data.local
|
||||
assert update_data.data["type"] == "Update"
|
||||
assert update_data.data["object"]["id"] == url
|
||||
assert update_data.data["object"]["type"] == "Document"
|
||||
assert update_data.data["object"]["name"] == @updated_resource_title
|
||||
|
||||
assert update_data.data["object"]["url"] == @resource_url
|
||||
|
||||
assert update_data.data["to"] == [group.url]
|
||||
assert update_data.data["actor"] == actor.url
|
||||
assert update_data.data["attributedTo"] == [actor.url]
|
||||
|
||||
assert_called(Utils.maybe_federate(update_data))
|
||||
end
|
||||
end
|
||||
|
||||
test "move resource" do
|
||||
with_mock Utils, [:passthrough], maybe_federate: fn _ -> :ok end do
|
||||
actor = insert(:actor)
|
||||
group = insert(:group)
|
||||
|
||||
%Resource{} =
|
||||
resource =
|
||||
insert(:resource,
|
||||
resource_url: @resource_url,
|
||||
actor: group,
|
||||
creator: actor,
|
||||
title: @resource_title
|
||||
)
|
||||
|
||||
%Resource{id: parent_id, url: parent_url} =
|
||||
insert(:resource, type: :folder, resource_url: nil, actor: group)
|
||||
|
||||
{:ok, update_data, %Resource{url: url}} =
|
||||
ActivityPub.move(
|
||||
:resource,
|
||||
resource,
|
||||
%{
|
||||
parent_id: parent_id
|
||||
},
|
||||
true
|
||||
)
|
||||
|
||||
assert update_data.local
|
||||
assert update_data.data["type"] == "Move"
|
||||
assert update_data.data["object"]["id"] == url
|
||||
assert update_data.data["object"]["type"] == "Document"
|
||||
assert update_data.data["object"]["name"] == @resource_title
|
||||
|
||||
assert update_data.data["object"]["url"] == @resource_url
|
||||
|
||||
assert update_data.data["to"] == [group.url]
|
||||
assert update_data.data["actor"] == actor.url
|
||||
assert update_data.data["origin"] == nil
|
||||
assert update_data.data["target"] == parent_url
|
||||
|
||||
assert_called(Utils.maybe_federate(update_data))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete resources" do
|
||||
test "delete resource" do
|
||||
with_mock Utils, [:passthrough], maybe_federate: fn _ -> :ok end do
|
||||
actor = insert(:actor)
|
||||
group = insert(:group)
|
||||
|
||||
%Resource{} =
|
||||
resource =
|
||||
insert(:resource,
|
||||
resource_url: @resource_url,
|
||||
actor: group,
|
||||
creator: actor,
|
||||
title: @resource_title
|
||||
)
|
||||
|
||||
{:ok, update_data, %Resource{url: url}} =
|
||||
ActivityPub.delete(
|
||||
resource,
|
||||
true
|
||||
)
|
||||
|
||||
assert update_data.local
|
||||
assert update_data.data["type"] == "Delete"
|
||||
assert update_data.data["object"] == url
|
||||
assert update_data.data["to"] == [group.url]
|
||||
# TODO : Add actor parameter to ActivityPub.delete/2
|
||||
# assert update_data.data["actor"] == actor.url
|
||||
# assert update_data.data["attributedTo"] == [actor.url]
|
||||
|
||||
assert_called(Utils.maybe_federate(update_data))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
39
test/federation/activity_pub/refresher_test.exs
Normal file
39
test/federation/activity_pub/refresher_test.exs
Normal file
@@ -0,0 +1,39 @@
|
||||
defmodule Mobilizon.Federation.ActivityPub.RefresherTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Refresher
|
||||
alias Mobilizon.Web.ActivityPub.ActorView
|
||||
import Mobilizon.Factory
|
||||
import Mock
|
||||
|
||||
test "refreshes a members collection" do
|
||||
%Actor{members_url: members_url, url: group_url} = group = insert(:group)
|
||||
%Actor{url: actor_url} = actor = insert(:actor)
|
||||
%Member{} = insert(:member, parent: group, actor: actor, role: :member)
|
||||
|
||||
data =
|
||||
ActorView.render("members.json", %{group: group, actor_applicant: actor}) |> Jason.encode!()
|
||||
|
||||
with_mocks([
|
||||
{HTTPoison, [],
|
||||
[
|
||||
get!: fn ^members_url, _headers, _options ->
|
||||
%HTTPoison.Response{status_code: 200, body: data}
|
||||
end
|
||||
]},
|
||||
{ActivityPub, [],
|
||||
[
|
||||
get_or_fetch_actor_by_url: fn url ->
|
||||
case url do
|
||||
^actor_url -> {:ok, actor}
|
||||
^group_url -> {:ok, group}
|
||||
end
|
||||
end
|
||||
]}
|
||||
]) do
|
||||
assert :ok == Refresher.fetch_collection(group.members_url, actor)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -10,15 +10,20 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
import Mobilizon.Factory
|
||||
import ExUnit.CaptureLog
|
||||
import Mock
|
||||
|
||||
alias Mobilizon.{Actors, Events, Tombstone}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.{Comment, Event, Participant}
|
||||
alias Mobilizon.{Actors, Conversations, Events, Resources, Tombstone}
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Collections.Resource
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Resources.Resource
|
||||
alias Mobilizon.Todos.{Todo, TodoList}
|
||||
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Utils
|
||||
alias Mobilizon.Federation.ActivityPub.{Activity, Relay, Transmogrifier}
|
||||
alias Mobilizon.Federation.ActivityStream.{Convertible}
|
||||
alias Mobilizon.Federation.ActivityStream.Convertible
|
||||
|
||||
alias Mobilizon.GraphQL.API
|
||||
|
||||
@@ -77,7 +82,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming notices" do
|
||||
describe "handle incoming comments" do
|
||||
test "it ignores an incoming comment if we already have it" do
|
||||
comment = insert(:comment)
|
||||
|
||||
@@ -113,7 +118,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
%Comment{} =
|
||||
origin_comment =
|
||||
Events.get_comment_from_url(
|
||||
Conversations.get_comment_from_url(
|
||||
"https://blob.cat/objects/02fdea3d-932c-4348-9ecb-3f9eb3fbdd94"
|
||||
)
|
||||
|
||||
@@ -241,7 +246,446 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
# assert data["object"]["url"] == "https://prismo.news/posts/83"
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming todo lists" do
|
||||
test "it ignores an incoming todo list if we already have it" do
|
||||
todo_list = insert(:todo_list)
|
||||
actor = insert(:actor)
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => actor.url,
|
||||
"object" => Convertible.model_to_as(todo_list)
|
||||
}
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", activity["object"])
|
||||
|
||||
assert {:ok, nil, _} = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
|
||||
test "it accepts incoming todo lists" do
|
||||
actor = insert(:actor)
|
||||
group = insert(:group, domain: "morebilizon.com")
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => actor.url,
|
||||
"object" => %{
|
||||
"type" => "TodoList",
|
||||
"actor" => group.url,
|
||||
"id" => "https://mobilizon.app/todo-list/gjfkghfkd",
|
||||
"name" => "My new todo list"
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, %Activity{data: data, local: false}, %TodoList{}} =
|
||||
Transmogrifier.handle_incoming(activity)
|
||||
|
||||
assert data["actor"] == actor.url
|
||||
assert data["object"]["actor"] == group.url
|
||||
end
|
||||
|
||||
@mobilizon_group_url "https://mobilizon.app/@mygroupe"
|
||||
test "it accepts incoming todo lists and fetches the group if needed" do
|
||||
group = insert(:group, domain: "morebilizon.com", url: @mobilizon_group_url)
|
||||
%Actor{url: actor_url} = actor = insert(:actor)
|
||||
|
||||
with_mock ActivityPub, [:passthrough],
|
||||
get_or_fetch_actor_by_url: fn url ->
|
||||
case url do
|
||||
@mobilizon_group_url -> {:ok, group}
|
||||
actor_url -> {:ok, actor}
|
||||
end
|
||||
end do
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => actor.url,
|
||||
"object" => %{
|
||||
"type" => "TodoList",
|
||||
"actor" => @mobilizon_group_url,
|
||||
"id" => "https://mobilizon.app/todo-list/gjfkghfkd",
|
||||
"name" => "My new todo list"
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, %Activity{data: data, local: false}, %TodoList{}} =
|
||||
Transmogrifier.handle_incoming(activity)
|
||||
|
||||
assert data["actor"] == actor.url
|
||||
assert data["object"]["actor"] == @mobilizon_group_url
|
||||
end
|
||||
end
|
||||
|
||||
test "it accepts incoming todo lists and handles group being not found" do
|
||||
%Actor{url: actor_url} = actor = insert(:actor)
|
||||
|
||||
with_mock ActivityPub, [:passthrough],
|
||||
get_or_fetch_actor_by_url: fn url ->
|
||||
case url do
|
||||
@mobilizon_group_url -> {:error, "Not found"}
|
||||
^actor_url -> {:ok, actor}
|
||||
end
|
||||
end do
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => actor_url,
|
||||
"object" => %{
|
||||
"type" => "TodoList",
|
||||
"actor" => @mobilizon_group_url,
|
||||
"id" => "https://mobilizon.app/todo-list/gjfkghfkd",
|
||||
"name" => "My new todo list"
|
||||
}
|
||||
}
|
||||
|
||||
assert :error = Transmogrifier.handle_incoming(activity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming todos" do
|
||||
test "it ignores an incoming todo if we already have it" do
|
||||
todo = insert(:todo)
|
||||
actor = insert(:actor)
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => actor.url,
|
||||
"object" => Convertible.model_to_as(todo)
|
||||
}
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", activity["object"])
|
||||
|
||||
assert {:ok, nil, _} = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
|
||||
test "it accepts incoming todos" do
|
||||
actor = insert(:actor)
|
||||
todo_list = insert(:todo_list)
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => actor.url,
|
||||
"object" => %{
|
||||
"type" => "Todo",
|
||||
"actor" => actor.url,
|
||||
"todoList" => todo_list.url,
|
||||
"id" => "https://mobilizon.app/todo/gjfkghfkd",
|
||||
"name" => "My new todo",
|
||||
"status" => false
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, %Activity{data: data, local: false},
|
||||
%Todo{todo_list: %TodoList{id: todo_list_id}}} =
|
||||
Transmogrifier.handle_incoming(activity)
|
||||
|
||||
assert data["actor"] == actor.url
|
||||
assert data["object"]["todoList"] == todo_list.url
|
||||
assert todo_list_id == todo_list.id
|
||||
end
|
||||
|
||||
@mobilizon_group_url "https://mobilizon.app/@mygroupe"
|
||||
test "it accepts incoming todos and fetches the todo list if needed" do
|
||||
group = insert(:group, domain: "morebilizon.com", url: @mobilizon_group_url)
|
||||
%Actor{url: actor_url} = actor = insert(:actor)
|
||||
|
||||
with_mock ActivityPub, [:passthrough],
|
||||
get_or_fetch_actor_by_url: fn url ->
|
||||
case url do
|
||||
@mobilizon_group_url -> {:ok, group}
|
||||
actor_url -> {:ok, actor}
|
||||
end
|
||||
end do
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => actor.url,
|
||||
"object" => %{
|
||||
"type" => "TodoList",
|
||||
"actor" => @mobilizon_group_url,
|
||||
"id" => "https://mobilizon.app/todo-list/gjfkghfkd",
|
||||
"name" => "My new todo list"
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, %Activity{data: data, local: false}, %TodoList{}} =
|
||||
Transmogrifier.handle_incoming(activity)
|
||||
|
||||
assert data["actor"] == actor.url
|
||||
assert data["object"]["actor"] == @mobilizon_group_url
|
||||
end
|
||||
end
|
||||
|
||||
test "it accepts incoming todo lists and handles group being not found" do
|
||||
%Actor{url: actor_url} = actor = insert(:actor)
|
||||
|
||||
with_mock ActivityPub, [:passthrough],
|
||||
get_or_fetch_actor_by_url: fn url ->
|
||||
case url do
|
||||
@mobilizon_group_url -> {:error, "Not found"}
|
||||
^actor_url -> {:ok, actor}
|
||||
end
|
||||
end do
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => actor_url,
|
||||
"object" => %{
|
||||
"type" => "TodoList",
|
||||
"actor" => @mobilizon_group_url,
|
||||
"id" => "https://mobilizon.app/todo-list/gjfkghfkd",
|
||||
"name" => "My new todo list"
|
||||
}
|
||||
}
|
||||
|
||||
assert :error = Transmogrifier.handle_incoming(activity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming resources" do
|
||||
test "it ignores an incoming resource if we already have it" do
|
||||
actor = insert(:actor)
|
||||
group = insert(:group)
|
||||
%Resource{} = resource = insert(:resource, actor: group, creator: actor)
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"actor" => actor.url,
|
||||
"target" => group.resources_url,
|
||||
"object" => Convertible.model_to_as(resource)
|
||||
}
|
||||
|
||||
assert {:ok, nil, _} = Transmogrifier.handle_incoming(activity)
|
||||
end
|
||||
|
||||
test "it accepts incoming resources" do
|
||||
creator =
|
||||
insert(:actor,
|
||||
domain: "mobilizon.app",
|
||||
url: "https://mobilizon.app/@myremoteactor",
|
||||
preferred_username: "myremoteactor"
|
||||
)
|
||||
|
||||
group =
|
||||
insert(:group,
|
||||
domain: "somewhere.com",
|
||||
url: "https://somewhere.com/@myremotegroup",
|
||||
preferred_username: "myremotegroup"
|
||||
)
|
||||
|
||||
insert(:member, parent: group, actor: creator, role: :member)
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"actor" => creator.url,
|
||||
"target" => group.resources_url,
|
||||
"object" => %{
|
||||
"type" => "Document",
|
||||
"actor" => creator.url,
|
||||
"attributedTo" => [group.url],
|
||||
"id" => "https://mobilizon.app/resource/gjfkghfkd",
|
||||
"name" => "My new resource",
|
||||
"summary" => "A description for the resource",
|
||||
"url" => "https://framasoft.org"
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, %Activity{data: data, local: false}, %Resource{} = resource} =
|
||||
Transmogrifier.handle_incoming(activity)
|
||||
|
||||
assert resource.actor_id == group.id
|
||||
assert resource.creator_id == creator.id
|
||||
assert resource.title == "My new resource"
|
||||
assert resource.type == :link
|
||||
assert is_nil(resource.parent_id)
|
||||
end
|
||||
|
||||
test "it accepts incoming folders" do
|
||||
creator =
|
||||
insert(:actor,
|
||||
domain: "mobilizon.app",
|
||||
url: "https://mobilizon.app/@myremoteactor",
|
||||
preferred_username: "myremoteactor"
|
||||
)
|
||||
|
||||
group =
|
||||
insert(:group,
|
||||
domain: "somewhere.com",
|
||||
url: "https://somewhere.com/@myremotegroup",
|
||||
preferred_username: "myremotegroup"
|
||||
)
|
||||
|
||||
insert(:member, parent: group, actor: creator, role: :member)
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"actor" => creator.url,
|
||||
"target" => group.resources_url,
|
||||
"object" => %{
|
||||
"type" => "ResourceCollection",
|
||||
"actor" => creator.url,
|
||||
"attributedTo" => [group.url],
|
||||
"id" => "https://mobilizon.app/resource/gjfkghfkd",
|
||||
"name" => "My new folder"
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, %Activity{data: data, local: false}, %Resource{} = resource} =
|
||||
Transmogrifier.handle_incoming(activity)
|
||||
|
||||
assert resource.actor_id == group.id
|
||||
assert resource.creator_id == creator.id
|
||||
assert resource.title == "My new folder"
|
||||
assert resource.type == :folder
|
||||
assert is_nil(resource.parent_id)
|
||||
end
|
||||
|
||||
@parent_url "http://mobilizon1.com/resource/e4ce71bd-6bcc-4c61-9774-7999dde0cc68"
|
||||
test "it accepts incoming resources that are in a folder" do
|
||||
creator =
|
||||
insert(:actor,
|
||||
domain: "mobilizon1.com",
|
||||
url: "http://mobilizon1.com/@tcit",
|
||||
preferred_username: "tcit",
|
||||
user: nil
|
||||
)
|
||||
|
||||
group =
|
||||
insert(:group,
|
||||
domain: "mobilizon1.com",
|
||||
url: "http://mobilizon1.com/@demo",
|
||||
preferred_username: "demo",
|
||||
resources_url: "http://mobilizon1.com/@demo/resources"
|
||||
)
|
||||
|
||||
insert(:member, parent: group, actor: creator, role: :member)
|
||||
|
||||
parent_resource =
|
||||
insert(:resource,
|
||||
type: :folder,
|
||||
title: "folder",
|
||||
path: "/folder",
|
||||
actor: group,
|
||||
creator: creator
|
||||
)
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"actor" => creator.url,
|
||||
"target" => parent_resource.url,
|
||||
"object" => %{
|
||||
"type" => "Document",
|
||||
"actor" => creator.url,
|
||||
"attributedTo" => [group.url],
|
||||
"id" => "https://mobilizon.app/resource/gjfkghfkd",
|
||||
"name" => "My new resource",
|
||||
"summary" => "A description for the resource",
|
||||
"context" => parent_resource.url,
|
||||
"url" => "https://framasoft.org"
|
||||
}
|
||||
}
|
||||
|
||||
assert {:ok, %Activity{data: data, local: false}, %Resource{} = resource} =
|
||||
Transmogrifier.handle_incoming(activity)
|
||||
|
||||
assert resource.actor_id == group.id
|
||||
assert resource.creator_id == creator.id
|
||||
assert resource.title == "My new resource"
|
||||
assert resource.type == :link
|
||||
refute is_nil(resource.parent_id)
|
||||
assert resource.parent_id == parent_resource.id
|
||||
end
|
||||
|
||||
test "it accepts incoming resources and handles group being not found" do
|
||||
creator =
|
||||
insert(:actor,
|
||||
domain: "mobilizon.app",
|
||||
url: "https://mobilizon.app/@myremoteactor",
|
||||
preferred_username: "myremoteactor"
|
||||
)
|
||||
|
||||
group =
|
||||
insert(:group,
|
||||
domain: "somewhere.com",
|
||||
url: "https://somewhere.com/@myremotegroup",
|
||||
preferred_username: "myremotegroup"
|
||||
)
|
||||
|
||||
insert(:member, parent: group, actor: creator, role: :member)
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"actor" => creator.url,
|
||||
"target" => group.resources_url,
|
||||
"object" => %{
|
||||
"type" => "Document",
|
||||
"actor" => "https://someurl.com/notfound",
|
||||
"attributedTo" => "https://someurl.com/notfound",
|
||||
"id" => "https://mobilizon.app/resource/gjfkghfkd",
|
||||
"name" => "My new resource",
|
||||
"summary" => "A description for the resource",
|
||||
"url" => "https://framasoft.org"
|
||||
}
|
||||
}
|
||||
|
||||
assert :error = Transmogrifier.handle_incoming(activity)
|
||||
end
|
||||
|
||||
test "it refuses incoming resources if actor is not a member of the group" do
|
||||
creator =
|
||||
insert(:actor,
|
||||
domain: "mobilizon.app",
|
||||
url: "https://mobilizon.app/@myremoteactor",
|
||||
preferred_username: "myremoteactor"
|
||||
)
|
||||
|
||||
group =
|
||||
insert(:group,
|
||||
domain: "somewhere.com",
|
||||
url: "https://somewhere.com/@myremotegroup",
|
||||
preferred_username: "myremotegroup"
|
||||
)
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"actor" => creator.url,
|
||||
"target" => group.resources_url,
|
||||
"object" => %{
|
||||
"type" => "Document",
|
||||
"actor" => creator.url,
|
||||
"attributedTo" => [group.url],
|
||||
"id" => "https://mobilizon.app/resource/gjfkghfkd",
|
||||
"name" => "My new resource",
|
||||
"summary" => "A description for the resource",
|
||||
"url" => "https://framasoft.org"
|
||||
}
|
||||
}
|
||||
|
||||
assert :error = Transmogrifier.handle_incoming(activity)
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming follow requests" do
|
||||
test "it works for incoming follow requests" do
|
||||
use_cassette "activity_pub/mastodon_follow_activity" do
|
||||
actor = insert(:actor)
|
||||
@@ -262,6 +706,18 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
end
|
||||
end
|
||||
|
||||
test "it rejects activities without a valid ID" do
|
||||
actor = insert(:actor)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", actor.url)
|
||||
|> Map.put("id", "")
|
||||
|
||||
:error = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
|
||||
# test "it works for incoming follow requests from hubzilla" do
|
||||
# user = insert(:user)
|
||||
|
||||
@@ -278,58 +734,60 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
# assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
|
||||
# assert User.is_following(User.get_by_ap_id(data["actor"]), user)
|
||||
# end
|
||||
end
|
||||
|
||||
# test "it works for incoming likes" do
|
||||
# %Comment{url: url} = insert(:comment)
|
||||
# test "it works for incoming likes" do
|
||||
# %Comment{url: url} = insert(:comment)
|
||||
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-like.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", url)
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-like.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", url)
|
||||
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
# assert data["type"] == "Like"
|
||||
# assert data["id"] == "http://mastodon.example.org/users/admin#likes/2"
|
||||
# assert data["object"] == url
|
||||
# end
|
||||
# assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
# assert data["type"] == "Like"
|
||||
# assert data["id"] == "http://mastodon.example.org/users/admin#likes/2"
|
||||
# assert data["object"] == url
|
||||
# end
|
||||
|
||||
# test "it returns an error for incoming unlikes wihout a like activity" do
|
||||
# %Comment{url: url} = insert(:comment)
|
||||
# test "it returns an error for incoming unlikes wihout a like activity" do
|
||||
# %Comment{url: url} = insert(:comment)
|
||||
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-undo-like.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", url)
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-undo-like.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", url)
|
||||
|
||||
# assert Transmogrifier.handle_incoming(data) == {:error, :not_supported}
|
||||
# end
|
||||
# assert Transmogrifier.handle_incoming(data) == {:error, :not_supported}
|
||||
# end
|
||||
|
||||
# test "it works for incoming unlikes with an existing like activity" do
|
||||
# comment = insert(:comment)
|
||||
# test "it works for incoming unlikes with an existing like activity" do
|
||||
# comment = insert(:comment)
|
||||
|
||||
# like_data =
|
||||
# File.read!("test/fixtures/mastodon-like.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", comment.url)
|
||||
# like_data =
|
||||
# File.read!("test/fixtures/mastodon-like.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", comment.url)
|
||||
|
||||
# {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
|
||||
# {:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
|
||||
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-undo-like.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", like_data)
|
||||
# |> Map.put("actor", like_data["actor"])
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-undo-like.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", like_data)
|
||||
# |> Map.put("actor", like_data["actor"])
|
||||
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
# assert data["type"] == "Undo"
|
||||
# assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
|
||||
# assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2"
|
||||
# end
|
||||
# assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
# assert data["type"] == "Undo"
|
||||
# assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
|
||||
# assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2"
|
||||
# end
|
||||
|
||||
describe "handle incoming follow announces" do
|
||||
test "it works for incoming announces" do
|
||||
use_cassette "activity_pub/mastodon_announce_activity" do
|
||||
data = File.read!("test/fixtures/mastodon-announce.json") |> Jason.decode!()
|
||||
@@ -345,7 +803,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
assert data["object"] ==
|
||||
"https://framapiaf.org/users/Framasoft/statuses/102501959686438400"
|
||||
|
||||
assert %Comment{} = Events.get_comment_from_url(data["object"])
|
||||
assert %Comment{} = Conversations.get_comment_from_url(data["object"])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -369,7 +827,9 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
assert data["object"] == comment.url
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming update activities" do
|
||||
test "it works for incoming update activities on actors" do
|
||||
use_cassette "activity_pub/update_actor_activity" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
||||
@@ -448,7 +908,9 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
# user = User.get_cached_by_ap_id(data["actor"])
|
||||
# assert user.info["locked"] == true
|
||||
# end
|
||||
end
|
||||
|
||||
describe "handle incoming delete activities" do
|
||||
test "it works for incoming deletes" do
|
||||
%Actor{url: actor_url} = actor = insert(:actor)
|
||||
%Comment{url: comment_url} = insert(:comment, actor: nil, actor_id: actor.id)
|
||||
@@ -466,12 +928,12 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|> Map.put("object", object)
|
||||
|> Map.put("actor", actor_url)
|
||||
|
||||
assert Events.get_comment_from_url(comment_url)
|
||||
assert is_nil(Events.get_comment_from_url(comment_url).deleted_at)
|
||||
assert Conversations.get_comment_from_url(comment_url)
|
||||
assert is_nil(Conversations.get_comment_from_url(comment_url).deleted_at)
|
||||
|
||||
{:ok, %Activity{local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
refute is_nil(Events.get_comment_from_url(comment_url).deleted_at)
|
||||
refute is_nil(Conversations.get_comment_from_url(comment_url).deleted_at)
|
||||
end
|
||||
|
||||
test "it fails for incoming deletes with spoofed origin" do
|
||||
@@ -498,7 +960,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
:error = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert Events.get_comment_from_url(comment.url)
|
||||
assert Conversations.get_comment_from_url(comment.url)
|
||||
end
|
||||
|
||||
test "it works for incoming actor deletes" do
|
||||
@@ -519,7 +981,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
assert {:ok, %Actor{suspended: true}} = Actors.get_actor_by_url(url)
|
||||
assert {:error, :event_not_found} = Events.get_event(event1.id)
|
||||
assert %Tombstone{} = Tombstone.find_tombstone(event1_url)
|
||||
assert %Comment{deleted_at: deleted_at} = Events.get_comment(comment1.id)
|
||||
assert %Comment{deleted_at: deleted_at} = Conversations.get_comment(comment1.id)
|
||||
refute is_nil(deleted_at)
|
||||
assert %Tombstone{} = Tombstone.find_tombstone(comment1_url)
|
||||
end
|
||||
@@ -538,7 +1000,9 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
assert Actors.get_actor_by_url(url)
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming undo activities" do
|
||||
test "it works for incoming unannounces with an existing notice" do
|
||||
use_cassette "activity_pub/mastodon_unannounce_activity" do
|
||||
comment = insert(:comment)
|
||||
@@ -595,83 +1059,85 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
refute Actors.is_following(followed, actor)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# test "it works for incoming blocks" do
|
||||
# user = insert(:user)
|
||||
# test "it works for incoming blocks" do
|
||||
# user = insert(:user)
|
||||
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-block-activity.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", user.ap_id)
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-block-activity.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", user.ap_id)
|
||||
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert data["type"] == "Block"
|
||||
# assert data["object"] == user.ap_id
|
||||
# assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
# assert data["type"] == "Block"
|
||||
# assert data["object"] == user.ap_id
|
||||
# assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
# blocker = User.get_by_ap_id(data["actor"])
|
||||
# blocker = User.get_by_ap_id(data["actor"])
|
||||
|
||||
# assert User.blocks?(blocker, user)
|
||||
# end
|
||||
# assert User.blocks?(blocker, user)
|
||||
# end
|
||||
|
||||
# test "incoming blocks successfully tear down any follow relationship" do
|
||||
# blocker = insert(:user)
|
||||
# blocked = insert(:user)
|
||||
# test "incoming blocks successfully tear down any follow relationship" do
|
||||
# blocker = insert(:user)
|
||||
# blocked = insert(:user)
|
||||
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-block-activity.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", blocked.ap_id)
|
||||
# |> Map.put("actor", blocker.ap_id)
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-block-activity.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", blocked.ap_id)
|
||||
# |> Map.put("actor", blocker.ap_id)
|
||||
|
||||
# {:ok, blocker} = User.follow(blocker, blocked)
|
||||
# {:ok, blocked} = User.follow(blocked, blocker)
|
||||
# {:ok, blocker} = User.follow(blocker, blocked)
|
||||
# {:ok, blocked} = User.follow(blocked, blocker)
|
||||
|
||||
# assert User.following?(blocker, blocked)
|
||||
# assert User.following?(blocked, blocker)
|
||||
# assert User.following?(blocker, blocked)
|
||||
# assert User.following?(blocked, blocker)
|
||||
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert data["type"] == "Block"
|
||||
# assert data["object"] == blocked.ap_id
|
||||
# assert data["actor"] == blocker.ap_id
|
||||
# assert data["type"] == "Block"
|
||||
# assert data["object"] == blocked.ap_id
|
||||
# assert data["actor"] == blocker.ap_id
|
||||
|
||||
# blocker = User.get_by_ap_id(data["actor"])
|
||||
# blocked = User.get_by_ap_id(data["object"])
|
||||
# blocker = User.get_by_ap_id(data["actor"])
|
||||
# blocked = User.get_by_ap_id(data["object"])
|
||||
|
||||
# assert User.blocks?(blocker, blocked)
|
||||
# assert User.blocks?(blocker, blocked)
|
||||
|
||||
# refute User.following?(blocker, blocked)
|
||||
# refute User.following?(blocked, blocker)
|
||||
# end
|
||||
# refute User.following?(blocker, blocked)
|
||||
# refute User.following?(blocked, blocker)
|
||||
# end
|
||||
|
||||
# test "it works for incoming unblocks with an existing block" do
|
||||
# user = insert(:user)
|
||||
# test "it works for incoming unblocks with an existing block" do
|
||||
# user = insert(:user)
|
||||
|
||||
# block_data =
|
||||
# File.read!("test/fixtures/mastodon-block-activity.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", user.ap_id)
|
||||
# block_data =
|
||||
# File.read!("test/fixtures/mastodon-block-activity.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", user.ap_id)
|
||||
|
||||
# {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(block_data)
|
||||
# {:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(block_data)
|
||||
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-unblock-activity.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", block_data)
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-unblock-activity.json")
|
||||
# |> Jason.decode!()
|
||||
# |> Map.put("object", block_data)
|
||||
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
# assert data["type"] == "Undo"
|
||||
# assert data["object"]["type"] == "Block"
|
||||
# assert data["object"]["object"] == user.ap_id
|
||||
# assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
# assert data["type"] == "Undo"
|
||||
# assert data["object"]["type"] == "Block"
|
||||
# assert data["object"]["object"] == user.ap_id
|
||||
# assert data["actor"] == "http://mastodon.example.org/users/admin"
|
||||
|
||||
# blocker = User.get_by_ap_id(data["actor"])
|
||||
# blocker = User.get_by_ap_id(data["actor"])
|
||||
|
||||
# refute User.blocks?(blocker, user)
|
||||
# end
|
||||
# refute User.blocks?(blocker, user)
|
||||
# end
|
||||
|
||||
describe "handle incoming follow accept activities" do
|
||||
test "it works for incoming accepts which were pre-accepted" do
|
||||
follower = insert(:actor)
|
||||
followed = insert(:actor)
|
||||
@@ -743,7 +1209,9 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
refute Actors.is_following(follower, followed)
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming follow reject activities" do
|
||||
test "it fails for incoming rejects which cannot be correlated" do
|
||||
follower = insert(:actor)
|
||||
followed = insert(:actor)
|
||||
@@ -781,19 +1249,9 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
refute Actors.is_following(follower, followed)
|
||||
end
|
||||
end
|
||||
|
||||
test "it rejects activities without a valid ID" do
|
||||
actor = insert(:actor)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", actor.url)
|
||||
|> Map.put("id", "")
|
||||
|
||||
:error = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
|
||||
describe "handle incoming flag activities" do
|
||||
test "it accepts Flag activities" do
|
||||
%Actor{url: reporter_url} = Relay.get_actor()
|
||||
%Actor{url: reported_url} = reported = insert(:actor)
|
||||
@@ -817,7 +1275,9 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
assert activity.data["actor"] == reporter_url
|
||||
assert activity.data["cc"] == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming join activities" do
|
||||
@join_message "I want to get in!"
|
||||
test "it accepts Join activities" do
|
||||
%Actor{url: organizer_url} = organizer = insert(:actor)
|
||||
@@ -846,7 +1306,9 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
assert activity.data["actor"] == organizer_url
|
||||
assert activity.data["id"] =~ "/accept/join/"
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming accept join activities" do
|
||||
test "it accepts Accept activities for Join activities" do
|
||||
%Actor{url: organizer_url} = organizer = insert(:actor)
|
||||
%Actor{} = participant_actor = insert(:actor)
|
||||
@@ -870,7 +1332,9 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
# We don't accept already accepted Accept activities
|
||||
:error = Transmogrifier.handle_incoming(accept_data)
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming reject join activities" do
|
||||
test "it accepts Reject activities for Join activities" do
|
||||
%Actor{url: organizer_url} = organizer = insert(:actor)
|
||||
%Actor{} = participant_actor = insert(:actor)
|
||||
@@ -905,7 +1369,9 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|> Enum.map(& &1.id) ==
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming leave activities on events" do
|
||||
test "it accepts Leave activities" do
|
||||
%Actor{url: _organizer_url} = organizer = insert(:actor)
|
||||
%Actor{url: participant_url} = participant_actor = insert(:actor)
|
||||
@@ -955,6 +1421,58 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle Invite activities on group" do
|
||||
test "it accepts Invite activities" do
|
||||
%Actor{url: group_url, id: group_id} = group = insert(:group)
|
||||
%Actor{url: group_admin_url, id: group_admin_id} = group_admin = insert(:actor)
|
||||
|
||||
%Member{} =
|
||||
_group_admin_member =
|
||||
insert(:member, parent: group, actor: group_admin, role: :administrator)
|
||||
|
||||
%Actor{url: invitee_url, id: invitee_id} = _invitee = insert(:actor)
|
||||
|
||||
invite_data =
|
||||
File.read!("test/fixtures/mobilizon-invite-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", group_admin_url)
|
||||
|> Map.put("object", group_url)
|
||||
|> Map.put("target", invitee_url)
|
||||
|
||||
assert {:ok, activity, %Member{}} = Transmogrifier.handle_incoming(invite_data)
|
||||
assert %Member{} = member = Actors.get_member_by_url(invite_data["id"])
|
||||
assert member.actor.id == invitee_id
|
||||
assert member.parent.id == group_id
|
||||
assert member.role == :invited
|
||||
assert member.invited_by_id == group_admin_id
|
||||
end
|
||||
|
||||
test "it refuses Invite activities for " do
|
||||
%Actor{url: group_url, id: group_id} = group = insert(:group)
|
||||
%Actor{url: group_admin_url, id: group_admin_id} = group_admin = insert(:actor)
|
||||
|
||||
%Member{} =
|
||||
_group_admin_member =
|
||||
insert(:member, parent: group, actor: group_admin, role: :administrator)
|
||||
|
||||
%Actor{url: invitee_url, id: invitee_id} = _invitee = insert(:actor)
|
||||
|
||||
invite_data =
|
||||
File.read!("test/fixtures/mobilizon-invite-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", group_admin_url)
|
||||
|> Map.put("object", group_url)
|
||||
|> Map.put("target", invitee_url)
|
||||
|
||||
assert {:ok, activity, %Member{}} = Transmogrifier.handle_incoming(invite_data)
|
||||
assert %Member{} = member = Actors.get_member_by_url(invite_data["id"])
|
||||
assert member.actor.id == invitee_id
|
||||
assert member.parent.id == group_id
|
||||
assert member.role == :invited
|
||||
assert member.invited_by_id == group_admin_id
|
||||
end
|
||||
end
|
||||
|
||||
describe "prepare outgoing" do
|
||||
test "it turns mentions into tags" do
|
||||
actor = insert(:actor)
|
||||
|
||||
@@ -16,7 +16,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.ActorTest do
|
||||
|
||||
describe "AS to Actor" do
|
||||
test "valid as data to model" do
|
||||
{:ok, actor} =
|
||||
actor =
|
||||
ActorConverter.as_to_model_data(%{
|
||||
"id" => "https://somedomain.tld/users/someone",
|
||||
"type" => "Person",
|
||||
|
||||
42
test/fixtures/mobilizon-invite-activity.json
vendored
Normal file
42
test/fixtures/mobilizon-invite-activity.json
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"type": "Invite",
|
||||
"signature": {
|
||||
"type": "RsaSignature2017",
|
||||
"signatureValue": "Kn1/UkAQGJVaXBfWLAHcnwHg8YMAUqlEaBuYLazAG+pz5hqivsyrBmPV186Xzr+B4ZLExA9+SnOoNx/GOz4hBm0kAmukNSILAsUd84tcJ2yT9zc1RKtembK4WiwOw7li0+maeDN0HaB6t+6eTqsCWmtiZpprhXD8V1GGT8yG7X24fQ9oFGn+ng7lasbcCC0988Y1eGqNe7KryxcPuQz57YkDapvtONzk8gyLTkZMV4De93MyRHq6GVjQVIgtiYabQAxrX6Q8C+4P/jQoqdWJHEe+MY5JKyNaT/hMPt2Md1ok9fZQBGHlErk22/zy8bSN19GdG09HmIysBUHRYpBLig==",
|
||||
"creator": "http://mobilizon.test/users/tcit#main-key",
|
||||
"created": "2018-02-17T13:29:31Z"
|
||||
},
|
||||
"object": "http://mobilizon.test/@mygroup",
|
||||
"id": "http://mobilizon2.test/member/some-uuid",
|
||||
"actor": "http://mobilizon2.test/@admin",
|
||||
"target": "http://mobilizon.test/@someuser",
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://litepub.social/litepub/context.jsonld",
|
||||
{
|
||||
"Hashtag": "as:Hashtag",
|
||||
"category": "sc:category",
|
||||
"ical": "http://www.w3.org/2002/12/cal/ical#",
|
||||
"joinMode": {
|
||||
"@id": "mz:joinMode",
|
||||
"@type": "mz:joinModeType"
|
||||
},
|
||||
"joinModeType": {
|
||||
"@id": "mz:joinModeType",
|
||||
"@type": "rdfs:Class"
|
||||
},
|
||||
"maximumAttendeeCapacity": "sc:maximumAttendeeCapacity",
|
||||
"mz": "https://joinmobilizon.org/ns#",
|
||||
"repliesModerationOption": {
|
||||
"@id": "mz:repliesModerationOption",
|
||||
"@type": "mz:repliesModerationOptionType"
|
||||
},
|
||||
"repliesModerationOptionType": {
|
||||
"@id": "mz:repliesModerationOptionType",
|
||||
"@type": "rdfs:Class"
|
||||
},
|
||||
"sc": "http://schema.org#",
|
||||
"uuid": "sc:identifier"
|
||||
}
|
||||
]
|
||||
}
|
||||
84
test/fixtures/mobilizon-members-collection.json
vendored
Normal file
84
test/fixtures/mobilizon-members-collection.json
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://litepub.social/litepub/context.jsonld",
|
||||
{
|
||||
"Hashtag": "as:Hashtag",
|
||||
"PostalAddress": "sc:PostalAddress",
|
||||
"address": {
|
||||
"@id": "sc:address",
|
||||
"@type": "sc:PostalAddress"
|
||||
},
|
||||
"addressCountry": "sc:addressCountry",
|
||||
"addressLocality": "sc:addressLocality",
|
||||
"addressRegion": "sc:addressRegion",
|
||||
"anonymousParticipationEnabled": {
|
||||
"@id": "mz:anonymousParticipationEnabled",
|
||||
"@type": "sc:Boolean"
|
||||
},
|
||||
"category": "sc:category",
|
||||
"commentsEnabled": {
|
||||
"@id": "pt:commentsEnabled",
|
||||
"@type": "sc:Boolean"
|
||||
},
|
||||
"ical": "http://www.w3.org/2002/12/cal/ical#",
|
||||
"joinMode": {
|
||||
"@id": "mz:joinMode",
|
||||
"@type": "mz:joinModeType"
|
||||
},
|
||||
"joinModeType": {
|
||||
"@id": "mz:joinModeType",
|
||||
"@type": "rdfs:Class"
|
||||
},
|
||||
"location": {
|
||||
"@id": "sc:location",
|
||||
"@type": "sc:Place"
|
||||
},
|
||||
"maximumAttendeeCapacity": "sc:maximumAttendeeCapacity",
|
||||
"mz": "https://joinmobilizon.org/ns#",
|
||||
"participationMessage": {
|
||||
"@id": "mz:participationMessage",
|
||||
"@type": "sc:Text"
|
||||
},
|
||||
"postalCode": "sc:postalCode",
|
||||
"pt": "https://joinpeertube.org/ns#",
|
||||
"repliesModerationOption": {
|
||||
"@id": "mz:repliesModerationOption",
|
||||
"@type": "mz:repliesModerationOptionType"
|
||||
},
|
||||
"repliesModerationOptionType": {
|
||||
"@id": "mz:repliesModerationOptionType",
|
||||
"@type": "rdfs:Class"
|
||||
},
|
||||
"sc": "http://schema.org#",
|
||||
"streetAddress": "sc:streetAddress",
|
||||
"uuid": "sc:identifier"
|
||||
}
|
||||
],
|
||||
"attributedTo": "http://mobilizon.test/@demo",
|
||||
"first": {
|
||||
"attributedTo": "http://mobilizon.test/@demo",
|
||||
"id": "http://mobilizon.test/@demo/members?page=1",
|
||||
"orderedItems": [
|
||||
{
|
||||
"actor": "http://mobilizon.test/@tcit",
|
||||
"id": "http://mobilizon.test/member/2fec2e84-5719-48f9-92bd-077f50ff2e6e",
|
||||
"object": "http://mobilizon.test/@demo",
|
||||
"role": "administrator",
|
||||
"type": "Member"
|
||||
},
|
||||
{
|
||||
"actor": "http://mobilizon2.com/@tcit",
|
||||
"id": "http://mobilizon.test/member/13b0fc1e-2ceb-401c-bef7-0eba02fb92dc",
|
||||
"object": "http://mobilizon.test/@demo",
|
||||
"role": "member",
|
||||
"type": "Member"
|
||||
}
|
||||
],
|
||||
"partOf": "http://mobilizon.test/@demo/members",
|
||||
"type": "OrderedCollectionPage"
|
||||
},
|
||||
"id": "http://mobilizon.test/@demo/members",
|
||||
"totalItems": 2,
|
||||
"type": "OrderedCollection"
|
||||
}
|
||||
79
test/fixtures/vcr_cassettes/activity_pub/mobilizon_parent_resource.json
vendored
Normal file
79
test/fixtures/vcr_cassettes/activity_pub/mobilizon_parent_resource.json
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -4,7 +4,8 @@ defmodule Mobilizon.GraphQL.API.ReportTest do
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.{Comment, Event}
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Reports.{Note, Report}
|
||||
alias Mobilizon.Users
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
@@ -207,7 +207,7 @@ defmodule Mobilizon.Web.Resolvers.EventTest do
|
||||
assert res["data"]["createEvent"]["title"] == "My Event title"
|
||||
|
||||
assert res["data"]["createEvent"]["description"] ==
|
||||
"<b>My description</b> <img src=\"http://placekitten.com/g/200/300\" />"
|
||||
"<b>My description</b> <img src=\"http://placekitten.com/g/200/300\"/>"
|
||||
|
||||
{id, ""} = res["data"]["createEvent"]["id"] |> Integer.parse()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ defmodule Mobilizon.Web.Resolvers.GroupTest do
|
||||
{:ok, conn: conn, actor: actor, user: user}
|
||||
end
|
||||
|
||||
describe "Group Resolver" do
|
||||
describe "create a group" do
|
||||
test "create_group/3 should check the user owns the identity", %{conn: conn, user: user} do
|
||||
another_actor = insert(:actor)
|
||||
|
||||
@@ -84,65 +84,130 @@ defmodule Mobilizon.Web.Resolvers.GroupTest do
|
||||
assert hd(json_response(res, 200)["errors"])["message"] ==
|
||||
"A group with this name already exists"
|
||||
end
|
||||
end
|
||||
|
||||
test "list_groups/3 returns all public or unlisted groups", context do
|
||||
describe "list groups" do
|
||||
test "list_groups/3 returns all public or unlisted groups", %{conn: conn} do
|
||||
group = insert(:group, visibility: :unlisted)
|
||||
insert(:group, visibility: :private)
|
||||
|
||||
query = """
|
||||
{
|
||||
groups {
|
||||
preferredUsername,
|
||||
elements {
|
||||
preferredUsername,
|
||||
},
|
||||
total
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
res =
|
||||
context.conn
|
||||
|> get("/api", AbsintheHelpers.query_skeleton(query, "groups"))
|
||||
res = AbsintheHelpers.graphql_query(conn, query: query)
|
||||
|
||||
assert length(json_response(res, 200)["data"]["groups"]) == 1
|
||||
assert res["data"]["groups"]["total"] == 1
|
||||
|
||||
assert hd(json_response(res, 200)["data"]["groups"])["preferredUsername"] ==
|
||||
assert hd(res["data"]["groups"]["elements"])["preferredUsername"] ==
|
||||
group.preferred_username
|
||||
end
|
||||
end
|
||||
|
||||
test "find_group/3 returns a group by its username", context do
|
||||
group = insert(:group)
|
||||
|
||||
query = """
|
||||
{
|
||||
group(preferredUsername: "#{group.preferred_username}") {
|
||||
describe "find a group" do
|
||||
@group_query """
|
||||
query Group($preferredUsername: String!) {
|
||||
group(preferredUsername: $preferredUsername) {
|
||||
preferredUsername,
|
||||
members {
|
||||
total,
|
||||
elements {
|
||||
role,
|
||||
actor {
|
||||
preferredUsername
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
"""
|
||||
|
||||
test "find_group/3 returns a group by its username", %{conn: conn, actor: actor, user: user} do
|
||||
group = insert(:group)
|
||||
insert(:member, parent: group, actor: actor, role: :administrator)
|
||||
insert(:member, parent: group, role: :member)
|
||||
|
||||
res =
|
||||
context.conn
|
||||
|> get("/api", AbsintheHelpers.query_skeleton(query, "group"))
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @group_query,
|
||||
variables: %{
|
||||
preferredUsername: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert json_response(res, 200)["data"]["group"]["preferredUsername"] ==
|
||||
assert res["errors"] == nil
|
||||
|
||||
assert res["data"]["group"]["preferredUsername"] ==
|
||||
group.preferred_username
|
||||
|
||||
query = """
|
||||
{
|
||||
group(preferredUsername: "#{@non_existent_username}") {
|
||||
preferredUsername,
|
||||
}
|
||||
}
|
||||
"""
|
||||
assert res["data"]["group"]["members"]["total"] == 2
|
||||
|
||||
res =
|
||||
context.conn
|
||||
|> get("/api", AbsintheHelpers.query_skeleton(query, "group"))
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @group_query,
|
||||
variables: %{
|
||||
preferredUsername: group.preferred_username,
|
||||
actorId: actor.id
|
||||
}
|
||||
)
|
||||
|
||||
assert json_response(res, 200)["data"]["group"] == nil
|
||||
assert res["errors"] == nil
|
||||
|
||||
assert hd(json_response(res, 200)["errors"])["message"] ==
|
||||
assert res["data"]["group"]["members"]["total"] == 2
|
||||
assert hd(res["data"]["group"]["members"]["elements"])["role"] == "ADMINISTRATOR"
|
||||
|
||||
assert hd(res["data"]["group"]["members"]["elements"])["actor"]["preferredUsername"] ==
|
||||
actor.preferred_username
|
||||
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @group_query,
|
||||
variables: %{preferredUsername: @non_existent_username}
|
||||
)
|
||||
|
||||
assert res["data"]["group"] == nil
|
||||
|
||||
assert hd(res["errors"])["message"] ==
|
||||
"Group with name #{@non_existent_username} not found"
|
||||
end
|
||||
|
||||
test "find_group doesn't list group members access if group is private", %{
|
||||
conn: conn,
|
||||
actor: actor
|
||||
} do
|
||||
group = insert(:group, visibility: :private)
|
||||
insert(:member, parent: group, actor: actor, role: :administrator)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @group_query,
|
||||
variables: %{
|
||||
preferredUsername: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert res["errors"] == nil
|
||||
|
||||
assert res["data"]["group"]["preferredUsername"] ==
|
||||
group.preferred_username
|
||||
|
||||
assert res["data"]["group"]["members"] == %{"elements" => [], "total" => 1}
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete a group" do
|
||||
test "delete_group/3 deletes a group", %{conn: conn, user: user, actor: actor} do
|
||||
group = insert(:group)
|
||||
insert(:member, parent: group, actor: actor, role: :administrator)
|
||||
|
||||
@@ -12,7 +12,7 @@ defmodule Mobilizon.GraphQL.Resolvers.MemberTest do
|
||||
{:ok, conn: conn, actor: actor, user: user}
|
||||
end
|
||||
|
||||
describe "Member Resolver" do
|
||||
describe "Member Resolver to join a group" do
|
||||
test "join_group/3 should create a member", %{conn: conn, user: user, actor: actor} do
|
||||
group = insert(:group)
|
||||
|
||||
@@ -39,7 +39,7 @@ defmodule Mobilizon.GraphQL.Resolvers.MemberTest do
|
||||
|> post("/api", AbsintheHelpers.mutation_skeleton(mutation))
|
||||
|
||||
assert json_response(res, 200)["errors"] == nil
|
||||
assert json_response(res, 200)["data"]["joinGroup"]["role"] == "not_approved"
|
||||
assert json_response(res, 200)["data"]["joinGroup"]["role"] == "NOT_APPROVED"
|
||||
assert json_response(res, 200)["data"]["joinGroup"]["parent"]["id"] == to_string(group.id)
|
||||
assert json_response(res, 200)["data"]["joinGroup"]["actor"]["id"] == to_string(actor.id)
|
||||
|
||||
@@ -136,7 +136,9 @@ defmodule Mobilizon.GraphQL.Resolvers.MemberTest do
|
||||
|
||||
assert hd(json_response(res, 200)["errors"])["message"] =~ "Group id not found"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Member Resolver to leave from a group" do
|
||||
test "leave_group/3 should delete a member from a group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
@@ -286,4 +288,211 @@ defmodule Mobilizon.GraphQL.Resolvers.MemberTest do
|
||||
assert hd(json_response(res, 200)["errors"])["message"] =~ "Member not found"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Member Resolver to invite to a group" do
|
||||
@invite_member_mutation """
|
||||
mutation InviteMember($groupId: ID!, $targetActorUsername: String!) {
|
||||
inviteMember(groupId: $groupId, targetActorUsername: $targetActorUsername) {
|
||||
parent {
|
||||
id
|
||||
},
|
||||
actor {
|
||||
id
|
||||
},
|
||||
role
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
setup %{conn: conn, actor: actor, user: user} do
|
||||
group = insert(:group)
|
||||
target_actor = insert(:actor, user: user)
|
||||
|
||||
{:ok, conn: conn, actor: actor, user: user, group: group, target_actor: target_actor}
|
||||
end
|
||||
|
||||
test "invite_member/3 invites a local actor to a group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
actor: actor,
|
||||
group: group,
|
||||
target_actor: target_actor
|
||||
} do
|
||||
_admin_member = insert(:member, %{actor: actor, parent: group, role: :creator})
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @invite_member_mutation,
|
||||
variables: %{
|
||||
groupId: group.id,
|
||||
targetActorUsername: target_actor.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
assert res["data"]["inviteMember"]["role"] == "INVITED"
|
||||
assert res["data"]["inviteMember"]["parent"]["id"] == to_string(group.id)
|
||||
assert res["data"]["inviteMember"]["actor"]["id"] == to_string(target_actor.id)
|
||||
end
|
||||
|
||||
test "invite_member/3 invites a remote actor to a group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
actor: actor,
|
||||
group: group
|
||||
} do
|
||||
_admin_member = insert(:member, %{actor: actor, parent: group, role: :creator})
|
||||
target_actor = insert(:actor, domain: "remote.tld")
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @invite_member_mutation,
|
||||
variables: %{
|
||||
groupId: group.id,
|
||||
targetActorUsername: "#{target_actor.preferred_username}@#{target_actor.domain}"
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
assert res["data"]["inviteMember"]["role"] == "INVITED"
|
||||
assert res["data"]["inviteMember"]["parent"]["id"] == to_string(group.id)
|
||||
assert res["data"]["inviteMember"]["actor"]["id"] == to_string(target_actor.id)
|
||||
end
|
||||
|
||||
test "invite_member/3 fails to invite a local actor to a group that invitor isn't in", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
actor: actor,
|
||||
group: group,
|
||||
target_actor: target_actor
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @invite_member_mutation,
|
||||
variables: %{
|
||||
groupId: group.id,
|
||||
targetActorUsername: target_actor.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "You are not a member of this group"
|
||||
end
|
||||
|
||||
test "invite_member/3 fails to invite a non existing local actor", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
actor: actor,
|
||||
group: group
|
||||
} do
|
||||
insert(:member, %{actor: actor, parent: group, role: :administrator})
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @invite_member_mutation,
|
||||
variables: %{
|
||||
groupId: group.id,
|
||||
targetActorUsername: "not_existing"
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "Actor invited doesn't exist"
|
||||
end
|
||||
|
||||
test "invite_member/3 fails to invite a non existing remote actor", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
actor: actor,
|
||||
group: group
|
||||
} do
|
||||
insert(:member, %{actor: actor, parent: group, role: :administrator})
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @invite_member_mutation,
|
||||
variables: %{
|
||||
groupId: group.id,
|
||||
targetActorUsername: "not_existing@nowhere.absolute"
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "Actor invited doesn't exist"
|
||||
end
|
||||
|
||||
test "invite_member/3 fails to invite a actor for a non-existing group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
actor: actor,
|
||||
target_actor: target_actor
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @invite_member_mutation,
|
||||
variables: %{
|
||||
groupId: "780907988778",
|
||||
targetActorUsername: target_actor.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "Group id not found"
|
||||
end
|
||||
|
||||
test "invite_member/3 fails to invite a actor if we are not an admin for the group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
actor: actor,
|
||||
group: group,
|
||||
target_actor: target_actor
|
||||
} do
|
||||
_admin_member = insert(:member, %{actor: actor, parent: group, role: :member})
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @invite_member_mutation,
|
||||
variables: %{
|
||||
groupId: group.id,
|
||||
targetActorUsername: target_actor.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "You cannot invite to this group"
|
||||
end
|
||||
|
||||
test "invite_member/3 fails to invite a actor if it's already a member of the group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
actor: actor,
|
||||
group: group,
|
||||
target_actor: target_actor
|
||||
} do
|
||||
insert(:member, %{actor: actor, parent: group, role: :member})
|
||||
insert(:member, %{actor: target_actor, parent: group, role: :member})
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @invite_member_mutation,
|
||||
variables: %{
|
||||
groupId: group.id,
|
||||
targetActorUsername: target_actor.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "You cannot invite to this group"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -483,11 +483,10 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do
|
||||
participant2 = insert(:participant, event: event, actor: actor3, role: :participant)
|
||||
|
||||
query = """
|
||||
{
|
||||
event(uuid: "#{event.uuid}") {
|
||||
participants(page: 1, limit: 1, roles: "participant,moderator,administrator,creator", actorId: "#{
|
||||
actor.id
|
||||
}") {
|
||||
query EventParticipants($uuid: UUID!, $actorId: ID, $roles: String, $page: Int, $limit: Int) {
|
||||
event(uuid: $uuid) {
|
||||
participants(page: $page, limit: $limit, roles: $roles, actorId: $actorId) {
|
||||
total,
|
||||
elements {
|
||||
role,
|
||||
actor {
|
||||
@@ -502,45 +501,21 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> get("/api", AbsintheHelpers.query_skeleton(query, "participants"))
|
||||
|
||||
sorted_participants =
|
||||
json_response(res, 200)["data"]["event"]["participants"]["elements"]
|
||||
|> Enum.filter(&(&1["role"] == "PARTICIPANT"))
|
||||
|
||||
assert sorted_participants == [
|
||||
%{
|
||||
"actor" => %{
|
||||
"preferredUsername" => participant2.actor.preferred_username
|
||||
},
|
||||
"role" => "PARTICIPANT"
|
||||
}
|
||||
]
|
||||
|
||||
query = """
|
||||
{
|
||||
event(uuid: "#{event.uuid}") {
|
||||
participants(page: 2, limit: 1, roles: "participant,moderator,administrator,creator", actorId: "#{
|
||||
actor.id
|
||||
}") {
|
||||
elements {
|
||||
role,
|
||||
actor {
|
||||
preferredUsername
|
||||
}
|
||||
}
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: query,
|
||||
variables: %{
|
||||
uuid: event.uuid,
|
||||
actorId: actor.id,
|
||||
roles: "participant,moderator,administrator,creator",
|
||||
page: 1,
|
||||
limit: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> get("/api", AbsintheHelpers.query_skeleton(query, "participants"))
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
sorted_participants =
|
||||
json_response(res, 200)["data"]["event"]["participants"]["elements"]
|
||||
res["data"]["event"]["participants"]["elements"]
|
||||
|> Enum.sort_by(
|
||||
&(&1
|
||||
|> Map.get("actor")
|
||||
@@ -555,6 +530,35 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do
|
||||
"role" => "CREATOR"
|
||||
}
|
||||
]
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: query,
|
||||
variables: %{
|
||||
uuid: event.uuid,
|
||||
actorId: actor.id,
|
||||
roles: "participant,moderator,administrator,creator",
|
||||
page: 2,
|
||||
limit: 1
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
sorted_participants =
|
||||
res["data"]["event"]["participants"]["elements"]
|
||||
|> Enum.filter(&(&1["role"] == "PARTICIPANT"))
|
||||
|
||||
assert sorted_participants == [
|
||||
%{
|
||||
"actor" => %{
|
||||
"preferredUsername" => participant2.actor.preferred_username
|
||||
},
|
||||
"role" => "PARTICIPANT"
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
test "stats_participants_for_event/3 give the number of (un)approved participants", %{
|
||||
@@ -1288,7 +1292,11 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do
|
||||
assert %Participant{
|
||||
role: :not_confirmed,
|
||||
metadata: %{confirmation_token: confirmation_token, email: @email}
|
||||
} = event.id |> Events.list_participants_for_event([]) |> Map.get(:elements) |> hd
|
||||
} =
|
||||
event.id
|
||||
|> Events.list_participants_for_event([:not_confirmed])
|
||||
|> Map.get(:elements)
|
||||
|> hd
|
||||
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
@@ -1307,7 +1315,10 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do
|
||||
}} = Events.get_event(event.id)
|
||||
|
||||
assert %Participant{role: :not_approved, id: participant_id} =
|
||||
event.id |> Events.list_participants_for_event([]) |> Map.get(:elements) |> hd
|
||||
event.id
|
||||
|> Events.list_participants_for_event([:not_approved])
|
||||
|> Map.get(:elements)
|
||||
|> hd
|
||||
|
||||
update_participation_mutation = """
|
||||
mutation UpdateParticipation($participantId: ID!, $role: String!, $moderatorActorId: ID!) {
|
||||
@@ -1339,7 +1350,10 @@ defmodule Mobilizon.GraphQL.Resolvers.ParticipantTest do
|
||||
assert res["errors"] == nil
|
||||
|
||||
assert %Participant{role: :participant} =
|
||||
event.id |> Events.list_participants_for_event([]) |> Map.get(:elements) |> hd
|
||||
event.id
|
||||
|> Events.list_participants_for_event([:participant])
|
||||
|> Map.get(:elements)
|
||||
|> hd
|
||||
|
||||
assert {:ok,
|
||||
%Event{
|
||||
|
||||
864
test/graphql/resolvers/resource_test.exs
Normal file
864
test/graphql/resolvers/resource_test.exs
Normal file
@@ -0,0 +1,864 @@
|
||||
defmodule Mobilizon.GraphQL.Resolvers.ResourceTest do
|
||||
use Mobilizon.Web.ConnCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Resources.Resource
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
alias Mobilizon.GraphQL.AbsintheHelpers
|
||||
|
||||
@metadata_fragment """
|
||||
fragment ResourceMetadataBasicFields on ResourceMetadata {
|
||||
imageRemoteUrl,
|
||||
height,
|
||||
width,
|
||||
type,
|
||||
faviconUrl
|
||||
}
|
||||
"""
|
||||
|
||||
@get_group_resources """
|
||||
query($name: String!) {
|
||||
group(preferredUsername: $name) {
|
||||
id,
|
||||
url,
|
||||
name,
|
||||
domain,
|
||||
summary,
|
||||
preferredUsername,
|
||||
resources(page: 1, limit: 3) {
|
||||
elements {
|
||||
id,
|
||||
title,
|
||||
resourceUrl,
|
||||
summary,
|
||||
updatedAt,
|
||||
type,
|
||||
path,
|
||||
metadata {
|
||||
...ResourceMetadataBasicFields
|
||||
}
|
||||
},
|
||||
total
|
||||
},
|
||||
}
|
||||
}
|
||||
#{@metadata_fragment}
|
||||
"""
|
||||
|
||||
@get_resource """
|
||||
query GetResource($path: String, $username: String) {
|
||||
resource(path: $path, username: $username) {
|
||||
id,
|
||||
title,
|
||||
summary,
|
||||
url,
|
||||
path,
|
||||
type,
|
||||
metadata {
|
||||
...ResourceMetadataBasicFields
|
||||
authorName,
|
||||
authorUrl,
|
||||
providerName,
|
||||
providerUrl,
|
||||
html
|
||||
},
|
||||
parent {
|
||||
id
|
||||
},
|
||||
actor {
|
||||
id,
|
||||
preferredUsername
|
||||
},
|
||||
children {
|
||||
total,
|
||||
elements {
|
||||
id,
|
||||
title,
|
||||
summary,
|
||||
url,
|
||||
type,
|
||||
path,
|
||||
resourceUrl,
|
||||
metadata {
|
||||
...ResourceMetadataBasicFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#{@metadata_fragment}
|
||||
"""
|
||||
|
||||
@create_resource """
|
||||
mutation CreateResource($title: String!, $parentId: ID, $summary: String, $actorId: ID!, $resourceUrl: String, $type: String) {
|
||||
createResource(title: $title, parentId: $parentId, summary: $summary, actorId: $actorId, resourceUrl: $resourceUrl, type: $type) {
|
||||
id,
|
||||
title,
|
||||
summary,
|
||||
url,
|
||||
resourceUrl,
|
||||
updatedAt,
|
||||
path,
|
||||
type,
|
||||
metadata {
|
||||
...ResourceMetadataBasicFields
|
||||
authorName,
|
||||
authorUrl,
|
||||
providerName,
|
||||
providerUrl,
|
||||
html
|
||||
}
|
||||
}
|
||||
}
|
||||
#{@metadata_fragment}
|
||||
"""
|
||||
|
||||
@update_resource """
|
||||
mutation UpdateResource($id: ID!, $title: String, $summary: String, $parentId: ID, $resourceUrl: String) {
|
||||
updateResource(id: $id, title: $title, parentId: $parentId, summary: $summary, resourceUrl: $resourceUrl) {
|
||||
id,
|
||||
title,
|
||||
summary,
|
||||
url,
|
||||
path,
|
||||
resourceUrl,
|
||||
type,
|
||||
children {
|
||||
total,
|
||||
elements {
|
||||
id,
|
||||
title,
|
||||
summary,
|
||||
url,
|
||||
type,
|
||||
path,
|
||||
resourceUrl,
|
||||
metadata {
|
||||
...ResourceMetadataBasicFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#{@metadata_fragment}
|
||||
"""
|
||||
|
||||
@delete_resource """
|
||||
mutation DeleteResource($id: ID!) {
|
||||
deleteResource(id: $id) {
|
||||
id
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
@resource_url "https://framasoft.org/fr/full"
|
||||
@resource_title "my resource"
|
||||
@updated_resource_title "my updated resource"
|
||||
@folder_title "my folder"
|
||||
|
||||
setup do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{} = actor = insert(:actor, user: user)
|
||||
%Actor{} = group = insert(:group)
|
||||
%Member{} = insert(:member, parent: group, actor: actor, role: :member)
|
||||
resource_in_root = %Resource{} = insert(:resource, actor: group)
|
||||
|
||||
folder_in_root =
|
||||
%Resource{id: parent_id, path: parent_path} =
|
||||
insert(:resource,
|
||||
type: :folder,
|
||||
resource_url: nil,
|
||||
actor: group,
|
||||
title: "root folder",
|
||||
path: "/root folder"
|
||||
)
|
||||
|
||||
resource_in_folder =
|
||||
%Resource{} =
|
||||
insert(:resource,
|
||||
resource_url: nil,
|
||||
actor: group,
|
||||
parent_id: parent_id,
|
||||
path: "#{parent_path}/titre",
|
||||
title: "titre"
|
||||
)
|
||||
|
||||
{:ok,
|
||||
user: user,
|
||||
group: group,
|
||||
root_resources: [folder_in_root, resource_in_root],
|
||||
resource_in_folder: resource_in_folder}
|
||||
end
|
||||
|
||||
describe "Resolver: Get group's resources" do
|
||||
test "find_resources_for_group/3", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group,
|
||||
root_resources: root_resources,
|
||||
resource_in_folder: resource_in_folder
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_group_resources,
|
||||
variables: %{
|
||||
name: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["group"]["resources"]["total"] == 3
|
||||
|
||||
assert res["data"]["group"]["resources"]["elements"]
|
||||
|> Enum.map(&{&1["path"], &1["type"]})
|
||||
|> MapSet.new() ==
|
||||
(root_resources ++ [resource_in_folder])
|
||||
|> Enum.map(&{&1.path, Atom.to_string(&1.type)})
|
||||
|> MapSet.new()
|
||||
end
|
||||
|
||||
test "find_resources_for_group/3 when not member of group", %{
|
||||
conn: conn,
|
||||
group: group
|
||||
} do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{} = insert(:actor, user: user)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_group_resources,
|
||||
variables: %{
|
||||
name: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["group"]["resources"]["total"] == 0
|
||||
assert res["data"]["group"]["resources"]["elements"] == []
|
||||
end
|
||||
|
||||
test "find_resources_for_group/3 when not connected", %{
|
||||
conn: conn,
|
||||
group: group
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_group_resources,
|
||||
variables: %{
|
||||
name: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["group"]["resources"]["total"] == 0
|
||||
assert res["data"]["group"]["resources"]["elements"] == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "Resolver: Get a specific resource" do
|
||||
test "get_resource/3 for the root path", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group,
|
||||
root_resources: root_resources
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_resource,
|
||||
variables: %{
|
||||
path: "/",
|
||||
username: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["resource"]["path"] == "/"
|
||||
assert String.starts_with?(res["data"]["resource"]["id"], "root_")
|
||||
|
||||
assert res["data"]["resource"]["children"]["elements"]
|
||||
|> Enum.map(& &1["id"])
|
||||
|> MapSet.new() == root_resources |> Enum.map(& &1.id) |> MapSet.new()
|
||||
end
|
||||
|
||||
test "get_resource/3 for a folder path", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group,
|
||||
root_resources: [root_folder, _],
|
||||
resource_in_folder: resource_in_folder
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_resource,
|
||||
variables: %{
|
||||
path: root_folder.path,
|
||||
username: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["resource"]["type"] == "folder"
|
||||
assert res["data"]["resource"]["path"] == root_folder.path
|
||||
assert is_nil(res["data"]["resource"]["parent"]["id"])
|
||||
|
||||
assert res["data"]["resource"]["children"]["total"] == 1
|
||||
|
||||
assert res["data"]["resource"]["children"]["elements"]
|
||||
|> Enum.map(& &1["id"])
|
||||
|> MapSet.new() == [resource_in_folder] |> Enum.map(& &1.id) |> MapSet.new()
|
||||
end
|
||||
|
||||
test "get_resource/3 for a non-existing path", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_resource,
|
||||
variables: %{
|
||||
path: "/non existing",
|
||||
username: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "No such resource"
|
||||
end
|
||||
|
||||
test "get_resource/3 for a non-existing group", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
} do
|
||||
%Actor{preferred_username: group_name} = insert(:group)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_resource,
|
||||
variables: %{
|
||||
path: "/non existing",
|
||||
username: group_name
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "Actor is not member of group"
|
||||
end
|
||||
|
||||
test "get_resource/3 when not connected", %{
|
||||
conn: conn,
|
||||
group: group,
|
||||
resource_in_folder: resource_in_folder
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_resource,
|
||||
variables: %{
|
||||
path: resource_in_folder.path,
|
||||
username: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "You need to be logged-in to access resources"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Resolver: Create a resource" do
|
||||
test "create_resource/3 creates a resource for a group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @create_resource,
|
||||
variables: %{
|
||||
title: @resource_title,
|
||||
parentId: nil,
|
||||
actorId: group.id,
|
||||
resourceUrl: @resource_url
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["createResource"]["metadata"]["faviconUrl"] ==
|
||||
"https://framasoft.org/icons/favicon.png"
|
||||
|
||||
assert res["data"]["createResource"]["metadata"]["imageRemoteUrl"] ==
|
||||
"https://framasoft.org/img/opengraph/full.jpg"
|
||||
|
||||
assert res["data"]["createResource"]["path"] == "/#{@resource_title}"
|
||||
assert res["data"]["createResource"]["resourceUrl"] == @resource_url
|
||||
assert res["data"]["createResource"]["title"] == @resource_title
|
||||
assert res["data"]["createResource"]["type"] == "link"
|
||||
end
|
||||
|
||||
test "create_resource/3 creates a folder", %{conn: conn, user: user, group: group} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @create_resource,
|
||||
variables: %{
|
||||
title: @folder_title,
|
||||
parentId: nil,
|
||||
actorId: group.id,
|
||||
type: "folder"
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["createResource"]["path"] == "/#{@folder_title}"
|
||||
assert res["data"]["createResource"]["title"] == @folder_title
|
||||
assert res["data"]["createResource"]["type"] == "folder"
|
||||
end
|
||||
|
||||
test "create_resource/3 creates a resource in a folder", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group
|
||||
} do
|
||||
%Resource{id: parent_id, path: parent_path} =
|
||||
insert(:resource, type: :folder, resource_url: nil, actor: group)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @create_resource,
|
||||
variables: %{
|
||||
title: @resource_title,
|
||||
parentId: parent_id,
|
||||
actorId: group.id,
|
||||
resourceUrl: @resource_url
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["createResource"]["metadata"]["faviconUrl"] ==
|
||||
"https://framasoft.org/icons/favicon.png"
|
||||
|
||||
assert res["data"]["createResource"]["metadata"]["imageRemoteUrl"] ==
|
||||
"https://framasoft.org/img/opengraph/full.jpg"
|
||||
|
||||
assert res["data"]["createResource"]["path"] == "#{parent_path}/#{@resource_title}"
|
||||
assert res["data"]["createResource"]["resourceUrl"] == @resource_url
|
||||
assert res["data"]["createResource"]["title"] == @resource_title
|
||||
assert res["data"]["createResource"]["type"] == "link"
|
||||
end
|
||||
|
||||
test "create_resource/3 doesn't create a resource in a folder if no group is defined", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @create_resource,
|
||||
variables: %{
|
||||
title: @resource_title,
|
||||
parentId: nil,
|
||||
resourceUrl: @resource_url
|
||||
}
|
||||
)
|
||||
|
||||
assert Enum.map(res["errors"], & &1["message"]) == [
|
||||
"In argument \"actorId\": Expected type \"ID!\", found null.",
|
||||
"Variable \"actorId\": Expected non-null, found null."
|
||||
]
|
||||
end
|
||||
|
||||
test "create_resource/3 doesn't create a resource if the actor is not a member of the group",
|
||||
%{
|
||||
conn: conn,
|
||||
group: group
|
||||
} do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{} = insert(:actor, user: user)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @create_resource,
|
||||
variables: %{
|
||||
title: @resource_title,
|
||||
parentId: nil,
|
||||
actorId: group.id,
|
||||
resourceUrl: @resource_url
|
||||
}
|
||||
)
|
||||
|
||||
assert Enum.map(res["errors"], & &1["message"]) == [
|
||||
"Actor id is not member of group"
|
||||
]
|
||||
end
|
||||
|
||||
test "create_resource/3 doesn't create a resource if the referenced parent folder is not owned by the group",
|
||||
%{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group
|
||||
} do
|
||||
%Actor{} = group2 = insert(:group)
|
||||
|
||||
%Resource{id: parent_id} =
|
||||
insert(:resource, type: :folder, resource_url: nil, actor: group2)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @create_resource,
|
||||
variables: %{
|
||||
title: @resource_title,
|
||||
parentId: parent_id,
|
||||
actorId: group.id,
|
||||
resourceUrl: @resource_url
|
||||
}
|
||||
)
|
||||
|
||||
assert Enum.map(res["errors"], & &1["message"]) == [
|
||||
"Parent resource doesn't match this group"
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe "Resolver: Update a resource" do
|
||||
test "update_resource/3 renames a resource for a group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group
|
||||
} do
|
||||
%Resource{id: resource_id} = insert(:resource, resource_url: @resource_url, actor: group)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @update_resource,
|
||||
variables: %{
|
||||
id: resource_id,
|
||||
title: @updated_resource_title
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["updateResource"]["path"] == "/#{@updated_resource_title}"
|
||||
assert res["data"]["updateResource"]["resourceUrl"] == @resource_url
|
||||
assert res["data"]["updateResource"]["title"] == @updated_resource_title
|
||||
assert res["data"]["updateResource"]["type"] == "link"
|
||||
end
|
||||
|
||||
test "update_resource/3 moves and renames a resource for a group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group,
|
||||
root_resources: [root_folder, _]
|
||||
} do
|
||||
%Resource{id: resource_id} = insert(:resource, resource_url: @resource_url, actor: group)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @update_resource,
|
||||
variables: %{
|
||||
id: resource_id,
|
||||
title: @updated_resource_title,
|
||||
parentId: root_folder.id
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["updateResource"]["path"] ==
|
||||
"#{root_folder.path}/#{@updated_resource_title}"
|
||||
|
||||
assert res["data"]["updateResource"]["resourceUrl"] == @resource_url
|
||||
assert res["data"]["updateResource"]["title"] == @updated_resource_title
|
||||
assert res["data"]["updateResource"]["type"] == "link"
|
||||
end
|
||||
|
||||
test "update_resource/3 moves a resource in a subfolder for a group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group,
|
||||
root_resources: [root_folder, _]
|
||||
} do
|
||||
%Resource{id: resource_id} =
|
||||
resource = insert(:resource, resource_url: @resource_url, actor: group)
|
||||
|
||||
folder =
|
||||
insert(:resource,
|
||||
parent_id: root_folder.id,
|
||||
actor: group,
|
||||
path: "#{root_folder.path}/subfolder",
|
||||
title: "subfolder"
|
||||
)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @update_resource,
|
||||
variables: %{
|
||||
id: resource_id,
|
||||
parentId: folder.id
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["updateResource"]["path"] ==
|
||||
"#{folder.path}/#{resource.title}"
|
||||
|
||||
assert res["data"]["updateResource"]["resourceUrl"] == @resource_url
|
||||
assert res["data"]["updateResource"]["title"] == resource.title
|
||||
assert res["data"]["updateResource"]["type"] == "link"
|
||||
end
|
||||
|
||||
test "update_resource/3 renames a folder and all the paths for it's children", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group,
|
||||
root_resources: [root_folder, _]
|
||||
} do
|
||||
folder =
|
||||
insert(:resource,
|
||||
parent_id: root_folder.id,
|
||||
actor: group,
|
||||
path: "#{root_folder.path}/subfolder",
|
||||
title: "subfolder",
|
||||
type: :folder
|
||||
)
|
||||
|
||||
%Resource{} =
|
||||
insert(:resource,
|
||||
resource_url: @resource_url,
|
||||
actor: group,
|
||||
parent_id: folder.id,
|
||||
path: "#{folder.path}/titre",
|
||||
title: "titre"
|
||||
)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @update_resource,
|
||||
variables: %{
|
||||
id: folder.id,
|
||||
title: "updated subfolder"
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["updateResource"]["path"] ==
|
||||
"#{root_folder.path}/updated subfolder"
|
||||
|
||||
assert res["data"]["updateResource"]["title"] == "updated subfolder"
|
||||
assert res["data"]["updateResource"]["type"] == "folder"
|
||||
|
||||
assert hd(res["data"]["updateResource"]["children"]["elements"])["path"] ==
|
||||
"#{root_folder.path}/updated subfolder/titre"
|
||||
end
|
||||
|
||||
test "update_resource/3 moves a folder and updates all the paths for it's children", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group,
|
||||
root_resources: [root_folder, _]
|
||||
} do
|
||||
folder =
|
||||
insert(:resource,
|
||||
parent_id: nil,
|
||||
actor: group,
|
||||
path: "/subfolder",
|
||||
title: "subfolder",
|
||||
type: :folder
|
||||
)
|
||||
|
||||
%Resource{} =
|
||||
insert(:resource,
|
||||
resource_url: @resource_url,
|
||||
actor: group,
|
||||
parent_id: folder.id,
|
||||
path: "#{folder.path}/titre",
|
||||
title: "titre"
|
||||
)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @update_resource,
|
||||
variables: %{
|
||||
id: folder.id,
|
||||
parentId: root_folder.id,
|
||||
title: "updated subfolder"
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["updateResource"]["path"] ==
|
||||
"#{root_folder.path}/updated subfolder"
|
||||
|
||||
assert res["data"]["updateResource"]["title"] == "updated subfolder"
|
||||
assert res["data"]["updateResource"]["type"] == "folder"
|
||||
|
||||
assert hd(res["data"]["updateResource"]["children"]["elements"])["path"] ==
|
||||
"#{root_folder.path}/updated subfolder/titre"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Resolver: Delete a resource" do
|
||||
test "delete_resource/3 deletes a resource", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group
|
||||
} do
|
||||
%Resource{id: resource_id, path: resource_path} =
|
||||
insert(:resource,
|
||||
resource_url: @resource_url,
|
||||
actor: group,
|
||||
parent_id: nil
|
||||
)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @delete_resource,
|
||||
variables: %{
|
||||
id: resource_id
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
assert res["data"]["deleteResource"]["id"] == resource_id
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_resource,
|
||||
variables: %{
|
||||
path: resource_path,
|
||||
username: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "No such resource"
|
||||
end
|
||||
|
||||
test "delete_resource/3 deletes a folder and children", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group
|
||||
} do
|
||||
%Resource{id: folder_id, path: folder_path} =
|
||||
insert(:resource,
|
||||
parent_id: nil,
|
||||
actor: group,
|
||||
path: "/subfolder",
|
||||
title: "subfolder",
|
||||
type: :folder
|
||||
)
|
||||
|
||||
%Resource{path: resource_path} =
|
||||
insert(:resource,
|
||||
resource_url: @resource_url,
|
||||
actor: group,
|
||||
parent_id: folder_id,
|
||||
path: "#{folder_path}/titre",
|
||||
title: "titre"
|
||||
)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @delete_resource,
|
||||
variables: %{
|
||||
id: folder_id
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
assert res["data"]["deleteResource"]["id"] == folder_id
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_resource,
|
||||
variables: %{
|
||||
path: folder_path,
|
||||
username: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "No such resource"
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_resource,
|
||||
variables: %{
|
||||
path: resource_path,
|
||||
username: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "No such resource"
|
||||
end
|
||||
|
||||
test "delete_resource/3 deletes a resource not found", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @delete_resource,
|
||||
variables: %{
|
||||
id: "58869b5b-2beb-423a-b483-1585d847e2cc"
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "Resource doesn't exist"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,9 +5,10 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.{Actors, Config, Events, Users}
|
||||
alias Mobilizon.{Actors, Config, Conversations, Events, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events.{Comment, Event, Participant}
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
alias Mobilizon.GraphQL.AbsintheHelpers
|
||||
@@ -1424,7 +1425,7 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do
|
||||
end
|
||||
|
||||
assert_raise Ecto.NoResultsError, fn ->
|
||||
Events.get_comment!(comment_id)
|
||||
Conversations.get_comment!(comment_id)
|
||||
end
|
||||
|
||||
# Actors are not deleted but emptied (to keep the username reserved)
|
||||
|
||||
@@ -5,9 +5,10 @@ defmodule Mobilizon.ActorsTest do
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.{Actors, Config, Events, Tombstone, Users}
|
||||
alias Mobilizon.{Actors, Config, Conversations, Events, Tombstone, Users}
|
||||
alias Mobilizon.Actors.{Actor, Bot, Follower, Member}
|
||||
alias Mobilizon.Events.{Comment, Event}
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Media.File, as: FileModel
|
||||
alias Mobilizon.Service.Workers
|
||||
alias Mobilizon.Storage.Page
|
||||
@@ -331,7 +332,7 @@ defmodule Mobilizon.ActorsTest do
|
||||
|
||||
assert {:error, :event_not_found} = Events.get_event(event1.id)
|
||||
assert %Tombstone{} = Tombstone.find_tombstone(event1_url)
|
||||
assert %Comment{deleted_at: deleted_at} = Events.get_comment(comment1.id)
|
||||
assert %Comment{deleted_at: deleted_at} = Conversations.get_comment(comment1.id)
|
||||
refute is_nil(deleted_at)
|
||||
assert %Tombstone{} = Tombstone.find_tombstone(comment1_url)
|
||||
|
||||
@@ -363,7 +364,11 @@ defmodule Mobilizon.ActorsTest do
|
||||
@invalid_attrs %{summary: nil, suspended: nil, preferred_username: nil, name: nil}
|
||||
|
||||
test "create_group/1 with valid data creates a group" do
|
||||
assert {:ok, %Actor{} = group} = Actors.create_group(@valid_attrs)
|
||||
%Actor{id: actor_id} = insert(:actor)
|
||||
|
||||
assert {:ok, %Actor{} = group} =
|
||||
Actors.create_group(Map.put(@valid_attrs, :creator_actor_id, actor_id))
|
||||
|
||||
assert group.summary == "some description"
|
||||
refute group.suspended
|
||||
assert group.preferred_username == "some-title"
|
||||
@@ -372,21 +377,23 @@ defmodule Mobilizon.ActorsTest do
|
||||
test "create_group/1 with an existing profile username fails" do
|
||||
_actor = insert(:actor, preferred_username: @valid_attrs.preferred_username)
|
||||
|
||||
assert {:error,
|
||||
%Ecto.Changeset{errors: [preferred_username: {"Username is already taken", []}]}} =
|
||||
Actors.create_group(@valid_attrs)
|
||||
assert {:error, :insert_group,
|
||||
%Ecto.Changeset{errors: [preferred_username: {"Username is already taken", []}]},
|
||||
%{}} = Actors.create_group(@valid_attrs)
|
||||
end
|
||||
|
||||
test "create_group/1 with an existing group username fails" do
|
||||
assert {:ok, %Actor{} = group} = Actors.create_group(@valid_attrs)
|
||||
%Actor{id: actor_id} = insert(:actor)
|
||||
attrs = Map.put(@valid_attrs, :creator_actor_id, actor_id)
|
||||
assert {:ok, %Actor{} = group} = Actors.create_group(attrs)
|
||||
|
||||
assert {:error,
|
||||
%Ecto.Changeset{errors: [preferred_username: {"Username is already taken", []}]}} =
|
||||
Actors.create_group(@valid_attrs)
|
||||
assert {:error, :insert_group,
|
||||
%Ecto.Changeset{errors: [preferred_username: {"Username is already taken", []}]},
|
||||
%{}} = Actors.create_group(attrs)
|
||||
end
|
||||
|
||||
test "create_group/1 with invalid data returns error changeset" do
|
||||
assert {:error, %Ecto.Changeset{}} = Actors.create_group(@invalid_attrs)
|
||||
assert {:error, :insert_group, %Ecto.Changeset{}, %{}} = Actors.create_group(@invalid_attrs)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -588,7 +595,7 @@ defmodule Mobilizon.ActorsTest do
|
||||
assert member.role == :member
|
||||
|
||||
assert [group] = Actors.list_groups_member_of(actor)
|
||||
assert [actor] = Actors.list_members_for_group(group)
|
||||
assert %Page{elements: [actor], total: 1} = Actors.list_members_for_group(group)
|
||||
end
|
||||
|
||||
test "create_member/1 with valid data but same actors fails to create a member", %{
|
||||
|
||||
72
test/mobilizon/conversations_test.exs
Normal file
72
test/mobilizon/conversations_test.exs
Normal file
@@ -0,0 +1,72 @@
|
||||
defmodule Mobilizon.ConversationsTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Conversations
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Service.Workers
|
||||
alias Mobilizon.Storage.Page
|
||||
|
||||
describe "comments" do
|
||||
@valid_attrs %{text: "some text"}
|
||||
@update_attrs %{text: "some updated text"}
|
||||
@invalid_attrs %{text: nil, url: nil}
|
||||
|
||||
test "list_comments/0 returns all comments" do
|
||||
%Comment{id: comment_id} = insert(:comment)
|
||||
comment_ids = Conversations.list_comments() |> Enum.map(& &1.id)
|
||||
assert comment_ids == [comment_id]
|
||||
end
|
||||
|
||||
test "get_comment!/1 returns the comment with given id" do
|
||||
%Comment{id: comment_id} = insert(:comment)
|
||||
comment_fetched = Conversations.get_comment!(comment_id)
|
||||
assert comment_fetched.id == comment_id
|
||||
end
|
||||
|
||||
test "create_comment/1 with valid data creates a comment" do
|
||||
%Actor{} = actor = insert(:actor)
|
||||
comment_data = Map.merge(@valid_attrs, %{actor_id: actor.id})
|
||||
|
||||
case Conversations.create_comment(comment_data) do
|
||||
{:ok, %Comment{} = comment} ->
|
||||
assert comment.text == "some text"
|
||||
assert comment.actor_id == actor.id
|
||||
|
||||
err ->
|
||||
flunk("Failed to create a comment #{inspect(err)}")
|
||||
end
|
||||
end
|
||||
|
||||
test "create_comment/1 with invalid data returns error changeset" do
|
||||
assert {:error, %Ecto.Changeset{}} = Conversations.create_comment(@invalid_attrs)
|
||||
end
|
||||
|
||||
test "update_comment/2 with valid data updates the comment" do
|
||||
%Comment{} = comment = insert(:comment)
|
||||
|
||||
case Conversations.update_comment(comment, @update_attrs) do
|
||||
{:ok, %Comment{} = comment} ->
|
||||
assert comment.text == "some updated text"
|
||||
|
||||
err ->
|
||||
flunk("Failed to update a comment #{inspect(err)}")
|
||||
end
|
||||
end
|
||||
|
||||
test "update_comment/2 with invalid data returns error changeset" do
|
||||
%Comment{} = comment = insert(:comment)
|
||||
assert {:error, %Ecto.Changeset{}} = Conversations.update_comment(comment, @invalid_attrs)
|
||||
%Comment{} = comment_fetched = Conversations.get_comment!(comment.id)
|
||||
assert comment = comment_fetched
|
||||
end
|
||||
|
||||
test "delete_comment/1 deletes the comment" do
|
||||
%Comment{} = comment = insert(:comment)
|
||||
assert {:ok, %Comment{}} = Conversations.delete_comment(comment)
|
||||
refute is_nil(Conversations.get_comment!(comment.id).deleted_at)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,8 +4,9 @@ defmodule Mobilizon.EventsTest do
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.{Comment, Event, Participant, Session, Tag, TagRelation, Track}
|
||||
alias Mobilizon.{Conversations, Events}
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Events.{Event, Participant, Session, Tag, TagRelation, Track}
|
||||
alias Mobilizon.Service.Workers
|
||||
alias Mobilizon.Storage.Page
|
||||
|
||||
@@ -530,65 +531,4 @@ defmodule Mobilizon.EventsTest do
|
||||
assert_raise Ecto.NoResultsError, fn -> Events.get_track!(track.id) end
|
||||
end
|
||||
end
|
||||
|
||||
describe "comments" do
|
||||
@valid_attrs %{text: "some text"}
|
||||
@update_attrs %{text: "some updated text"}
|
||||
@invalid_attrs %{text: nil, url: nil}
|
||||
|
||||
test "list_comments/0 returns all comments" do
|
||||
%Comment{id: comment_id} = insert(:comment)
|
||||
comment_ids = Events.list_comments() |> Enum.map(& &1.id)
|
||||
assert comment_ids == [comment_id]
|
||||
end
|
||||
|
||||
test "get_comment!/1 returns the comment with given id" do
|
||||
%Comment{id: comment_id} = insert(:comment)
|
||||
comment_fetched = Events.get_comment!(comment_id)
|
||||
assert comment_fetched.id == comment_id
|
||||
end
|
||||
|
||||
test "create_comment/1 with valid data creates a comment" do
|
||||
actor = insert(:actor)
|
||||
comment_data = Map.merge(@valid_attrs, %{actor_id: actor.id})
|
||||
|
||||
case Events.create_comment(comment_data) do
|
||||
{:ok, %Comment{} = comment} ->
|
||||
assert comment.text == "some text"
|
||||
assert comment.actor_id == actor.id
|
||||
|
||||
err ->
|
||||
flunk("Failed to create a comment #{inspect(err)}")
|
||||
end
|
||||
end
|
||||
|
||||
test "create_comment/1 with invalid data returns error changeset" do
|
||||
assert {:error, %Ecto.Changeset{}} = Events.create_comment(@invalid_attrs)
|
||||
end
|
||||
|
||||
test "update_comment/2 with valid data updates the comment" do
|
||||
comment = insert(:comment)
|
||||
|
||||
case Events.update_comment(comment, @update_attrs) do
|
||||
{:ok, %Comment{} = comment} ->
|
||||
assert comment.text == "some updated text"
|
||||
|
||||
err ->
|
||||
flunk("Failed to update a comment #{inspect(err)}")
|
||||
end
|
||||
end
|
||||
|
||||
test "update_comment/2 with invalid data returns error changeset" do
|
||||
comment = insert(:comment)
|
||||
assert {:error, %Ecto.Changeset{}} = Events.update_comment(comment, @invalid_attrs)
|
||||
comment_fetched = Events.get_comment!(comment.id)
|
||||
assert comment = comment_fetched
|
||||
end
|
||||
|
||||
test "delete_comment/1 deletes the comment" do
|
||||
comment = insert(:comment)
|
||||
assert {:ok, %Comment{}} = Events.delete_comment(comment)
|
||||
refute is_nil(Events.get_comment!(comment.id).deleted_at)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ defmodule Mobilizon.UsersTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
alias Mobilizon.Users
|
||||
alias Mobilizon.Users.User
|
||||
alias Mobilizon.Users.{Setting, User}
|
||||
import Mobilizon.Factory
|
||||
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
||||
|
||||
@@ -101,4 +101,60 @@ defmodule Mobilizon.UsersTest do
|
||||
assert id == user.id
|
||||
end
|
||||
end
|
||||
|
||||
describe "user_settings" do
|
||||
@valid_attrs %{timezone: "Europe/Paris", notification_each_week: true}
|
||||
@update_attrs %{timezone: "Atlantic/Cape_Verde", notification_each_week: false}
|
||||
@invalid_attrs %{timezone: nil, notification_each_week: nil}
|
||||
|
||||
def setting_fixture(attrs \\ %{}) do
|
||||
{:ok, setting} =
|
||||
attrs
|
||||
|> Enum.into(@valid_attrs)
|
||||
|> Users.create_setting()
|
||||
|
||||
setting
|
||||
end
|
||||
|
||||
test "get_setting!/1 returns the setting with given id" do
|
||||
%User{id: user_id} = insert(:user)
|
||||
setting = setting_fixture(user_id: user_id)
|
||||
assert Users.get_setting!(setting.user_id) == setting
|
||||
end
|
||||
|
||||
test "create_setting/1 with valid data creates a setting" do
|
||||
%User{id: user_id} = insert(:user)
|
||||
|
||||
assert {:ok, %Setting{} = setting} =
|
||||
Users.create_setting(Map.put(@valid_attrs, :user_id, user_id))
|
||||
|
||||
assert setting.timezone == "Europe/Paris"
|
||||
assert setting.notification_each_week == true
|
||||
end
|
||||
|
||||
test "create_setting/1 with invalid data returns error changeset" do
|
||||
assert {:error, %Ecto.Changeset{}} = Users.create_setting(@invalid_attrs)
|
||||
end
|
||||
|
||||
test "update_setting/2 with valid data updates the setting" do
|
||||
%User{id: user_id} = insert(:user)
|
||||
setting = setting_fixture(user_id: user_id)
|
||||
assert {:ok, %Setting{} = setting} = Users.update_setting(setting, @update_attrs)
|
||||
assert setting.timezone == "Atlantic/Cape_Verde"
|
||||
assert setting.notification_each_week == false
|
||||
end
|
||||
|
||||
test "delete_setting/1 deletes the setting" do
|
||||
%User{id: user_id} = insert(:user)
|
||||
setting = setting_fixture(user_id: user_id)
|
||||
assert {:ok, %Setting{}} = Users.delete_setting(setting)
|
||||
assert_raise Ecto.NoResultsError, fn -> Users.get_setting!(setting.user_id) end
|
||||
end
|
||||
|
||||
test "change_setting/1 returns a setting changeset" do
|
||||
%User{id: user_id} = insert(:user)
|
||||
setting = setting_fixture(user_id: user_id)
|
||||
assert %Ecto.Changeset{} = Users.change_setting(setting)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,11 @@ defmodule Mobilizon.Service.Geospatial.AddokTest do
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Service.Geospatial.Addok
|
||||
|
||||
@http_options [
|
||||
follow_redirect: true,
|
||||
ssl: [{:versions, [:"tlsv1.2"]}]
|
||||
]
|
||||
|
||||
setup do
|
||||
# Config.instance_user_agent/0 makes database calls so because of ownership connection
|
||||
# we need to define it like this instead of a constant
|
||||
@@ -24,17 +29,21 @@ defmodule Mobilizon.Service.Geospatial.AddokTest do
|
||||
|
||||
describe "search address" do
|
||||
test "produces a valid search address", %{httpoison_headers: httpoison_headers} do
|
||||
with_mock HTTPoison, get: fn _url, _headers -> "{}" end do
|
||||
with_mock HTTPoison, get: fn _url, _headers, _options -> "{}" end do
|
||||
Addok.search("10 Rue Jangot")
|
||||
|
||||
assert_called(
|
||||
HTTPoison.get("#{@endpoint}/search/?q=10%20Rue%20Jangot&limit=10", httpoison_headers)
|
||||
HTTPoison.get(
|
||||
"#{@endpoint}/search/?q=10%20Rue%20Jangot&limit=10",
|
||||
httpoison_headers,
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "produces a valid search address with options", %{httpoison_headers: httpoison_headers} do
|
||||
with_mock HTTPoison, get: fn _url, _headers -> "{}" end do
|
||||
with_mock HTTPoison, get: fn _url, _headers, _options -> "{}" end do
|
||||
Addok.search("10 Rue Jangot",
|
||||
endpoint: @fake_endpoint,
|
||||
limit: 5,
|
||||
@@ -44,7 +53,8 @@ defmodule Mobilizon.Service.Geospatial.AddokTest do
|
||||
assert_called(
|
||||
HTTPoison.get(
|
||||
"#{@fake_endpoint}/search/?q=10%20Rue%20Jangot&limit=5&lat=49&lon=12",
|
||||
httpoison_headers
|
||||
httpoison_headers,
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -8,6 +8,11 @@ defmodule Mobilizon.Service.Geospatial.GoogleMapsTest do
|
||||
alias Mobilizon.Addresses.Address
|
||||
alias Mobilizon.Service.Geospatial.GoogleMaps
|
||||
|
||||
@http_options [
|
||||
follow_redirect: true,
|
||||
ssl: [{:versions, [:"tlsv1.2"]}]
|
||||
]
|
||||
|
||||
describe "search address" do
|
||||
test "without API Key triggers an error" do
|
||||
assert_raise ArgumentError, "API Key required to use Google Maps", fn ->
|
||||
@@ -17,7 +22,7 @@ defmodule Mobilizon.Service.Geospatial.GoogleMapsTest do
|
||||
|
||||
test "produces a valid search address with options" do
|
||||
with_mock HTTPoison,
|
||||
get: fn _url ->
|
||||
get: fn _url, _headers, _options ->
|
||||
{:ok,
|
||||
%HTTPoison.Response{status_code: 200, body: "{\"status\": \"OK\", \"results\": []}"}}
|
||||
end do
|
||||
@@ -29,7 +34,9 @@ defmodule Mobilizon.Service.Geospatial.GoogleMapsTest do
|
||||
|
||||
assert_called(
|
||||
HTTPoison.get(
|
||||
"https://maps.googleapis.com/maps/api/geocode/json?limit=5&key=toto&language=fr&address=10%20Rue%20Jangot"
|
||||
"https://maps.googleapis.com/maps/api/geocode/json?limit=5&key=toto&language=fr&address=10%20Rue%20Jangot",
|
||||
[],
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -9,6 +9,11 @@ defmodule Mobilizon.Service.Geospatial.MapQuestTest do
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Service.Geospatial.MapQuest
|
||||
|
||||
@http_options [
|
||||
follow_redirect: true,
|
||||
ssl: [{:versions, [:"tlsv1.2"]}]
|
||||
]
|
||||
|
||||
setup do
|
||||
# Config.instance_user_agent/0 makes database calls so because of ownership connection
|
||||
# we need to define it like this instead of a constant
|
||||
@@ -28,7 +33,7 @@ defmodule Mobilizon.Service.Geospatial.MapQuestTest do
|
||||
|
||||
test "produces a valid search address with options", %{httpoison_headers: httpoison_headers} do
|
||||
with_mock HTTPoison,
|
||||
get: fn _url, _headers ->
|
||||
get: fn _url, _headers, _options ->
|
||||
{:ok,
|
||||
%HTTPoison.Response{
|
||||
status_code: 200,
|
||||
@@ -44,7 +49,8 @@ defmodule Mobilizon.Service.Geospatial.MapQuestTest do
|
||||
assert_called(
|
||||
HTTPoison.get(
|
||||
"https://open.mapquestapi.com/geocoding/v1/address?key=toto&location=10%20Rue%20Jangot&maxResults=5",
|
||||
httpoison_headers
|
||||
httpoison_headers,
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -7,6 +7,11 @@ defmodule Mobilizon.Service.Geospatial.NominatimTest do
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Service.Geospatial.Nominatim
|
||||
|
||||
@http_options [
|
||||
follow_redirect: true,
|
||||
ssl: [{:versions, [:"tlsv1.2"]}]
|
||||
]
|
||||
|
||||
setup do
|
||||
# Config.instance_user_agent/0 makes database calls so because of ownership connection
|
||||
# we need to define it like this instead of a constant
|
||||
@@ -20,7 +25,7 @@ defmodule Mobilizon.Service.Geospatial.NominatimTest do
|
||||
describe "search address" do
|
||||
test "produces a valid search address with options", %{httpoison_headers: httpoison_headers} do
|
||||
with_mock HTTPoison,
|
||||
get: fn _url, _headers ->
|
||||
get: fn _url, _headers, _options ->
|
||||
{:ok, %HTTPoison.Response{status_code: 200, body: "[]"}}
|
||||
end do
|
||||
Nominatim.search("10 Rue Jangot",
|
||||
@@ -31,7 +36,8 @@ defmodule Mobilizon.Service.Geospatial.NominatimTest do
|
||||
assert_called(
|
||||
HTTPoison.get(
|
||||
"https://nominatim.openstreetmap.org/search?format=geocodejson&q=10%20Rue%20Jangot&limit=5&accept-language=fr&addressdetails=1&namedetails=1",
|
||||
httpoison_headers
|
||||
httpoison_headers,
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -9,6 +9,11 @@ defmodule Mobilizon.Service.Geospatial.PhotonTest do
|
||||
alias Mobilizon.Config
|
||||
alias Mobilizon.Service.Geospatial.Photon
|
||||
|
||||
@http_options [
|
||||
follow_redirect: true,
|
||||
ssl: [{:versions, [:"tlsv1.2"]}]
|
||||
]
|
||||
|
||||
setup do
|
||||
# Config.instance_user_agent/0 makes database calls so because of ownership connection
|
||||
# we need to define it like this instead of a constant
|
||||
@@ -22,7 +27,7 @@ defmodule Mobilizon.Service.Geospatial.PhotonTest do
|
||||
describe "search address" do
|
||||
test "produces a valid search address with options", %{httpoison_headers: httpoison_headers} do
|
||||
with_mock HTTPoison,
|
||||
get: fn _url, _headers ->
|
||||
get: fn _url, _headers, _options ->
|
||||
{:ok, %HTTPoison.Response{status_code: 200, body: "{\"features\": []"}}
|
||||
end do
|
||||
Photon.search("10 Rue Jangot",
|
||||
@@ -33,7 +38,8 @@ defmodule Mobilizon.Service.Geospatial.PhotonTest do
|
||||
assert_called(
|
||||
HTTPoison.get(
|
||||
"https://photon.komoot.de/api/?q=10%20Rue%20Jangot&lang=fr&limit=5",
|
||||
httpoison_headers
|
||||
httpoison_headers,
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
147
test/service/notifications/scheduler_test.exs
Normal file
147
test/service/notifications/scheduler_test.exs
Normal file
@@ -0,0 +1,147 @@
|
||||
defmodule Mobilizon.Service.Notifications.SchedulerTest do
|
||||
@moduledoc """
|
||||
Test the scheduler module
|
||||
"""
|
||||
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Service.Notifications.Scheduler
|
||||
alias Mobilizon.Service.Workers.Notification
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
use Oban.Testing, repo: Mobilizon.Storage.Repo
|
||||
|
||||
describe "Joining an event registers a job for notification before event" do
|
||||
test "if the user has allowed it" do
|
||||
%User{id: user_id} = user = insert(:user)
|
||||
settings = insert(:settings, user_id: user_id, notification_before_event: true)
|
||||
user = Map.put(user, :settings, settings)
|
||||
actor = insert(:actor, user: user)
|
||||
|
||||
%Participant{id: participant_id, event: %Event{begins_on: begins_on}} =
|
||||
participant = insert(:participant, actor: actor)
|
||||
|
||||
Scheduler.before_event_notification(participant)
|
||||
|
||||
scheduled_at = DateTime.add(begins_on, -3600, :second)
|
||||
|
||||
assert_enqueued(
|
||||
worker: Notification,
|
||||
args: %{participant_id: participant_id, op: :before_event_notification},
|
||||
scheduled_at: scheduled_at
|
||||
)
|
||||
end
|
||||
|
||||
test "not if the user hasn't allowed it" do
|
||||
%User{} = user = insert(:user)
|
||||
actor = insert(:actor, user: user)
|
||||
|
||||
%Participant{id: participant_id} = participant = insert(:participant, actor: actor)
|
||||
|
||||
Scheduler.before_event_notification(participant)
|
||||
|
||||
refute_enqueued(
|
||||
worker: Notification,
|
||||
args: %{participant_id: participant_id, op: :before_event_notification}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Joining an event registers a job for notification on the day of the event" do
|
||||
test "if the user has allowed it" do
|
||||
%User{id: user_id} = user = insert(:user)
|
||||
|
||||
settings =
|
||||
insert(:settings, user_id: user_id, notification_on_day: true, timezone: "Europe/Paris")
|
||||
|
||||
user = Map.put(user, :settings, settings)
|
||||
actor = insert(:actor, user: user)
|
||||
|
||||
%DateTime{} = tomorrow = DateTime.utc_now() |> DateTime.add(3600 * 24)
|
||||
begins_on = %{tomorrow | hour: 16, minute: 0, second: 0, microsecond: {0, 0}}
|
||||
|
||||
%Event{begins_on: begins_on} = event = insert(:event, begins_on: begins_on)
|
||||
|
||||
%Participant{} = participant = insert(:participant, actor: actor, event: event)
|
||||
|
||||
Scheduler.on_day_notification(participant)
|
||||
|
||||
assert_enqueued(
|
||||
worker: Notification,
|
||||
args: %{user_id: user_id, op: :on_day_notification},
|
||||
scheduled_at: %{DateTime.shift_zone!(begins_on, settings.timezone) | hour: 8}
|
||||
)
|
||||
end
|
||||
|
||||
test "not if the user hasn't allowed it" do
|
||||
%User{id: user_id} = user = insert(:user)
|
||||
actor = insert(:actor, user: user)
|
||||
|
||||
%Participant{} = participant = insert(:participant, actor: actor)
|
||||
|
||||
Scheduler.on_day_notification(participant)
|
||||
|
||||
refute_enqueued(
|
||||
worker: Notification,
|
||||
args: %{user_id: user_id, op: :on_day_notification}
|
||||
)
|
||||
end
|
||||
|
||||
test "not if it's too late" do
|
||||
%User{id: user_id} = user = insert(:user)
|
||||
|
||||
settings =
|
||||
insert(:settings, user_id: user_id, notification_on_day: true, timezone: "Europe/Paris")
|
||||
|
||||
user = Map.put(user, :settings, settings)
|
||||
actor = insert(:actor, user: user)
|
||||
|
||||
%Event{} = event = insert(:event, begins_on: DateTime.add(DateTime.utc_now(), -3600))
|
||||
|
||||
%Participant{} = participant = insert(:participant, actor: actor, event: event)
|
||||
|
||||
Scheduler.on_day_notification(participant)
|
||||
|
||||
refute_enqueued(
|
||||
worker: Notification,
|
||||
args: %{user_id: user_id, op: :on_day_notification}
|
||||
)
|
||||
end
|
||||
|
||||
test "only once" do
|
||||
%User{id: user_id} = user = insert(:user)
|
||||
|
||||
settings =
|
||||
insert(:settings, user_id: user_id, notification_on_day: true, timezone: "Europe/Paris")
|
||||
|
||||
user = Map.put(user, :settings, settings)
|
||||
actor = insert(:actor, user: user)
|
||||
|
||||
%DateTime{} = tomorrow = DateTime.utc_now() |> DateTime.add(3600 * 24)
|
||||
begins_on = %{tomorrow | hour: 16, minute: 0, second: 0, microsecond: {0, 0}}
|
||||
|
||||
%Event{begins_on: begins_on} = event = insert(:event, begins_on: begins_on)
|
||||
|
||||
%Participant{} = participant = insert(:participant, actor: actor, event: event)
|
||||
|
||||
Scheduler.on_day_notification(participant)
|
||||
|
||||
assert_enqueued(
|
||||
worker: Notification,
|
||||
args: %{user_id: user_id, op: :on_day_notification},
|
||||
scheduled_at: %{DateTime.shift_zone!(begins_on, settings.timezone) | hour: 8}
|
||||
)
|
||||
|
||||
%DateTime{} = tomorrow = DateTime.utc_now() |> DateTime.add(3600 * 24)
|
||||
begins_on = %{tomorrow | hour: 19, minute: 0, second: 0, microsecond: {0, 0}}
|
||||
|
||||
%Event{} = event = insert(:event, begins_on: begins_on)
|
||||
|
||||
%Participant{} = participant = insert(:participant, actor: actor, event: event)
|
||||
|
||||
Scheduler.on_day_notification(participant)
|
||||
end
|
||||
end
|
||||
end
|
||||
210
test/service/workers/notification_test.exs
Normal file
210
test/service/workers/notification_test.exs
Normal file
@@ -0,0 +1,210 @@
|
||||
defmodule Mobilizon.Service.Workers.NotificationTest do
|
||||
@moduledoc """
|
||||
Test the scheduler module
|
||||
"""
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Service.Workers.Notification
|
||||
alias Mobilizon.Users.User
|
||||
alias Mobilizon.Web.Email.Notification, as: NotificationMailer
|
||||
|
||||
use Mobilizon.DataCase
|
||||
use Bamboo.Test
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
||||
describe "A before_event_notification job sends an email" do
|
||||
test "if the user is still participating" do
|
||||
%User{id: user_id} = user = insert(:user)
|
||||
|
||||
settings =
|
||||
insert(:settings,
|
||||
user_id: user_id,
|
||||
notification_before_event: true
|
||||
)
|
||||
|
||||
user = Map.put(user, :settings, settings)
|
||||
|
||||
%Actor{} = actor = insert(:actor, user: user)
|
||||
|
||||
%Participant{id: participant_id} =
|
||||
participant = insert(:participant, role: :participant, actor: actor)
|
||||
|
||||
Notification.perform(
|
||||
%{"op" => "before_event_notification", "participant_id" => participant_id},
|
||||
nil
|
||||
)
|
||||
|
||||
assert_delivered_email(
|
||||
NotificationMailer.before_event_notification(
|
||||
participant.actor.user.email,
|
||||
participant
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
test "unless the person is no longer participating" do
|
||||
%Event{id: event_id} = insert(:event)
|
||||
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{id: actor_id} = insert(:actor, user: user)
|
||||
|
||||
{:ok, %Participant{id: participant_id} = participant} =
|
||||
Events.create_participant(%{actor_id: actor_id, event_id: event_id, role: :participant})
|
||||
|
||||
actor = Map.put(participant.actor, :user, user)
|
||||
participant = Map.put(participant, :actor, actor)
|
||||
|
||||
assert {:ok, %Participant{}} = Events.delete_participant(participant)
|
||||
|
||||
Notification.perform(
|
||||
%{"op" => "before_event_notification", "participant_id" => participant_id},
|
||||
nil
|
||||
)
|
||||
|
||||
refute_delivered_email(
|
||||
NotificationMailer.before_event_notification(
|
||||
participant.actor.user.email,
|
||||
participant
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
test "unless the event has been cancelled" do
|
||||
%Event{} = event = insert(:event, status: :cancelled)
|
||||
|
||||
%Participant{id: participant_id} =
|
||||
participant = insert(:participant, role: :participant, event: event)
|
||||
|
||||
Notification.perform(
|
||||
%{"op" => "before_event_notification", "participant_id" => participant_id},
|
||||
nil
|
||||
)
|
||||
|
||||
refute_delivered_email(
|
||||
NotificationMailer.before_event_notification(
|
||||
participant.actor.user.email,
|
||||
participant
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "A on_day_notification job sends an email" do
|
||||
test "if the user is still participating" do
|
||||
%User{id: user_id} = user = insert(:user)
|
||||
|
||||
settings =
|
||||
insert(:settings, user_id: user_id, notification_on_day: true, timezone: "Europe/Paris")
|
||||
|
||||
user = Map.put(user, :settings, settings)
|
||||
%Actor{} = actor = insert(:actor, user: user)
|
||||
|
||||
%Participant{} = participant = insert(:participant, role: :participant, actor: actor)
|
||||
|
||||
Notification.perform(
|
||||
%{"op" => "on_day_notification", "user_id" => user_id},
|
||||
nil
|
||||
)
|
||||
|
||||
assert_delivered_email(
|
||||
NotificationMailer.on_day_notification(
|
||||
user,
|
||||
[participant],
|
||||
1
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
test "unless the person is no longer participating" do
|
||||
%Event{id: event_id} = insert(:event)
|
||||
|
||||
%User{id: user_id} = user = insert(:user)
|
||||
|
||||
settings =
|
||||
insert(:settings, user_id: user_id, notification_on_day: true, timezone: "Europe/Paris")
|
||||
|
||||
user = Map.put(user, :settings, settings)
|
||||
%Actor{} = actor = insert(:actor, user: user)
|
||||
|
||||
{:ok, %Participant{} = participant} =
|
||||
Events.create_participant(%{actor_id: actor.id, event_id: event_id, role: :participant})
|
||||
|
||||
actor = Map.put(participant.actor, :user, user)
|
||||
participant = Map.put(participant, :actor, actor)
|
||||
|
||||
assert {:ok, %Participant{}} = Events.delete_participant(participant)
|
||||
|
||||
Notification.perform(
|
||||
%{"op" => "on_day_notification", "user_id" => user_id},
|
||||
nil
|
||||
)
|
||||
|
||||
refute_delivered_email(
|
||||
NotificationMailer.on_day_notification(
|
||||
user,
|
||||
[participant],
|
||||
1
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
test "unless the event has been cancelled" do
|
||||
%User{id: user_id} = user = insert(:user)
|
||||
|
||||
settings =
|
||||
insert(:settings, user_id: user_id, notification_on_day: true, timezone: "Europe/Paris")
|
||||
|
||||
user = Map.put(user, :settings, settings)
|
||||
%Actor{} = actor = insert(:actor, user: user)
|
||||
%Event{} = event = insert(:event, status: :cancelled)
|
||||
|
||||
%Participant{} =
|
||||
participant = insert(:participant, role: :participant, event: event, actor: actor)
|
||||
|
||||
Notification.perform(
|
||||
%{"op" => "on_day_notification", "user_id" => user_id},
|
||||
nil
|
||||
)
|
||||
|
||||
refute_delivered_email(
|
||||
NotificationMailer.on_day_notification(
|
||||
user,
|
||||
[participant],
|
||||
1
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
test "with a lot of events" do
|
||||
%User{id: user_id} = user = insert(:user)
|
||||
|
||||
settings =
|
||||
insert(:settings, user_id: user_id, notification_on_day: true, timezone: "Europe/Paris")
|
||||
|
||||
user = Map.put(user, :settings, settings)
|
||||
%Actor{} = actor = insert(:actor, user: user)
|
||||
|
||||
participants =
|
||||
Enum.reduce(0..10, [], fn _i, acc ->
|
||||
%Participant{} = participant = insert(:participant, role: :participant, actor: actor)
|
||||
acc ++ [participant]
|
||||
end)
|
||||
|
||||
Notification.perform(
|
||||
%{"op" => "on_day_notification", "user_id" => user_id},
|
||||
nil
|
||||
)
|
||||
|
||||
refute_delivered_email(
|
||||
NotificationMailer.on_day_notification(
|
||||
user,
|
||||
participants,
|
||||
3
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,7 +3,10 @@ defmodule Mobilizon.GraphQL.AbsintheHelpers do
|
||||
Absinthe helpers for tests
|
||||
"""
|
||||
|
||||
use Phoenix.ConnTest
|
||||
import Plug.Conn
|
||||
import Phoenix.ConnTest
|
||||
|
||||
alias Plug.Conn
|
||||
|
||||
@endpoint Mobilizon.Web.Endpoint
|
||||
|
||||
@@ -23,6 +26,7 @@ defmodule Mobilizon.GraphQL.AbsintheHelpers do
|
||||
}
|
||||
end
|
||||
|
||||
@spec graphql_query(Conn.t(), Keyword.t()) :: map | no_return
|
||||
def graphql_query(conn, options) do
|
||||
conn
|
||||
|> post("/api", build_query(options[:query], Keyword.get(options, :variables, %{})))
|
||||
|
||||
@@ -25,7 +25,9 @@ defmodule Mobilizon.Web.ConnCase do
|
||||
using do
|
||||
quote do
|
||||
# Import conveniences for testing with connections
|
||||
use Phoenix.ConnTest
|
||||
import Plug.Conn
|
||||
import Phoenix.ConnTest
|
||||
|
||||
import Mobilizon.Web.Router.Helpers
|
||||
|
||||
# The default endpoint for testing
|
||||
|
||||
@@ -22,6 +22,16 @@ defmodule Mobilizon.Factory do
|
||||
}
|
||||
end
|
||||
|
||||
def settings_factory do
|
||||
%Mobilizon.Users.Setting{
|
||||
timezone: nil,
|
||||
notification_on_day: false,
|
||||
notification_each_week: false,
|
||||
notification_before_event: false,
|
||||
user_id: nil
|
||||
}
|
||||
end
|
||||
|
||||
def actor_factory do
|
||||
preferred_username = sequence("thomas")
|
||||
|
||||
@@ -39,16 +49,28 @@ defmodule Mobilizon.Factory do
|
||||
following_url: Actor.build_url(preferred_username, :following),
|
||||
inbox_url: Actor.build_url(preferred_username, :inbox),
|
||||
outbox_url: Actor.build_url(preferred_username, :outbox),
|
||||
shared_inbox_url: "#{Endpoint.url()}/inbox",
|
||||
last_refreshed_at: DateTime.utc_now(),
|
||||
user: build(:user)
|
||||
}
|
||||
end
|
||||
|
||||
def group_factory do
|
||||
preferred_username = sequence("myGroup")
|
||||
|
||||
struct!(
|
||||
actor_factory(),
|
||||
%{
|
||||
type: :Group
|
||||
preferred_username: preferred_username,
|
||||
type: :Group,
|
||||
url: Actor.build_url(preferred_username, :page),
|
||||
followers_url: Actor.build_url(preferred_username, :followers),
|
||||
following_url: Actor.build_url(preferred_username, :following),
|
||||
members_url: Actor.build_url(preferred_username, :members),
|
||||
resources_url: Actor.build_url(preferred_username, :resources),
|
||||
inbox_url: Actor.build_url(preferred_username, :inbox),
|
||||
outbox_url: Actor.build_url(preferred_username, :outbox),
|
||||
user: nil
|
||||
}
|
||||
)
|
||||
end
|
||||
@@ -94,7 +116,7 @@ defmodule Mobilizon.Factory do
|
||||
def comment_factory do
|
||||
uuid = Ecto.UUID.generate()
|
||||
|
||||
%Mobilizon.Events.Comment{
|
||||
%Mobilizon.Conversations.Comment{
|
||||
text: "My Comment",
|
||||
actor: build(:actor),
|
||||
event: build(:event),
|
||||
@@ -130,7 +152,8 @@ defmodule Mobilizon.Factory do
|
||||
uuid: uuid,
|
||||
join_options: :free,
|
||||
options: %{},
|
||||
participant_stats: %{}
|
||||
participant_stats: %{},
|
||||
status: :confirmed
|
||||
}
|
||||
end
|
||||
|
||||
@@ -175,10 +198,14 @@ defmodule Mobilizon.Factory do
|
||||
end
|
||||
|
||||
def member_factory do
|
||||
uuid = Ecto.UUID.generate()
|
||||
|
||||
%Mobilizon.Actors.Member{
|
||||
parent: build(:actor),
|
||||
actor: build(:actor),
|
||||
role: :not_approved
|
||||
role: :not_approved,
|
||||
id: uuid,
|
||||
url: "#{Endpoint.url()}/member/#{uuid}"
|
||||
}
|
||||
end
|
||||
|
||||
@@ -244,4 +271,47 @@ defmodule Mobilizon.Factory do
|
||||
report: build(:report)
|
||||
}
|
||||
end
|
||||
|
||||
def todo_list_factory do
|
||||
uuid = Ecto.UUID.generate()
|
||||
|
||||
%Mobilizon.Todos.TodoList{
|
||||
title: sequence("todo list"),
|
||||
actor: build(:group),
|
||||
id: uuid,
|
||||
url: Routes.todo_list_url(Endpoint, :todo_list, uuid)
|
||||
}
|
||||
end
|
||||
|
||||
def todo_factory do
|
||||
uuid = Ecto.UUID.generate()
|
||||
|
||||
%Mobilizon.Todos.Todo{
|
||||
id: uuid,
|
||||
title: sequence("my todo"),
|
||||
todo_list: build(:todo_list),
|
||||
status: false,
|
||||
due_date: Timex.shift(DateTime.utc_now(), hours: 2),
|
||||
assigned_to: build(:actor),
|
||||
url: Routes.todo_url(Endpoint, :todo, uuid),
|
||||
creator: build(:actor)
|
||||
}
|
||||
end
|
||||
|
||||
def resource_factory do
|
||||
uuid = Ecto.UUID.generate()
|
||||
title = sequence("my resource")
|
||||
|
||||
%Mobilizon.Resources.Resource{
|
||||
id: uuid,
|
||||
title: title,
|
||||
type: :link,
|
||||
resource_url: "https://somewebsite.com/path",
|
||||
actor: build(:group),
|
||||
creator: build(:actor),
|
||||
parent: nil,
|
||||
url: Routes.resource_url(Endpoint, :resource, uuid),
|
||||
path: "/#{title}"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -336,46 +336,96 @@ defmodule Mobilizon.Web.ActivityPubControllerTest do
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# describe "/@:preferred_username/following" do
|
||||
# test "it returns the following in a collection", %{conn: conn} do
|
||||
# actor = insert(:actor)
|
||||
# actor2 = insert(:actor)
|
||||
# Mobilizon.Federation.ActivityPub.follow(actor, actor2)
|
||||
describe "/@actor/members for a group" do
|
||||
test "it returns the members in a group", %{conn: conn} do
|
||||
actor = insert(:actor)
|
||||
|
||||
# result =
|
||||
# conn
|
||||
# |> get("/@#{actor.preferred_username}/following")
|
||||
# |> json_response(200)
|
||||
assert {:ok, %Actor{} = group} =
|
||||
Actors.create_group(%{
|
||||
creator_actor_id: actor.id,
|
||||
preferred_username: "my_group",
|
||||
visibility: :public
|
||||
})
|
||||
|
||||
# assert result["first"]["orderedItems"] == [actor2.url]
|
||||
# end
|
||||
result =
|
||||
conn
|
||||
|> get(Actor.build_url(group.preferred_username, :members))
|
||||
|> json_response(200)
|
||||
|
||||
# test "it works for more than 10 actors", %{conn: conn} do
|
||||
# actor = insert(:actor)
|
||||
assert hd(result["first"]["orderedItems"])["actor"] == actor.url
|
||||
assert hd(result["first"]["orderedItems"])["object"] == group.url
|
||||
assert hd(result["first"]["orderedItems"])["role"] == "administrator"
|
||||
assert hd(result["first"]["orderedItems"])["type"] == "Member"
|
||||
end
|
||||
|
||||
# Enum.each(1..15, fn _ ->
|
||||
# actor = Repo.get(Actor, actor.id)
|
||||
# other_actor = insert(:actor)
|
||||
# Actors.follow(actor, other_actor)
|
||||
# end)
|
||||
test "it returns no members for a private group", %{conn: conn} do
|
||||
actor = insert(:actor)
|
||||
|
||||
# result =
|
||||
# conn
|
||||
# |> get("/@#{actor.preferred_username}/following")
|
||||
# |> json_response(200)
|
||||
assert {:ok, %Actor{} = group} =
|
||||
Actors.create_group(%{creator_actor_id: actor.id, preferred_username: "my_group"})
|
||||
|
||||
# assert length(result["first"]["orderedItems"]) == 10
|
||||
# assert result["first"]["totalItems"] == 15
|
||||
# assert result["totalItems"] == 15
|
||||
result =
|
||||
conn
|
||||
|> get(Actor.build_url(actor.preferred_username, :members))
|
||||
|> json_response(200)
|
||||
|
||||
# result =
|
||||
# conn
|
||||
# |> get("/@#{actor.preferred_username}/following?page=2")
|
||||
# |> json_response(200)
|
||||
assert result["first"]["orderedItems"] == []
|
||||
end
|
||||
|
||||
# assert length(result["orderedItems"]) == 5
|
||||
# assert result["totalItems"] == 15
|
||||
# end
|
||||
# end
|
||||
test "it works for more than 10 actors", %{conn: conn} do
|
||||
actor = insert(:actor, preferred_username: "my_admin")
|
||||
|
||||
assert {:ok, %Actor{} = group} =
|
||||
Actors.create_group(%{
|
||||
creator_actor_id: actor.id,
|
||||
preferred_username: "my_group",
|
||||
visibility: :public
|
||||
})
|
||||
|
||||
Enum.each(1..15, fn _ ->
|
||||
other_actor = insert(:actor)
|
||||
insert(:member, actor: other_actor, parent: group, role: :member)
|
||||
end)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get(Actor.build_url(group.preferred_username, :members))
|
||||
|> json_response(200)
|
||||
|
||||
assert length(result["first"]["orderedItems"]) == 10
|
||||
# 15 members + 1 admin
|
||||
assert result["totalItems"] == 16
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get(Actor.build_url(group.preferred_username, :members, page: 2))
|
||||
|> json_response(200)
|
||||
|
||||
assert length(result["orderedItems"]) == 6
|
||||
end
|
||||
|
||||
test "it returns members for a private group but request is signed by an actor", %{conn: conn} do
|
||||
actor_group_admin = insert(:actor)
|
||||
actor_applicant = insert(:actor)
|
||||
|
||||
assert {:ok, %Actor{} = group} =
|
||||
Actors.create_group(%{
|
||||
creator_actor_id: actor_group_admin.id,
|
||||
preferred_username: "my_group"
|
||||
})
|
||||
|
||||
insert(:member, actor: actor_applicant, parent: group, role: :member)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:actor, actor_applicant)
|
||||
|> get(Actor.build_url(group.preferred_username, :members))
|
||||
|> json_response(200)
|
||||
|
||||
assert [admin_member | [member]] = result["first"]["orderedItems"]
|
||||
assert admin_member["role"] == "administrator"
|
||||
assert member["role"] == "member"
|
||||
assert result["totalItems"] == 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,8 @@ defmodule Mobilizon.Web.ErrorViewTest do
|
||||
alias Mobilizon.Web.ErrorView
|
||||
|
||||
test "renders 404.html" do
|
||||
assert render_to_string(ErrorView, "404.html", []) =~
|
||||
# Produced HTML might have new lines inside
|
||||
assert Regex.replace(~r/(\r\n|\n|\r) +/, render_to_string(ErrorView, "404.html", []), " ") =~
|
||||
"We're sorry but mobilizon doesn't work properly without JavaScript enabled. Please enable it to continue."
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user