2020-01-26 20:36:50 +00:00
|
|
|
defmodule Mobilizon.Web.FeedControllerTest do
|
|
|
|
use Mobilizon.Web.ConnCase
|
2019-09-22 14:26:23 +00:00
|
|
|
|
2019-02-27 15:28:09 +00:00
|
|
|
import Mobilizon.Factory
|
2019-09-22 14:26:23 +00:00
|
|
|
|
2021-01-19 10:24:21 +00:00
|
|
|
alias Mobilizon.Config
|
2023-12-01 11:06:18 +00:00
|
|
|
use Mobilizon.Web, :verified_routes
|
2019-02-27 15:28:09 +00:00
|
|
|
|
2019-03-06 16:07:42 +00:00
|
|
|
describe "/@:preferred_username/feed/atom" do
|
2019-04-25 17:05:05 +00:00
|
|
|
test "it returns an RSS representation of the actor's public events if the actor is publicly visible",
|
|
|
|
%{conn: conn} do
|
|
|
|
actor = insert(:actor, visibility: :public)
|
2019-03-01 11:57:22 +00:00
|
|
|
tag1 = insert(:tag, title: "RSS", slug: "rss")
|
|
|
|
tag2 = insert(:tag, title: "ATOM", slug: "atom")
|
|
|
|
event1 = insert(:event, organizer_actor: actor, tags: [tag1])
|
|
|
|
event2 = insert(:event, organizer_actor: actor, tags: [tag1, tag2])
|
2019-02-27 15:28:09 +00:00
|
|
|
|
2023-04-20 09:30:10 +00:00
|
|
|
event3 =
|
|
|
|
insert(:event,
|
|
|
|
organizer_actor: actor,
|
|
|
|
begins_on: DateTime.add(DateTime.utc_now(), -2, :day)
|
|
|
|
)
|
|
|
|
|
2019-02-27 15:28:09 +00:00
|
|
|
conn =
|
|
|
|
conn
|
2023-12-01 11:06:18 +00:00
|
|
|
|> get(URI.decode(~p"/@#{actor.preferred_username}/feed/atom"))
|
2019-02-27 15:28:09 +00:00
|
|
|
|
|
|
|
assert response(conn, 200) =~ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
|
|
|
assert response_content_type(conn, :xml) =~ "charset=utf-8"
|
|
|
|
|
2019-03-01 11:57:22 +00:00
|
|
|
{:ok, feed} = ElixirFeedParser.parse(conn.resp_body)
|
2019-02-27 15:28:09 +00:00
|
|
|
|
2021-01-19 10:24:21 +00:00
|
|
|
assert feed.title ==
|
2021-10-21 15:55:16 +00:00
|
|
|
actor.name <> "'s public events feed on #{Config.instance_name()}"
|
2019-02-27 15:28:09 +00:00
|
|
|
|
2019-03-01 11:57:22 +00:00
|
|
|
[entry1, entry2] = entries = feed.entries
|
|
|
|
|
|
|
|
Enum.each(entries, fn entry ->
|
2019-02-27 15:28:09 +00:00
|
|
|
assert entry.title in [event1.title, event2.title]
|
2023-04-20 09:30:10 +00:00
|
|
|
refute entry.title == event3.title
|
2019-02-27 15:28:09 +00:00
|
|
|
end)
|
2019-03-01 11:57:22 +00:00
|
|
|
|
2019-11-05 16:49:40 +00:00
|
|
|
# It seems categories takes term instead of Label
|
|
|
|
# <category label=\"RSS\" term=\"rss\"/>
|
|
|
|
assert entry1.categories == [tag2.title, tag1.title] |> Enum.map(&String.downcase/1)
|
|
|
|
assert entry2.categories == [tag1.title] |> Enum.map(&String.downcase/1)
|
2019-03-01 11:57:22 +00:00
|
|
|
end
|
|
|
|
|
2019-04-25 17:05:05 +00:00
|
|
|
test "it returns a 404 for the actor's public events Atom feed if the actor is not publicly visible",
|
2019-03-01 11:57:22 +00:00
|
|
|
%{conn: conn} do
|
2020-09-02 15:42:17 +00:00
|
|
|
actor = insert(:actor, visibility: :private)
|
2019-04-25 17:05:05 +00:00
|
|
|
tag1 = insert(:tag, title: "RSS", slug: "rss")
|
|
|
|
tag2 = insert(:tag, title: "ATOM", slug: "atom")
|
|
|
|
insert(:event, organizer_actor: actor, tags: [tag1])
|
|
|
|
insert(:event, organizer_actor: actor, tags: [tag1, tag2])
|
|
|
|
|
|
|
|
conn =
|
|
|
|
conn
|
|
|
|
|> get(
|
2023-12-01 11:06:18 +00:00
|
|
|
~p"/@#{actor.preferred_username}/feed/atom"
|
2019-04-25 17:05:05 +00:00
|
|
|
|> URI.decode()
|
|
|
|
)
|
|
|
|
|
|
|
|
assert response(conn, 404)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "it returns an RSS representation of the actor's public events with the proper accept header",
|
|
|
|
%{conn: conn} do
|
|
|
|
actor = insert(:actor, visibility: :unlisted)
|
2019-03-01 11:57:22 +00:00
|
|
|
|
|
|
|
conn =
|
|
|
|
conn
|
|
|
|
|> put_req_header("accept", "application/atom+xml")
|
|
|
|
|> get(
|
2023-12-01 11:06:18 +00:00
|
|
|
~p"/@#{actor.preferred_username}/feed/atom"
|
2019-03-01 11:57:22 +00:00
|
|
|
|> URI.decode()
|
|
|
|
)
|
|
|
|
|
|
|
|
assert response(conn, 200) =~ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
|
|
|
assert response_content_type(conn, :xml) =~ "charset=utf-8"
|
2019-02-27 15:28:09 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
test "it doesn't return anything for an not existing actor", %{conn: conn} do
|
|
|
|
conn =
|
|
|
|
conn
|
|
|
|
|> put_req_header("accept", "application/atom+xml")
|
2019-03-01 11:57:22 +00:00
|
|
|
|> get("/@notexistent/feed/atom")
|
2019-02-27 15:28:09 +00:00
|
|
|
|
2019-03-01 11:57:22 +00:00
|
|
|
assert response(conn, 404)
|
2019-02-27 15:28:09 +00:00
|
|
|
end
|
|
|
|
end
|
2019-03-06 16:07:42 +00:00
|
|
|
|
|
|
|
describe "/@:preferred_username/feed/ics" do
|
2019-04-25 17:05:05 +00:00
|
|
|
test "it returns an iCalendar representation of the actor's public events with an actor publicly visible",
|
|
|
|
%{conn: conn} do
|
2020-07-09 15:24:28 +00:00
|
|
|
actor = insert(:actor)
|
|
|
|
group = insert(:group, visibility: :public)
|
2019-03-06 16:07:42 +00:00
|
|
|
tag1 = insert(:tag, title: "iCalendar", slug: "icalendar")
|
|
|
|
tag2 = insert(:tag, title: "Apple", slug: "apple")
|
2021-01-12 10:18:04 +00:00
|
|
|
|
|
|
|
event1 =
|
|
|
|
insert(:event,
|
|
|
|
organizer_actor: actor,
|
|
|
|
attributed_to: group,
|
|
|
|
tags: [tag1],
|
|
|
|
title: "Event One"
|
|
|
|
)
|
|
|
|
|
|
|
|
event2 =
|
|
|
|
insert(:event,
|
|
|
|
organizer_actor: actor,
|
|
|
|
attributed_to: group,
|
|
|
|
tags: [tag1, tag2],
|
|
|
|
title: "Event Two",
|
2023-04-20 09:30:10 +00:00
|
|
|
begins_on: DateTime.add(DateTime.utc_now(), 4, :day)
|
|
|
|
)
|
|
|
|
|
|
|
|
event3 =
|
|
|
|
insert(:event,
|
|
|
|
organizer_actor: actor,
|
|
|
|
attributed_to: group,
|
|
|
|
title: "Event Three",
|
|
|
|
begins_on: DateTime.add(DateTime.utc_now(), -2, :day)
|
2021-01-12 10:18:04 +00:00
|
|
|
)
|
2019-03-06 16:07:42 +00:00
|
|
|
|
|
|
|
conn =
|
|
|
|
conn
|
2023-12-01 08:49:54 +00:00
|
|
|
|> get(URI.decode(~p"/@#{group.preferred_username}/feed/ics"))
|
2019-03-06 16:07:42 +00:00
|
|
|
|
2020-07-09 15:24:28 +00:00
|
|
|
assert res = response(conn, 200)
|
|
|
|
assert res =~ "BEGIN:VCALENDAR"
|
2019-03-06 16:07:42 +00:00
|
|
|
assert response_content_type(conn, :calendar) =~ "charset=utf-8"
|
|
|
|
|
2021-01-12 10:18:04 +00:00
|
|
|
[entry2, entry1] = entries = ExIcal.parse(res)
|
2019-03-06 16:07:42 +00:00
|
|
|
|
|
|
|
Enum.each(entries, fn entry ->
|
|
|
|
assert entry.summary in [event1.title, event2.title]
|
2023-04-20 09:30:10 +00:00
|
|
|
refute entry.summary == event3.title
|
2019-03-06 16:07:42 +00:00
|
|
|
end)
|
|
|
|
|
2019-11-05 16:49:40 +00:00
|
|
|
assert entry1.categories == [tag1.title]
|
|
|
|
assert entry2.categories == [tag1.title, tag2.title]
|
2019-03-06 16:07:42 +00:00
|
|
|
end
|
|
|
|
|
2019-04-25 17:05:05 +00:00
|
|
|
test "it returns a 404 page for the actor's public events iCal feed with an actor not publicly visible",
|
|
|
|
%{conn: conn} do
|
2020-07-09 15:24:28 +00:00
|
|
|
actor = insert(:group, visibility: :private)
|
2019-04-25 17:05:05 +00:00
|
|
|
tag1 = insert(:tag, title: "iCalendar", slug: "icalendar")
|
|
|
|
tag2 = insert(:tag, title: "Apple", slug: "apple")
|
|
|
|
insert(:event, organizer_actor: actor, tags: [tag1])
|
|
|
|
insert(:event, organizer_actor: actor, tags: [tag1, tag2])
|
|
|
|
|
|
|
|
conn =
|
|
|
|
conn
|
2023-12-01 08:49:54 +00:00
|
|
|
|> get(URI.decode(~p"/@#{actor.preferred_username}/feed/ics"))
|
2019-04-25 17:05:05 +00:00
|
|
|
|
|
|
|
assert response(conn, 404)
|
|
|
|
end
|
|
|
|
|
2019-03-06 16:07:42 +00:00
|
|
|
test "it returns an iCalendar representation of the actor's public events with the proper accept header",
|
|
|
|
%{conn: conn} do
|
2019-04-25 17:05:05 +00:00
|
|
|
actor = insert(:actor, visibility: :unlisted)
|
2019-03-06 16:07:42 +00:00
|
|
|
|
|
|
|
conn =
|
|
|
|
conn
|
|
|
|
|> put_req_header("accept", "text/calendar")
|
2023-12-01 08:49:54 +00:00
|
|
|
|> get(URI.decode(~p"/@#{actor.preferred_username}/feed/ics"))
|
2019-03-06 16:07:42 +00:00
|
|
|
|
|
|
|
assert response(conn, 200) =~ "BEGIN:VCALENDAR"
|
|
|
|
assert response_content_type(conn, :calendar) =~ "charset=utf-8"
|
|
|
|
end
|
|
|
|
|
|
|
|
test "it doesn't return anything for an not existing actor", %{conn: conn} do
|
|
|
|
conn =
|
|
|
|
conn
|
|
|
|
|> put_req_header("accept", "text/calendar")
|
|
|
|
|> get("/@notexistent/feed/ics")
|
|
|
|
|
|
|
|
assert response(conn, 404)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "/events/:uuid/export/ics" do
|
|
|
|
test "it returns an iCalendar representation of the event", %{conn: conn} do
|
|
|
|
tag1 = insert(:tag, title: "iCalendar", slug: "icalendar")
|
|
|
|
tag2 = insert(:tag, title: "Apple", slug: "apple")
|
|
|
|
event1 = insert(:event, tags: [tag1, tag2])
|
|
|
|
|
|
|
|
conn =
|
|
|
|
conn
|
|
|
|
|> get(
|
2023-12-01 11:06:18 +00:00
|
|
|
~p"/events/#{event1.uuid}/export/ics"
|
2019-03-06 16:07:42 +00:00
|
|
|
|> URI.decode()
|
|
|
|
)
|
|
|
|
|
|
|
|
assert response(conn, 200) =~ "BEGIN:VCALENDAR"
|
|
|
|
assert response_content_type(conn, :calendar) =~ "charset=utf-8"
|
|
|
|
|
|
|
|
[entry1] = ExIcal.parse(conn.resp_body)
|
|
|
|
|
|
|
|
assert entry1.summary == event1.title
|
|
|
|
|
2019-11-05 16:49:40 +00:00
|
|
|
assert entry1.categories == [tag1.title, tag2.title]
|
2019-03-06 16:07:42 +00:00
|
|
|
end
|
|
|
|
end
|
2019-03-08 11:25:06 +00:00
|
|
|
|
|
|
|
describe "/events/going/:token/atom" do
|
|
|
|
test "it returns an atom feed of all events for all identities for an user token", %{
|
|
|
|
conn: conn
|
|
|
|
} do
|
|
|
|
user = insert(:user)
|
|
|
|
actor1 = insert(:actor, user: user)
|
|
|
|
actor2 = insert(:actor, user: user)
|
|
|
|
event1 = insert(:event)
|
|
|
|
event2 = insert(:event)
|
2023-04-20 09:30:10 +00:00
|
|
|
event3 = insert(:event, begins_on: DateTime.add(DateTime.utc_now(), -5, :day))
|
2019-03-08 11:25:06 +00:00
|
|
|
insert(:participant, event: event1, actor: actor1)
|
|
|
|
insert(:participant, event: event2, actor: actor2)
|
2023-04-20 09:30:10 +00:00
|
|
|
insert(:participant, event: event3, actor: actor2)
|
2019-03-08 11:25:06 +00:00
|
|
|
feed_token = insert(:feed_token, user: user, actor: nil)
|
|
|
|
|
|
|
|
conn =
|
|
|
|
conn
|
2023-12-01 11:06:18 +00:00
|
|
|
|> get(URI.decode(~p"/events/going/#{ShortUUID.encode!(feed_token.token)}/atom"))
|
2019-03-08 11:25:06 +00:00
|
|
|
|
|
|
|
assert response(conn, 200) =~ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
|
|
|
assert response_content_type(conn, :xml) =~ "charset=utf-8"
|
|
|
|
|
|
|
|
{:ok, feed} = ElixirFeedParser.parse(conn.resp_body)
|
|
|
|
|
2021-01-19 10:24:21 +00:00
|
|
|
assert feed.title == "Feed for #{user.email} on #{Config.instance_name()}"
|
2019-03-08 11:25:06 +00:00
|
|
|
|
|
|
|
entries = feed.entries
|
|
|
|
|
|
|
|
Enum.each(entries, fn entry ->
|
|
|
|
assert entry.title in [event1.title, event2.title]
|
2023-04-20 09:30:10 +00:00
|
|
|
refute entry.title == event3.title
|
2019-03-08 11:25:06 +00:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "it returns an atom feed of all events a single identity for an actor token", %{
|
|
|
|
conn: conn
|
|
|
|
} do
|
|
|
|
user = insert(:user)
|
|
|
|
actor1 = insert(:actor, user: user)
|
|
|
|
actor2 = insert(:actor, user: user)
|
|
|
|
event1 = insert(:event)
|
|
|
|
event2 = insert(:event)
|
2023-04-20 09:30:10 +00:00
|
|
|
event3 = insert(:event, begins_on: DateTime.add(DateTime.utc_now(), -5, :day))
|
2019-03-08 11:25:06 +00:00
|
|
|
insert(:participant, event: event1, actor: actor1)
|
|
|
|
insert(:participant, event: event2, actor: actor2)
|
2023-04-20 09:30:10 +00:00
|
|
|
insert(:participant, event: event3, actor: actor1)
|
2019-03-08 11:25:06 +00:00
|
|
|
feed_token = insert(:feed_token, user: user, actor: actor1)
|
|
|
|
|
|
|
|
conn =
|
|
|
|
conn
|
|
|
|
|> put_req_header("accept", "application/atom+xml")
|
2023-12-01 11:06:18 +00:00
|
|
|
|> get(URI.decode(~p"/events/going/#{ShortUUID.encode!(feed_token.token)}/atom"))
|
2019-03-08 11:25:06 +00:00
|
|
|
|
|
|
|
assert response(conn, 200) =~ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
|
|
|
assert response_content_type(conn, :xml) =~ "charset=utf-8"
|
|
|
|
|
|
|
|
{:ok, feed} = ElixirFeedParser.parse(conn.resp_body)
|
|
|
|
|
2021-01-19 10:24:21 +00:00
|
|
|
assert feed.title ==
|
2021-10-21 15:55:16 +00:00
|
|
|
"#{actor1.name}'s private events feed on #{Config.instance_name()}"
|
2019-03-08 11:25:06 +00:00
|
|
|
|
|
|
|
[entry] = feed.entries
|
|
|
|
assert entry.title == event1.title
|
2023-04-20 09:30:10 +00:00
|
|
|
refute entry.title == event3.title
|
2019-03-08 11:25:06 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
test "it returns 404 for an not existing feed", %{conn: conn} do
|
|
|
|
conn =
|
|
|
|
conn
|
2023-12-01 08:49:54 +00:00
|
|
|
|> get(URI.decode(~p"/events/going/not_existing/atom"))
|
2019-03-08 11:25:06 +00:00
|
|
|
|
|
|
|
assert response(conn, 404)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "/events/going/:token/ics" do
|
|
|
|
test "it returns an ical feed of all events for all identities for an user token", %{
|
|
|
|
conn: conn
|
|
|
|
} do
|
|
|
|
user = insert(:user)
|
|
|
|
actor1 = insert(:actor, user: user)
|
|
|
|
actor2 = insert(:actor, user: user)
|
|
|
|
event1 = insert(:event)
|
|
|
|
event2 = insert(:event)
|
2023-04-20 09:30:10 +00:00
|
|
|
event3 = insert(:event, begins_on: DateTime.add(DateTime.utc_now(), -5, :day))
|
2019-03-08 11:25:06 +00:00
|
|
|
insert(:participant, event: event1, actor: actor1)
|
|
|
|
insert(:participant, event: event2, actor: actor2)
|
2023-04-20 09:30:10 +00:00
|
|
|
insert(:participant, event: event3, actor: actor1)
|
2019-03-08 11:25:06 +00:00
|
|
|
feed_token = insert(:feed_token, user: user, actor: nil)
|
|
|
|
|
|
|
|
conn =
|
|
|
|
conn
|
|
|
|
|> put_req_header("accept", "text/calendar")
|
2023-12-01 11:06:18 +00:00
|
|
|
|> get(URI.decode(~p"/events/going/#{ShortUUID.encode!(feed_token.token)}/ics"))
|
2019-03-08 11:25:06 +00:00
|
|
|
|
|
|
|
assert response(conn, 200) =~ "BEGIN:VCALENDAR"
|
|
|
|
assert response_content_type(conn, :calendar) =~ "charset=utf-8"
|
|
|
|
|
|
|
|
entries = ExIcal.parse(conn.resp_body)
|
|
|
|
|
|
|
|
Enum.each(entries, fn entry ->
|
|
|
|
assert entry.summary in [event1.title, event2.title]
|
2023-04-20 09:30:10 +00:00
|
|
|
refute entry.summary == event3.title
|
2019-03-08 11:25:06 +00:00
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "it returns an ical feed of all events a single identity for an actor token", %{
|
|
|
|
conn: conn
|
|
|
|
} do
|
|
|
|
user = insert(:user)
|
|
|
|
actor1 = insert(:actor, user: user)
|
|
|
|
actor2 = insert(:actor, user: user)
|
|
|
|
event1 = insert(:event)
|
|
|
|
event2 = insert(:event)
|
2023-04-20 09:30:10 +00:00
|
|
|
event3 = insert(:event, begins_on: DateTime.add(DateTime.utc_now(), -5, :day))
|
2019-03-08 11:25:06 +00:00
|
|
|
insert(:participant, event: event1, actor: actor1)
|
|
|
|
insert(:participant, event: event2, actor: actor2)
|
2023-04-20 09:30:10 +00:00
|
|
|
insert(:participant, event: event3, actor: actor1)
|
2019-03-08 11:25:06 +00:00
|
|
|
feed_token = insert(:feed_token, user: user, actor: actor1)
|
|
|
|
|
|
|
|
conn =
|
|
|
|
conn
|
|
|
|
|> put_req_header("accept", "text/calendar")
|
2023-12-01 11:06:18 +00:00
|
|
|
|> get(URI.decode(~p"/events/going/#{ShortUUID.encode!(feed_token.token)}/ics"))
|
2019-03-08 11:25:06 +00:00
|
|
|
|
|
|
|
assert response(conn, 200) =~ "BEGIN:VCALENDAR"
|
|
|
|
assert response_content_type(conn, :calendar) =~ "charset=utf-8"
|
|
|
|
|
|
|
|
[entry1] = ExIcal.parse(conn.resp_body)
|
|
|
|
assert entry1.summary == event1.title
|
2019-11-05 16:49:40 +00:00
|
|
|
assert entry1.categories == event1.tags |> Enum.map(& &1.title)
|
2023-04-20 09:30:10 +00:00
|
|
|
refute entry1.summary == event3.title
|
2019-03-08 11:25:06 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
test "it returns 404 for an not existing feed", %{conn: conn} do
|
|
|
|
conn =
|
|
|
|
conn
|
|
|
|
|> get(
|
2023-12-01 11:06:18 +00:00
|
|
|
~p"/events/going/not_existing/ics"
|
2019-03-08 11:25:06 +00:00
|
|
|
|> URI.decode()
|
|
|
|
)
|
|
|
|
|
|
|
|
assert response(conn, 404)
|
|
|
|
end
|
|
|
|
end
|
2019-02-27 15:28:09 +00:00
|
|
|
end
|