@@ -8,9 +8,10 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mock
|
||||
import Mox
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.{Actors, Conversations, Events}
|
||||
alias Mobilizon.{Actors, Discussions, Events}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Resources.Resource
|
||||
alias Mobilizon.Todos.{Todo, TodoList}
|
||||
@@ -18,13 +19,10 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Utils
|
||||
alias Mobilizon.Federation.HTTPSignatures.Signature
|
||||
alias Mobilizon.Service.HTTP.ActivityPub.Mock
|
||||
|
||||
@activity_pub_public_audience "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
setup_all do
|
||||
HTTPoison.start()
|
||||
end
|
||||
|
||||
describe "setting HTTP signature" do
|
||||
test "set http signature header" do
|
||||
actor = insert(:actor)
|
||||
@@ -140,40 +138,75 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
|
||||
describe "fetching an" do
|
||||
test "object by url" do
|
||||
use_cassette "activity_pub/fetch_framapiaf_framasoft_status" do
|
||||
{:ok, object} =
|
||||
ActivityPub.fetch_object_from_url(
|
||||
"https://framapiaf.org/users/Framasoft/statuses/102093631881522097"
|
||||
)
|
||||
url = "https://framapiaf.org/users/Framasoft/statuses/102093631881522097"
|
||||
|
||||
{:ok, object_again} =
|
||||
ActivityPub.fetch_object_from_url(
|
||||
"https://framapiaf.org/users/Framasoft/statuses/102093631881522097"
|
||||
)
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-status-2.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
assert object.id == object_again.id
|
||||
end
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: ^url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
{:ok, object} = ActivityPub.fetch_object_from_url(url)
|
||||
|
||||
{:ok, object_again} = ActivityPub.fetch_object_from_url(url)
|
||||
|
||||
assert object.id == object_again.id
|
||||
end
|
||||
|
||||
test "object reply by url" do
|
||||
use_cassette "activity_pub/fetch_framasoft_framapiaf_reply" do
|
||||
{:ok, object} =
|
||||
ActivityPub.fetch_object_from_url("https://mamot.fr/@imacrea/102094441327423790")
|
||||
url = "https://zoltasila.pl/objects/1c295713-8e3c-411e-9e62-57a7b9c9e514"
|
||||
reply_to_url = "https://framapiaf.org/users/peertube/statuses/104584600044284729"
|
||||
|
||||
assert object.in_reply_to_comment.url ==
|
||||
"https://framapiaf.org/users/Framasoft/statuses/102093632302210150"
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-status-3.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
reply_to_data =
|
||||
File.read!("test/fixtures/mastodon-status-4.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, 2, fn
|
||||
%{method: :get, url: ^url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
|
||||
%{method: :get, url: ^reply_to_url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: reply_to_data}}
|
||||
end)
|
||||
|
||||
{:ok, object} = ActivityPub.fetch_object_from_url(url)
|
||||
|
||||
assert object.in_reply_to_comment.url == reply_to_url
|
||||
end
|
||||
|
||||
test "object reply to a video by url" do
|
||||
use_cassette "activity_pub/fetch_reply_to_framatube" do
|
||||
{:ok, object} =
|
||||
ActivityPub.fetch_object_from_url(
|
||||
"https://diaspodon.fr/users/dada/statuses/100820008426311925"
|
||||
)
|
||||
url = "https://diaspodon.fr/users/dada/statuses/100820008426311925"
|
||||
origin_url = "https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d"
|
||||
|
||||
assert object.in_reply_to_comment == nil
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-status-5.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
origin_data =
|
||||
File.read!("test/fixtures/peertube-video.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, 2, fn
|
||||
%{method: :get, url: ^url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
|
||||
%{method: :get, url: ^origin_url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: origin_data}}
|
||||
end)
|
||||
|
||||
{:ok, object} = ActivityPub.fetch_object_from_url(url)
|
||||
|
||||
assert object.in_reply_to_comment == nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -181,26 +214,28 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
test "it creates a delete activity and deletes the original event" do
|
||||
event = insert(:event)
|
||||
event = Events.get_public_event_by_url_with_preload!(event.url)
|
||||
{:ok, delete, _} = ActivityPub.delete(event)
|
||||
{:ok, delete, _} = ActivityPub.delete(event, event.organizer_actor)
|
||||
|
||||
assert delete.data["type"] == "Delete"
|
||||
assert delete.data["actor"] == event.organizer_actor.url
|
||||
assert delete.data["object"] == event.url
|
||||
assert delete.data["object"]["type"] == "Event"
|
||||
assert delete.data["object"]["id"] == event.url
|
||||
|
||||
assert Events.get_event_by_url(event.url) == nil
|
||||
end
|
||||
|
||||
test "it deletes the original event but only locally if needed" do
|
||||
with_mock Utils,
|
||||
with_mock Utils, [:passthrough],
|
||||
maybe_federate: fn _ -> :ok end,
|
||||
lazy_put_activity_defaults: fn args -> args end do
|
||||
event = insert(:event)
|
||||
event = Events.get_public_event_by_url_with_preload!(event.url)
|
||||
{:ok, delete, _} = ActivityPub.delete(event, false)
|
||||
{:ok, delete, _} = ActivityPub.delete(event, event.organizer_actor, false)
|
||||
|
||||
assert delete.data["type"] == "Delete"
|
||||
assert delete.data["actor"] == event.organizer_actor.url
|
||||
assert delete.data["object"] == event.url
|
||||
assert delete.data["object"]["type"] == "Event"
|
||||
assert delete.data["object"]["id"] == event.url
|
||||
assert delete.local == false
|
||||
|
||||
assert Events.get_event_by_url(event.url) == nil
|
||||
@@ -211,15 +246,16 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
|
||||
test "it creates a delete activity and deletes the original comment" do
|
||||
comment = insert(:comment)
|
||||
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)
|
||||
comment = Discussions.get_comment_from_url_with_preload!(comment.url)
|
||||
assert is_nil(Discussions.get_comment_from_url(comment.url).deleted_at)
|
||||
{:ok, delete, _} = ActivityPub.delete(comment, comment.actor)
|
||||
|
||||
assert delete.data["type"] == "Delete"
|
||||
assert delete.data["actor"] == comment.actor.url
|
||||
assert delete.data["object"] == comment.url
|
||||
assert delete.data["object"]["type"] == "Note"
|
||||
assert delete.data["object"]["id"] == comment.url
|
||||
|
||||
refute is_nil(Conversations.get_comment_from_url(comment.url).deleted_at)
|
||||
refute is_nil(Discussions.get_comment_from_url(comment.url).deleted_at)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -230,7 +266,7 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
actor = insert(:actor)
|
||||
actor_data = %{summary: @updated_actor_summary}
|
||||
|
||||
{:ok, update, _} = ActivityPub.update(:actor, actor, actor_data, false)
|
||||
{:ok, update, _} = ActivityPub.update(actor, actor_data, false)
|
||||
|
||||
assert update.data["actor"] == actor.url
|
||||
assert update.data["to"] == [@activity_pub_public_audience]
|
||||
@@ -246,7 +282,7 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
event = insert(:event, organizer_actor: actor)
|
||||
event_data = %{begins_on: @updated_start_time}
|
||||
|
||||
{:ok, update, _} = ActivityPub.update(:event, event, event_data)
|
||||
{:ok, update, _} = ActivityPub.update(event, event_data)
|
||||
|
||||
assert update.data["actor"] == actor.url
|
||||
assert update.data["to"] == [@activity_pub_public_audience]
|
||||
@@ -272,8 +308,8 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
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["object"]["name"] == @todo_list_title
|
||||
assert create_data.data["to"] == [group.members_url]
|
||||
assert create_data.data["actor"] == actor.url
|
||||
|
||||
assert_called(Utils.maybe_federate(create_data))
|
||||
@@ -301,7 +337,7 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
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["to"] == [todo_list.actor.members_url]
|
||||
assert create_data.data["actor"] == actor.url
|
||||
|
||||
assert_called(Utils.maybe_federate(create_data))
|
||||
@@ -341,7 +377,7 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
|
||||
assert create_data.data["object"]["url"] == @resource_url
|
||||
|
||||
assert create_data.data["to"] == [group.url]
|
||||
assert create_data.data["to"] == [group.members_url]
|
||||
assert create_data.data["actor"] == actor.url
|
||||
assert create_data.data["attributedTo"] == [actor.url]
|
||||
|
||||
@@ -372,7 +408,7 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
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["to"] == [group.members_url]
|
||||
assert create_data.data["actor"] == actor.url
|
||||
assert create_data.data["attributedTo"] == [actor.url]
|
||||
|
||||
@@ -411,7 +447,7 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
|
||||
assert create_data.data["object"]["url"] == @resource_url
|
||||
|
||||
assert create_data.data["to"] == [group.url]
|
||||
assert create_data.data["to"] == [group.members_url]
|
||||
assert create_data.data["actor"] == actor.url
|
||||
assert create_data.data["attributedTo"] == [actor.url]
|
||||
|
||||
@@ -437,7 +473,6 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
|
||||
{:ok, update_data, %Resource{url: url}} =
|
||||
ActivityPub.update(
|
||||
:resource,
|
||||
resource,
|
||||
%{
|
||||
title: @updated_resource_title
|
||||
@@ -453,7 +488,7 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
|
||||
assert update_data.data["object"]["url"] == @resource_url
|
||||
|
||||
assert update_data.data["to"] == [group.url]
|
||||
assert update_data.data["to"] == [group.members_url]
|
||||
assert update_data.data["actor"] == actor.url
|
||||
assert update_data.data["attributedTo"] == [actor.url]
|
||||
|
||||
@@ -496,7 +531,7 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
|
||||
assert update_data.data["object"]["url"] == @resource_url
|
||||
|
||||
assert update_data.data["to"] == [group.url]
|
||||
assert update_data.data["to"] == [group.members_url]
|
||||
assert update_data.data["actor"] == actor.url
|
||||
assert update_data.data["origin"] == nil
|
||||
assert update_data.data["target"] == parent_url
|
||||
@@ -524,19 +559,23 @@ defmodule Mobilizon.Federation.ActivityPubTest do
|
||||
{:ok, update_data, %Resource{url: url}} =
|
||||
ActivityPub.delete(
|
||||
resource,
|
||||
actor,
|
||||
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 update_data.data["object"]["type"] == "Document"
|
||||
assert update_data.data["object"]["id"] == url
|
||||
assert update_data.data["to"] == [group.members_url]
|
||||
assert update_data.data["actor"] == actor.url
|
||||
assert update_data.data["attributedTo"] == [group.url]
|
||||
|
||||
assert_called(Utils.maybe_federate(update_data))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "announce" do
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,37 +2,35 @@ 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.Service.HTTP.ActivityPub.Mock
|
||||
alias Mobilizon.Web.ActivityPub.ActorView
|
||||
import Mobilizon.Factory
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
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)
|
||||
describe "refreshes a" do
|
||||
setup :verify_on_exit!
|
||||
|
||||
data =
|
||||
ActorView.render("members.json", %{group: group, actor_applicant: actor}) |> Jason.encode!()
|
||||
test "members collection" do
|
||||
%Actor{members_url: members_url} =
|
||||
group =
|
||||
insert(:group,
|
||||
url: "https://remoteinstance.tld/@group",
|
||||
members_url: "https://remoteinstance.tld/@group/members",
|
||||
domain: "remoteinstance.tld"
|
||||
)
|
||||
|
||||
%Actor{} = actor = insert(:actor)
|
||||
%Member{} = insert(:member, parent: group, actor: actor, role: :member)
|
||||
|
||||
data = ActorView.render("members.json", %{actor: group, actor_applicant: actor})
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: ^members_url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
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
|
||||
|
||||
173
test/federation/activity_pub/transmogrifier/announces_test.exs
Normal file
173
test/federation/activity_pub/transmogrifier/announces_test.exs
Normal file
@@ -0,0 +1,173 @@
|
||||
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.AnnouncesTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
import Mox
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Discussions
|
||||
alias Mobilizon.Discussions.{Comment, Discussion}
|
||||
alias Mobilizon.Federation.ActivityPub.Transmogrifier
|
||||
alias Mobilizon.Federation.ActivityStream.Convertible
|
||||
alias Mobilizon.Service.HTTP.ActivityPub.Mock
|
||||
alias Mobilizon.Tombstone
|
||||
|
||||
@comment_text "my comment"
|
||||
|
||||
describe "incoming announces for discussion creation" do
|
||||
setup :verify_on_exit!
|
||||
|
||||
test "by group member works" do
|
||||
actor = insert(:actor)
|
||||
group = insert(:group)
|
||||
insert(:member, parent: group, actor: actor, role: :member)
|
||||
|
||||
%Comment{url: comment_url} =
|
||||
comment = build(:comment, actor: actor, attributed_to: group, event: nil)
|
||||
|
||||
comment_data = Convertible.model_to_as(comment)
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: ^comment_url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: comment_data}}
|
||||
end)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", group.url)
|
||||
|> Map.put("object", comment.url)
|
||||
|
||||
{:ok, _, %Comment{actor: %Actor{url: actor_url}, url: comment_url}} =
|
||||
Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert actor_url == comment.actor.url
|
||||
|
||||
assert comment_url == comment.url
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming announces for discussion updates" do
|
||||
setup :verify_on_exit!
|
||||
|
||||
@updated_title "Updated title"
|
||||
|
||||
test "by group member works" do
|
||||
actor =
|
||||
insert(:actor,
|
||||
domain: "otherremoteinstance.tld",
|
||||
url: "http://otherremoteinstance.tld/@somemember"
|
||||
)
|
||||
|
||||
group =
|
||||
insert(:group,
|
||||
url: "http://remoteinstance.tld/@mygroup",
|
||||
domain: "remoteinstance.tld",
|
||||
members_url: "http://remoteinstance.tld/@mygroup/members"
|
||||
)
|
||||
|
||||
insert(:member, parent: group, actor: actor, role: :member)
|
||||
|
||||
%Comment{url: _comment_url} =
|
||||
comment =
|
||||
insert(:comment,
|
||||
actor: actor,
|
||||
attributed_to: group,
|
||||
text: @comment_text,
|
||||
url: "http://otherremoteinstance.tld/@somemember/uuid"
|
||||
)
|
||||
|
||||
%Discussion{url: discussion_url} =
|
||||
discussion =
|
||||
insert(:discussion,
|
||||
last_comment: comment,
|
||||
comments: [comment],
|
||||
creator: actor,
|
||||
actor: group,
|
||||
url: "http://otherremoteinstance.tld/@mygroup/c/talk-of-something-sh0rt-uu1d"
|
||||
)
|
||||
|
||||
discussion_updated = Map.put(discussion, :title, @updated_title)
|
||||
|
||||
discussion_updated_data = Convertible.model_to_as(discussion_updated)
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{url: ^discussion_url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: discussion_updated_data}}
|
||||
end)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", group.url)
|
||||
|> Map.put("object", discussion_url)
|
||||
|
||||
assert {:ok, _, %Discussion{title: title}} = Transmogrifier.handle_incoming(data)
|
||||
assert title == @updated_title
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming announces for discussion deletion" do
|
||||
setup :verify_on_exit!
|
||||
|
||||
test "by group member works" do
|
||||
actor =
|
||||
insert(:actor,
|
||||
url: "http://otherremoteinstance.tld/@somemember",
|
||||
domain: "otherremoteinstance.tld"
|
||||
)
|
||||
|
||||
group =
|
||||
insert(:group,
|
||||
url: "http://remoteinstance.tld/@mygroup",
|
||||
domain: "remoteinstance.tld",
|
||||
members_url: "http://remoteinstance.tld/@mygroup/members"
|
||||
)
|
||||
|
||||
insert(:member, parent: group, actor: actor, role: :member)
|
||||
|
||||
%Comment{url: comment_url} =
|
||||
comment =
|
||||
insert(:comment,
|
||||
actor: actor,
|
||||
attributed_to: group,
|
||||
text: @comment_text,
|
||||
url: "http://otherremoteinstance.tld/comment/uuid"
|
||||
)
|
||||
|
||||
tombstone = build(:tombstone, uri: comment.url, actor: actor)
|
||||
tombstone_data = Convertible.model_to_as(tombstone)
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{url: ^comment_url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: tombstone_data}}
|
||||
end)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", group.url)
|
||||
|> Map.put("object", comment.url)
|
||||
|
||||
%Comment{deleted_at: deleted_at, text: comment_text} =
|
||||
Discussions.get_comment_from_url(comment.url)
|
||||
|
||||
assert is_nil(deleted_at)
|
||||
assert comment_text == @comment_text
|
||||
|
||||
{:ok, _, %Comment{deleted_at: deleted_at, text: comment_text}} =
|
||||
Transmogrifier.handle_incoming(data)
|
||||
|
||||
refute is_nil(deleted_at)
|
||||
refute comment_text == @comment_text
|
||||
|
||||
%Tombstone{actor_id: _actor_id, uri: tombstone_uri} = Tombstone.find_tombstone(comment_url)
|
||||
|
||||
# assert actor_id == comment.actor.id
|
||||
|
||||
assert tombstone_uri == comment.url
|
||||
end
|
||||
end
|
||||
end
|
||||
155
test/federation/activity_pub/transmogrifier/comments_test.exs
Normal file
155
test/federation/activity_pub/transmogrifier/comments_test.exs
Normal file
@@ -0,0 +1,155 @@
|
||||
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.CommentsTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
import Mox
|
||||
import ExUnit.CaptureLog
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Discussions
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Federation.ActivityPub.{Activity, Transmogrifier}
|
||||
alias Mobilizon.Federation.ActivityStream.Convertible
|
||||
alias Mobilizon.Service.HTTP.ActivityPub.Mock
|
||||
|
||||
describe "handle incoming comments" do
|
||||
setup :verify_on_exit!
|
||||
|
||||
test "it ignores an incoming comment if we already have it" do
|
||||
comment = insert(:comment)
|
||||
comment = Repo.preload(comment, [:attributed_to])
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => comment.actor.url,
|
||||
"object" => Convertible.model_to_as(comment)
|
||||
}
|
||||
|
||||
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 fetches replied-to activities if we don't have them" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
reply_to_url = "https://blob.cat/objects/02fdea3d-932c-4348-9ecb-3f9eb3fbdd94"
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("inReplyTo", reply_to_url)
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|
||||
reply_to_data =
|
||||
File.read!("test/fixtures/pleroma-comment-object.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: ^reply_to_url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: reply_to_data}}
|
||||
end)
|
||||
|
||||
{:ok, returned_activity, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
%Comment{} =
|
||||
origin_comment =
|
||||
Discussions.get_comment_from_url(
|
||||
"https://blob.cat/objects/02fdea3d-932c-4348-9ecb-3f9eb3fbdd94"
|
||||
)
|
||||
|
||||
assert returned_activity.data["object"]["inReplyTo"] ==
|
||||
"https://blob.cat/objects/02fdea3d-932c-4348-9ecb-3f9eb3fbdd94"
|
||||
|
||||
assert returned_activity.data["object"]["inReplyTo"] == origin_comment.url
|
||||
end
|
||||
|
||||
@url_404 "https://404.site/whatever"
|
||||
test "it does not crash if the object in inReplyTo can't be fetched" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("inReplyTo", @url_404)
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: "https://404.site/whatever"}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 404, body: "Not found"}}
|
||||
end)
|
||||
|
||||
assert capture_log([level: :warn], fn ->
|
||||
{:ok, _returned_activity, _entity} = Transmogrifier.handle_incoming(data)
|
||||
end) =~ "[warn] Parent object is something we don't handle"
|
||||
end
|
||||
|
||||
test "it works for incoming notices" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["id"] ==
|
||||
"https://framapiaf.org/users/admin/statuses/99512778738411822/activity"
|
||||
|
||||
assert data["to"] == [
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
"https://framapiaf.org/users/tcit"
|
||||
]
|
||||
|
||||
# assert data["cc"] == [
|
||||
# "https://framapiaf.org/users/admin/followers",
|
||||
# "http://mobilizon.com/@tcit"
|
||||
# ]
|
||||
|
||||
assert data["actor"] == "https://framapiaf.org/users/admin"
|
||||
|
||||
object = data["object"]
|
||||
assert object["id"] == "https://framapiaf.org/users/admin/statuses/99512778738411822"
|
||||
|
||||
assert object["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
|
||||
# assert object["cc"] == [
|
||||
# "https://framapiaf.org/users/admin/followers",
|
||||
# "http://localtesting.pleroma.lol/users/lain"
|
||||
# ]
|
||||
|
||||
assert object["actor"] == "https://framapiaf.org/users/admin"
|
||||
assert object["attributedTo"] == "https://framapiaf.org/users/admin"
|
||||
|
||||
{:ok, %Actor{}} = Actors.get_actor_by_url(object["actor"])
|
||||
end
|
||||
|
||||
test "it works for incoming notices with hashtags" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
assert Enum.at(data["object"]["tag"], 0)["name"] == "@tcit@framapiaf.org"
|
||||
assert Enum.at(data["object"]["tag"], 1)["name"] == "#moo"
|
||||
end
|
||||
|
||||
test "it works for incoming notices with url not being a string (prismo)" do
|
||||
data = File.read!("test/fixtures/prismo-url-map.json") |> Jason.decode!()
|
||||
|
||||
assert {:error, :not_supported} == Transmogrifier.handle_incoming(data)
|
||||
# Pages without groups are not supported
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert data["object"]["url"] == "https://prismo.news/posts/83"
|
||||
end
|
||||
end
|
||||
end
|
||||
122
test/federation/activity_pub/transmogrifier/follow_test.exs
Normal file
122
test/federation/activity_pub/transmogrifier/follow_test.exs
Normal file
@@ -0,0 +1,122 @@
|
||||
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.FollowTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.{Activity, Transmogrifier}
|
||||
|
||||
describe "handle incoming follow accept activities" do
|
||||
test "it works for incoming accepts which were pre-accepted" do
|
||||
follower = insert(:actor)
|
||||
followed = insert(:actor)
|
||||
|
||||
refute Actors.is_following(follower, followed)
|
||||
|
||||
{:ok, follow_activity, _} = ActivityPub.follow(follower, followed)
|
||||
assert Actors.is_following(follower, followed)
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-accept-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", followed.url)
|
||||
|
||||
object =
|
||||
accept_data["object"]
|
||||
|> Map.put("actor", follower.url)
|
||||
|> Map.put("id", follow_activity.data["id"])
|
||||
|
||||
accept_data = Map.put(accept_data, "object", object)
|
||||
|
||||
{:ok, activity, _} = Transmogrifier.handle_incoming(accept_data)
|
||||
refute activity.local
|
||||
|
||||
assert activity.data["object"]["id"] == follow_activity.data["id"]
|
||||
|
||||
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
||||
|
||||
assert Actors.is_following(follower, followed)
|
||||
end
|
||||
|
||||
test "it works for incoming accepts which are referenced by IRI only" do
|
||||
follower = insert(:actor)
|
||||
followed = insert(:actor)
|
||||
|
||||
{:ok, follow_activity, _} = ActivityPub.follow(follower, followed)
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-accept-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", followed.url)
|
||||
|> Map.put("object", follow_activity.data["id"])
|
||||
|
||||
{:ok, activity, _} = Transmogrifier.handle_incoming(accept_data)
|
||||
assert activity.data["object"]["id"] == follow_activity.data["id"]
|
||||
assert activity.data["object"]["id"] =~ "/follow/"
|
||||
assert activity.data["id"] =~ "/accept/follow/"
|
||||
|
||||
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
||||
|
||||
assert Actors.is_following(follower, followed)
|
||||
end
|
||||
|
||||
test "it fails for incoming accepts which cannot be correlated" do
|
||||
follower = insert(:actor)
|
||||
followed = insert(:actor)
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-accept-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", followed.url)
|
||||
|
||||
accept_data =
|
||||
Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.url))
|
||||
|
||||
:error = Transmogrifier.handle_incoming(accept_data)
|
||||
|
||||
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
||||
|
||||
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)
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-reject-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", followed.url)
|
||||
|
||||
accept_data =
|
||||
Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.url))
|
||||
|
||||
:error = Transmogrifier.handle_incoming(accept_data)
|
||||
|
||||
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
||||
|
||||
refute Actors.is_following(follower, followed)
|
||||
end
|
||||
|
||||
test "it works for incoming rejects which are referenced by IRI only" do
|
||||
follower = insert(:actor)
|
||||
followed = insert(:actor)
|
||||
|
||||
{:ok, follow_activity, _} = ActivityPub.follow(follower, followed)
|
||||
|
||||
assert Actors.is_following(follower, followed)
|
||||
|
||||
reject_data =
|
||||
File.read!("test/fixtures/mastodon-reject-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", followed.url)
|
||||
|> Map.put("object", follow_activity.data["id"])
|
||||
|
||||
{:ok, %Activity{data: _}, _} = Transmogrifier.handle_incoming(reject_data)
|
||||
|
||||
refute Actors.is_following(follower, followed)
|
||||
end
|
||||
end
|
||||
end
|
||||
60
test/federation/activity_pub/transmogrifier/invite_test.exs
Normal file
60
test/federation/activity_pub/transmogrifier/invite_test.exs
Normal file
@@ -0,0 +1,60 @@
|
||||
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.InviteTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Federation.ActivityPub.Transmogrifier
|
||||
|
||||
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
|
||||
end
|
||||
104
test/federation/activity_pub/transmogrifier/join_test.exs
Normal file
104
test/federation/activity_pub/transmogrifier/join_test.exs
Normal file
@@ -0,0 +1,104 @@
|
||||
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.JoinTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
import ExUnit.CaptureLog
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Transmogrifier
|
||||
|
||||
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)
|
||||
%Actor{url: participant_url} = _participant = insert(:actor)
|
||||
|
||||
%Event{url: event_url} = _event = insert(:event, organizer_actor: organizer)
|
||||
|
||||
join_data =
|
||||
File.read!("test/fixtures/mobilizon-join-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", participant_url)
|
||||
|> Map.put("object", event_url)
|
||||
|> Map.put("participationMessage", @join_message)
|
||||
|
||||
assert {:ok, activity, %Participant{} = participant} =
|
||||
Transmogrifier.handle_incoming(join_data)
|
||||
|
||||
assert participant.metadata.message == @join_message
|
||||
assert participant.role == :participant
|
||||
|
||||
assert activity.data["type"] == "Accept"
|
||||
assert activity.data["object"]["object"] == event_url
|
||||
assert activity.data["object"]["id"] =~ "/join/event/"
|
||||
assert activity.data["object"]["type"] =~ "Join"
|
||||
assert activity.data["object"]["participationMessage"] == @join_message
|
||||
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)
|
||||
|
||||
%Event{} = event = insert(:event, organizer_actor: organizer, join_options: :restricted)
|
||||
|
||||
{:ok, join_activity, participation} =
|
||||
ActivityPub.join(event, participant_actor, false, %{metadata: %{role: :not_approved}})
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-accept-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", organizer_url)
|
||||
|> Map.put("object", participation.url)
|
||||
|
||||
{:ok, accept_activity, _} = Transmogrifier.handle_incoming(accept_data)
|
||||
assert accept_activity.data["object"]["id"] == join_activity.data["id"]
|
||||
assert accept_activity.data["object"]["id"] =~ "/join/"
|
||||
assert accept_activity.data["id"] =~ "/accept/join/"
|
||||
|
||||
# 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)
|
||||
|
||||
%Event{} = event = insert(:event, organizer_actor: organizer, join_options: :restricted)
|
||||
|
||||
{:ok, join_activity, participation} = ActivityPub.join(event, participant_actor)
|
||||
|
||||
reject_data =
|
||||
File.read!("test/fixtures/mastodon-reject-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", organizer_url)
|
||||
|> Map.put("object", participation.url)
|
||||
|
||||
{:ok, reject_activity, _} = Transmogrifier.handle_incoming(reject_data)
|
||||
assert reject_activity.data["object"]["id"] == join_activity.data["id"]
|
||||
assert reject_activity.data["object"]["id"] =~ "/join/"
|
||||
assert reject_activity.data["id"] =~ "/reject/join/"
|
||||
|
||||
# We don't accept already rejected Reject activities
|
||||
assert capture_log([level: :warn], fn ->
|
||||
assert :error == Transmogrifier.handle_incoming(reject_data)
|
||||
end) =~
|
||||
"Unable to process Reject activity \"http://mastodon.example.org/users/admin#rejects/follows/4\". Object \"#{
|
||||
join_activity.data["id"]
|
||||
}\" wasn't found."
|
||||
|
||||
# Organiser is not present since we use factories directly
|
||||
assert event.id
|
||||
|> Events.list_participants_for_event()
|
||||
|> Map.get(:elements)
|
||||
|> Enum.map(& &1.role) == [:rejected]
|
||||
end
|
||||
end
|
||||
end
|
||||
60
test/federation/activity_pub/transmogrifier/leave_test.exs
Normal file
60
test/federation/activity_pub/transmogrifier/leave_test.exs
Normal file
@@ -0,0 +1,60 @@
|
||||
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.LeaveTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Federation.ActivityPub
|
||||
alias Mobilizon.Federation.ActivityPub.Transmogrifier
|
||||
|
||||
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)
|
||||
|
||||
%Event{url: event_url} =
|
||||
event = insert(:event, organizer_actor: organizer, join_options: :restricted)
|
||||
|
||||
organizer_participation =
|
||||
%Participant{} = insert(:participant, event: event, actor: organizer, role: :creator)
|
||||
|
||||
{:ok, _join_activity, _participation} = ActivityPub.join(event, participant_actor)
|
||||
|
||||
join_data =
|
||||
File.read!("test/fixtures/mobilizon-leave-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", participant_url)
|
||||
|> Map.put("object", event_url)
|
||||
|
||||
assert {:ok, activity, _} = Transmogrifier.handle_incoming(join_data)
|
||||
|
||||
assert activity.data["object"] == event_url
|
||||
assert activity.data["actor"] == participant_url
|
||||
|
||||
# The only participant left is the organizer
|
||||
assert event.id
|
||||
|> Events.list_participants_for_event()
|
||||
|> Map.get(:elements)
|
||||
|> Enum.map(& &1.id) ==
|
||||
[organizer_participation.id]
|
||||
end
|
||||
|
||||
test "it refuses Leave activities when actor is the only organizer" do
|
||||
%Actor{url: organizer_url} = organizer = insert(:actor)
|
||||
|
||||
%Event{url: event_url} =
|
||||
event = insert(:event, organizer_actor: organizer, join_options: :restricted)
|
||||
|
||||
%Participant{} = insert(:participant, event: event, actor: organizer, role: :creator)
|
||||
|
||||
join_data =
|
||||
File.read!("test/fixtures/mobilizon-leave-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", organizer_url)
|
||||
|> Map.put("object", event_url)
|
||||
|
||||
assert :error = Transmogrifier.handle_incoming(join_data)
|
||||
end
|
||||
end
|
||||
end
|
||||
85
test/federation/activity_pub/transmogrifier/undo_test.exs
Normal file
85
test/federation/activity_pub/transmogrifier/undo_test.exs
Normal file
@@ -0,0 +1,85 @@
|
||||
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.UndoTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
import Mox
|
||||
alias Mobilizon.Actors
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Federation.ActivityPub.{Activity, Transmogrifier}
|
||||
alias Mobilizon.Service.HTTP.ActivityPub.Mock
|
||||
|
||||
describe "handle incoming undo activities" do
|
||||
test "it works for incoming unannounces with an existing notice" do
|
||||
comment = insert(:comment)
|
||||
|
||||
announce_data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", comment.url)
|
||||
|
||||
actor_data =
|
||||
File.read!("test/fixtures/mastodon-actor.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: "https://framapiaf.org/users/Framasoft"}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: actor_data}}
|
||||
end)
|
||||
|
||||
{:ok, _, %Comment{}} = Transmogrifier.handle_incoming(announce_data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-undo-announce.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", announce_data)
|
||||
|> Map.put("actor", announce_data["actor"])
|
||||
|
||||
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["type"] == "Undo"
|
||||
assert data["object"]["type"] == "Announce"
|
||||
assert data["object"]["object"] == comment.url
|
||||
|
||||
assert data["object"]["id"] ==
|
||||
"https://framapiaf.org/users/peertube/statuses/104584600044284729/activity"
|
||||
end
|
||||
|
||||
test "it works for incomming unfollows with an existing follow" do
|
||||
actor = insert(:actor)
|
||||
|
||||
follow_data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", actor.url)
|
||||
|
||||
actor_data =
|
||||
File.read!("test/fixtures/mastodon-actor.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("id", "https://social.tcit.fr/users/tcit")
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: "https://social.tcit.fr/users/tcit"}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: actor_data}}
|
||||
end)
|
||||
|
||||
{:ok, %Activity{data: _, local: false}, _} = Transmogrifier.handle_incoming(follow_data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-unfollow-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", follow_data)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["type"] == "Undo"
|
||||
assert data["object"]["type"] == "Follow"
|
||||
assert data["object"]["object"] == actor.url
|
||||
assert data["actor"] == "https://social.tcit.fr/users/tcit"
|
||||
|
||||
{:ok, followed} = Actors.get_actor_by_url(data["actor"])
|
||||
refute Actors.is_following(followed, actor)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -11,11 +11,12 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
import Mobilizon.Factory
|
||||
import ExUnit.CaptureLog
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
alias Mobilizon.{Actors, Conversations, Events}
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.{Actors, Discussions, Events}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Resources.Resource
|
||||
alias Mobilizon.Todos.{Todo, TodoList}
|
||||
|
||||
@@ -25,13 +26,10 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
alias Mobilizon.Federation.ActivityStream.Convertible
|
||||
|
||||
alias Mobilizon.GraphQL.API
|
||||
|
||||
alias Mobilizon.Service.HTTP.ActivityPub.Mock
|
||||
alias Mobilizon.Tombstone
|
||||
alias Mobilizon.Web.Endpoint
|
||||
|
||||
setup_all do
|
||||
HTTPoison.start()
|
||||
end
|
||||
|
||||
describe "handle incoming events" do
|
||||
test "it works for incoming events" do
|
||||
use_cassette "activity_pub/fetch_mobilizon_post_activity" do
|
||||
@@ -67,7 +65,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
assert object["actor"] == "https://test.mobilizon.org/@Alicia"
|
||||
assert object["location"]["name"] == "Locaux de Framasoft"
|
||||
assert object["attributedTo"] == "https://test.mobilizon.org/@Alicia"
|
||||
# assert object["attributedTo"] == "https://test.mobilizon.org/@Alicia"
|
||||
|
||||
assert event.physical_address.street == "10 Rue Jangot"
|
||||
|
||||
@@ -79,172 +77,47 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
{:ok, %Actor{}} = Actors.get_actor_by_url(object["actor"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming comments" do
|
||||
test "it ignores an incoming comment if we already have it" do
|
||||
comment = insert(:comment)
|
||||
test "it works for incoming events for local groups" do
|
||||
%Actor{url: group_url, id: group_id} = group = insert(:group)
|
||||
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"actor" => comment.actor.url,
|
||||
"object" => Convertible.model_to_as(comment)
|
||||
}
|
||||
|
||||
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 fetches replied-to activities if we don't have them" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("inReplyTo", "https://blob.cat/objects/02fdea3d-932c-4348-9ecb-3f9eb3fbdd94")
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|
||||
{:ok, returned_activity, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
%Comment{} =
|
||||
origin_comment =
|
||||
Conversations.get_comment_from_url(
|
||||
"https://blob.cat/objects/02fdea3d-932c-4348-9ecb-3f9eb3fbdd94"
|
||||
%Actor{url: actor_url, id: actor_id} =
|
||||
actor =
|
||||
insert(:actor,
|
||||
domain: "test.mobilizon.org",
|
||||
url: "https://test.mobilizon.org/@member",
|
||||
preferred_username: "member"
|
||||
)
|
||||
|
||||
assert returned_activity.data["object"]["inReplyTo"] ==
|
||||
"https://blob.cat/objects/02fdea3d-932c-4348-9ecb-3f9eb3fbdd94"
|
||||
with_mock ActivityPub, [:passthrough],
|
||||
get_or_fetch_actor_by_url: fn url ->
|
||||
case url do
|
||||
^group_url -> {:ok, group}
|
||||
^actor_url -> {:ok, actor}
|
||||
end
|
||||
end do
|
||||
data = File.read!("test/fixtures/mobilizon-post-activity-group.json") |> Jason.decode!()
|
||||
|
||||
assert returned_activity.data["object"]["inReplyTo"] == origin_comment.url
|
||||
end
|
||||
object =
|
||||
data["object"] |> Map.put("actor", actor_url) |> Map.put("attributedTo", group_url)
|
||||
|
||||
test "it does not crash if the object in inReplyTo can't be fetched" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|> Poison.decode!()
|
||||
data =
|
||||
data
|
||||
|> Map.put("actor", actor_url)
|
||||
|> Map.put("attributedTo", group_url)
|
||||
|> Map.put("object", object)
|
||||
|
||||
object =
|
||||
data["object"]
|
||||
|> Map.put("inReplyTo", "https://404.site/whatever")
|
||||
assert {:ok, %Activity{data: activity_data, local: false}, %Event{} = event} =
|
||||
Transmogrifier.handle_incoming(data)
|
||||
|
||||
data =
|
||||
data
|
||||
|> Map.put("object", object)
|
||||
|
||||
assert capture_log([level: :warn], fn ->
|
||||
{:ok, _returned_activity, _entity} = Transmogrifier.handle_incoming(data)
|
||||
end) =~ "[warn] Parent object is something we don't handle"
|
||||
end
|
||||
|
||||
test "it works for incoming notices" do
|
||||
use_cassette "activity_pub/mastodon_post_activity" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["id"] ==
|
||||
"https://framapiaf.org/users/admin/statuses/99512778738411822/activity"
|
||||
|
||||
assert data["to"] == [
|
||||
"https://www.w3.org/ns/activitystreams#Public",
|
||||
"https://framapiaf.org/users/tcit"
|
||||
]
|
||||
|
||||
# assert data["cc"] == [
|
||||
# "https://framapiaf.org/users/admin/followers",
|
||||
# "http://mobilizon.com/@tcit"
|
||||
# ]
|
||||
|
||||
assert data["actor"] == "https://framapiaf.org/users/admin"
|
||||
|
||||
object = data["object"]
|
||||
assert object["id"] == "https://framapiaf.org/users/admin/statuses/99512778738411822"
|
||||
|
||||
assert object["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
|
||||
# assert object["cc"] == [
|
||||
# "https://framapiaf.org/users/admin/followers",
|
||||
# "http://localtesting.pleroma.lol/users/lain"
|
||||
# ]
|
||||
|
||||
assert object["actor"] == "https://framapiaf.org/users/admin"
|
||||
assert object["attributedTo"] == "https://framapiaf.org/users/admin"
|
||||
|
||||
{:ok, %Actor{}} = Actors.get_actor_by_url(object["actor"])
|
||||
assert event.organizer_actor_id == actor_id
|
||||
assert event.attributed_to_id == group_id
|
||||
assert activity_data["actor"] == actor_url
|
||||
assert activity_data["attributedTo"] == group_url
|
||||
assert activity_data["object"]["actor"] == actor_url
|
||||
assert activity_data["object"]["attributedTo"] == group_url
|
||||
end
|
||||
end
|
||||
|
||||
test "it works for incoming notices with hashtags" do
|
||||
use_cassette "activity_pub/mastodon_activity_hashtag" do
|
||||
data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
assert Enum.at(data["object"]["tag"], 0)["name"] == "@tcit@framapiaf.org"
|
||||
assert Enum.at(data["object"]["tag"], 1)["name"] == "#moo"
|
||||
end
|
||||
end
|
||||
|
||||
# test "it works for incoming notices with contentMap" do
|
||||
# data =
|
||||
# File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Jason.decode!()
|
||||
|
||||
# {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert data["object"]["content"] ==
|
||||
# "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"
|
||||
# end
|
||||
|
||||
# test "it works for incoming notices with to/cc not being an array (kroeg)" do
|
||||
# data = File.read!("test/fixtures/kroeg-post-activity.json") |> Jason.decode!()
|
||||
|
||||
# {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert data["object"]["content"] ==
|
||||
# "<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>"
|
||||
# end
|
||||
|
||||
# test "it works for incoming announces with actor being inlined (kroeg)" do
|
||||
# data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Jason.decode!()
|
||||
|
||||
# {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert data["actor"] == "https://puckipedia.com/"
|
||||
# end
|
||||
|
||||
# test "it works for incoming notices with tag not being an array (kroeg)" do
|
||||
# data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Jason.decode!()
|
||||
|
||||
# {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert data["object"]["emoji"] == %{
|
||||
# "icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
|
||||
# }
|
||||
|
||||
# data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Jason.decode!()
|
||||
|
||||
# {:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert "test" in data["object"]["tag"]
|
||||
# end
|
||||
|
||||
test "it works for incoming notices with url not being a string (prismo)" do
|
||||
data = File.read!("test/fixtures/prismo-url-map.json") |> Jason.decode!()
|
||||
|
||||
assert {:error, :not_supported} == Transmogrifier.handle_incoming(data)
|
||||
# Pages are not supported
|
||||
# {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
# assert data["object"]["url"] == "https://prismo.news/posts/83"
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming todo lists" do
|
||||
@@ -463,7 +336,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"to" => [group.members_url],
|
||||
"actor" => actor.url,
|
||||
"target" => group.resources_url,
|
||||
"object" => Convertible.model_to_as(resource)
|
||||
@@ -491,7 +364,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"to" => [group.members_url],
|
||||
"actor" => creator.url,
|
||||
"target" => group.resources_url,
|
||||
"object" => %{
|
||||
@@ -534,7 +407,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"to" => [group.members_url],
|
||||
"actor" => creator.url,
|
||||
"target" => group.resources_url,
|
||||
"object" => %{
|
||||
@@ -586,7 +459,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"to" => [group.members_url],
|
||||
"actor" => creator.url,
|
||||
"target" => parent_resource.url,
|
||||
"object" => %{
|
||||
@@ -631,7 +504,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"to" => [group.members_url],
|
||||
"actor" => creator.url,
|
||||
"target" => group.resources_url,
|
||||
"object" => %{
|
||||
@@ -665,7 +538,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
activity = %{
|
||||
"type" => "Add",
|
||||
"to" => [group.url],
|
||||
"to" => [group.members_url],
|
||||
"actor" => creator.url,
|
||||
"target" => group.resources_url,
|
||||
"object" => %{
|
||||
@@ -787,43 +660,49 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
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!()
|
||||
data = File.read!("test/fixtures/mastodon-announce.json") |> Jason.decode!()
|
||||
status_data = File.read!("test/fixtures/mastodon-status.json") |> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: "https://framapiaf.org/users/peertube/statuses/104584600044284729"},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: status_data}}
|
||||
end)
|
||||
|
||||
assert data["actor"] == "https://framapiaf.org/users/Framasoft"
|
||||
assert data["type"] == "Announce"
|
||||
{:ok, _, %Comment{actor: %Actor{url: actor_url}, url: comment_url}} =
|
||||
Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["id"] ==
|
||||
"https://framapiaf.org/users/Framasoft/statuses/102501959686438400/activity"
|
||||
assert actor_url == "https://framapiaf.org/users/peertube"
|
||||
|
||||
assert data["object"] ==
|
||||
"https://framapiaf.org/users/Framasoft/statuses/102501959686438400"
|
||||
|
||||
assert %Comment{} = Conversations.get_comment_from_url(data["object"])
|
||||
end
|
||||
assert comment_url ==
|
||||
"https://framapiaf.org/users/peertube/statuses/104584600044284729"
|
||||
end
|
||||
|
||||
test "it works for incoming announces with an existing activity" do
|
||||
use_cassette "activity_pub/mastodon_announce_existing_activity" do
|
||||
comment = insert(:comment)
|
||||
%Comment{url: comment_url, actor: %Actor{url: actor_url} = actor} = insert(:comment)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", comment.url)
|
||||
actor_data =
|
||||
File.read!("test/fixtures/mastodon-actor.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", comment_url)
|
||||
|
||||
assert data["actor"] == "https://framapiaf.org/users/Framasoft"
|
||||
assert data["type"] == "Announce"
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: actor_url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: actor_data}}
|
||||
end)
|
||||
|
||||
assert data["id"] ==
|
||||
"https://framapiaf.org/users/Framasoft/statuses/102501959686438400/activity"
|
||||
{:ok, _, %Comment{actor: %Actor{url: actor_url}, url: comment_url_2}} =
|
||||
Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["object"] == comment.url
|
||||
end
|
||||
assert actor_url == actor.url
|
||||
|
||||
assert comment_url == comment_url_2
|
||||
end
|
||||
end
|
||||
|
||||
@@ -926,12 +805,12 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|> Map.put("object", object)
|
||||
|> Map.put("actor", actor_url)
|
||||
|
||||
assert Conversations.get_comment_from_url(comment_url)
|
||||
assert is_nil(Conversations.get_comment_from_url(comment_url).deleted_at)
|
||||
assert Discussions.get_comment_from_url(comment_url)
|
||||
assert is_nil(Discussions.get_comment_from_url(comment_url).deleted_at)
|
||||
|
||||
{:ok, %Activity{local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
refute is_nil(Conversations.get_comment_from_url(comment_url).deleted_at)
|
||||
refute is_nil(Discussions.get_comment_from_url(comment_url).deleted_at)
|
||||
end
|
||||
|
||||
test "it fails for incoming deletes with spoofed origin" do
|
||||
@@ -942,7 +821,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", comment.url)
|
||||
|
||||
{:ok, %Activity{local: false}, _} = Transmogrifier.handle_incoming(announce_data)
|
||||
{:ok, _, _} = Transmogrifier.handle_incoming(announce_data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete.json")
|
||||
@@ -958,9 +837,11 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
:error = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert Conversations.get_comment_from_url(comment.url)
|
||||
assert Discussions.get_comment_from_url(comment.url)
|
||||
end
|
||||
|
||||
setup :set_mox_from_context
|
||||
|
||||
test "it works for incoming actor deletes" do
|
||||
%Actor{url: url} = actor = insert(:actor, url: "https://framapiaf.org/users/admin")
|
||||
%Event{url: event1_url} = event1 = insert(:event, organizer_actor: actor)
|
||||
@@ -971,7 +852,13 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete-user.json")
|
||||
|> Poison.decode!()
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 410, body: "Gone"}}
|
||||
end)
|
||||
|
||||
{:ok, _activity, _actor} = Transmogrifier.handle_incoming(data)
|
||||
assert %{success: 1, failure: 0} == Oban.drain_queue(:background)
|
||||
@@ -980,19 +867,31 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
assert {:error, :event_not_found} = Events.get_event(event1.id)
|
||||
# Tombstone are cascade deleted, seems correct for now
|
||||
# assert %Tombstone{} = Tombstone.find_tombstone(event1_url)
|
||||
assert %Comment{deleted_at: deleted_at} = Conversations.get_comment(comment1.id)
|
||||
assert %Comment{deleted_at: deleted_at} = Discussions.get_comment(comment1.id)
|
||||
refute is_nil(deleted_at)
|
||||
# assert %Tombstone{} = Tombstone.find_tombstone(comment1_url)
|
||||
end
|
||||
|
||||
test "it fails for incoming actor deletes with spoofed origin" do
|
||||
%{url: url} = insert(:actor)
|
||||
deleted_actor_url = "https://framapiaf.org/users/admin"
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-delete-user.json")
|
||||
|> Poison.decode!()
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", url)
|
||||
|
||||
deleted_actor_data =
|
||||
File.read!("test/fixtures/mastodon-actor.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("id", deleted_actor_url)
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{url: ^deleted_actor_url}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: deleted_actor_data}}
|
||||
end)
|
||||
|
||||
assert capture_log(fn ->
|
||||
assert :error == Transmogrifier.handle_incoming(data)
|
||||
end) =~ "Object origin check failed"
|
||||
@@ -1001,62 +900,29 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
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)
|
||||
describe "handle tombstones" do
|
||||
setup :verify_on_exit!
|
||||
|
||||
announce_data =
|
||||
File.read!("test/fixtures/mastodon-announce.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", comment.url)
|
||||
# This is a hack to handle fetching tombstones
|
||||
test "works for incoming tombstone creations" do
|
||||
%Comment{url: comment_url} = comment = insert(:comment, local: false)
|
||||
tombstone = build(:tombstone, uri: comment_url)
|
||||
data = Convertible.model_to_as(tombstone)
|
||||
|
||||
{:ok, %Activity{data: announce_data, local: false}, _} =
|
||||
Transmogrifier.handle_incoming(announce_data)
|
||||
activity = %{
|
||||
"type" => "Create",
|
||||
"to" => data["to"],
|
||||
"cc" => data["cc"],
|
||||
"actor" => data["actor"],
|
||||
"attributedTo" => data["attributedTo"],
|
||||
"object" => data
|
||||
}
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-undo-announce.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", announce_data)
|
||||
|> Map.put("actor", announce_data["actor"])
|
||||
|
||||
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["type"] == "Undo"
|
||||
assert data["object"]["type"] == "Announce"
|
||||
assert data["object"]["object"] == comment.url
|
||||
|
||||
assert data["object"]["id"] ==
|
||||
"https://framapiaf.org/users/Framasoft/statuses/102501959686438400/activity"
|
||||
end
|
||||
end
|
||||
|
||||
test "it works for incomming unfollows with an existing follow" do
|
||||
use_cassette "activity_pub/unfollow_existing_follow_activity" do
|
||||
actor = insert(:actor)
|
||||
|
||||
follow_data =
|
||||
File.read!("test/fixtures/mastodon-follow-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", actor.url)
|
||||
|
||||
{:ok, %Activity{data: _, local: false}, _} = Transmogrifier.handle_incoming(follow_data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-unfollow-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", follow_data)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}, _} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["type"] == "Undo"
|
||||
assert data["object"]["type"] == "Follow"
|
||||
assert data["object"]["object"] == actor.url
|
||||
assert data["actor"] == "https://social.tcit.fr/users/tcit"
|
||||
|
||||
{:ok, followed} = Actors.get_actor_by_url(data["actor"])
|
||||
refute Actors.is_following(followed, actor)
|
||||
end
|
||||
{:ok, _activity, %Comment{url: comment_url}} = Transmogrifier.handle_incoming(activity)
|
||||
assert comment_url == comment.url
|
||||
assert %Comment{} = comment = Discussions.get_comment_from_url(comment_url)
|
||||
assert %Tombstone{} = Tombstone.find_tombstone(comment_url)
|
||||
refute is_nil(comment.deleted_at)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1136,120 +1002,6 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
# 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)
|
||||
|
||||
refute Actors.is_following(follower, followed)
|
||||
|
||||
{:ok, follow_activity, _} = ActivityPub.follow(follower, followed)
|
||||
assert Actors.is_following(follower, followed)
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-accept-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", followed.url)
|
||||
|
||||
object =
|
||||
accept_data["object"]
|
||||
|> Map.put("actor", follower.url)
|
||||
|> Map.put("id", follow_activity.data["id"])
|
||||
|
||||
accept_data = Map.put(accept_data, "object", object)
|
||||
|
||||
{:ok, activity, _} = Transmogrifier.handle_incoming(accept_data)
|
||||
refute activity.local
|
||||
|
||||
assert activity.data["object"]["id"] == follow_activity.data["id"]
|
||||
|
||||
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
||||
|
||||
assert Actors.is_following(follower, followed)
|
||||
end
|
||||
|
||||
test "it works for incoming accepts which are referenced by IRI only" do
|
||||
follower = insert(:actor)
|
||||
followed = insert(:actor)
|
||||
|
||||
{:ok, follow_activity, _} = ActivityPub.follow(follower, followed)
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-accept-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", followed.url)
|
||||
|> Map.put("object", follow_activity.data["id"])
|
||||
|
||||
{:ok, activity, _} = Transmogrifier.handle_incoming(accept_data)
|
||||
assert activity.data["object"]["id"] == follow_activity.data["id"]
|
||||
assert activity.data["object"]["id"] =~ "/follow/"
|
||||
assert activity.data["id"] =~ "/accept/follow/"
|
||||
|
||||
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
||||
|
||||
assert Actors.is_following(follower, followed)
|
||||
end
|
||||
|
||||
test "it fails for incoming accepts which cannot be correlated" do
|
||||
follower = insert(:actor)
|
||||
followed = insert(:actor)
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-accept-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", followed.url)
|
||||
|
||||
accept_data =
|
||||
Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.url))
|
||||
|
||||
:error = Transmogrifier.handle_incoming(accept_data)
|
||||
|
||||
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
||||
|
||||
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)
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-reject-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", followed.url)
|
||||
|
||||
accept_data =
|
||||
Map.put(accept_data, "object", Map.put(accept_data["object"], "actor", follower.url))
|
||||
|
||||
:error = Transmogrifier.handle_incoming(accept_data)
|
||||
|
||||
{:ok, follower} = Actors.get_actor_by_url(follower.url)
|
||||
|
||||
refute Actors.is_following(follower, followed)
|
||||
end
|
||||
|
||||
test "it works for incoming rejects which are referenced by IRI only" do
|
||||
follower = insert(:actor)
|
||||
followed = insert(:actor)
|
||||
|
||||
{:ok, follow_activity, _} = ActivityPub.follow(follower, followed)
|
||||
|
||||
assert Actors.is_following(follower, followed)
|
||||
|
||||
reject_data =
|
||||
File.read!("test/fixtures/mastodon-reject-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", followed.url)
|
||||
|> Map.put("object", follow_activity.data["id"])
|
||||
|
||||
{:ok, %Activity{data: _}, _} = Transmogrifier.handle_incoming(reject_data)
|
||||
|
||||
refute Actors.is_following(follower, followed)
|
||||
end
|
||||
end
|
||||
|
||||
describe "handle incoming flag activities" do
|
||||
test "it accepts Flag activities" do
|
||||
%Actor{url: reporter_url} = Relay.get_actor()
|
||||
@@ -1276,201 +1028,6 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
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)
|
||||
%Actor{url: participant_url} = _participant = insert(:actor)
|
||||
|
||||
%Event{url: event_url} = _event = insert(:event, organizer_actor: organizer)
|
||||
|
||||
join_data =
|
||||
File.read!("test/fixtures/mobilizon-join-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", participant_url)
|
||||
|> Map.put("object", event_url)
|
||||
|> Map.put("participationMessage", @join_message)
|
||||
|
||||
assert {:ok, activity, %Participant{} = participant} =
|
||||
Transmogrifier.handle_incoming(join_data)
|
||||
|
||||
assert participant.metadata.message == @join_message
|
||||
assert participant.role == :participant
|
||||
|
||||
assert activity.data["type"] == "Accept"
|
||||
assert activity.data["object"]["object"] == event_url
|
||||
assert activity.data["object"]["id"] =~ "/join/event/"
|
||||
assert activity.data["object"]["type"] =~ "Join"
|
||||
assert activity.data["object"]["participationMessage"] == @join_message
|
||||
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)
|
||||
|
||||
%Event{} = event = insert(:event, organizer_actor: organizer, join_options: :restricted)
|
||||
|
||||
{:ok, join_activity, participation} =
|
||||
ActivityPub.join(event, participant_actor, false, %{metadata: %{role: :not_approved}})
|
||||
|
||||
accept_data =
|
||||
File.read!("test/fixtures/mastodon-accept-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", organizer_url)
|
||||
|> Map.put("object", participation.url)
|
||||
|
||||
{:ok, accept_activity, _} = Transmogrifier.handle_incoming(accept_data)
|
||||
assert accept_activity.data["object"]["id"] == join_activity.data["id"]
|
||||
assert accept_activity.data["object"]["id"] =~ "/join/"
|
||||
assert accept_activity.data["id"] =~ "/accept/join/"
|
||||
|
||||
# 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)
|
||||
|
||||
%Event{} = event = insert(:event, organizer_actor: organizer, join_options: :restricted)
|
||||
|
||||
{:ok, join_activity, participation} = ActivityPub.join(event, participant_actor)
|
||||
|
||||
reject_data =
|
||||
File.read!("test/fixtures/mastodon-reject-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", organizer_url)
|
||||
|> Map.put("object", participation.url)
|
||||
|
||||
{:ok, reject_activity, _} = Transmogrifier.handle_incoming(reject_data)
|
||||
assert reject_activity.data["object"]["id"] == join_activity.data["id"]
|
||||
assert reject_activity.data["object"]["id"] =~ "/join/"
|
||||
assert reject_activity.data["id"] =~ "/reject/join/"
|
||||
|
||||
# We don't accept already rejected Reject activities
|
||||
assert capture_log([level: :warn], fn ->
|
||||
assert :error == Transmogrifier.handle_incoming(reject_data)
|
||||
end) =~
|
||||
"Unable to process Reject activity \"http://mastodon.example.org/users/admin#rejects/follows/4\". Object \"#{
|
||||
join_activity.data["id"]
|
||||
}\" wasn't found."
|
||||
|
||||
# Organiser is not present since we use factories directly
|
||||
assert event.id
|
||||
|> Events.list_participants_for_event()
|
||||
|> Map.get(:elements)
|
||||
|> Enum.map(& &1.role) == [:rejected]
|
||||
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)
|
||||
|
||||
%Event{url: event_url} =
|
||||
event = insert(:event, organizer_actor: organizer, join_options: :restricted)
|
||||
|
||||
organizer_participation =
|
||||
%Participant{} = insert(:participant, event: event, actor: organizer, role: :creator)
|
||||
|
||||
{:ok, _join_activity, _participation} = ActivityPub.join(event, participant_actor)
|
||||
|
||||
join_data =
|
||||
File.read!("test/fixtures/mobilizon-leave-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", participant_url)
|
||||
|> Map.put("object", event_url)
|
||||
|
||||
assert {:ok, activity, _} = Transmogrifier.handle_incoming(join_data)
|
||||
|
||||
assert activity.data["object"] == event_url
|
||||
assert activity.data["actor"] == participant_url
|
||||
|
||||
# The only participant left is the organizer
|
||||
assert event.id
|
||||
|> Events.list_participants_for_event()
|
||||
|> Map.get(:elements)
|
||||
|> Enum.map(& &1.id) ==
|
||||
[organizer_participation.id]
|
||||
end
|
||||
|
||||
test "it refuses Leave activities when actor is the only organizer" do
|
||||
%Actor{url: organizer_url} = organizer = insert(:actor)
|
||||
|
||||
%Event{url: event_url} =
|
||||
event = insert(:event, organizer_actor: organizer, join_options: :restricted)
|
||||
|
||||
%Participant{} = insert(:participant, event: event, actor: organizer, role: :creator)
|
||||
|
||||
join_data =
|
||||
File.read!("test/fixtures/mobilizon-leave-activity.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("actor", organizer_url)
|
||||
|> Map.put("object", event_url)
|
||||
|
||||
assert :error = Transmogrifier.handle_incoming(join_data)
|
||||
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)
|
||||
@@ -1501,7 +1058,7 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
assert Enum.member?(object["tag"], expected_mention)
|
||||
end
|
||||
|
||||
test "it adds the json-ld context and the conversation property" do
|
||||
test "it adds the json-ld context and the discussion property" do
|
||||
actor = insert(:actor)
|
||||
|
||||
{:ok, activity, _} = API.Comments.create_comment(%{actor_id: actor.id, text: "hey"})
|
||||
@@ -1558,24 +1115,40 @@ defmodule Mobilizon.Federation.ActivityPub.TransmogrifierTest do
|
||||
|
||||
describe "actor origin check" do
|
||||
test "it rejects objects with a bogus origin" do
|
||||
use_cassette "activity_pub/object_bogus_origin" do
|
||||
{:error, _} = ActivityPub.fetch_object_from_url("https://info.pleroma.site/activity.json")
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/https__info.pleroma.site_activity.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: "https://info.pleroma.site/activity.json"}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
{:error, _} = ActivityPub.fetch_object_from_url("https://info.pleroma.site/activity.json")
|
||||
end
|
||||
|
||||
test "it rejects activities which reference objects with bogus origins" do
|
||||
use_cassette "activity_pub/activity_object_bogus" do
|
||||
data = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"id" => "https://framapiaf.org/users/admin/activities/1234",
|
||||
"actor" => "https://framapiaf.org/users/admin",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => "https://info.pleroma.site/activity.json",
|
||||
"type" => "Announce"
|
||||
}
|
||||
data =
|
||||
File.read!("test/fixtures/https__info.pleroma.site_activity.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
:error = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{method: :get, url: "https://info.pleroma.site/activity.json"}, _opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
data = %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"id" => "https://framapiaf.org/users/admin/activities/1234",
|
||||
"actor" => "https://framapiaf.org/users/admin",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => "https://info.pleroma.site/activity.json",
|
||||
"type" => "Announce"
|
||||
}
|
||||
|
||||
:error = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,15 +10,11 @@ defmodule Mobilizon.Federation.ActivityPub.UtilsTest do
|
||||
alias Mobilizon.Web.Endpoint
|
||||
alias Mobilizon.Web.Router.Helpers, as: Routes
|
||||
|
||||
setup_all do
|
||||
HTTPoison.start()
|
||||
end
|
||||
|
||||
describe "make" do
|
||||
test "comment data from struct" do
|
||||
comment = insert(:comment)
|
||||
tag = insert(:tag, title: "MyTag")
|
||||
reply = insert(:comment, in_reply_to_comment: comment, tags: [tag])
|
||||
reply = insert(:comment, in_reply_to_comment: comment, tags: [tag], attributed_to: nil)
|
||||
|
||||
assert %{
|
||||
"type" => "Note",
|
||||
@@ -42,8 +38,8 @@ defmodule Mobilizon.Federation.ActivityPub.UtilsTest do
|
||||
end
|
||||
|
||||
test "comment data from map" do
|
||||
comment = insert(:comment)
|
||||
reply = insert(:comment, in_reply_to_comment: comment)
|
||||
comment = insert(:comment, attributed_to: nil)
|
||||
reply = insert(:comment, in_reply_to_comment: comment, attributed_to: nil)
|
||||
to = ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
comment_data = Converter.Comment.model_to_as(reply)
|
||||
assert comment_data["type"] == "Note"
|
||||
|
||||
31
test/fixtures/geospatial/addok/geocode.json
vendored
Normal file
31
test/fixtures/geospatial/addok/geocode.json
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"version": "draft",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [4.842569, 45.751718] },
|
||||
"properties": {
|
||||
"label": "10 Rue Jangot 69007 Lyon",
|
||||
"score": 0.9999999999926557,
|
||||
"housenumber": "10",
|
||||
"id": "69387_3650_00010",
|
||||
"type": "housenumber",
|
||||
"x": 843232.29,
|
||||
"y": 6518573.31,
|
||||
"importance": 0.5454797306366062,
|
||||
"name": "10 Rue Jangot",
|
||||
"postcode": "69007",
|
||||
"citycode": "69387",
|
||||
"city": "Lyon",
|
||||
"district": "Lyon 7e Arrondissement",
|
||||
"context": "69, Rh\u00f4ne, Auvergne-Rh\u00f4ne-Alpes",
|
||||
"street": "Rue Jangot",
|
||||
"distance": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"attribution": "BAN",
|
||||
"licence": "ETALAB-2.0",
|
||||
"limit": 1
|
||||
}
|
||||
49
test/fixtures/geospatial/addok/search.json
vendored
Normal file
49
test/fixtures/geospatial/addok/search.json
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"version": "draft",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [4.842569, 45.751718] },
|
||||
"properties": {
|
||||
"label": "10 Rue Jangot 69007 Lyon",
|
||||
"score": 0.8677708846033279,
|
||||
"housenumber": "10",
|
||||
"id": "69387_3650_00010",
|
||||
"type": "housenumber",
|
||||
"x": 843232.29,
|
||||
"y": 6518573.31,
|
||||
"importance": 0.5454797306366062,
|
||||
"name": "10 Rue Jangot",
|
||||
"postcode": "69007",
|
||||
"citycode": "69387",
|
||||
"city": "Lyon",
|
||||
"district": "Lyon 7e Arrondissement",
|
||||
"context": "69, Rh\u00f4ne, Auvergne-Rh\u00f4ne-Alpes",
|
||||
"street": "Rue Jangot"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": { "type": "Point", "coordinates": [2.440319, 50.371266] },
|
||||
"properties": {
|
||||
"label": "Rue Jangon 62127 Bailleul-aux-Cornailles",
|
||||
"score": 0.5269641371131077,
|
||||
"id": "62070_0100",
|
||||
"type": "street",
|
||||
"x": 660129.18,
|
||||
"y": 7030540.46,
|
||||
"importance": 0.25814396978264664,
|
||||
"name": "Rue Jangon",
|
||||
"postcode": "62127",
|
||||
"citycode": "62070",
|
||||
"city": "Bailleul-aux-Cornailles",
|
||||
"context": "62, Pas-de-Calais, Hauts-de-France"
|
||||
}
|
||||
}
|
||||
],
|
||||
"attribution": "BAN",
|
||||
"licence": "ETALAB-2.0",
|
||||
"query": "10 Rue Jangot",
|
||||
"limit": 5
|
||||
}
|
||||
5
test/fixtures/geospatial/google_maps/api_key_invalid.json
vendored
Normal file
5
test/fixtures/geospatial/google_maps/api_key_invalid.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"error_message": "The provided API key is invalid.",
|
||||
"results": [],
|
||||
"status": "REQUEST_DENIED"
|
||||
}
|
||||
109
test/fixtures/geospatial/google_maps/geocode.json
vendored
Normal file
109
test/fixtures/geospatial/google_maps/geocode.json
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"plus_code": {
|
||||
"compound_code": "QR2V+M2 Lyon, France",
|
||||
"global_code": "8FQ6QR2V+M2"
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"address_components": [
|
||||
{
|
||||
"long_name": "10bis",
|
||||
"short_name": "10bis",
|
||||
"types": ["street_number"]
|
||||
},
|
||||
{
|
||||
"long_name": "Rue Jangot",
|
||||
"short_name": "Rue Jangot",
|
||||
"types": ["route"]
|
||||
},
|
||||
{
|
||||
"long_name": "Lyon",
|
||||
"short_name": "Lyon",
|
||||
"types": ["locality", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "Rhône",
|
||||
"short_name": "Rhône",
|
||||
"types": ["administrative_area_level_2", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "Auvergne-Rhône-Alpes",
|
||||
"short_name": "Auvergne-Rhône-Alpes",
|
||||
"types": ["administrative_area_level_1", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "France",
|
||||
"short_name": "FR",
|
||||
"types": ["country", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "69007",
|
||||
"short_name": "69007",
|
||||
"types": ["postal_code"]
|
||||
}
|
||||
],
|
||||
"formatted_address": "10bis Rue Jangot, 69007 Lyon, France",
|
||||
"geometry": {
|
||||
"location": { "lat": 45.751725, "lng": 4.8424966 },
|
||||
"location_type": "ROOFTOP",
|
||||
"viewport": {
|
||||
"northeast": { "lat": 45.7530739802915, "lng": 4.843845580291503 },
|
||||
"southwest": { "lat": 45.7503760197085, "lng": 4.841147619708499 }
|
||||
}
|
||||
},
|
||||
"place_id": "ChIJrW0QikTq9EcR96jk2OnO75w",
|
||||
"plus_code": {
|
||||
"compound_code": "QR2R+MX Lyon, France",
|
||||
"global_code": "8FQ6QR2R+MX"
|
||||
},
|
||||
"types": ["street_address"]
|
||||
},
|
||||
{
|
||||
"address_components": [
|
||||
{ "long_name": "9", "short_name": "9", "types": ["street_number"] },
|
||||
{
|
||||
"long_name": "Rue Jangot",
|
||||
"short_name": "Rue Jangot",
|
||||
"types": ["route"]
|
||||
},
|
||||
{
|
||||
"long_name": "Lyon",
|
||||
"short_name": "Lyon",
|
||||
"types": ["locality", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "Rhône",
|
||||
"short_name": "Rhône",
|
||||
"types": ["administrative_area_level_2", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "Auvergne-Rhône-Alpes",
|
||||
"short_name": "Auvergne-Rhône-Alpes",
|
||||
"types": ["administrative_area_level_1", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "France",
|
||||
"short_name": "FR",
|
||||
"types": ["country", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "69007",
|
||||
"short_name": "69007",
|
||||
"types": ["postal_code"]
|
||||
}
|
||||
],
|
||||
"formatted_address": "9 Rue Jangot, 69007 Lyon, France",
|
||||
"geometry": {
|
||||
"location": { "lat": 45.7518165, "lng": 4.8427168 },
|
||||
"location_type": "RANGE_INTERPOLATED",
|
||||
"viewport": {
|
||||
"northeast": { "lat": 45.7531654802915, "lng": 4.844065780291502 },
|
||||
"southwest": { "lat": 45.7504675197085, "lng": 4.841367819708497 }
|
||||
}
|
||||
},
|
||||
"place_id": "EiA5IFJ1ZSBKYW5nb3QsIDY5MDA3IEx5b24sIEZyYW5jZSIaEhgKFAoSCR8N2ItE6vRHEW9tyPnhQsUIEAk",
|
||||
"types": ["street_address"]
|
||||
}
|
||||
],
|
||||
"status": "OK"
|
||||
}
|
||||
62
test/fixtures/geospatial/google_maps/geocode_2.json
vendored
Normal file
62
test/fixtures/geospatial/google_maps/geocode_2.json
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"html_attributions": [],
|
||||
"result": {
|
||||
"address_components": [
|
||||
{
|
||||
"long_name": "10bis",
|
||||
"short_name": "10bis",
|
||||
"types": ["street_number"]
|
||||
},
|
||||
{
|
||||
"long_name": "Rue Jangot",
|
||||
"short_name": "Rue Jangot",
|
||||
"types": ["route"]
|
||||
},
|
||||
{
|
||||
"long_name": "Lyon",
|
||||
"short_name": "Lyon",
|
||||
"types": ["locality", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "Rhône",
|
||||
"short_name": "Rhône",
|
||||
"types": ["administrative_area_level_2", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "Auvergne-Rhône-Alpes",
|
||||
"short_name": "Auvergne-Rhône-Alpes",
|
||||
"types": ["administrative_area_level_1", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "France",
|
||||
"short_name": "FR",
|
||||
"types": ["country", "political"]
|
||||
},
|
||||
{ "long_name": "69007", "short_name": "69007", "types": ["postal_code"] }
|
||||
],
|
||||
"adr_address": "\u003cspan class=\"street-address\"\u003e10bis Rue Jangot\u003c/span\u003e, \u003cspan class=\"postal-code\"\u003e69007\u003c/span\u003e \u003cspan class=\"locality\"\u003eLyon\u003c/span\u003e, \u003cspan class=\"country-name\"\u003eFrance\u003c/span\u003e",
|
||||
"formatted_address": "10bis Rue Jangot, 69007 Lyon, France",
|
||||
"geometry": {
|
||||
"location": { "lat": 45.751725, "lng": 4.8424966 },
|
||||
"viewport": {
|
||||
"northeast": { "lat": 45.7531097802915, "lng": 4.843951380291502 },
|
||||
"southwest": { "lat": 45.7504118197085, "lng": 4.841253419708497 }
|
||||
}
|
||||
},
|
||||
"icon": "https://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png",
|
||||
"id": "4a3482a7a74c6203048adf713b736186c4ace7cd",
|
||||
"name": "10bis Rue Jangot",
|
||||
"place_id": "ChIJrW0QikTq9EcR96jk2OnO75w",
|
||||
"plus_code": {
|
||||
"compound_code": "QR2R+MX Lyon, France",
|
||||
"global_code": "8FQ6QR2R+MX"
|
||||
},
|
||||
"reference": "ChIJrW0QikTq9EcR96jk2OnO75w",
|
||||
"scope": "GOOGLE",
|
||||
"types": ["street_address"],
|
||||
"url": "https://maps.google.com/?q=10bis+Rue+Jangot,+69007+Lyon,+France&ftid=0x47f4ea448a106dad:0x9cefcee9d8e4a8f7",
|
||||
"utc_offset": 120,
|
||||
"vicinity": "Lyon"
|
||||
},
|
||||
"status": "OK"
|
||||
}
|
||||
55
test/fixtures/geospatial/google_maps/search.json
vendored
Normal file
55
test/fixtures/geospatial/google_maps/search.json
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"address_components": [
|
||||
{ "long_name": "10", "short_name": "10", "types": ["street_number"] },
|
||||
{
|
||||
"long_name": "Rue Jangot",
|
||||
"short_name": "Rue Jangot",
|
||||
"types": ["route"]
|
||||
},
|
||||
{
|
||||
"long_name": "Lyon",
|
||||
"short_name": "Lyon",
|
||||
"types": ["locality", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "Rhône",
|
||||
"short_name": "Rhône",
|
||||
"types": ["administrative_area_level_2", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "Auvergne-Rhône-Alpes",
|
||||
"short_name": "Auvergne-Rhône-Alpes",
|
||||
"types": ["administrative_area_level_1", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "France",
|
||||
"short_name": "FR",
|
||||
"types": ["country", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "69007",
|
||||
"short_name": "69007",
|
||||
"types": ["postal_code"]
|
||||
}
|
||||
],
|
||||
"formatted_address": "10 Rue Jangot, 69007 Lyon, France",
|
||||
"geometry": {
|
||||
"location": { "lat": 45.75164940000001, "lng": 4.8424032 },
|
||||
"location_type": "ROOFTOP",
|
||||
"viewport": {
|
||||
"northeast": { "lat": 45.75299838029151, "lng": 4.843752180291502 },
|
||||
"southwest": { "lat": 45.75030041970851, "lng": 4.841054219708497 }
|
||||
}
|
||||
},
|
||||
"place_id": "ChIJtW0QikTq9EcRLI4Vy6bRx0U",
|
||||
"plus_code": {
|
||||
"compound_code": "QR2R+MX Lyon, France",
|
||||
"global_code": "8FQ6QR2R+MX"
|
||||
},
|
||||
"types": ["street_address"]
|
||||
}
|
||||
],
|
||||
"status": "OK"
|
||||
}
|
||||
58
test/fixtures/geospatial/google_maps/search_2.json
vendored
Normal file
58
test/fixtures/geospatial/google_maps/search_2.json
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"html_attributions": [],
|
||||
"result": {
|
||||
"address_components": [
|
||||
{ "long_name": "10", "short_name": "10", "types": ["street_number"] },
|
||||
{
|
||||
"long_name": "Rue Jangot",
|
||||
"short_name": "Rue Jangot",
|
||||
"types": ["route"]
|
||||
},
|
||||
{
|
||||
"long_name": "Lyon",
|
||||
"short_name": "Lyon",
|
||||
"types": ["locality", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "Rhône",
|
||||
"short_name": "Rhône",
|
||||
"types": ["administrative_area_level_2", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "Auvergne-Rhône-Alpes",
|
||||
"short_name": "Auvergne-Rhône-Alpes",
|
||||
"types": ["administrative_area_level_1", "political"]
|
||||
},
|
||||
{
|
||||
"long_name": "France",
|
||||
"short_name": "FR",
|
||||
"types": ["country", "political"]
|
||||
},
|
||||
{ "long_name": "69007", "short_name": "69007", "types": ["postal_code"] }
|
||||
],
|
||||
"adr_address": "\u003cspan class=\"street-address\"\u003e10 Rue Jangot\u003c/span\u003e, \u003cspan class=\"postal-code\"\u003e69007\u003c/span\u003e \u003cspan class=\"locality\"\u003eLyon\u003c/span\u003e, \u003cspan class=\"country-name\"\u003eFrance\u003c/span\u003e",
|
||||
"formatted_address": "10 Rue Jangot, 69007 Lyon, France",
|
||||
"geometry": {
|
||||
"location": { "lat": 45.75164940000001, "lng": 4.842403200000001 },
|
||||
"viewport": {
|
||||
"northeast": { "lat": 45.7530412802915, "lng": 4.843668630291503 },
|
||||
"southwest": { "lat": 45.75034331970851, "lng": 4.840970669708498 }
|
||||
}
|
||||
},
|
||||
"icon": "https://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png",
|
||||
"id": "61b9418d092d2ed05ddd65a55dddefda5b9628cc",
|
||||
"name": "10 Rue Jangot",
|
||||
"place_id": "ChIJtW0QikTq9EcRLI4Vy6bRx0U",
|
||||
"plus_code": {
|
||||
"compound_code": "QR2R+MX Lyon, France",
|
||||
"global_code": "8FQ6QR2R+MX"
|
||||
},
|
||||
"reference": "ChIJtW0QikTq9EcRLI4Vy6bRx0U",
|
||||
"scope": "GOOGLE",
|
||||
"types": ["street_address"],
|
||||
"url": "https://maps.google.com/?q=10+Rue+Jangot,+69007+Lyon,+France&ftid=0x47f4ea448a106db5:0x45c7d1a6cb158e2c",
|
||||
"utc_offset": 120,
|
||||
"vicinity": "Lyon"
|
||||
},
|
||||
"status": "OK"
|
||||
}
|
||||
43
test/fixtures/geospatial/map_quest/geocode.json
vendored
Normal file
43
test/fixtures/geospatial/map_quest/geocode.json
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"info": {
|
||||
"statuscode": 0,
|
||||
"copyright": {
|
||||
"text": "\\u00A9 2019 MapQuest, Inc.",
|
||||
"imageUrl": "http://api.mqcdn.com/res/mqlogo.gif",
|
||||
"imageAltText": "\\u00A9 2019 MapQuest, Inc."
|
||||
},
|
||||
"messages": []
|
||||
},
|
||||
"options": { "maxResults": 1, "thumbMaps": true, "ignoreLatLngInput": false },
|
||||
"results": [
|
||||
{
|
||||
"providedLocation": { "latLng": { "lat": 45.751718, "lng": 4.842569 } },
|
||||
"locations": [
|
||||
{
|
||||
"street": "10 Rue Jangot",
|
||||
"adminArea6": "",
|
||||
"adminArea6Type": "Neighborhood",
|
||||
"adminArea5": "Lyon",
|
||||
"adminArea5Type": "City",
|
||||
"adminArea4": "",
|
||||
"adminArea4Type": "County",
|
||||
"adminArea3": "Auvergne-Rhône-Alpes",
|
||||
"adminArea3Type": "State",
|
||||
"adminArea1": "FR",
|
||||
"adminArea1Type": "Country",
|
||||
"postalCode": "69007",
|
||||
"geocodeQualityCode": "P1AAA",
|
||||
"geocodeQuality": "POINT",
|
||||
"dragPoint": false,
|
||||
"sideOfStreet": "N",
|
||||
"linkId": "0",
|
||||
"unknownInput": "",
|
||||
"type": "s",
|
||||
"latLng": { "lat": 45.751714, "lng": 4.842566 },
|
||||
"displayLatLng": { "lat": 45.751714, "lng": 4.842566 },
|
||||
"mapUrl": "http://open.mapquestapi.com/staticmap/v5/map?key=secret_key&type=map&size=225,160&locations=45.7517141,4.8425657|marker-sm-50318A-1&scalebar=true&zoom=15&rand=-570915433"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
47
test/fixtures/geospatial/map_quest/search.json
vendored
Normal file
47
test/fixtures/geospatial/map_quest/search.json
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"info": {
|
||||
"statuscode": 0,
|
||||
"copyright": {
|
||||
"text": "\\u00A9 2019 MapQuest, Inc.",
|
||||
"imageUrl": "http://api.mqcdn.com/res/mqlogo.gif",
|
||||
"imageAltText": "\\u00A9 2019 MapQuest, Inc."
|
||||
},
|
||||
"messages": []
|
||||
},
|
||||
"options": {
|
||||
"maxResults": 10,
|
||||
"thumbMaps": true,
|
||||
"ignoreLatLngInput": false
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"providedLocation": { "location": "10 rue Jangot" },
|
||||
"locations": [
|
||||
{
|
||||
"street": "10 Rue Jangot",
|
||||
"adminArea6": "7e",
|
||||
"adminArea6Type": "Neighborhood",
|
||||
"adminArea5": "Lyon",
|
||||
"adminArea5Type": "City",
|
||||
"adminArea4": "Lyon",
|
||||
"adminArea4Type": "County",
|
||||
"adminArea3": "Auvergne-Rhône-Alpes",
|
||||
"adminArea3Type": "State",
|
||||
"adminArea1": "FR",
|
||||
"adminArea1Type": "Country",
|
||||
"postalCode": "69007",
|
||||
"geocodeQualityCode": "P1AXX",
|
||||
"geocodeQuality": "POINT",
|
||||
"dragPoint": false,
|
||||
"sideOfStreet": "N",
|
||||
"linkId": "0",
|
||||
"unknownInput": "",
|
||||
"type": "s",
|
||||
"latLng": { "lat": 45.751714, "lng": 4.842566 },
|
||||
"displayLatLng": { "lat": 45.751714, "lng": 4.842566 },
|
||||
"mapUrl": "http://open.mapquestapi.com/staticmap/v5/map?key=secret_key&type=map&size=225,160&locations=45.7517141,4.8425657|marker-sm-50318A-1&scalebar=true&zoom=15&rand=1358091752"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
43
test/fixtures/geospatial/nominatim/geocode.json
vendored
Normal file
43
test/fixtures/geospatial/nominatim/geocode.json
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"geocoding": {
|
||||
"version": "0.1.0",
|
||||
"attribution": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
|
||||
"licence": "ODbL",
|
||||
"query": "45.751718,4.842569"
|
||||
},
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"geocoding": {
|
||||
"place_id": 41453794,
|
||||
"osm_type": "node",
|
||||
"osm_id": 3078260611,
|
||||
"type": "house",
|
||||
"accuracy": 0,
|
||||
"label": "10, Rue Jangot, La Guillotière, Lyon 7e Arrondissement, Lyon, Métropole de Lyon, Departemental constituency of Rhône, Auvergne-Rhône-Alpes, Metropolitan France, 69007, France",
|
||||
"name": null,
|
||||
"housenumber": "10",
|
||||
"street": "Rue Jangot",
|
||||
"postcode": "69007",
|
||||
"city": "Lyon",
|
||||
"county": "Lyon",
|
||||
"state": "Auvergne-Rhône-Alpes",
|
||||
"country": "France",
|
||||
"admin": {
|
||||
"level2": "France",
|
||||
"level3": "Metropolitan France",
|
||||
"level4": "Auvergne-Rhône-Alpes",
|
||||
"level5": "Departemental constituency of Rhône",
|
||||
"level6": "Métropole de Lyon",
|
||||
"level7": "Lyon",
|
||||
"level8": "Lyon",
|
||||
"level9": "Lyon 7e Arrondissement"
|
||||
}
|
||||
}
|
||||
},
|
||||
"geometry": { "type": "Point", "coordinates": [4.8425657, 45.7517141] }
|
||||
}
|
||||
]
|
||||
}
|
||||
42
test/fixtures/geospatial/nominatim/search.json
vendored
Normal file
42
test/fixtures/geospatial/nominatim/search.json
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"geocoding": {
|
||||
"version": "0.1.0",
|
||||
"attribution": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
|
||||
"licence": "ODbL",
|
||||
"query": "10 rue Jangot"
|
||||
},
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"geocoding": {
|
||||
"place_id": 41453794,
|
||||
"osm_type": "node",
|
||||
"osm_id": 3078260611,
|
||||
"type": "house",
|
||||
"label": "10, Rue Jangot, La Guillotière, Lyon 7e Arrondissement, Lyon, Métropole de Lyon, Departemental constituency of Rhône, Auvergne-Rhône-Alpes, Metropolitan France, 69007, France",
|
||||
"name": null,
|
||||
"housenumber": "10",
|
||||
"street": "Rue Jangot",
|
||||
"postcode": "69007",
|
||||
"city": "Lyon",
|
||||
"county": "Lyon",
|
||||
"state": "Auvergne-Rhône-Alpes",
|
||||
"country": "France",
|
||||
"admin": {
|
||||
"level2": "France",
|
||||
"level3": "Metropolitan France",
|
||||
"level4": "Auvergne-Rhône-Alpes",
|
||||
"level5": "Departemental constituency of Rhône",
|
||||
"level6": "Métropole de Lyon",
|
||||
"level7": "Lyon",
|
||||
"level8": "Lyon",
|
||||
"level9": "Lyon 7e Arrondissement"
|
||||
}
|
||||
}
|
||||
},
|
||||
"geometry": { "type": "Point", "coordinates": [4.8425657, 45.7517141] }
|
||||
}
|
||||
]
|
||||
}
|
||||
37
test/fixtures/geospatial/photon/search.json
vendored
Normal file
37
test/fixtures/geospatial/photon/search.json
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"features": [
|
||||
{
|
||||
"geometry": { "coordinates": [4.8425657, 45.7517141], "type": "Point" },
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"osm_id": 3078260611,
|
||||
"osm_type": "N",
|
||||
"country": "France",
|
||||
"osm_key": "place",
|
||||
"housenumber": "10",
|
||||
"city": "Lyon",
|
||||
"street": "Rue Jangot",
|
||||
"osm_value": "house",
|
||||
"postcode": "69007",
|
||||
"state": "Auvergne-Rhône-Alpes"
|
||||
}
|
||||
},
|
||||
{
|
||||
"geometry": { "coordinates": [4.8424254, 45.7517056], "type": "Point" },
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"osm_id": 3078260612,
|
||||
"osm_type": "N",
|
||||
"country": "France",
|
||||
"osm_key": "place",
|
||||
"housenumber": "10bis",
|
||||
"city": "Lyon",
|
||||
"street": "Rue Jangot",
|
||||
"osm_value": "house",
|
||||
"postcode": "69007",
|
||||
"state": "Auvergne-Rhône-Alpes"
|
||||
}
|
||||
}
|
||||
],
|
||||
"type": "FeatureCollection"
|
||||
}
|
||||
12
test/fixtures/https__info.pleroma.site_activity.json
vendored
Normal file
12
test/fixtures/https__info.pleroma.site_activity.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"actor": "http://mastodon.example.org/users/admin",
|
||||
"attachment": [],
|
||||
"attributedTo": "http://mastodon.example.org/users/admin",
|
||||
"content": "<p>this post was not actually written by Haelwenn</p>",
|
||||
"id": "https://info.pleroma.site/activity.json",
|
||||
"published": "2018-09-01T22:15:00Z",
|
||||
"tag": [],
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type": "Note"
|
||||
}
|
||||
91
test/fixtures/mastodon-actor.json
vendored
Normal file
91
test/fixtures/mastodon-actor.json
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"featured": {
|
||||
"@id": "toot:featured",
|
||||
"@type": "@id"
|
||||
},
|
||||
"alsoKnownAs": {
|
||||
"@id": "as:alsoKnownAs",
|
||||
"@type": "@id"
|
||||
},
|
||||
"movedTo": {
|
||||
"@id": "as:movedTo",
|
||||
"@type": "@id"
|
||||
},
|
||||
"schema": "http://schema.org#",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"value": "schema:value",
|
||||
"IdentityProof": "toot:IdentityProof",
|
||||
"discoverable": "toot:discoverable",
|
||||
"Device": "toot:Device",
|
||||
"Ed25519Signature": "toot:Ed25519Signature",
|
||||
"Ed25519Key": "toot:Ed25519Key",
|
||||
"Curve25519Key": "toot:Curve25519Key",
|
||||
"EncryptedMessage": "toot:EncryptedMessage",
|
||||
"publicKeyBase64": "toot:publicKeyBase64",
|
||||
"deviceId": "toot:deviceId",
|
||||
"claim": {
|
||||
"@type": "@id",
|
||||
"@id": "toot:claim"
|
||||
},
|
||||
"fingerprintKey": {
|
||||
"@type": "@id",
|
||||
"@id": "toot:fingerprintKey"
|
||||
},
|
||||
"identityKey": {
|
||||
"@type": "@id",
|
||||
"@id": "toot:identityKey"
|
||||
},
|
||||
"devices": {
|
||||
"@type": "@id",
|
||||
"@id": "toot:devices"
|
||||
},
|
||||
"messageFranking": "toot:messageFranking",
|
||||
"messageType": "toot:messageType",
|
||||
"cipherText": "toot:cipherText",
|
||||
"focalPoint": {
|
||||
"@container": "@list",
|
||||
"@id": "toot:focalPoint"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "https://framapiaf.org/users/peertube",
|
||||
"type": "Person",
|
||||
"following": "https://framapiaf.org/users/peertube/following",
|
||||
"followers": "https://framapiaf.org/users/peertube/followers",
|
||||
"inbox": "https://framapiaf.org/users/peertube/inbox",
|
||||
"outbox": "https://framapiaf.org/users/peertube/outbox",
|
||||
"featured": "https://framapiaf.org/users/peertube/collections/featured",
|
||||
"preferredUsername": "peertube",
|
||||
"name": "PeerTube",
|
||||
"summary": "<p>PeerTube Software Official Account - No support here // Compte officiel du logiciel PeerTube (animé par Framasoft). Nous ne faisons pas de support depuis ce compte. Merci de contacter l'administrateur⋅ice de l'instance concernée ou de vous rendre sur <a href=\"https://framacolibri.org/c/peertube\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"\">framacolibri.org/c/peertube</span><span class=\"invisible\"></span></a></p>",
|
||||
"url": "https://framapiaf.org/@peertube",
|
||||
"manuallyApprovesFollowers": false,
|
||||
"discoverable": false,
|
||||
"devices": "https://framapiaf.org/users/peertube/collections/devices",
|
||||
"publicKey": {
|
||||
"id": "https://framapiaf.org/users/peertube#main-key",
|
||||
"owner": "https://framapiaf.org/users/peertube",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn1y53r+ymOmDoP8iYxa1\nb1VvXkldZVpxJg1ZVeq4SijVS3oNurrQQhpTwTmCCAue2m+UvG4eEEYAYSfb5+C3\nbqH3kLlQrptkp8y/qz3d4tk/b8RConAaws7/SwksDC5rs+cYLnnXgD7rAaT1uH/B\nVTzG79YLgnasK6IxpnBth6Vru+9g2U8PzIUOfuwPV3aZeu9q2xEdC5/GnnjsfKZv\nWEzpG3HkRAlaTRDYadl9dWOPlfhy/LMkknAP02j+Qt/s7y83YqsrUyvQcfTSy3Zf\nLNNFrpU4u1ACyZXzvaoDXQH8HetKSA06xqa4pJO4xmM2PWMoBq1KX3Us4sP291w4\nEQIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||
},
|
||||
"tag": [],
|
||||
"attachment": [],
|
||||
"endpoints": {
|
||||
"sharedInbox": "https://framapiaf.org/inbox"
|
||||
},
|
||||
"icon": {
|
||||
"type": "Image",
|
||||
"mediaType": "image/png",
|
||||
"url": "https://framapiaf.s3.framasoft.org/framapiaf/accounts/avatars/000/223/824/original/03ed95406a9a3cd0.png"
|
||||
},
|
||||
"image": {
|
||||
"type": "Image",
|
||||
"mediaType": "image/png",
|
||||
"url": "https://framapiaf.s3.framasoft.org/framapiaf/accounts/headers/000/223/824/original/2fbb4d6268c2fb20.png"
|
||||
}
|
||||
}
|
||||
16
test/fixtures/mastodon-announce.json
vendored
16
test/fixtures/mastodon-announce.json
vendored
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"type": "Announce",
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"signature": {
|
||||
"type": "RsaSignature2017",
|
||||
"signatureValue": "T95DRE0eAligvMuRMkQA01lsoz2PKi4XXF+cyZ0BqbrO12p751TEWTyyRn5a+HH0e4kc77EUhQVXwMq80WAYDzHKVUTf2XBJPBa68vl0j6RXw3+HK4ef5hR4KWFNBU34yePS7S1fEmc1mTG4Yx926wtmZwDpEMTp1CXOeVEjCYzmdyHpepPPH2ZZettiacmPRSqBLPGWZoot7kH/SioIdnrMGY0I7b+rqkIdnnEcdhu9N1BKPEO9Sr+KmxgAUiidmNZlbBXX6gCxp8BiIdH4ABsIcwoDcGNkM5EmWunGW31LVjsEQXhH5c1Wly0ugYYPCg/0eHLNBOhKkY/teSM8Lg==",
|
||||
@@ -10,14 +8,14 @@
|
||||
"created": "2018-02-17T19:39:15Z"
|
||||
},
|
||||
"published": "2018-02-17T19:39:15Z",
|
||||
"object": "https://framapiaf.org/users/Framasoft/statuses/102501959686438400",
|
||||
"id": "https://framapiaf.org/users/Framasoft/statuses/102501959686438400/activity",
|
||||
"object": "https://framapiaf.org/users/peertube/statuses/104584600044284729",
|
||||
"id": "https://framapiaf.org/users/peertube/statuses/104584600044284729/activity",
|
||||
"cc": [
|
||||
"https://framapiaf.org/users/Framasoft",
|
||||
"https://framapiaf.org/users/Framasoft/followers"
|
||||
"https://framapiaf.org/users/peertube",
|
||||
"https://framapiaf.org/users/peertube/followers"
|
||||
],
|
||||
"atomUri": "https://framapiaf.org/users/Framasoft/statuses/102501959686438400/activity",
|
||||
"actor": "https://framapiaf.org/users/Framasoft",
|
||||
"atomUri": "https://framapiaf.org/users/peertube/statuses/104584600044284729/activity",
|
||||
"actor": "https://framapiaf.org/users/peertube",
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
|
||||
68
test/fixtures/mastodon-status-2.json
vendored
Normal file
68
test/fixtures/mastodon-status-2.json
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
{
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"atomUri": "ostatus:atomUri",
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"conversation": "ostatus:conversation",
|
||||
"sensitive": "as:sensitive",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"votersCount": "toot:votersCount",
|
||||
"blurhash": "toot:blurhash",
|
||||
"focalPoint": {
|
||||
"@container": "@list",
|
||||
"@id": "toot:focalPoint"
|
||||
},
|
||||
"Hashtag": "as:Hashtag"
|
||||
}
|
||||
],
|
||||
"id": "https://framapiaf.org/users/Framasoft/statuses/102093631881522097",
|
||||
"type": "Note",
|
||||
"summary": null,
|
||||
"inReplyTo": null,
|
||||
"published": "2019-05-14T09:13:13Z",
|
||||
"url": "https://framapiaf.org/@Framasoft/102093631881522097",
|
||||
"attributedTo": "https://framapiaf.org/users/Framasoft",
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc": ["https://framapiaf.org/users/Framasoft/followers"],
|
||||
"sensitive": false,
|
||||
"atomUri": "https://framapiaf.org/users/Framasoft/statuses/102093631881522097",
|
||||
"inReplyToAtomUri": null,
|
||||
"conversation": "tag:framapiaf.org,2019-05-14:objectId=16200311:objectType=Conversation",
|
||||
"content": "<p>Mobilizon : Finançons un outil pour sortir nos événements de Facebook !</p><p><a href=\"https://framablog.org/2019/05/14/mobilizon-financons-un-outil-pour-sortir-nos-evenements-de-facebook/\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">framablog.org/2019/05/14/mobil</span><span class=\"invisible\">izon-financons-un-outil-pour-sortir-nos-evenements-de-facebook/</span></a> <a href=\"https://framapiaf.org/tags/Framablog\" class=\"mention hashtag\" rel=\"tag\">#<span>Framablog</span></a> <a href=\"https://framapiaf.org/tags/TootOuRien\" class=\"mention hashtag\" rel=\"tag\">#<span>TootOuRien</span></a></p><p>Nous avons moins de 60 jours pour financer Mobilizon. Moins de 60 jours pour faire connaître notre projet d'alternative libre et fédérée aux événements Facebook ; et pour savoir à quel point nous devons nous y investir.</p><p>Changer le logiciel de celles et ceux qui changent le …</p>",
|
||||
"contentMap": {
|
||||
"fr": "<p>Mobilizon : Finançons un outil pour sortir nos événements de Facebook !</p><p><a href=\"https://framablog.org/2019/05/14/mobilizon-financons-un-outil-pour-sortir-nos-evenements-de-facebook/\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">framablog.org/2019/05/14/mobil</span><span class=\"invisible\">izon-financons-un-outil-pour-sortir-nos-evenements-de-facebook/</span></a> <a href=\"https://framapiaf.org/tags/Framablog\" class=\"mention hashtag\" rel=\"tag\">#<span>Framablog</span></a> <a href=\"https://framapiaf.org/tags/TootOuRien\" class=\"mention hashtag\" rel=\"tag\">#<span>TootOuRien</span></a></p><p>Nous avons moins de 60 jours pour financer Mobilizon. Moins de 60 jours pour faire connaître notre projet d'alternative libre et fédérée aux événements Facebook ; et pour savoir à quel point nous devons nous y investir.</p><p>Changer le logiciel de celles et ceux qui changent le …</p>"
|
||||
},
|
||||
"attachment": [
|
||||
{
|
||||
"type": "Document",
|
||||
"mediaType": "image/jpeg",
|
||||
"url": "https://framapiaf.s3.framasoft.org/framapiaf/media_attachments/files/003/337/144/original/39d457fd9e0f0171.jpg",
|
||||
"name": null,
|
||||
"blurhash": "UIF=jrpIM|~q~VT0%2t6Ne9a?G-;9ZRP%2Rk"
|
||||
}
|
||||
],
|
||||
"tag": [
|
||||
{
|
||||
"type": "Hashtag",
|
||||
"href": "https://framapiaf.org/tags/framablog",
|
||||
"name": "#framablog"
|
||||
},
|
||||
{
|
||||
"type": "Hashtag",
|
||||
"href": "https://framapiaf.org/tags/tootourien",
|
||||
"name": "#tootourien"
|
||||
}
|
||||
],
|
||||
"replies": {
|
||||
"id": "https://framapiaf.org/users/Framasoft/statuses/102093631881522097/replies",
|
||||
"type": "Collection",
|
||||
"first": {
|
||||
"type": "CollectionPage",
|
||||
"next": "https://framapiaf.org/users/Framasoft/statuses/102093631881522097/replies?only_other_accounts=true&page=true",
|
||||
"partOf": "https://framapiaf.org/users/Framasoft/statuses/102093631881522097/replies",
|
||||
"items": []
|
||||
}
|
||||
}
|
||||
}
|
||||
34
test/fixtures/mastodon-status-3.json
vendored
Normal file
34
test/fixtures/mastodon-status-3.json
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://zoltasila.pl/schemas/litepub-0.1.jsonld",
|
||||
{
|
||||
"@language": "und"
|
||||
}
|
||||
],
|
||||
"actor": "https://zoltasila.pl/users/mkljczk",
|
||||
"attachment": [],
|
||||
"attributedTo": "https://zoltasila.pl/users/mkljczk",
|
||||
"cc": ["https://zoltasila.pl/users/mkljczk/followers"],
|
||||
"content": "<p><span class=\"h-card\"><a class=\"u-url mention\" data-user=\"9xUDK5nC4I2pNtyIsq\" href=\"https://framapiaf.org/@peertube\" rel=\"ugc\">@<span>peertube</span></a></span> guess you wanted to put the <a href=\"https://joinpeertube.org/en_US/news#release-2-3-0\">en_US lang link</a></p>",
|
||||
"context": "tag:framapiaf.org,2020-07-27:objectId=39135637:objectType=Conversation",
|
||||
"conversation": "tag:framapiaf.org,2020-07-27:objectId=39135637:objectType=Conversation",
|
||||
"id": "https://zoltasila.pl/objects/1c295713-8e3c-411e-9e62-57a7b9c9e514",
|
||||
"inReplyTo": "https://framapiaf.org/users/peertube/statuses/104584600044284729",
|
||||
"published": "2020-07-27T09:37:57.202806Z",
|
||||
"sensitive": false,
|
||||
"source": "@peertube@framapiaf.org guess you wanted to put the [en_US lang link](https://joinpeertube.org/en_US/news#release-2-3-0)",
|
||||
"summary": "",
|
||||
"tag": [
|
||||
{
|
||||
"href": "https://framapiaf.org/users/peertube",
|
||||
"name": "@peertube@framapiaf.org",
|
||||
"type": "Mention"
|
||||
}
|
||||
],
|
||||
"to": [
|
||||
"https://framapiaf.org/users/peertube",
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"type": "Note"
|
||||
}
|
||||
56
test/fixtures/mastodon-status-4.json
vendored
Normal file
56
test/fixtures/mastodon-status-4.json
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
{
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"atomUri": "ostatus:atomUri",
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"conversation": "ostatus:conversation",
|
||||
"sensitive": "as:sensitive",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"votersCount": "toot:votersCount",
|
||||
"blurhash": "toot:blurhash",
|
||||
"focalPoint": {
|
||||
"@container": "@list",
|
||||
"@id": "toot:focalPoint"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "https://framapiaf.org/users/peertube/statuses/104584600044284729",
|
||||
"type": "Note",
|
||||
"summary": null,
|
||||
"inReplyTo": null,
|
||||
"published": "2020-07-27T07:19:11Z",
|
||||
"url": "https://framapiaf.org/@peertube/104584600044284729",
|
||||
"attributedTo": "https://framapiaf.org/users/peertube",
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc": ["https://framapiaf.org/users/peertube/followers"],
|
||||
"sensitive": false,
|
||||
"atomUri": "https://framapiaf.org/users/peertube/statuses/104584600044284729",
|
||||
"inReplyToAtomUri": null,
|
||||
"conversation": "tag:framapiaf.org,2020-07-27:objectId=39135637:objectType=Conversation",
|
||||
"content": "<p>PeerTube 2.3 is out! Discover on <a href=\"https://joinpeertube.org/fr_FR/news#release-2-3-0\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">joinpeertube.org/fr_FR/news#re</span><span class=\"invisible\">lease-2-3-0</span></a> the list of new features! </p><p>Have you seen the broadcast message system ? 🤩</p>",
|
||||
"contentMap": {
|
||||
"en": "<p>PeerTube 2.3 is out! Discover on <a href=\"https://joinpeertube.org/fr_FR/news#release-2-3-0\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">joinpeertube.org/fr_FR/news#re</span><span class=\"invisible\">lease-2-3-0</span></a> the list of new features! </p><p>Have you seen the broadcast message system ? 🤩</p>"
|
||||
},
|
||||
"attachment": [
|
||||
{
|
||||
"type": "Document",
|
||||
"mediaType": "image/png",
|
||||
"url": "https://framapiaf.s3.framasoft.org/framapiaf/media_attachments/files/104/584/599/807/860/387/original/88c94143f78fdfa3.png",
|
||||
"name": null,
|
||||
"blurhash": "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{"
|
||||
}
|
||||
],
|
||||
"tag": [],
|
||||
"replies": {
|
||||
"id": "https://framapiaf.org/users/peertube/statuses/104584600044284729/replies",
|
||||
"type": "Collection",
|
||||
"first": {
|
||||
"type": "CollectionPage",
|
||||
"next": "https://framapiaf.org/users/peertube/statuses/104584600044284729/replies?only_other_accounts=true&page=true",
|
||||
"partOf": "https://framapiaf.org/users/peertube/statuses/104584600044284729/replies",
|
||||
"items": []
|
||||
}
|
||||
}
|
||||
}
|
||||
58
test/fixtures/mastodon-status-5.json
vendored
Normal file
58
test/fixtures/mastodon-status-5.json
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
{
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"atomUri": "ostatus:atomUri",
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"conversation": "ostatus:conversation",
|
||||
"sensitive": "as:sensitive",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"votersCount": "toot:votersCount"
|
||||
}
|
||||
],
|
||||
"id": "https://diaspodon.fr/users/dada/statuses/100820008426311925",
|
||||
"type": "Note",
|
||||
"summary": null,
|
||||
"inReplyTo": "https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d",
|
||||
"published": "2018-10-01T10:54:01Z",
|
||||
"url": "https://diaspodon.fr/@dada/100820008426311925",
|
||||
"attributedTo": "https://diaspodon.fr/users/dada",
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc": [
|
||||
"https://diaspodon.fr/users/dada/followers",
|
||||
"https://framapiaf.org/users/Pouhiou",
|
||||
"https://framatube.org/accounts/framasoft"
|
||||
],
|
||||
"sensitive": false,
|
||||
"atomUri": "https://diaspodon.fr/users/dada/statuses/100820008426311925",
|
||||
"inReplyToAtomUri": "https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d",
|
||||
"conversation": "tag:diaspodon.fr,2018-10-01:objectId=1187066:objectType=Conversation",
|
||||
"content": "<p><span class=\"h-card\"><a href=\"https://framatube.org/accounts/framasoft\" class=\"u-url mention\">@<span>framasoft</span></a></span> Ça ne serait pas la voix de <span class=\"h-card\"><a href=\"https://framapiaf.org/@Pouhiou\" class=\"u-url mention\">@<span>Pouhiou</span></a></span> ? 🤔</p>",
|
||||
"contentMap": {
|
||||
"fr": "<p><span class=\"h-card\"><a href=\"https://framatube.org/accounts/framasoft\" class=\"u-url mention\">@<span>framasoft</span></a></span> Ça ne serait pas la voix de <span class=\"h-card\"><a href=\"https://framapiaf.org/@Pouhiou\" class=\"u-url mention\">@<span>Pouhiou</span></a></span> ? 🤔</p>"
|
||||
},
|
||||
"attachment": [],
|
||||
"tag": [
|
||||
{
|
||||
"type": "Mention",
|
||||
"href": "https://framatube.org/accounts/framasoft",
|
||||
"name": "@framasoft@framatube.org"
|
||||
},
|
||||
{
|
||||
"type": "Mention",
|
||||
"href": "https://framapiaf.org/users/Pouhiou",
|
||||
"name": "@Pouhiou@framapiaf.org"
|
||||
}
|
||||
],
|
||||
"replies": {
|
||||
"id": "https://diaspodon.fr/users/dada/statuses/100820008426311925/replies",
|
||||
"type": "Collection",
|
||||
"first": {
|
||||
"type": "CollectionPage",
|
||||
"next": "https://diaspodon.fr/users/dada/statuses/100820008426311925/replies?only_other_accounts=true&page=true",
|
||||
"partOf": "https://diaspodon.fr/users/dada/statuses/100820008426311925/replies",
|
||||
"items": []
|
||||
}
|
||||
}
|
||||
}
|
||||
56
test/fixtures/mastodon-status.json
vendored
Normal file
56
test/fixtures/mastodon-status.json
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
{
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"atomUri": "ostatus:atomUri",
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"conversation": "ostatus:conversation",
|
||||
"sensitive": "as:sensitive",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"votersCount": "toot:votersCount",
|
||||
"blurhash": "toot:blurhash",
|
||||
"focalPoint": {
|
||||
"@container": "@list",
|
||||
"@id": "toot:focalPoint"
|
||||
}
|
||||
}
|
||||
],
|
||||
"id": "https://framapiaf.org/users/peertube/statuses/104584600044284729",
|
||||
"type": "Note",
|
||||
"summary": null,
|
||||
"inReplyTo": null,
|
||||
"published": "2020-07-27T07:19:11Z",
|
||||
"url": "https://framapiaf.org/@peertube/104584600044284729",
|
||||
"attributedTo": "https://framapiaf.org/users/peertube",
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc": ["https://framapiaf.org/users/peertube/followers"],
|
||||
"sensitive": false,
|
||||
"atomUri": "https://framapiaf.org/users/peertube/statuses/104584600044284729",
|
||||
"inReplyToAtomUri": null,
|
||||
"conversation": "tag:framapiaf.org,2020-07-27:objectId=39135637:objectType=Conversation",
|
||||
"content": "<p>PeerTube 2.3 is out! Discover on <a href=\"https://joinpeertube.org/fr_FR/news#release-2-3-0\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">joinpeertube.org/fr_FR/news#re</span><span class=\"invisible\">lease-2-3-0</span></a> the list of new features! </p><p>Have you seen the broadcast message system ? 🤩</p>",
|
||||
"contentMap": {
|
||||
"en": "<p>PeerTube 2.3 is out! Discover on <a href=\"https://joinpeertube.org/fr_FR/news#release-2-3-0\" rel=\"nofollow noopener noreferrer\" target=\"_blank\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">joinpeertube.org/fr_FR/news#re</span><span class=\"invisible\">lease-2-3-0</span></a> the list of new features! </p><p>Have you seen the broadcast message system ? 🤩</p>"
|
||||
},
|
||||
"attachment": [
|
||||
{
|
||||
"type": "Document",
|
||||
"mediaType": "image/png",
|
||||
"url": "https://framapiaf.s3.framasoft.org/framapiaf/media_attachments/files/104/584/599/807/860/387/original/88c94143f78fdfa3.png",
|
||||
"name": null,
|
||||
"blurhash": "U5SY?Z00nOxu7ORP.8-pU^kVS#NGXyxbMxM{"
|
||||
}
|
||||
],
|
||||
"tag": [],
|
||||
"replies": {
|
||||
"id": "https://framapiaf.org/users/peertube/statuses/104584600044284729/replies",
|
||||
"type": "Collection",
|
||||
"first": {
|
||||
"type": "CollectionPage",
|
||||
"next": "https://framapiaf.org/users/peertube/statuses/104584600044284729/replies?only_other_accounts=true&page=true",
|
||||
"partOf": "https://framapiaf.org/users/peertube/statuses/104584600044284729/replies",
|
||||
"items": []
|
||||
}
|
||||
}
|
||||
}
|
||||
52
test/fixtures/mobilizon-post-activity-group.json
vendored
Normal file
52
test/fixtures/mobilizon-post-activity-group.json
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"@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"
|
||||
}
|
||||
],
|
||||
"actor": "http://mobilizon1.com/@user",
|
||||
"attributedTo": "http://mobilizon1.com/@group",
|
||||
"cc": [],
|
||||
"id": "http://mobilizon1.com/events/f270ae07-7991-453c-9bb7-3d2122ededae/activity",
|
||||
"object": {
|
||||
"actor": "http://mobilizon1.com/@user",
|
||||
"attributedTo": "http://mobilizon1.com/@group",
|
||||
"startTime": "2018-02-12T14:08:20Z",
|
||||
"cc": [],
|
||||
"content": "<p><span class=\"h-card\"><a href=\"https://framapiaf.org/users/tcit\" class=\"u-url mention\">@<span>tcit</span></a></span></p>",
|
||||
"id": "http://mobilizon1.com/events/f270ae07-7991-453c-9bb7-3d2122ededae",
|
||||
"name": "My first event",
|
||||
"published": "2018-02-12T14:08:20Z",
|
||||
"tag": [],
|
||||
"to": ["http://mobilizon1.com/@group"],
|
||||
"type": "Event",
|
||||
"uuid": "f270ae07-7991-453c-9bb7-3d2122ededae"
|
||||
},
|
||||
"published": "2018-02-12T14:08:20Z",
|
||||
"to": ["http://mobilizon1.com/@group"],
|
||||
"type": "Create"
|
||||
}
|
||||
393
test/fixtures/peertube-video.json
vendored
Normal file
393
test/fixtures/peertube-video.json
vendored
Normal file
@@ -0,0 +1,393 @@
|
||||
{
|
||||
"type": "Video",
|
||||
"id": "https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d",
|
||||
"name": "What is PeerTube?",
|
||||
"duration": "PT113S",
|
||||
"uuid": "9c9de5e8-0a1e-484a-b099-e80766180a6d",
|
||||
"tag": [
|
||||
{
|
||||
"type": "Hashtag",
|
||||
"name": "framasoft"
|
||||
},
|
||||
{
|
||||
"type": "Hashtag",
|
||||
"name": "peertube"
|
||||
}
|
||||
],
|
||||
"category": {
|
||||
"identifier": "15",
|
||||
"name": "Science & Technology"
|
||||
},
|
||||
"licence": {
|
||||
"identifier": "2",
|
||||
"name": "Attribution - Share Alike"
|
||||
},
|
||||
"language": {
|
||||
"identifier": "en",
|
||||
"name": "English"
|
||||
},
|
||||
"views": 53137,
|
||||
"sensitive": false,
|
||||
"waitTranscoding": true,
|
||||
"state": 1,
|
||||
"commentsEnabled": true,
|
||||
"downloadEnabled": true,
|
||||
"published": "2018-10-01T10:52:46.396Z",
|
||||
"originallyPublishedAt": null,
|
||||
"updated": "2020-07-30T08:01:00.836Z",
|
||||
"mediaType": "text/markdown",
|
||||
"content": "**[Want to help to translate this video?](https://weblate.framasoft.org/projects/what-is-peertube-video/)**\r\n\r\n**Take back the control of your videos! [#JoinPeertube](https://joinpeertube.org)**\r\n*A decentralized video hosting network, based on free/libre software!*\r\n\r\n**Animation Produced by:** [LILA](https://libreart.info) - [ZeMarmot Team](https://film.zemarmot.net)\r\n*Directed by* Aryeom\r\n*Assistant* Jehan\r\n**Licence**: [CC-By-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)\r\n\r\n**Sponsored by** [Framasoft](https://framasoft.org)\r\n\r\n**Music**: [Red Step Forward](http://play.dogmazic.net/song.php?song_id=52491) - CC-By Ken Bushima\r\n\r\n**Movie Clip**: [Caminades 3: Llamigos](http://www.caminandes.com/) CC-By Blender Institute\r\n\r\n**Video sources**: https://gitlab.gnome.org/Jehan/what-is-peertube/",
|
||||
"support": null,
|
||||
"subtitleLanguage": [
|
||||
{
|
||||
"identifier": "ca",
|
||||
"name": "Catalan",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-ca.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "cs",
|
||||
"name": "Czech",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-cs.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "de",
|
||||
"name": "German",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-de.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "en",
|
||||
"name": "English",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-en.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "es",
|
||||
"name": "Spanish",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-es.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "eu",
|
||||
"name": "Basque",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-eu.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "fr",
|
||||
"name": "French",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-fr.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "gl",
|
||||
"name": "Galician",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-gl.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "hu",
|
||||
"name": "Hungarian",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-hu.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "it",
|
||||
"name": "Italian",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-it.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "lt",
|
||||
"name": "Lithuanian",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-lt.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "nl",
|
||||
"name": "Dutch",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-nl.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "pl",
|
||||
"name": "Polish",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-pl.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "pt",
|
||||
"name": "Portuguese",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-pt.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "ru",
|
||||
"name": "Russian",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-ru.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "sv",
|
||||
"name": "Swedish",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-sv.vtt"
|
||||
},
|
||||
{
|
||||
"identifier": "zh",
|
||||
"name": "Chinese",
|
||||
"url": "https://framatube.org/static/video-captions/9c9de5e8-0a1e-484a-b099-e80766180a6d-zh.vtt"
|
||||
}
|
||||
],
|
||||
"icon": [
|
||||
{
|
||||
"type": "Image",
|
||||
"url": "https://framatube.org/static/thumbnails/9c9de5e8-0a1e-484a-b099-e80766180a6d.jpg",
|
||||
"mediaType": "image/jpeg",
|
||||
"width": 223,
|
||||
"height": 122
|
||||
},
|
||||
{
|
||||
"type": "Image",
|
||||
"url": "https://framatube.org/static/previews/9c9de5e8-0a1e-484a-b099-e80766180a6d.jpg",
|
||||
"mediaType": "image/jpeg",
|
||||
"width": 850,
|
||||
"height": 480
|
||||
}
|
||||
],
|
||||
"url": [
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "text/html",
|
||||
"href": "https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d"
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "video/mp4",
|
||||
"href": "https://framatube.org/static/webseed/9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4",
|
||||
"height": 1080,
|
||||
"size": 14689568,
|
||||
"fps": 24
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"rel": ["metadata", "video/mp4"],
|
||||
"mediaType": "application/json",
|
||||
"href": "https://framatube.org/api/v1/videos/9c9de5e8-0a1e-484a-b099-e80766180a6d/metadata/10124",
|
||||
"height": 1080,
|
||||
"fps": 24
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "application/x-bittorrent",
|
||||
"href": "https://framatube.org/static/torrents/9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.torrent",
|
||||
"height": 1080
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
|
||||
"href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.torrent&xt=urn:btih:dc84b692c4002fec0cae873df0dc7f5d67fc09db&dn=What+is+PeerTube%3F&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fvideo.antopie.org%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fpeertube.foxfam.club%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fpeertube.freeforge.eu%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fpeertube.krapace.fr%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fvideo.blueline.mg%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fpeertube.video%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Ftube.crapaud-fou.org%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fflim.ml%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4&ws=https%3A%2F%2Fpeertube.nomagic.uk%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-1080.mp4",
|
||||
"height": 1080
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "video/mp4",
|
||||
"href": "https://framatube.org/static/webseed/9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4",
|
||||
"height": 720,
|
||||
"size": 8365049,
|
||||
"fps": 24
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"rel": ["metadata", "video/mp4"],
|
||||
"mediaType": "application/json",
|
||||
"href": "https://framatube.org/api/v1/videos/9c9de5e8-0a1e-484a-b099-e80766180a6d/metadata/10127",
|
||||
"height": 720,
|
||||
"fps": 24
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "application/x-bittorrent",
|
||||
"href": "https://framatube.org/static/torrents/9c9de5e8-0a1e-484a-b099-e80766180a6d-720.torrent",
|
||||
"height": 720
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
|
||||
"href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.torrent&xt=urn:btih:9fb0e35b4945565fa842b2bb0fe8b03edf223b15&dn=What+is+PeerTube%3F&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fvideo.antopie.org%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fpeertube.freeforge.eu%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fpeertube.krapace.fr%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fvideo.blueline.mg%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fpeertube.video%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Ftube.crapaud-fou.org%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fflim.ml%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fpeertube.foxfam.club%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4&ws=https%3A%2F%2Fpeertube.nomagic.uk%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-720.mp4",
|
||||
"height": 720
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "video/mp4",
|
||||
"href": "https://framatube.org/static/webseed/9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4",
|
||||
"height": 480,
|
||||
"size": 5650553,
|
||||
"fps": 24
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"rel": ["metadata", "video/mp4"],
|
||||
"mediaType": "application/json",
|
||||
"href": "https://framatube.org/api/v1/videos/9c9de5e8-0a1e-484a-b099-e80766180a6d/metadata/10125",
|
||||
"height": 480,
|
||||
"fps": 24
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "application/x-bittorrent",
|
||||
"href": "https://framatube.org/static/torrents/9c9de5e8-0a1e-484a-b099-e80766180a6d-480.torrent",
|
||||
"height": 480
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
|
||||
"href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.torrent&xt=urn:btih:bf02027a9aad4275d8baa25afae230b85187bcf7&dn=What+is+PeerTube%3F&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fvideo.antopie.org%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fpeertube.freeforge.eu%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fpeertube.krapace.fr%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fvideo.blueline.mg%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fpeertube.video%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Ftube.crapaud-fou.org%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fflim.ml%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fpeertube.foxfam.club%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4&ws=https%3A%2F%2Fpeertube.nomagic.uk%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-480.mp4",
|
||||
"height": 480
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "video/mp4",
|
||||
"href": "https://framatube.org/static/webseed/9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4",
|
||||
"height": 360,
|
||||
"size": 4524751,
|
||||
"fps": 24
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"rel": ["metadata", "video/mp4"],
|
||||
"mediaType": "application/json",
|
||||
"href": "https://framatube.org/api/v1/videos/9c9de5e8-0a1e-484a-b099-e80766180a6d/metadata/10126",
|
||||
"height": 360,
|
||||
"fps": 24
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "application/x-bittorrent",
|
||||
"href": "https://framatube.org/static/torrents/9c9de5e8-0a1e-484a-b099-e80766180a6d-360.torrent",
|
||||
"height": 360
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
|
||||
"href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.torrent&xt=urn:btih:16b3720b18752523e2848341d3207120f2de26f8&dn=What+is+PeerTube%3F&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fvideo.antopie.org%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fpeertube.freeforge.eu%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fpeertube.krapace.fr%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fvideo.blueline.mg%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fpeertube.video%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Ftube.crapaud-fou.org%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fflim.ml%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fpeertube.foxfam.club%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4&ws=https%3A%2F%2Fpeertube.nomagic.uk%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-360.mp4",
|
||||
"height": 360
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "video/mp4",
|
||||
"href": "https://framatube.org/static/webseed/9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4",
|
||||
"height": 240,
|
||||
"size": 3452697,
|
||||
"fps": 24
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"rel": ["metadata", "video/mp4"],
|
||||
"mediaType": "application/json",
|
||||
"href": "https://framatube.org/api/v1/videos/9c9de5e8-0a1e-484a-b099-e80766180a6d/metadata/10128",
|
||||
"height": 240,
|
||||
"fps": 24
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "application/x-bittorrent",
|
||||
"href": "https://framatube.org/static/torrents/9c9de5e8-0a1e-484a-b099-e80766180a6d-240.torrent",
|
||||
"height": 240
|
||||
},
|
||||
{
|
||||
"type": "Link",
|
||||
"mediaType": "application/x-bittorrent;x-scheme-handler/magnet",
|
||||
"href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Fstatic%2Ftorrents%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.torrent&xt=urn:btih:38b4747ff788b30bf61f59d1965cd38f9e48e01f&dn=What+is+PeerTube%3F&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fwebseed%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fvideo.antopie.org%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fpeertube.live%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Ftube.privacytools.io%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fpeertube.social%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fpeertube.foxfam.club%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fpeertube.iselfhost.com%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fpeertube.freeforge.eu%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fpeertube.krapace.fr%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fvideo.blueline.mg%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fpeertube.video%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Ftube.crapaud-fou.org%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fflim.ml%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4&ws=https%3A%2F%2Fpeertube.nomagic.uk%2Fstatic%2Fredundancy%2F9c9de5e8-0a1e-484a-b099-e80766180a6d-240.mp4",
|
||||
"height": 240
|
||||
}
|
||||
],
|
||||
"likes": "https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d/likes",
|
||||
"dislikes": "https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d/dislikes",
|
||||
"shares": "https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d/announces",
|
||||
"comments": "https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d/comments",
|
||||
"attributedTo": [
|
||||
{
|
||||
"type": "Person",
|
||||
"id": "https://framatube.org/accounts/framasoft"
|
||||
},
|
||||
{
|
||||
"type": "Group",
|
||||
"id": "https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8"
|
||||
}
|
||||
],
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc": ["https://framatube.org/accounts/framasoft/followers"],
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"RsaSignature2017": "https://w3id.org/security#RsaSignature2017"
|
||||
},
|
||||
{
|
||||
"pt": "https://joinpeertube.org/ns#",
|
||||
"sc": "http://schema.org#",
|
||||
"Hashtag": "as:Hashtag",
|
||||
"uuid": "sc:identifier",
|
||||
"category": "sc:category",
|
||||
"licence": "sc:license",
|
||||
"subtitleLanguage": "sc:subtitleLanguage",
|
||||
"sensitive": "as:sensitive",
|
||||
"language": "sc:inLanguage",
|
||||
"Infohash": "pt:Infohash",
|
||||
"Playlist": "pt:Playlist",
|
||||
"PlaylistElement": "pt:PlaylistElement",
|
||||
"originallyPublishedAt": "sc:datePublished",
|
||||
"views": {
|
||||
"@type": "sc:Number",
|
||||
"@id": "pt:views"
|
||||
},
|
||||
"state": {
|
||||
"@type": "sc:Number",
|
||||
"@id": "pt:state"
|
||||
},
|
||||
"size": {
|
||||
"@type": "sc:Number",
|
||||
"@id": "pt:size"
|
||||
},
|
||||
"fps": {
|
||||
"@type": "sc:Number",
|
||||
"@id": "pt:fps"
|
||||
},
|
||||
"startTimestamp": {
|
||||
"@type": "sc:Number",
|
||||
"@id": "pt:startTimestamp"
|
||||
},
|
||||
"stopTimestamp": {
|
||||
"@type": "sc:Number",
|
||||
"@id": "pt:stopTimestamp"
|
||||
},
|
||||
"position": {
|
||||
"@type": "sc:Number",
|
||||
"@id": "pt:position"
|
||||
},
|
||||
"commentsEnabled": {
|
||||
"@type": "sc:Boolean",
|
||||
"@id": "pt:commentsEnabled"
|
||||
},
|
||||
"downloadEnabled": {
|
||||
"@type": "sc:Boolean",
|
||||
"@id": "pt:downloadEnabled"
|
||||
},
|
||||
"waitTranscoding": {
|
||||
"@type": "sc:Boolean",
|
||||
"@id": "pt:waitTranscoding"
|
||||
},
|
||||
"support": {
|
||||
"@type": "sc:Text",
|
||||
"@id": "pt:support"
|
||||
},
|
||||
"likes": {
|
||||
"@id": "as:likes",
|
||||
"@type": "@id"
|
||||
},
|
||||
"dislikes": {
|
||||
"@id": "as:dislikes",
|
||||
"@type": "@id"
|
||||
},
|
||||
"playlists": {
|
||||
"@id": "pt:playlists",
|
||||
"@type": "@id"
|
||||
},
|
||||
"shares": {
|
||||
"@id": "as:shares",
|
||||
"@type": "@id"
|
||||
},
|
||||
"comments": {
|
||||
"@id": "as:comments",
|
||||
"@type": "@id"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
30
test/fixtures/pleroma-comment-object.json
vendored
Normal file
30
test/fixtures/pleroma-comment-object.json
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://blob.cat/schemas/litepub-0.1.jsonld",
|
||||
{
|
||||
"@language": "und"
|
||||
}
|
||||
],
|
||||
"actor": "https://blob.cat/users/comicbot",
|
||||
"attachment": [
|
||||
{
|
||||
"mediaType": "image/gif",
|
||||
"name": "1574936800141.gif",
|
||||
"type": "Document",
|
||||
"url": "https://blob.cat/media/143ba9b1ed15e67d7401906f7b71a459b90680af7075af5b8ac9cb8e3b86868a.gif"
|
||||
}
|
||||
],
|
||||
"attributedTo": "https://blob.cat/users/comicbot",
|
||||
"cc": ["https://blob.cat/users/comicbot/followers"],
|
||||
"content": "Super Mega Comics <br> <a href=\"http://supermegacomics.com/\" rel=\"ugc\">http://supermegacomics.com/</a>",
|
||||
"context": "https://blob.cat/contexts/26f3271a-3eb8-4f3f-8fb1-8ff96e2c4a47",
|
||||
"conversation": "https://blob.cat/contexts/26f3271a-3eb8-4f3f-8fb1-8ff96e2c4a47",
|
||||
"id": "https://blob.cat/objects/02fdea3d-932c-4348-9ecb-3f9eb3fbdd94",
|
||||
"published": "2019-11-28T10:26:42.503473Z",
|
||||
"sensitive": false,
|
||||
"summary": "",
|
||||
"tag": [],
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type": "Note"
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
[
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": {
|
||||
"Accept": "*/*",
|
||||
"Accept-Encoding":"deflate, gzip"
|
||||
},
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://api-adresse.data.gouv.fr/reverse/?lon=4.842569&lat=45.751718"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\"type\": \"FeatureCollection\", \"version\": \"draft\", \"features\": [{\"type\": \"Feature\", \"geometry\": {\"type\": \"Point\", \"coordinates\": [4.842569, 45.751718]}, \"properties\": {\"label\": \"10 Rue Jangot 69007 Lyon\", \"score\": 0.9999999999926557, \"housenumber\": \"10\", \"id\": \"69387_3650_00010\", \"type\": \"housenumber\", \"x\": 843232.29, \"y\": 6518573.31, \"importance\": 0.5454797306366062, \"name\": \"10 Rue Jangot\", \"postcode\": \"69007\", \"citycode\": \"69387\", \"city\": \"Lyon\", \"district\": \"Lyon 7e Arrondissement\", \"context\": \"69, Rh\u00f4ne, Auvergne-Rh\u00f4ne-Alpes\", \"street\": \"Rue Jangot\", \"distance\": 0}}], \"attribution\": \"BAN\", \"licence\": \"ETALAB-2.0\", \"limit\": 1}",
|
||||
"headers": {
|
||||
"Server": "nginx/1.9.3",
|
||||
"Date": "Thu, 14 Mar 2019 10:46:45 GMT",
|
||||
"Content-type":"application/json; charset=utf-8",
|
||||
"Vary":"Accept-Encoding",
|
||||
"X-cache-status":"MISS",
|
||||
"Access-control-allow-origin":"*",
|
||||
"Access-control-allow-headers":"X-Requested-With,Content-Type",
|
||||
"Content-encoding":"gzip"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,31 +0,0 @@
|
||||
[
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": {
|
||||
"Accept": "*/*",
|
||||
"Accept-Encoding":"deflate, gzip"
|
||||
},
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://api-adresse.data.gouv.fr/search/?q=10%20Rue%20Jangot"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\"type\": \"FeatureCollection\", \"version\": \"draft\", \"features\": [{\"type\": \"Feature\", \"geometry\": {\"type\": \"Point\", \"coordinates\": [4.842569, 45.751718]}, \"properties\": {\"label\": \"10 Rue Jangot 69007 Lyon\", \"score\": 0.8677708846033279, \"housenumber\": \"10\", \"id\": \"69387_3650_00010\", \"type\": \"housenumber\", \"x\": 843232.29, \"y\": 6518573.31, \"importance\": 0.5454797306366062, \"name\": \"10 Rue Jangot\", \"postcode\": \"69007\", \"citycode\": \"69387\", \"city\": \"Lyon\", \"district\": \"Lyon 7e Arrondissement\", \"context\": \"69, Rh\u00f4ne, Auvergne-Rh\u00f4ne-Alpes\", \"street\": \"Rue Jangot\"}}, {\"type\": \"Feature\", \"geometry\": {\"type\": \"Point\", \"coordinates\": [2.440319, 50.371266]}, \"properties\": {\"label\": \"Rue Jangon 62127 Bailleul-aux-Cornailles\", \"score\": 0.5269641371131077, \"id\": \"62070_0100\", \"type\": \"street\", \"x\": 660129.18, \"y\": 7030540.46, \"importance\": 0.25814396978264664, \"name\": \"Rue Jangon\", \"postcode\": \"62127\", \"citycode\": \"62070\", \"city\": \"Bailleul-aux-Cornailles\", \"context\": \"62, Pas-de-Calais, Hauts-de-France\"}}], \"attribution\": \"BAN\", \"licence\": \"ETALAB-2.0\", \"query\": \"10 Rue Jangot\", \"limit\": 5}",
|
||||
"headers": {
|
||||
"Server":"nginx/1.10.3",
|
||||
"Date":"Thu, 25 Jun 2020 11:23:54 GMT",
|
||||
"Content-type":"application/json; charset=utf-8",
|
||||
"Vary":"Accept-Encoding",
|
||||
"X-cache-status":"MISS",
|
||||
"Access-control-allow-origin":"*",
|
||||
"Access-control-allow-headers":"X-Requested-With,Content-Type",
|
||||
"Content-encoding":"gzip"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,63 +0,0 @@
|
||||
[
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": [],
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://maps.googleapis.com/maps/api/place/details/json?key=toto&placeid=ChIJrW0QikTq9EcR96jk2OnO75w"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\n \"html_attributions\" : [],\n \"result\" : {\n \"address_components\" : [\n {\n \"long_name\" : \"10bis\",\n \"short_name\" : \"10bis\",\n \"types\" : [ \"street_number\" ]\n },\n {\n \"long_name\" : \"Rue Jangot\",\n \"short_name\" : \"Rue Jangot\",\n \"types\" : [ \"route\" ]\n },\n {\n \"long_name\" : \"Lyon\",\n \"short_name\" : \"Lyon\",\n \"types\" : [ \"locality\", \"political\" ]\n },\n {\n \"long_name\" : \"Rhône\",\n \"short_name\" : \"Rhône\",\n \"types\" : [ \"administrative_area_level_2\", \"political\" ]\n },\n {\n \"long_name\" : \"Auvergne-Rhône-Alpes\",\n \"short_name\" : \"Auvergne-Rhône-Alpes\",\n \"types\" : [ \"administrative_area_level_1\", \"political\" ]\n },\n {\n \"long_name\" : \"France\",\n \"short_name\" : \"FR\",\n \"types\" : [ \"country\", \"political\" ]\n },\n {\n \"long_name\" : \"69007\",\n \"short_name\" : \"69007\",\n \"types\" : [ \"postal_code\" ]\n }\n ],\n \"adr_address\" : \"\\u003cspan class=\\\"street-address\\\"\\u003e10bis Rue Jangot\\u003c/span\\u003e, \\u003cspan class=\\\"postal-code\\\"\\u003e69007\\u003c/span\\u003e \\u003cspan class=\\\"locality\\\"\\u003eLyon\\u003c/span\\u003e, \\u003cspan class=\\\"country-name\\\"\\u003eFrance\\u003c/span\\u003e\",\n \"formatted_address\" : \"10bis Rue Jangot, 69007 Lyon, France\",\n \"geometry\" : {\n \"location\" : {\n \"lat\" : 45.751725,\n \"lng\" : 4.8424966\n },\n \"viewport\" : {\n \"northeast\" : {\n \"lat\" : 45.7531097802915,\n \"lng\" : 4.843951380291502\n },\n \"southwest\" : {\n \"lat\" : 45.7504118197085,\n \"lng\" : 4.841253419708497\n }\n }\n },\n \"icon\" : \"https://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png\",\n \"id\" : \"4a3482a7a74c6203048adf713b736186c4ace7cd\",\n \"name\" : \"10bis Rue Jangot\",\n \"place_id\" : \"ChIJrW0QikTq9EcR96jk2OnO75w\",\n \"plus_code\" : {\n \"compound_code\" : \"QR2R+MX Lyon, France\",\n \"global_code\" : \"8FQ6QR2R+MX\"\n },\n \"reference\" : \"ChIJrW0QikTq9EcR96jk2OnO75w\",\n \"scope\" : \"GOOGLE\",\n \"types\" : [ \"street_address\" ],\n \"url\" : \"https://maps.google.com/?q=10bis+Rue+Jangot,+69007+Lyon,+France&ftid=0x47f4ea448a106dad:0x9cefcee9d8e4a8f7\",\n \"utc_offset\" : 120,\n \"vicinity\" : \"Lyon\"\n },\n \"status\" : \"OK\"\n}\n",
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Date": "Thu, 22 Aug 2019 13:18:50 GMT",
|
||||
"Expires": "Thu, 22 Aug 2019 13:23:50 GMT",
|
||||
"Cache-Control": "public, max-age=300",
|
||||
"Server": "scaffolding on HTTPServer2",
|
||||
"X-XSS-Protection": "0",
|
||||
"X-Frame-Options": "SAMEORIGIN",
|
||||
"Server-Timing": "gfet4t7; dur=87",
|
||||
"Alt-Svc": "quic=\":443\"; ma=2592000; v=\"46,43,39\"",
|
||||
"Accept-Ranges": "none",
|
||||
"Vary": "Accept-Language,Accept-Encoding",
|
||||
"Transfer-Encoding": "chunked"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
},
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": [],
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://maps.googleapis.com/maps/api/geocode/json?limit=10&key=toto&language=en&latlng=45.751718,4.842569&result_type=street_address"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\n \"plus_code\" : {\n \"compound_code\" : \"QR2V+M2 Lyon, France\",\n \"global_code\" : \"8FQ6QR2V+M2\"\n },\n \"results\" : [\n {\n \"address_components\" : [\n {\n \"long_name\" : \"10bis\",\n \"short_name\" : \"10bis\",\n \"types\" : [ \"street_number\" ]\n },\n {\n \"long_name\" : \"Rue Jangot\",\n \"short_name\" : \"Rue Jangot\",\n \"types\" : [ \"route\" ]\n },\n {\n \"long_name\" : \"Lyon\",\n \"short_name\" : \"Lyon\",\n \"types\" : [ \"locality\", \"political\" ]\n },\n {\n \"long_name\" : \"Rhône\",\n \"short_name\" : \"Rhône\",\n \"types\" : [ \"administrative_area_level_2\", \"political\" ]\n },\n {\n \"long_name\" : \"Auvergne-Rhône-Alpes\",\n \"short_name\" : \"Auvergne-Rhône-Alpes\",\n \"types\" : [ \"administrative_area_level_1\", \"political\" ]\n },\n {\n \"long_name\" : \"France\",\n \"short_name\" : \"FR\",\n \"types\" : [ \"country\", \"political\" ]\n },\n {\n \"long_name\" : \"69007\",\n \"short_name\" : \"69007\",\n \"types\" : [ \"postal_code\" ]\n }\n ],\n \"formatted_address\" : \"10bis Rue Jangot, 69007 Lyon, France\",\n \"geometry\" : {\n \"location\" : {\n \"lat\" : 45.751725,\n \"lng\" : 4.8424966\n },\n \"location_type\" : \"ROOFTOP\",\n \"viewport\" : {\n \"northeast\" : {\n \"lat\" : 45.7530739802915,\n \"lng\" : 4.843845580291503\n },\n \"southwest\" : {\n \"lat\" : 45.7503760197085,\n \"lng\" : 4.841147619708499\n }\n }\n },\n \"place_id\" : \"ChIJrW0QikTq9EcR96jk2OnO75w\",\n \"plus_code\" : {\n \"compound_code\" : \"QR2R+MX Lyon, France\",\n \"global_code\" : \"8FQ6QR2R+MX\"\n },\n \"types\" : [ \"street_address\" ]\n },\n {\n \"address_components\" : [\n {\n \"long_name\" : \"9\",\n \"short_name\" : \"9\",\n \"types\" : [ \"street_number\" ]\n },\n {\n \"long_name\" : \"Rue Jangot\",\n \"short_name\" : \"Rue Jangot\",\n \"types\" : [ \"route\" ]\n },\n {\n \"long_name\" : \"Lyon\",\n \"short_name\" : \"Lyon\",\n \"types\" : [ \"locality\", \"political\" ]\n },\n {\n \"long_name\" : \"Rhône\",\n \"short_name\" : \"Rhône\",\n \"types\" : [ \"administrative_area_level_2\", \"political\" ]\n },\n {\n \"long_name\" : \"Auvergne-Rhône-Alpes\",\n \"short_name\" : \"Auvergne-Rhône-Alpes\",\n \"types\" : [ \"administrative_area_level_1\", \"political\" ]\n },\n {\n \"long_name\" : \"France\",\n \"short_name\" : \"FR\",\n \"types\" : [ \"country\", \"political\" ]\n },\n {\n \"long_name\" : \"69007\",\n \"short_name\" : \"69007\",\n \"types\" : [ \"postal_code\" ]\n }\n ],\n \"formatted_address\" : \"9 Rue Jangot, 69007 Lyon, France\",\n \"geometry\" : {\n \"location\" : {\n \"lat\" : 45.7518165,\n \"lng\" : 4.8427168\n },\n \"location_type\" : \"RANGE_INTERPOLATED\",\n \"viewport\" : {\n \"northeast\" : {\n \"lat\" : 45.7531654802915,\n \"lng\" : 4.844065780291502\n },\n \"southwest\" : {\n \"lat\" : 45.7504675197085,\n \"lng\" : 4.841367819708497\n }\n }\n },\n \"place_id\" : \"EiA5IFJ1ZSBKYW5nb3QsIDY5MDA3IEx5b24sIEZyYW5jZSIaEhgKFAoSCR8N2ItE6vRHEW9tyPnhQsUIEAk\",\n \"types\" : [ \"street_address\" ]\n }\n ],\n \"status\" : \"OK\"\n}\n",
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Date": "Thu, 22 Aug 2019 13:18:50 GMT",
|
||||
"Expires": "Thu, 22 Aug 2019 13:19:20 GMT",
|
||||
"Cache-Control": "public, max-age=30",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Server": "mafe",
|
||||
"X-XSS-Protection": "0",
|
||||
"X-Frame-Options": "SAMEORIGIN",
|
||||
"Server-Timing": "gfet4t7; dur=30",
|
||||
"Alt-Svc": "quic=\":443\"; ma=2592000; v=\"46,43,39\"",
|
||||
"Accept-Ranges": "none",
|
||||
"Vary": "Accept-Encoding",
|
||||
"Transfer-Encoding": "chunked"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,63 +0,0 @@
|
||||
[
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": [],
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://maps.googleapis.com/maps/api/geocode/json?limit=10&key=toto&language=en&address=10%20rue%20Jangot"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\n \"results\" : [\n {\n \"address_components\" : [\n {\n \"long_name\" : \"10\",\n \"short_name\" : \"10\",\n \"types\" : [ \"street_number\" ]\n },\n {\n \"long_name\" : \"Rue Jangot\",\n \"short_name\" : \"Rue Jangot\",\n \"types\" : [ \"route\" ]\n },\n {\n \"long_name\" : \"Lyon\",\n \"short_name\" : \"Lyon\",\n \"types\" : [ \"locality\", \"political\" ]\n },\n {\n \"long_name\" : \"Rhône\",\n \"short_name\" : \"Rhône\",\n \"types\" : [ \"administrative_area_level_2\", \"political\" ]\n },\n {\n \"long_name\" : \"Auvergne-Rhône-Alpes\",\n \"short_name\" : \"Auvergne-Rhône-Alpes\",\n \"types\" : [ \"administrative_area_level_1\", \"political\" ]\n },\n {\n \"long_name\" : \"France\",\n \"short_name\" : \"FR\",\n \"types\" : [ \"country\", \"political\" ]\n },\n {\n \"long_name\" : \"69007\",\n \"short_name\" : \"69007\",\n \"types\" : [ \"postal_code\" ]\n }\n ],\n \"formatted_address\" : \"10 Rue Jangot, 69007 Lyon, France\",\n \"geometry\" : {\n \"location\" : {\n \"lat\" : 45.75164940000001,\n \"lng\" : 4.8424032\n },\n \"location_type\" : \"ROOFTOP\",\n \"viewport\" : {\n \"northeast\" : {\n \"lat\" : 45.75299838029151,\n \"lng\" : 4.843752180291502\n },\n \"southwest\" : {\n \"lat\" : 45.75030041970851,\n \"lng\" : 4.841054219708497\n }\n }\n },\n \"place_id\" : \"ChIJtW0QikTq9EcRLI4Vy6bRx0U\",\n \"plus_code\" : {\n \"compound_code\" : \"QR2R+MX Lyon, France\",\n \"global_code\" : \"8FQ6QR2R+MX\"\n },\n \"types\" : [ \"street_address\" ]\n }\n ],\n \"status\" : \"OK\"\n}\n",
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Date": "Thu, 22 Aug 2019 13:05:39 GMT",
|
||||
"Expires": "Thu, 22 Aug 2019 13:06:09 GMT",
|
||||
"Cache-Control": "public, max-age=30",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Server": "mafe",
|
||||
"X-XSS-Protection": "0",
|
||||
"X-Frame-Options": "SAMEORIGIN",
|
||||
"Server-Timing": "gfet4t7; dur=44",
|
||||
"Alt-Svc": "quic=\":443\"; ma=2592000; v=\"46,43,39\"",
|
||||
"Accept-Ranges": "none",
|
||||
"Vary": "Accept-Encoding",
|
||||
"Transfer-Encoding": "chunked"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
},
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": [],
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://maps.googleapis.com/maps/api/place/details/json?key=toto&placeid=ChIJtW0QikTq9EcRLI4Vy6bRx0U"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\n \"html_attributions\" : [],\n \"result\" : {\n \"address_components\" : [\n {\n \"long_name\" : \"10\",\n \"short_name\" : \"10\",\n \"types\" : [ \"street_number\" ]\n },\n {\n \"long_name\" : \"Rue Jangot\",\n \"short_name\" : \"Rue Jangot\",\n \"types\" : [ \"route\" ]\n },\n {\n \"long_name\" : \"Lyon\",\n \"short_name\" : \"Lyon\",\n \"types\" : [ \"locality\", \"political\" ]\n },\n {\n \"long_name\" : \"Rhône\",\n \"short_name\" : \"Rhône\",\n \"types\" : [ \"administrative_area_level_2\", \"political\" ]\n },\n {\n \"long_name\" : \"Auvergne-Rhône-Alpes\",\n \"short_name\" : \"Auvergne-Rhône-Alpes\",\n \"types\" : [ \"administrative_area_level_1\", \"political\" ]\n },\n {\n \"long_name\" : \"France\",\n \"short_name\" : \"FR\",\n \"types\" : [ \"country\", \"political\" ]\n },\n {\n \"long_name\" : \"69007\",\n \"short_name\" : \"69007\",\n \"types\" : [ \"postal_code\" ]\n }\n ],\n \"adr_address\" : \"\\u003cspan class=\\\"street-address\\\"\\u003e10 Rue Jangot\\u003c/span\\u003e, \\u003cspan class=\\\"postal-code\\\"\\u003e69007\\u003c/span\\u003e \\u003cspan class=\\\"locality\\\"\\u003eLyon\\u003c/span\\u003e, \\u003cspan class=\\\"country-name\\\"\\u003eFrance\\u003c/span\\u003e\",\n \"formatted_address\" : \"10 Rue Jangot, 69007 Lyon, France\",\n \"geometry\" : {\n \"location\" : {\n \"lat\" : 45.75164940000001,\n \"lng\" : 4.842403200000001\n },\n \"viewport\" : {\n \"northeast\" : {\n \"lat\" : 45.7530412802915,\n \"lng\" : 4.843668630291503\n },\n \"southwest\" : {\n \"lat\" : 45.75034331970851,\n \"lng\" : 4.840970669708498\n }\n }\n },\n \"icon\" : \"https://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png\",\n \"id\" : \"61b9418d092d2ed05ddd65a55dddefda5b9628cc\",\n \"name\" : \"10 Rue Jangot\",\n \"place_id\" : \"ChIJtW0QikTq9EcRLI4Vy6bRx0U\",\n \"plus_code\" : {\n \"compound_code\" : \"QR2R+MX Lyon, France\",\n \"global_code\" : \"8FQ6QR2R+MX\"\n },\n \"reference\" : \"ChIJtW0QikTq9EcRLI4Vy6bRx0U\",\n \"scope\" : \"GOOGLE\",\n \"types\" : [ \"street_address\" ],\n \"url\" : \"https://maps.google.com/?q=10+Rue+Jangot,+69007+Lyon,+France&ftid=0x47f4ea448a106db5:0x45c7d1a6cb158e2c\",\n \"utc_offset\" : 120,\n \"vicinity\" : \"Lyon\"\n },\n \"status\" : \"OK\"\n}\n",
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"Date": "Thu, 22 Aug 2019 13:05:39 GMT",
|
||||
"Expires": "Thu, 22 Aug 2019 13:10:39 GMT",
|
||||
"Cache-Control": "public, max-age=300",
|
||||
"Server": "scaffolding on HTTPServer2",
|
||||
"X-XSS-Protection": "0",
|
||||
"X-Frame-Options": "SAMEORIGIN",
|
||||
"Server-Timing": "gfet4t7; dur=86",
|
||||
"Alt-Svc": "quic=\":443\"; ma=2592000; v=\"46,43,39\"",
|
||||
"Accept-Ranges": "none",
|
||||
"Vary": "Accept-Language,Accept-Encoding",
|
||||
"Transfer-Encoding": "chunked"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,36 +0,0 @@
|
||||
[
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": [],
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://open.mapquestapi.com/geocoding/v1/reverse?key=secret_key&location=45.751718,4.842569&maxResults=10"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\"info\":{\"statuscode\":0,\"copyright\":{\"text\":\"\\u00A9 2019 MapQuest, Inc.\",\"imageUrl\":\"http://api.mqcdn.com/res/mqlogo.gif\",\"imageAltText\":\"\\u00A9 2019 MapQuest, Inc.\"},\"messages\":[]},\"options\":{\"maxResults\":1,\"thumbMaps\":true,\"ignoreLatLngInput\":false},\"results\":[{\"providedLocation\":{\"latLng\":{\"lat\":45.751718,\"lng\":4.842569}},\"locations\":[{\"street\":\"10 Rue Jangot\",\"adminArea6\":\"\",\"adminArea6Type\":\"Neighborhood\",\"adminArea5\":\"Lyon\",\"adminArea5Type\":\"City\",\"adminArea4\":\"\",\"adminArea4Type\":\"County\",\"adminArea3\":\"Auvergne-Rh\\u00F4ne-Alpes\",\"adminArea3Type\":\"State\",\"adminArea1\":\"FR\",\"adminArea1Type\":\"Country\",\"postalCode\":\"69007\",\"geocodeQualityCode\":\"P1AAA\",\"geocodeQuality\":\"POINT\",\"dragPoint\":false,\"sideOfStreet\":\"N\",\"linkId\":\"0\",\"unknownInput\":\"\",\"type\":\"s\",\"latLng\":{\"lat\":45.751714,\"lng\":4.842566},\"displayLatLng\":{\"lat\":45.751714,\"lng\":4.842566},\"mapUrl\":\"http://open.mapquestapi.com/staticmap/v5/map?key=secret_key&type=map&size=225,160&locations=45.7517141,4.8425657|marker-sm-50318A-1&scalebar=true&zoom=15&rand=-570915433\"}]}]}",
|
||||
"headers": {
|
||||
"Access-Control-Allow-Methods": "OPTIONS,GET,POST",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Cache-Control": "no-cache, must-revalidate",
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
"Date": "Thu, 14 Mar 2019 09:27:01 GMT",
|
||||
"Expires": "Mon, 20 Dec 1998 01:00:00 GMT",
|
||||
"GeocodeTransactionCount": "0",
|
||||
"Last-Modified": "Thu, 14 Mar 2019 09:27:01 GMT",
|
||||
"Pragma": "no-cache",
|
||||
"ReverseGeocodeTransactionCount": "1",
|
||||
"Server": "Apache-Coyote/1.1",
|
||||
"Set-Cookie": "JSESSIONID=something; Path=/; HttpOnly",
|
||||
"status": "success",
|
||||
"transactionWeight": "1.0",
|
||||
"Content-Length": "1063",
|
||||
"Connection": "keep-alive"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,36 +0,0 @@
|
||||
[
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": [],
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://open.mapquestapi.com/geocoding/v1/address?key=secret_key&location=10%20rue%20Jangot&maxResults=10"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\"info\":{\"statuscode\":0,\"copyright\":{\"text\":\"\\u00A9 2019 MapQuest, Inc.\",\"imageUrl\":\"http://api.mqcdn.com/res/mqlogo.gif\",\"imageAltText\":\"\\u00A9 2019 MapQuest, Inc.\"},\"messages\":[]},\"options\":{\"maxResults\":10,\"thumbMaps\":true,\"ignoreLatLngInput\":false},\"results\":[{\"providedLocation\":{\"location\":\"10 rue Jangot\"},\"locations\":[{\"street\":\"10 Rue Jangot\",\"adminArea6\":\"7e\",\"adminArea6Type\":\"Neighborhood\",\"adminArea5\":\"Lyon\",\"adminArea5Type\":\"City\",\"adminArea4\":\"Lyon\",\"adminArea4Type\":\"County\",\"adminArea3\":\"Auvergne-Rh\\u00F4ne-Alpes\",\"adminArea3Type\":\"State\",\"adminArea1\":\"FR\",\"adminArea1Type\":\"Country\",\"postalCode\":\"69007\",\"geocodeQualityCode\":\"P1AXX\",\"geocodeQuality\":\"POINT\",\"dragPoint\":false,\"sideOfStreet\":\"N\",\"linkId\":\"0\",\"unknownInput\":\"\",\"type\":\"s\",\"latLng\":{\"lat\":45.751714,\"lng\":4.842566},\"displayLatLng\":{\"lat\":45.751714,\"lng\":4.842566},\"mapUrl\":\"http://open.mapquestapi.com/staticmap/v5/map?key=secret_key&type=map&size=225,160&locations=45.7517141,4.8425657|marker-sm-50318A-1&scalebar=true&zoom=15&rand=1358091752\"}]}]}",
|
||||
"headers": {
|
||||
"Access-Control-Allow-Methods": "OPTIONS,GET,POST",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Cache-Control": "no-cache, must-revalidate",
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
"Date": "Thu, 14 Mar 2019 09:27:01 GMT",
|
||||
"Expires": "Mon, 20 Dec 1998 01:00:00 GMT",
|
||||
"GeocodeTransactionCount": "1",
|
||||
"Last-Modified": "Thu, 14 Mar 2019 09:27:01 GMT",
|
||||
"Pragma": "no-cache",
|
||||
"ReverseGeocodeTransactionCount": "0",
|
||||
"Server": "Apache-Coyote/1.1",
|
||||
"Set-Cookie": "JSESSIONID=something; Path=/; HttpOnly",
|
||||
"status": "success",
|
||||
"transactionWeight": "1.0",
|
||||
"Content-Length": "1055",
|
||||
"Connection": "keep-alive"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,32 +0,0 @@
|
||||
[
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": {
|
||||
"User-Agent": "Test instance mobilizon.test - Mobilizon 1.0.0-beta.1"
|
||||
},
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=45.751718&lon=4.842569&accept-language=en&addressdetails=1&namedetails=1"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\"type\":\"FeatureCollection\",\"geocoding\":{\"version\":\"0.1.0\",\"attribution\":\"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright\",\"licence\":\"ODbL\",\"query\":\"45.751718,4.842569\"},\"features\":[{\"type\":\"Feature\",\"properties\":{\"geocoding\":{\"place_id\":41453794,\"osm_type\":\"node\",\"osm_id\":3078260611,\"type\":\"house\",\"accuracy\":0,\"label\":\"10, Rue Jangot, La Guillotière, Lyon 7e Arrondissement, Lyon, Métropole de Lyon, Departemental constituency of Rhône, Auvergne-Rhône-Alpes, Metropolitan France, 69007, France\",\"name\":null,\"housenumber\":\"10\",\"street\":\"Rue Jangot\",\"postcode\":\"69007\",\"city\":\"Lyon\",\"county\":\"Lyon\",\"state\":\"Auvergne-Rhône-Alpes\",\"country\":\"France\",\"admin\":{\"level2\":\"France\",\"level3\":\"Metropolitan France\",\"level4\":\"Auvergne-Rhône-Alpes\",\"level5\":\"Departemental constituency of Rhône\",\"level6\":\"Métropole de Lyon\",\"level7\":\"Lyon\",\"level8\":\"Lyon\",\"level9\":\"Lyon 7e Arrondissement\"}}},\"geometry\":{\"type\":\"Point\",\"coordinates\":[4.8425657,45.7517141]}}]}",
|
||||
"headers": {
|
||||
"Date": "Tue, 12 Nov 2019 12:21:45 GMT",
|
||||
"Server": "Apache/2.4.29 (Ubuntu)",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Methods": "OPTIONS,GET",
|
||||
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
|
||||
"Expect-CT": "max-age=0, report-uri=\"https://openstreetmap.report-uri.com/r/d/ct/reportOnly\"",
|
||||
"Upgrade": "h2",
|
||||
"Connection": "Upgrade, close",
|
||||
"Transfer-Encoding": "chunked",
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,32 +0,0 @@
|
||||
[
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": {
|
||||
"User-Agent": "Test instance mobilizon.test - Mobilizon 1.0.0-beta.1"
|
||||
},
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://nominatim.openstreetmap.org/search?format=geocodejson&q=10%20rue%20Jangot&limit=10&accept-language=en&addressdetails=1&namedetails=1"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\"type\":\"FeatureCollection\",\"geocoding\":{\"version\":\"0.1.0\",\"attribution\":\"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright\",\"licence\":\"ODbL\",\"query\":\"10 rue Jangot\"},\"features\":[{\"type\":\"Feature\",\"properties\":{\"geocoding\":{\"place_id\":41453794,\"osm_type\":\"node\",\"osm_id\":3078260611,\"type\":\"house\",\"label\":\"10, Rue Jangot, La Guillotière, Lyon 7e Arrondissement, Lyon, Métropole de Lyon, Departemental constituency of Rhône, Auvergne-Rhône-Alpes, Metropolitan France, 69007, France\",\"name\":null,\"housenumber\":\"10\",\"street\":\"Rue Jangot\",\"postcode\":\"69007\",\"city\":\"Lyon\",\"county\":\"Lyon\",\"state\":\"Auvergne-Rhône-Alpes\",\"country\":\"France\",\"admin\":{\"level2\":\"France\",\"level3\":\"Metropolitan France\",\"level4\":\"Auvergne-Rhône-Alpes\",\"level5\":\"Departemental constituency of Rhône\",\"level6\":\"Métropole de Lyon\",\"level7\":\"Lyon\",\"level8\":\"Lyon\",\"level9\":\"Lyon 7e Arrondissement\"}}},\"geometry\":{\"type\":\"Point\",\"coordinates\":[4.8425657,45.7517141]}}]}",
|
||||
"headers": {
|
||||
"Date": "Tue, 12 Nov 2019 12:21:46 GMT",
|
||||
"Server": "Apache/2.4.29 (Ubuntu)",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Methods": "OPTIONS,GET",
|
||||
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
|
||||
"Expect-CT": "max-age=0, report-uri=\"https://openstreetmap.report-uri.com/r/d/ct/reportOnly\"",
|
||||
"Upgrade": "h2",
|
||||
"Connection": "Upgrade, close",
|
||||
"Transfer-Encoding": "chunked",
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,26 +0,0 @@
|
||||
[
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": [],
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://photon.komoot.de/reverse?lon=4.842569&lat=45.751718"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\"features\":[{\"geometry\":{\"coordinates\":[4.8416864,45.7605435],\"type\":\"Point\"},\"type\":\"Feature\",\"properties\":{\"osm_id\":4662865602,\"osm_type\":\"N\",\"country\":\"France\",\"osm_key\":\"leisure\",\"city\":\"Lyon\",\"street\":\"Rue Pravaz\",\"osm_value\":\"fitness_centre\",\"postcode\":\"69003\",\"name\":\"L'appart Fitness\",\"state\":\"Auvergne-Rhône-Alpes\"}}],\"type\":\"FeatureCollection\"}",
|
||||
"headers": {
|
||||
"Server": "nginx/1.9.3 (Ubuntu)",
|
||||
"Date": "Thu, 14 Mar 2019 10:46:45 GMT",
|
||||
"Content-Type": "application/json;charset=utf-8",
|
||||
"Transfer-Encoding": "chunked",
|
||||
"Connection": "keep-alive",
|
||||
"Access-Control-Allow-Origin": "*"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1,26 +0,0 @@
|
||||
[
|
||||
{
|
||||
"request": {
|
||||
"body": "",
|
||||
"headers": [],
|
||||
"method": "get",
|
||||
"options": [],
|
||||
"request_body": "",
|
||||
"url": "https://photon.komoot.de/api/?q=10%20rue%20Jangot&lang=en&limit=10"
|
||||
},
|
||||
"response": {
|
||||
"binary": false,
|
||||
"body": "{\"features\":[{\"geometry\":{\"coordinates\":[4.8425657,45.7517141],\"type\":\"Point\"},\"type\":\"Feature\",\"properties\":{\"osm_id\":3078260611,\"osm_type\":\"N\",\"country\":\"France\",\"osm_key\":\"place\",\"housenumber\":\"10\",\"city\":\"Lyon\",\"street\":\"Rue Jangot\",\"osm_value\":\"house\",\"postcode\":\"69007\",\"state\":\"Auvergne-Rhône-Alpes\"}},{\"geometry\":{\"coordinates\":[4.8424254,45.7517056],\"type\":\"Point\"},\"type\":\"Feature\",\"properties\":{\"osm_id\":3078260612,\"osm_type\":\"N\",\"country\":\"France\",\"osm_key\":\"place\",\"housenumber\":\"10bis\",\"city\":\"Lyon\",\"street\":\"Rue Jangot\",\"osm_value\":\"house\",\"postcode\":\"69007\",\"state\":\"Auvergne-Rhône-Alpes\"}}],\"type\":\"FeatureCollection\"}",
|
||||
"headers": {
|
||||
"Server": "nginx/1.9.3 (Ubuntu)",
|
||||
"Date": "Thu, 14 Mar 2019 10:46:43 GMT",
|
||||
"Content-Type": "application/json;charset=utf-8",
|
||||
"Transfer-Encoding": "chunked",
|
||||
"Connection": "keep-alive",
|
||||
"Access-Control-Allow-Origin": "*"
|
||||
},
|
||||
"status_code": 200,
|
||||
"type": "ok"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -4,7 +4,7 @@ defmodule Mobilizon.GraphQL.API.ReportTest do
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Reports.{Note, Report}
|
||||
alias Mobilizon.Service.Formatter.HTML
|
||||
|
||||
627
test/graphql/resolvers/post_test.exs
Normal file
627
test/graphql/resolvers/post_test.exs
Normal file
@@ -0,0 +1,627 @@
|
||||
defmodule Mobilizon.GraphQL.Resolvers.PostTest do
|
||||
use Mobilizon.Web.ConnCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.Actors.{Actor, Member}
|
||||
alias Mobilizon.Posts.Post
|
||||
alias Mobilizon.Users.User
|
||||
|
||||
alias Mobilizon.GraphQL.AbsintheHelpers
|
||||
|
||||
@post_fragment """
|
||||
fragment PostFragment on Post {
|
||||
id
|
||||
title
|
||||
slug
|
||||
url
|
||||
body
|
||||
author {
|
||||
id
|
||||
preferredUsername
|
||||
name
|
||||
avatar {
|
||||
url
|
||||
}
|
||||
}
|
||||
attributedTo {
|
||||
id
|
||||
preferredUsername
|
||||
name
|
||||
avatar {
|
||||
url
|
||||
}
|
||||
}
|
||||
visibility
|
||||
insertedAt
|
||||
updatedAt
|
||||
draft
|
||||
}
|
||||
"""
|
||||
|
||||
@get_group_posts """
|
||||
query($name: String!, $page: Int, $limit: Int) {
|
||||
group(preferredUsername: $name) {
|
||||
id
|
||||
posts(page: $page, limit: $limit) {
|
||||
elements {
|
||||
id,
|
||||
title,
|
||||
},
|
||||
total
|
||||
},
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
@post_query """
|
||||
query Post($slug: String!) {
|
||||
post(slug: $slug) {
|
||||
...PostFragment
|
||||
}
|
||||
}
|
||||
#{@post_fragment}
|
||||
"""
|
||||
|
||||
@create_post """
|
||||
mutation CreatePost($title: String!, $body: String, $attributedToId: ID!, $draft: Boolean) {
|
||||
createPost(title: $title, body: $body, attributedToId: $attributedToId, draft: $draft) {
|
||||
...PostFragment
|
||||
}
|
||||
}
|
||||
#{@post_fragment}
|
||||
"""
|
||||
|
||||
@update_post """
|
||||
mutation UpdatePost($id: ID!, $title: String, $body: String, $attributedToId: ID, $draft: Boolean) {
|
||||
updatePost(id: $id, title: $title, body: $body, attributedToId: $attributedToId, draft: $draft) {
|
||||
...PostFragment
|
||||
}
|
||||
}
|
||||
#{@post_fragment}
|
||||
"""
|
||||
|
||||
@delete_post """
|
||||
mutation DeletePost($id: ID!) {
|
||||
deletePost(id: $id) {
|
||||
id
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
@post_title "my post"
|
||||
@updated_post_title "my updated post"
|
||||
|
||||
setup do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{} = actor = insert(:actor, user: user)
|
||||
%Actor{} = group = insert(:group)
|
||||
%Post{} = post = insert(:post, attributed_to: group, author: actor)
|
||||
|
||||
%Post{} =
|
||||
post_unlisted = insert(:post, attributed_to: group, author: actor, visibility: :unlisted)
|
||||
|
||||
%Post{} = post_draft = insert(:post, attributed_to: group, author: actor, draft: true)
|
||||
%Member{} = insert(:member, parent: group, actor: actor, role: :member)
|
||||
|
||||
%Post{} =
|
||||
post_private = insert(:post, attributed_to: group, author: actor, visibility: :private)
|
||||
|
||||
{:ok,
|
||||
user: user,
|
||||
group: group,
|
||||
post: post,
|
||||
post_unlisted: post_unlisted,
|
||||
post_draft: post_draft,
|
||||
post_private: post_private}
|
||||
end
|
||||
|
||||
describe "Resolver: Get group's posts" do
|
||||
test "find_posts_for_group/3", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group,
|
||||
post: post,
|
||||
post_unlisted: post_unlisted,
|
||||
post_draft: post_draft,
|
||||
post_private: post_private
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_group_posts,
|
||||
variables: %{
|
||||
name: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["group"]["posts"]["total"] == 4
|
||||
|
||||
assert res["data"]["group"]["posts"]["elements"] |> Enum.map(& &1["id"]) |> MapSet.new() ==
|
||||
MapSet.new([
|
||||
post.id,
|
||||
post_unlisted.id,
|
||||
post_draft.id,
|
||||
post_private.id
|
||||
])
|
||||
end
|
||||
|
||||
test "find_posts_for_group/3 when not member of group", %{
|
||||
conn: conn,
|
||||
group: group,
|
||||
post: post
|
||||
} do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{} = insert(:actor, user: user)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_group_posts,
|
||||
variables: %{
|
||||
name: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["group"]["posts"]["total"] == 1
|
||||
|
||||
assert res["data"]["group"]["posts"]["elements"] |> Enum.map(& &1["id"]) == [post.id]
|
||||
end
|
||||
|
||||
test "find_posts_for_group/3 when not connected", %{
|
||||
conn: conn,
|
||||
group: group,
|
||||
post: post
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @get_group_posts,
|
||||
variables: %{
|
||||
name: group.preferred_username
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["group"]["posts"]["total"] == 1
|
||||
|
||||
assert res["data"]["group"]["posts"]["elements"] |> Enum.map(& &1["id"]) == [post.id]
|
||||
end
|
||||
end
|
||||
|
||||
describe "Resolver: Get a specific post" do
|
||||
test "get_post/3 for a public post", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
post: post
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["post"]["title"] == post.title
|
||||
end
|
||||
|
||||
test "get_post/3 for a non-existing post", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: "not existing"
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "No such post"
|
||||
end
|
||||
|
||||
test "get_post/3 for an unlisted post", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
post_unlisted: post_unlisted
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post_unlisted.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["post"]["title"] == post_unlisted.title
|
||||
|
||||
assert res["data"]["post"]["visibility"] ==
|
||||
post_unlisted.visibility |> to_string() |> String.upcase()
|
||||
end
|
||||
|
||||
test "get_post/3 for a private post", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
post_private: post_private
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post_private.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["post"]["title"] == post_private.title
|
||||
|
||||
assert res["data"]["post"]["visibility"] ==
|
||||
post_private.visibility |> to_string() |> String.upcase()
|
||||
end
|
||||
|
||||
test "get_post/3 for a draft post", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
post_draft: post_draft
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post_draft.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["post"]["title"] == post_draft.title
|
||||
assert res["data"]["post"]["draft"] == true
|
||||
end
|
||||
|
||||
test "get_post/3 without being a member for a public post", %{
|
||||
conn: conn,
|
||||
post: post
|
||||
} do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{} = insert(:actor, user: user)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["post"]["title"] == post.title
|
||||
end
|
||||
|
||||
test "get_post/3 without being connected for a public post", %{
|
||||
conn: conn,
|
||||
post: post
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["post"]["title"] == post.title
|
||||
end
|
||||
|
||||
test "get_post/3 without being a member for an unlisted post", %{
|
||||
conn: conn,
|
||||
post_unlisted: post_unlisted
|
||||
} do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{} = insert(:actor, user: user)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post_unlisted.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["post"]["title"] == post_unlisted.title
|
||||
|
||||
assert res["data"]["post"]["visibility"] ==
|
||||
post_unlisted.visibility |> to_string() |> String.upcase()
|
||||
end
|
||||
|
||||
test "get_post/3 without being a member for a private post", %{
|
||||
conn: conn,
|
||||
post_private: post_private
|
||||
} do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{} = insert(:actor, user: user)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post_private.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "No such post"
|
||||
end
|
||||
|
||||
test "get_post/3 without being connected for an unlisted post still gives the post", %{
|
||||
conn: conn,
|
||||
post_unlisted: post_unlisted
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post_unlisted.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["post"]["title"] == post_unlisted.title
|
||||
|
||||
assert res["data"]["post"]["visibility"] ==
|
||||
post_unlisted.visibility |> to_string() |> String.upcase()
|
||||
end
|
||||
|
||||
test "get_post/3 without being connected for a private post", %{
|
||||
conn: conn,
|
||||
post_private: post_private
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post_private.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "No such post"
|
||||
end
|
||||
|
||||
test "get_post/3 without being a member for a draft post", %{
|
||||
conn: conn,
|
||||
post_draft: post_draft
|
||||
} do
|
||||
%User{} = user = insert(:user)
|
||||
%Actor{} = insert(:actor, user: user)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post_draft.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "No such post"
|
||||
end
|
||||
|
||||
test "get_post/3 without being connected for a draft post", %{
|
||||
conn: conn,
|
||||
post_draft: post_draft
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post_draft.slug
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "No such post"
|
||||
end
|
||||
end
|
||||
|
||||
describe "Resolver: Create a post" do
|
||||
test "create_post/3 creates a post for a group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @create_post,
|
||||
variables: %{
|
||||
title: @post_title,
|
||||
body: "My new post is here",
|
||||
attributedToId: group.id
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["createPost"]["title"] == @post_title
|
||||
id = res["data"]["createPost"]["id"]
|
||||
assert res["data"]["createPost"]["slug"] == "my-post-#{ShortUUID.encode!(id)}"
|
||||
end
|
||||
|
||||
test "create_post/3 doesn't create a post if no group is defined", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @create_post,
|
||||
variables: %{
|
||||
title: @post_title,
|
||||
body: "some body",
|
||||
attributedToId: nil
|
||||
}
|
||||
)
|
||||
|
||||
assert Enum.map(res["errors"], & &1["message"]) == [
|
||||
"Argument \"attributedToId\" has invalid value $attributedToId.",
|
||||
"Variable \"attributedToId\": Expected non-null, found null."
|
||||
]
|
||||
end
|
||||
|
||||
test "create_post/3 doesn't create a post 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_post,
|
||||
variables: %{
|
||||
title: @post_title,
|
||||
body: "My body",
|
||||
attributedToId: group.id
|
||||
}
|
||||
)
|
||||
|
||||
assert Enum.map(res["errors"], & &1["message"]) == [
|
||||
"Actor id is not member of group"
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
describe "Resolver: Update a post" do
|
||||
test "update_post/3 updates a post for a group", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group
|
||||
} do
|
||||
%Post{id: post_id} = insert(:post, attributed_to: group)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @update_post,
|
||||
variables: %{
|
||||
id: post_id,
|
||||
title: @updated_post_title
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
|
||||
assert res["data"]["updatePost"]["title"] == @updated_post_title
|
||||
end
|
||||
end
|
||||
|
||||
describe "Resolver: Delete a post" do
|
||||
test "delete_post/3 deletes a post", %{
|
||||
conn: conn,
|
||||
user: user,
|
||||
group: group
|
||||
} do
|
||||
%Post{id: post_id, slug: post_slug} =
|
||||
insert(:post,
|
||||
attributed_to: group
|
||||
)
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @delete_post,
|
||||
variables: %{
|
||||
id: post_id
|
||||
}
|
||||
)
|
||||
|
||||
assert is_nil(res["errors"])
|
||||
assert res["data"]["deletePost"]["id"] == post_id
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @post_query,
|
||||
variables: %{
|
||||
slug: post_slug
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "No such post"
|
||||
end
|
||||
|
||||
test "delete_post/3 deletes a post not found", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
} do
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @delete_post,
|
||||
variables: %{
|
||||
id: "not found"
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "Post ID is not a valid ID"
|
||||
|
||||
res =
|
||||
conn
|
||||
|> auth_conn(user)
|
||||
|> AbsintheHelpers.graphql_query(
|
||||
query: @delete_post,
|
||||
variables: %{
|
||||
id: "d276ef98-8433-48d7-890e-c24eda0dcdbe"
|
||||
}
|
||||
)
|
||||
|
||||
assert hd(res["errors"])["message"] == "Post doesn't exist"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,9 +5,9 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.{Actors, Config, Conversations, Events, Users}
|
||||
alias Mobilizon.{Actors, Config, Discussions, Events, Users}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Events.{Event, Participant}
|
||||
alias Mobilizon.Service.Auth.Authenticator
|
||||
alias Mobilizon.Users.User
|
||||
@@ -1388,7 +1388,7 @@ defmodule Mobilizon.GraphQL.Resolvers.UserTest do
|
||||
end
|
||||
|
||||
assert_raise Ecto.NoResultsError, fn ->
|
||||
Conversations.get_comment!(comment_id)
|
||||
Discussions.get_comment!(comment_id)
|
||||
end
|
||||
|
||||
# Actors are not deleted but emptied (to keep the username reserved)
|
||||
|
||||
@@ -5,9 +5,9 @@ defmodule Mobilizon.ActorsTest do
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.{Actors, Config, Conversations, Events, Tombstone, Users}
|
||||
alias Mobilizon.{Actors, Config, Discussions, Events, Tombstone, Users}
|
||||
alias Mobilizon.Actors.{Actor, Bot, Follower, Member}
|
||||
alias Mobilizon.Conversations.Comment
|
||||
alias Mobilizon.Discussions.Comment
|
||||
alias Mobilizon.Events.Event
|
||||
alias Mobilizon.Media.File, as: FileModel
|
||||
alias Mobilizon.Service.Workers
|
||||
@@ -291,6 +291,56 @@ defmodule Mobilizon.ActorsTest do
|
||||
assert actor = actor_fetched
|
||||
end
|
||||
|
||||
test "perform delete the actor actually deletes the actor", %{
|
||||
actor: %Actor{avatar: %{url: avatar_url}, banner: %{url: banner_url}, id: actor_id} = actor
|
||||
} do
|
||||
%Event{url: event1_url} = event1 = insert(:event, organizer_actor: actor)
|
||||
insert(:event, organizer_actor: actor)
|
||||
|
||||
%Comment{url: comment1_url} = comment1 = insert(:comment, actor: actor)
|
||||
insert(:comment, actor: actor)
|
||||
|
||||
%URI{path: "/media/" <> avatar_path} = URI.parse(avatar_url)
|
||||
%URI{path: "/media/" <> banner_path} = URI.parse(banner_url)
|
||||
|
||||
assert File.exists?(
|
||||
Config.get!([Uploader.Local, :uploads]) <>
|
||||
"/" <> avatar_path
|
||||
)
|
||||
|
||||
assert File.exists?(
|
||||
Config.get!([Uploader.Local, :uploads]) <>
|
||||
"/" <> banner_path
|
||||
)
|
||||
|
||||
assert {:ok, %Actor{}} = Actors.perform(:delete_actor, actor)
|
||||
|
||||
assert %Actor{
|
||||
name: nil,
|
||||
summary: nil,
|
||||
suspended: true,
|
||||
avatar: nil,
|
||||
banner: nil,
|
||||
user_id: nil
|
||||
} = Actors.get_actor(actor_id)
|
||||
|
||||
assert {:error, :event_not_found} = Events.get_event(event1.id)
|
||||
assert %Tombstone{} = Tombstone.find_tombstone(event1_url)
|
||||
assert %Comment{deleted_at: deleted_at} = Discussions.get_comment(comment1.id)
|
||||
refute is_nil(deleted_at)
|
||||
assert %Tombstone{} = Tombstone.find_tombstone(comment1_url)
|
||||
|
||||
refute File.exists?(
|
||||
Config.get!([Uploader.Local, :uploads]) <>
|
||||
"/" <> avatar_path
|
||||
)
|
||||
|
||||
refute File.exists?(
|
||||
Config.get!([Uploader.Local, :uploads]) <>
|
||||
"/" <> banner_path
|
||||
)
|
||||
end
|
||||
|
||||
test "delete_actor/1 deletes the actor", %{
|
||||
actor: %Actor{avatar: %{url: avatar_url}, banner: %{url: banner_url}, id: actor_id} = actor
|
||||
} do
|
||||
@@ -333,7 +383,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} = Conversations.get_comment(comment1.id)
|
||||
assert %Comment{deleted_at: deleted_at} = Discussions.get_comment(comment1.id)
|
||||
refute is_nil(deleted_at)
|
||||
assert %Tombstone{} = Tombstone.find_tombstone(comment1_url)
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
defmodule Mobilizon.ConversationsTest do
|
||||
defmodule Mobilizon.DiscussionsTest 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
|
||||
alias Mobilizon.Discussions
|
||||
alias Mobilizon.Discussions.Comment
|
||||
|
||||
describe "comments" do
|
||||
@valid_attrs %{text: "some text"}
|
||||
@@ -16,13 +14,13 @@ defmodule Mobilizon.ConversationsTest do
|
||||
|
||||
test "list_comments/0 returns all comments" do
|
||||
%Comment{id: comment_id} = insert(:comment)
|
||||
comment_ids = Conversations.list_comments() |> Enum.map(& &1.id)
|
||||
comment_ids = Discussions.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)
|
||||
comment_fetched = Discussions.get_comment!(comment_id)
|
||||
assert comment_fetched.id == comment_id
|
||||
end
|
||||
|
||||
@@ -30,7 +28,7 @@ defmodule Mobilizon.ConversationsTest do
|
||||
%Actor{} = actor = insert(:actor)
|
||||
comment_data = Map.merge(@valid_attrs, %{actor_id: actor.id})
|
||||
|
||||
case Conversations.create_comment(comment_data) do
|
||||
case Discussions.create_comment(comment_data) do
|
||||
{:ok, %Comment{} = comment} ->
|
||||
assert comment.text == "some text"
|
||||
assert comment.actor_id == actor.id
|
||||
@@ -41,13 +39,13 @@ defmodule Mobilizon.ConversationsTest do
|
||||
end
|
||||
|
||||
test "create_comment/1 with invalid data returns error changeset" do
|
||||
assert {:error, %Ecto.Changeset{}} = Conversations.create_comment(@invalid_attrs)
|
||||
assert {:error, %Ecto.Changeset{}} = Discussions.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
|
||||
case Discussions.update_comment(comment, @update_attrs) do
|
||||
{:ok, %Comment{} = comment} ->
|
||||
assert comment.text == "some updated text"
|
||||
|
||||
@@ -58,15 +56,15 @@ defmodule Mobilizon.ConversationsTest do
|
||||
|
||||
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 {:error, %Ecto.Changeset{}} = Discussions.update_comment(comment, @invalid_attrs)
|
||||
%Comment{} = comment_fetched = Discussions.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)
|
||||
assert {:ok, %Comment{}} = Discussions.delete_comment(comment)
|
||||
refute is_nil(Discussions.get_comment!(comment.id).deleted_at)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -141,7 +141,7 @@ defmodule Mobilizon.EventsTest do
|
||||
end
|
||||
|
||||
test "list_public_events_for_actor/1", %{actor: actor, event: event} do
|
||||
assert {:ok, [event_found], 1} = Events.list_public_events_for_actor(actor)
|
||||
assert %Page{elements: [event_found], total: 1} = Events.list_public_events_for_actor(actor)
|
||||
assert event_found.title == event.title
|
||||
end
|
||||
|
||||
@@ -149,7 +149,7 @@ defmodule Mobilizon.EventsTest do
|
||||
event1 = insert(:event, organizer_actor: actor)
|
||||
|
||||
case Events.list_public_events_for_actor(actor, 1, 10) do
|
||||
{:ok, events_found, 2} ->
|
||||
%Page{elements: events_found, total: 2} ->
|
||||
event_ids = MapSet.new(events_found |> Enum.map(& &1.id))
|
||||
assert event_ids == MapSet.new([event.id, event1.id])
|
||||
|
||||
@@ -162,7 +162,7 @@ defmodule Mobilizon.EventsTest do
|
||||
event1 = insert(:event, organizer_actor: actor)
|
||||
|
||||
case Events.list_public_events_for_actor(actor, 1, 1) do
|
||||
{:ok, [%Event{id: event_found_id}], 2} ->
|
||||
%Page{elements: [%Event{id: event_found_id}], total: 2} ->
|
||||
assert event_found_id in [event.id, event1.id]
|
||||
|
||||
err ->
|
||||
|
||||
82
test/mobilizon/posts_test.exs
Normal file
82
test/mobilizon/posts_test.exs
Normal file
@@ -0,0 +1,82 @@
|
||||
defmodule Mobilizon.PostsTest do
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mobilizon.Factory
|
||||
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Posts
|
||||
alias Mobilizon.Posts.Post
|
||||
|
||||
describe "posts" do
|
||||
@valid_attrs %{body: "some text", title: "some title"}
|
||||
@update_attrs %{body: "some updated text", title: "some updated title"}
|
||||
@invalid_attrs %{body: nil}
|
||||
|
||||
test "list_posts/0 returns all posts" do
|
||||
group = insert(:group)
|
||||
%Post{id: post_id} = insert(:post, attributed_to: group)
|
||||
post_ids = Posts.get_posts_for_group(group).elements |> Enum.map(& &1.id)
|
||||
assert post_ids == [post_id]
|
||||
end
|
||||
|
||||
test "get_post!/1 returns the post with given id" do
|
||||
%Post{id: post_id} = insert(:post)
|
||||
post_fetched = Posts.get_post(post_id)
|
||||
assert post_fetched.id == post_id
|
||||
end
|
||||
|
||||
test "create_post/1 with valid data creates a post" do
|
||||
%Actor{} = actor = insert(:actor)
|
||||
%Actor{} = group = insert(:group)
|
||||
post_data = Map.merge(@valid_attrs, %{author_id: actor.id, attributed_to_id: group.id})
|
||||
|
||||
case Posts.create_post(post_data) do
|
||||
{:ok, %Post{} = post} ->
|
||||
assert post.body == "some text"
|
||||
assert post.author_id == actor.id
|
||||
assert post.title == "some title"
|
||||
assert post.slug == "some-title-" <> ShortUUID.encode!(post.id)
|
||||
|
||||
err ->
|
||||
flunk("Failed to create a post #{inspect(err)}")
|
||||
end
|
||||
end
|
||||
|
||||
test "create_post/1 with invalid data returns error changeset" do
|
||||
assert {:error, %Ecto.Changeset{}} = Posts.create_post(@invalid_attrs)
|
||||
end
|
||||
|
||||
test "update_post/2 with valid data updates the post" do
|
||||
%Actor{} = actor = insert(:actor)
|
||||
%Actor{} = group = insert(:group)
|
||||
post_data = Map.merge(@valid_attrs, %{author_id: actor.id, attributed_to_id: group.id})
|
||||
|
||||
{:ok, %Post{} = post} = Posts.create_post(post_data)
|
||||
|
||||
case Posts.update_post(post, @update_attrs) do
|
||||
{:ok, %Post{} = updated_post} ->
|
||||
assert updated_post.body == @update_attrs.body
|
||||
assert updated_post.title == @update_attrs.title
|
||||
# Slug and URL don't change
|
||||
assert updated_post.slug == post.slug
|
||||
assert updated_post.url == post.url
|
||||
|
||||
err ->
|
||||
flunk("Failed to update a post #{inspect(err)}")
|
||||
end
|
||||
end
|
||||
|
||||
test "update_post/2 with invalid data returns error changeset" do
|
||||
%Post{} = post = insert(:post)
|
||||
assert {:error, %Ecto.Changeset{}} = Posts.update_post(post, @invalid_attrs)
|
||||
%Post{} = post_fetched = Posts.get_post(post.id)
|
||||
assert post = post_fetched
|
||||
end
|
||||
|
||||
test "delete_post/1 deletes the post" do
|
||||
%Post{} = post = insert(:post)
|
||||
assert {:ok, %Post{}} = Posts.delete_post(post)
|
||||
assert is_nil(Posts.get_post(post.id))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,91 +1,63 @@
|
||||
defmodule Mobilizon.Service.Geospatial.AddokTest do
|
||||
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
||||
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
alias Mobilizon.Addresses.Address
|
||||
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
|
||||
# See https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html
|
||||
{:ok,
|
||||
httpoison_headers: [
|
||||
{"User-Agent", Config.instance_user_agent()}
|
||||
]}
|
||||
end
|
||||
|
||||
@endpoint get_in(Application.get_env(:mobilizon, Addok), [:endpoint])
|
||||
@fake_endpoint "https://domain.tld"
|
||||
alias Mobilizon.Service.HTTP.BaseClient.Mock
|
||||
|
||||
describe "search address" do
|
||||
test "produces a valid search address", %{httpoison_headers: httpoison_headers} 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,
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "produces a valid search address with options", %{httpoison_headers: httpoison_headers} do
|
||||
with_mock HTTPoison, get: fn _url, _headers, _options -> "{}" end do
|
||||
Addok.search("10 Rue Jangot",
|
||||
endpoint: @fake_endpoint,
|
||||
limit: 5,
|
||||
coords: %{lat: 49, lon: 12}
|
||||
)
|
||||
|
||||
assert_called(
|
||||
HTTPoison.get(
|
||||
"#{@fake_endpoint}/search/?q=10%20Rue%20Jangot&limit=5&lat=49&lon=12",
|
||||
httpoison_headers,
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "returns a valid address from search" do
|
||||
use_cassette "geospatial/addok/search" do
|
||||
assert %Address{
|
||||
country: "France",
|
||||
region: "69, Rhône, Auvergne-Rhône-Alpes",
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{coordinates: {4.842569, 45.751718}, properties: %{}, srid: 4326}
|
||||
} == Addok.search("10 rue Jangot") |> hd
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/geospatial/addok/search.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{
|
||||
method: :get,
|
||||
url: "https://api-adresse.data.gouv.fr/search/?q=10%20rue%20Jangot&limit=10"
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
assert %Address{
|
||||
country: "France",
|
||||
region: "69, Rhône, Auvergne-Rhône-Alpes",
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{coordinates: {4.842569, 45.751718}, properties: %{}, srid: 4326}
|
||||
} == Addok.search("10 rue Jangot") |> hd
|
||||
end
|
||||
|
||||
test "returns a valid address from reverse geocode" do
|
||||
use_cassette "geospatial/addok/geocode" do
|
||||
assert %Address{
|
||||
country: "France",
|
||||
region: "69, Rhône, Auvergne-Rhône-Alpes",
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{coordinates: {4.842569, 45.751718}, properties: %{}, srid: 4326}
|
||||
} == Addok.geocode(4.842569, 45.751718) |> hd
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/geospatial/addok/geocode.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{
|
||||
method: :get,
|
||||
url: "https://api-adresse.data.gouv.fr/reverse/?lon=4.842569&lat=45.751718&limit=10"
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
assert %Address{
|
||||
country: "France",
|
||||
region: "69, Rhône, Auvergne-Rhône-Alpes",
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{coordinates: {4.842569, 45.751718}, properties: %{}, srid: 4326}
|
||||
} == Addok.geocode(4.842569, 45.751718) |> hd
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
defmodule Mobilizon.Service.Geospatial.GoogleMapsTest do
|
||||
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
||||
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
alias Mobilizon.Addresses.Address
|
||||
alias Mobilizon.Service.Geospatial.GoogleMaps
|
||||
|
||||
@http_options [
|
||||
follow_redirect: true,
|
||||
ssl: [{:versions, [:"tlsv1.2"]}]
|
||||
]
|
||||
alias Mobilizon.Service.HTTP.BaseClient.Mock
|
||||
|
||||
describe "search address" do
|
||||
test "without API Key triggers an error" do
|
||||
@@ -20,76 +14,117 @@ defmodule Mobilizon.Service.Geospatial.GoogleMapsTest do
|
||||
end
|
||||
end
|
||||
|
||||
test "produces a valid search address with options" do
|
||||
with_mock HTTPoison,
|
||||
get: fn _url, _headers, _options ->
|
||||
{:ok,
|
||||
%HTTPoison.Response{status_code: 200, body: "{\"status\": \"OK\", \"results\": []}"}}
|
||||
end do
|
||||
GoogleMaps.search("10 Rue Jangot",
|
||||
limit: 5,
|
||||
lang: "fr",
|
||||
api_key: "toto"
|
||||
)
|
||||
|
||||
assert_called(
|
||||
HTTPoison.get(
|
||||
"https://maps.googleapis.com/maps/api/geocode/json?limit=5&key=toto&language=fr&address=10%20Rue%20Jangot",
|
||||
[],
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "triggers an error with an invalid API Key" do
|
||||
data =
|
||||
File.read!("test/fixtures/geospatial/google_maps/api_key_invalid.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{
|
||||
method: :get,
|
||||
url:
|
||||
"https://maps.googleapis.com/maps/api/geocode/json?limit=10&key=secret_key&language=en&address=10%20rue%20Jangot"
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
assert_raise ArgumentError, "The provided API key is invalid.", fn ->
|
||||
GoogleMaps.search("10 rue Jangot", api_key: "secret_key")
|
||||
end
|
||||
end
|
||||
|
||||
test "returns a valid address from search" do
|
||||
use_cassette "geospatial/google_maps/search" do
|
||||
assert %Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "France",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.8424032, 45.75164940000001},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
},
|
||||
origin_id: "gm:ChIJtW0QikTq9EcRLI4Vy6bRx0U"
|
||||
} ==
|
||||
GoogleMaps.search("10 rue Jangot",
|
||||
api_key: "toto"
|
||||
)
|
||||
|> hd
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/geospatial/google_maps/search.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
data_2 =
|
||||
File.read!("test/fixtures/geospatial/google_maps/search_2.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, 3, fn
|
||||
%{
|
||||
method: :get,
|
||||
url:
|
||||
"https://maps.googleapis.com/maps/api/geocode/json?limit=10&key=toto&language=en&address=10%20rue%20Jangot"
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: _url
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data_2}}
|
||||
end)
|
||||
|
||||
assert %Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "France",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.8424032, 45.75164940000001},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
},
|
||||
origin_id: "gm:ChIJtW0QikTq9EcRLI4Vy6bRx0U"
|
||||
} ==
|
||||
GoogleMaps.search("10 rue Jangot",
|
||||
api_key: "toto"
|
||||
)
|
||||
|> hd
|
||||
end
|
||||
|
||||
test "returns a valid address from reverse geocode" do
|
||||
use_cassette "geospatial/google_maps/geocode" do
|
||||
assert %Address{
|
||||
locality: "Lyon",
|
||||
description: "10bis Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "France",
|
||||
postal_code: "69007",
|
||||
street: "10bis Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.8424966, 45.751725},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
},
|
||||
origin_id: "gm:ChIJrW0QikTq9EcR96jk2OnO75w"
|
||||
} ==
|
||||
GoogleMaps.geocode(4.842569, 45.751718, api_key: "toto")
|
||||
|> hd
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/geospatial/google_maps/geocode.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
data_2 =
|
||||
File.read!("test/fixtures/geospatial/google_maps/geocode_2.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, 3, fn
|
||||
%{
|
||||
method: :get,
|
||||
url:
|
||||
"https://maps.googleapis.com/maps/api/geocode/json?limit=10&key=toto&language=en&latlng=45.751718,4.842569&result_type=street_address"
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
|
||||
%{
|
||||
method: :get,
|
||||
url: _url
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data_2}}
|
||||
end)
|
||||
|
||||
assert %Address{
|
||||
locality: "Lyon",
|
||||
description: "10bis Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "France",
|
||||
postal_code: "69007",
|
||||
street: "10bis Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.8424966, 45.751725},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
},
|
||||
origin_id: "gm:ChIJrW0QikTq9EcR96jk2OnO75w"
|
||||
} ==
|
||||
GoogleMaps.geocode(4.842569, 45.751718, api_key: "toto")
|
||||
|> hd
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,28 +1,11 @@
|
||||
defmodule Mobilizon.Service.Geospatial.MapQuestTest do
|
||||
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
||||
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
alias Mobilizon.Addresses.Address
|
||||
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
|
||||
# See https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html
|
||||
{:ok,
|
||||
httpoison_headers: [
|
||||
{"User-Agent", Config.instance_user_agent()}
|
||||
]}
|
||||
end
|
||||
alias Mobilizon.Service.HTTP.BaseClient.Mock
|
||||
|
||||
describe "search address" do
|
||||
test "without API Key triggers an error" do
|
||||
@@ -31,75 +14,88 @@ defmodule Mobilizon.Service.Geospatial.MapQuestTest do
|
||||
end
|
||||
end
|
||||
|
||||
test "produces a valid search address with options", %{httpoison_headers: httpoison_headers} do
|
||||
with_mock HTTPoison,
|
||||
get: fn _url, _headers, _options ->
|
||||
{:ok,
|
||||
%HTTPoison.Response{
|
||||
status_code: 200,
|
||||
body: "{\"info\": {\"statuscode\": 0}, \"results\": []}"
|
||||
}}
|
||||
end do
|
||||
MapQuest.search("10 Rue Jangot",
|
||||
limit: 5,
|
||||
lang: "fr",
|
||||
api_key: "toto"
|
||||
)
|
||||
|
||||
assert_called(
|
||||
HTTPoison.get(
|
||||
"https://open.mapquestapi.com/geocoding/v1/address?key=toto&location=10%20Rue%20Jangot&maxResults=5",
|
||||
httpoison_headers,
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "triggers an error with an invalid API Key" do
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{
|
||||
method: :get,
|
||||
url:
|
||||
"https://open.mapquestapi.com/geocoding/v1/address?key=secret_key&location=10%20rue%20Jangot&maxResults=10"
|
||||
},
|
||||
_opts ->
|
||||
{:ok,
|
||||
%Tesla.Env{status: 403, body: "The AppKey submitted with this request is invalid."}}
|
||||
end)
|
||||
|
||||
assert_raise ArgumentError, "The AppKey submitted with this request is invalid.", fn ->
|
||||
MapQuest.search("10 rue Jangot", api_key: "secret_key")
|
||||
end
|
||||
end
|
||||
|
||||
test "returns a valid address from search" do
|
||||
use_cassette "geospatial/map_quest/search" do
|
||||
assert %Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "FR",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.842566, 45.751714},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
}
|
||||
} ==
|
||||
MapQuest.search("10 rue Jangot", api_key: "secret_key")
|
||||
|> hd
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/geospatial/map_quest/search.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{
|
||||
method: :get,
|
||||
url:
|
||||
"https://open.mapquestapi.com/geocoding/v1/address?key=secret_key&location=10%20rue%20Jangot&maxResults=10"
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
assert %Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "FR",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.842566, 45.751714},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
}
|
||||
} ==
|
||||
MapQuest.search("10 rue Jangot", api_key: "secret_key")
|
||||
|> hd
|
||||
end
|
||||
|
||||
test "returns a valid address from reverse geocode" do
|
||||
use_cassette "geospatial/map_quest/geocode" do
|
||||
assert %Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "FR",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.842569, 45.751718},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
}
|
||||
} ==
|
||||
MapQuest.geocode(4.842569, 45.751718, api_key: "secret_key")
|
||||
|> hd
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/geospatial/map_quest/geocode.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{
|
||||
method: :get,
|
||||
url:
|
||||
"https://open.mapquestapi.com/geocoding/v1/reverse?key=secret_key&location=45.751718,4.842569&maxResults=10"
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
assert %Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "FR",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.842569, 45.751718},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
}
|
||||
} ==
|
||||
MapQuest.geocode(4.842569, 45.751718, api_key: "secret_key")
|
||||
|> hd
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,91 +1,81 @@
|
||||
defmodule Mobilizon.Service.Geospatial.NominatimTest do
|
||||
use Mobilizon.DataCase, async: false
|
||||
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
||||
import Mock
|
||||
use Mobilizon.DataCase
|
||||
import Mox
|
||||
|
||||
alias Mobilizon.Addresses.Address
|
||||
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
|
||||
# See https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html
|
||||
{:ok,
|
||||
httpoison_headers: [
|
||||
{"User-Agent", Config.instance_user_agent()}
|
||||
]}
|
||||
end
|
||||
alias Mobilizon.Service.HTTP.BaseClient.Mock
|
||||
|
||||
describe "search address" do
|
||||
test "produces a valid search address with options", %{httpoison_headers: httpoison_headers} do
|
||||
with_mock HTTPoison,
|
||||
get: fn _url, _headers, _options ->
|
||||
{:ok, %HTTPoison.Response{status_code: 200, body: "[]"}}
|
||||
end do
|
||||
Nominatim.search("10 Rue Jangot",
|
||||
limit: 5,
|
||||
lang: "fr"
|
||||
)
|
||||
|
||||
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,
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "returns a valid address from search" do
|
||||
use_cassette "geospatial/nominatim/search" do
|
||||
assert [
|
||||
%Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "France",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.8425657, 45.7517141},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
},
|
||||
origin_id: "nominatim:3078260611",
|
||||
type: "house"
|
||||
}
|
||||
] == Nominatim.search("10 rue Jangot")
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/geospatial/nominatim/search.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{
|
||||
method: :get,
|
||||
url:
|
||||
"https://nominatim.openstreetmap.org/search?format=geocodejson&q=10%20rue%20Jangot&limit=10&accept-language=en&addressdetails=1&namedetails=1"
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
assert [
|
||||
%Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "France",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.8425657, 45.7517141},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
},
|
||||
origin_id: "nominatim:3078260611",
|
||||
type: "house"
|
||||
}
|
||||
] == Nominatim.search("10 rue Jangot")
|
||||
end
|
||||
|
||||
test "returns a valid address from reverse geocode" do
|
||||
use_cassette "geospatial/nominatim/geocode" do
|
||||
assert [
|
||||
%Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "France",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.8425657, 45.7517141},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
},
|
||||
origin_id: "nominatim:3078260611",
|
||||
type: "house"
|
||||
}
|
||||
] ==
|
||||
Nominatim.geocode(4.842569, 45.751718)
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/geospatial/nominatim/geocode.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{
|
||||
method: :get,
|
||||
url:
|
||||
"https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=45.751718&lon=4.842569&accept-language=en&addressdetails=1&namedetails=1"
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
assert [
|
||||
%Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "France",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.8425657, 45.7517141},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
},
|
||||
origin_id: "nominatim:3078260611",
|
||||
type: "house"
|
||||
}
|
||||
] ==
|
||||
Nominatim.geocode(4.842569, 45.751718)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,66 +1,41 @@
|
||||
defmodule Mobilizon.Service.Geospatial.PhotonTest do
|
||||
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
||||
|
||||
use Mobilizon.DataCase
|
||||
|
||||
import Mock
|
||||
import Mox
|
||||
|
||||
alias Mobilizon.Addresses.Address
|
||||
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
|
||||
# See https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html
|
||||
{:ok,
|
||||
httpoison_headers: [
|
||||
{"User-Agent", Config.instance_user_agent()}
|
||||
]}
|
||||
end
|
||||
alias Mobilizon.Service.HTTP.BaseClient.Mock
|
||||
|
||||
describe "search address" do
|
||||
test "produces a valid search address with options", %{httpoison_headers: httpoison_headers} do
|
||||
with_mock HTTPoison,
|
||||
get: fn _url, _headers, _options ->
|
||||
{:ok, %HTTPoison.Response{status_code: 200, body: "{\"features\": []"}}
|
||||
end do
|
||||
Photon.search("10 Rue Jangot",
|
||||
limit: 5,
|
||||
lang: "fr"
|
||||
)
|
||||
|
||||
assert_called(
|
||||
HTTPoison.get(
|
||||
"https://photon.komoot.de/api/?q=10%20Rue%20Jangot&lang=fr&limit=5",
|
||||
httpoison_headers,
|
||||
@http_options
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "returns a valid address from search" do
|
||||
use_cassette "geospatial/photon/search" do
|
||||
assert %Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "France",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.8425657, 45.7517141},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
}
|
||||
} == Photon.search("10 rue Jangot") |> hd
|
||||
end
|
||||
data =
|
||||
File.read!("test/fixtures/geospatial/photon/search.json")
|
||||
|> Jason.decode!()
|
||||
|
||||
Mock
|
||||
|> expect(:call, fn
|
||||
%{
|
||||
method: :get,
|
||||
url: "https://photon.komoot.de/api/?q=10%20rue%20Jangot&lang=en&limit=10"
|
||||
},
|
||||
_opts ->
|
||||
{:ok, %Tesla.Env{status: 200, body: data}}
|
||||
end)
|
||||
|
||||
assert %Address{
|
||||
locality: "Lyon",
|
||||
description: "10 Rue Jangot",
|
||||
region: "Auvergne-Rhône-Alpes",
|
||||
country: "France",
|
||||
postal_code: "69007",
|
||||
street: "10 Rue Jangot",
|
||||
geom: %Geo.Point{
|
||||
coordinates: {4.8425657, 45.7517141},
|
||||
properties: %{},
|
||||
srid: 4326
|
||||
}
|
||||
} == Photon.search("10 rue Jangot") |> hd
|
||||
end
|
||||
|
||||
# Photon returns something quite wrong, so no need to test this right now.
|
||||
|
||||
@@ -73,4 +73,7 @@ defmodule Mobilizon.DataCase do
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
Mox.defmock(Mobilizon.Service.HTTP.ActivityPub.Mock, for: Tesla.Adapter)
|
||||
Mox.defmock(Mobilizon.Service.HTTP.BaseClient.Mock, for: Tesla.Adapter)
|
||||
end
|
||||
|
||||
@@ -118,12 +118,15 @@ defmodule Mobilizon.Factory do
|
||||
def comment_factory do
|
||||
uuid = Ecto.UUID.generate()
|
||||
|
||||
%Mobilizon.Conversations.Comment{
|
||||
%Mobilizon.Discussions.Comment{
|
||||
text: "My Comment",
|
||||
actor: build(:actor),
|
||||
event: build(:event),
|
||||
uuid: uuid,
|
||||
mentions: [],
|
||||
attributed_to: nil,
|
||||
local: true,
|
||||
deleted_at: nil,
|
||||
tags: build_list(3, :tag),
|
||||
in_reply_to_comment: nil,
|
||||
url: Routes.page_url(Endpoint, :comment, uuid)
|
||||
@@ -142,6 +145,7 @@ defmodule Mobilizon.Factory do
|
||||
begins_on: start,
|
||||
ends_on: Timex.shift(start, hours: 2),
|
||||
organizer_actor: actor,
|
||||
attributed_to: nil,
|
||||
category: sequence("something"),
|
||||
physical_address: build(:address),
|
||||
visibility: :public,
|
||||
@@ -324,4 +328,50 @@ defmodule Mobilizon.Factory do
|
||||
value: sequence("value")
|
||||
}
|
||||
end
|
||||
|
||||
def post_factory do
|
||||
uuid = Ecto.UUID.generate()
|
||||
|
||||
%Mobilizon.Posts.Post{
|
||||
body: "The <b>HTML</b>body for my Article",
|
||||
title: "My Awesome article",
|
||||
slug: "my-awesome-article-#{ShortUUID.encode!(uuid)}",
|
||||
author: build(:actor),
|
||||
attributed_to: build(:group),
|
||||
id: uuid,
|
||||
draft: false,
|
||||
tags: build_list(3, :tag),
|
||||
visibility: :public,
|
||||
publish_at: DateTime.utc_now(),
|
||||
url: Routes.page_url(Endpoint, :post, uuid)
|
||||
}
|
||||
end
|
||||
|
||||
def tombstone_factory do
|
||||
uuid = Ecto.UUID.generate()
|
||||
|
||||
%Mobilizon.Tombstone{
|
||||
uri: "https://mobilizon.test/comments/#{uuid}",
|
||||
actor: build(:actor)
|
||||
}
|
||||
end
|
||||
|
||||
def discussion_factory do
|
||||
uuid = Ecto.UUID.generate()
|
||||
actor = build(:actor)
|
||||
group = build(:group)
|
||||
comment = build(:comment, actor: actor, attributed_to: group)
|
||||
slug = "my-awesome-discussion-#{ShortUUID.encode!(uuid)}"
|
||||
|
||||
%Mobilizon.Discussions.Discussion{
|
||||
title: "My Awesome discussion",
|
||||
slug: slug,
|
||||
creator: actor,
|
||||
actor: group,
|
||||
id: uuid,
|
||||
last_comment: comment,
|
||||
comments: [comment],
|
||||
url: Routes.page_url(Endpoint, :discussion, group.preferred_username, slug)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -344,11 +344,12 @@ defmodule Mobilizon.Web.ActivityPubControllerTest do
|
||||
Actors.create_group(%{
|
||||
creator_actor_id: actor.id,
|
||||
preferred_username: "my_group",
|
||||
visibility: :public
|
||||
local: true
|
||||
})
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:actor, actor)
|
||||
|> get(Actor.build_url(group.preferred_username, :members))
|
||||
|> json_response(200)
|
||||
|
||||
@@ -358,15 +359,21 @@ defmodule Mobilizon.Web.ActivityPubControllerTest do
|
||||
assert hd(result["first"]["orderedItems"])["type"] == "Member"
|
||||
end
|
||||
|
||||
test "it returns no members for a private group", %{conn: conn} do
|
||||
test "it returns no members when not a member of the group", %{conn: conn} do
|
||||
actor = insert(:actor)
|
||||
actor2 = insert(:actor)
|
||||
|
||||
assert {:ok, %Actor{} = group} =
|
||||
Actors.create_group(%{creator_actor_id: actor.id, preferred_username: "my_group"})
|
||||
Actors.create_group(%{
|
||||
creator_actor_id: actor.id,
|
||||
preferred_username: "my_group",
|
||||
local: true
|
||||
})
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get(Actor.build_url(actor.preferred_username, :members))
|
||||
|> assign(:actor, actor2)
|
||||
|> get(Actor.build_url(group.preferred_username, :members))
|
||||
|> json_response(200)
|
||||
|
||||
assert result["first"]["orderedItems"] == []
|
||||
@@ -379,7 +386,7 @@ defmodule Mobilizon.Web.ActivityPubControllerTest do
|
||||
Actors.create_group(%{
|
||||
creator_actor_id: actor.id,
|
||||
preferred_username: "my_group",
|
||||
visibility: :public
|
||||
local: true
|
||||
})
|
||||
|
||||
Enum.each(1..15, fn _ ->
|
||||
@@ -389,6 +396,7 @@ defmodule Mobilizon.Web.ActivityPubControllerTest do
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:actor, actor)
|
||||
|> get(Actor.build_url(group.preferred_username, :members))
|
||||
|> json_response(200)
|
||||
|
||||
@@ -398,6 +406,7 @@ defmodule Mobilizon.Web.ActivityPubControllerTest do
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:actor, actor)
|
||||
|> get(Actor.build_url(group.preferred_username, :members, page: 2))
|
||||
|> json_response(200)
|
||||
|
||||
@@ -411,7 +420,8 @@ defmodule Mobilizon.Web.ActivityPubControllerTest do
|
||||
assert {:ok, %Actor{} = group} =
|
||||
Actors.create_group(%{
|
||||
creator_actor_id: actor_group_admin.id,
|
||||
preferred_username: "my_group"
|
||||
preferred_username: "my_group",
|
||||
local: true
|
||||
})
|
||||
|
||||
insert(:member, actor: actor_applicant, parent: group, role: :member)
|
||||
|
||||
@@ -91,24 +91,26 @@ defmodule Mobilizon.Web.FeedControllerTest do
|
||||
describe "/@:preferred_username/feed/ics" do
|
||||
test "it returns an iCalendar representation of the actor's public events with an actor publicly visible",
|
||||
%{conn: conn} do
|
||||
actor = insert(:actor, visibility: :public)
|
||||
actor = insert(:actor)
|
||||
group = insert(:group, visibility: :public)
|
||||
tag1 = insert(:tag, title: "iCalendar", slug: "icalendar")
|
||||
tag2 = insert(:tag, title: "Apple", slug: "apple")
|
||||
event1 = insert(:event, organizer_actor: actor, tags: [tag1])
|
||||
event2 = insert(:event, organizer_actor: actor, tags: [tag1, tag2])
|
||||
event1 = insert(:event, organizer_actor: actor, attributed_to: group, tags: [tag1])
|
||||
event2 = insert(:event, organizer_actor: actor, attributed_to: group, tags: [tag1, tag2])
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> get(
|
||||
Endpoint
|
||||
|> Routes.feed_url(:actor, actor.preferred_username, "ics")
|
||||
|> Routes.feed_url(:actor, group.preferred_username, "ics")
|
||||
|> URI.decode()
|
||||
)
|
||||
|
||||
assert response(conn, 200) =~ "BEGIN:VCALENDAR"
|
||||
assert res = response(conn, 200)
|
||||
assert res =~ "BEGIN:VCALENDAR"
|
||||
assert response_content_type(conn, :calendar) =~ "charset=utf-8"
|
||||
|
||||
[entry1, entry2] = entries = ExIcal.parse(conn.resp_body)
|
||||
[entry1, entry2] = entries = ExIcal.parse(res)
|
||||
|
||||
Enum.each(entries, fn entry ->
|
||||
assert entry.summary in [event1.title, event2.title]
|
||||
@@ -120,7 +122,7 @@ defmodule Mobilizon.Web.FeedControllerTest do
|
||||
|
||||
test "it returns a 404 page for the actor's public events iCal feed with an actor not publicly visible",
|
||||
%{conn: conn} do
|
||||
actor = insert(:actor, visibility: :private)
|
||||
actor = insert(:group, visibility: :private)
|
||||
tag1 = insert(:tag, title: "iCalendar", slug: "icalendar")
|
||||
tag2 = insert(:tag, title: "Apple", slug: "apple")
|
||||
insert(:event, organizer_actor: actor, tags: [tag1])
|
||||
|
||||
Reference in New Issue
Block a user