Merge branch 'develop' into issue-7887-featured-collection
This commit is contained in:
commit
33fdc59bc1
17 changed files with 418 additions and 65 deletions
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
|
||||
alias Pleroma.Integration.WebsocketClient
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
alias Pleroma.Web.OAuth
|
||||
|
||||
@moduletag needs_streamer: true, capture_log: true
|
||||
|
|
@ -31,6 +32,48 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
WebsocketClient.start_link(self(), path, headers)
|
||||
end
|
||||
|
||||
defp raw_websocket_handshake(qs, headers) do
|
||||
uri = URI.parse(@path <> qs)
|
||||
port = uri.port || 80
|
||||
path = uri.path <> if(uri.query, do: "?" <> uri.query, else: "")
|
||||
|
||||
default_headers = [
|
||||
{"host", "#{uri.host}:#{port}"},
|
||||
{"upgrade", "websocket"},
|
||||
{"connection", "Upgrade"},
|
||||
{"sec-websocket-key", Base.encode64(:crypto.strong_rand_bytes(16))},
|
||||
{"sec-websocket-version", "13"}
|
||||
]
|
||||
|
||||
request = [
|
||||
"GET #{path} HTTP/1.1\r\n",
|
||||
Enum.map(default_headers ++ headers, fn {name, value} -> "#{name}: #{value}\r\n" end),
|
||||
"\r\n"
|
||||
]
|
||||
|
||||
with {:ok, socket} <-
|
||||
:gen_tcp.connect(String.to_charlist(uri.host), port, [:binary, active: false], 1_000),
|
||||
:ok <- :gen_tcp.send(socket, request),
|
||||
{:ok, response} <- :gen_tcp.recv(socket, 0, 1_000) do
|
||||
:gen_tcp.close(socket)
|
||||
{:ok, parse_http_response(response)}
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_http_response(response) do
|
||||
[headers | _] = String.split(response, "\r\n\r\n", parts: 2)
|
||||
[status_line | header_lines] = String.split(headers, "\r\n")
|
||||
[_, status | _] = String.split(status_line, " ")
|
||||
|
||||
headers =
|
||||
Enum.map(header_lines, fn line ->
|
||||
[name, value] = String.split(line, ":", parts: 2)
|
||||
{String.downcase(name), String.trim(value)}
|
||||
end)
|
||||
|
||||
%{status: String.to_integer(status), headers: headers}
|
||||
end
|
||||
|
||||
defp decode_json(json) do
|
||||
with {:ok, %{"event" => event, "payload" => payload_text}} <- Jason.decode(json),
|
||||
{:ok, payload} <- Jason.decode(payload_text) do
|
||||
|
|
@ -85,9 +128,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
assert json["payload"]
|
||||
assert {:ok, json} = Jason.decode(json["payload"])
|
||||
|
||||
view_json =
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("show.json", activity: activity, for: nil)
|
||||
|> atom_key_to_string()
|
||||
view_json = atom_key_to_string(StatusView.render("show.json", activity: activity, for: nil))
|
||||
|
||||
assert json == view_json
|
||||
end
|
||||
|
|
@ -114,10 +155,7 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
assert json["payload"]
|
||||
assert {:ok, json} = Jason.decode(json["payload"])
|
||||
|
||||
view_json =
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("show.json", activity: activity, for: nil)
|
||||
|> Jason.encode!()
|
||||
|> Jason.decode!()
|
||||
view_json = atom_key_to_string(StatusView.render("show.json", activity: activity, for: nil))
|
||||
|
||||
assert json == view_json
|
||||
end
|
||||
|
|
@ -279,6 +317,34 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
end)
|
||||
end
|
||||
|
||||
test "echoes the Sec-WebSocket-Protocol token in the handshake", %{token: token} do
|
||||
assert {:ok, %{status: 101, headers: headers}} =
|
||||
raw_websocket_handshake("?stream=user", [
|
||||
{"sec-websocket-protocol", token.token}
|
||||
])
|
||||
|
||||
assert {"sec-websocket-protocol", token.token} in headers
|
||||
end
|
||||
|
||||
test "echoes the selected Sec-WebSocket-Protocol token", %{token: token} do
|
||||
assert {:ok, %{status: 101, headers: headers}} =
|
||||
raw_websocket_handshake("?stream=user", [
|
||||
{"sec-websocket-protocol", "#{token.token}, phoenix"}
|
||||
])
|
||||
|
||||
assert {"sec-websocket-protocol", token.token} in headers
|
||||
end
|
||||
|
||||
test "does not echo an invalid Sec-WebSocket-Protocol token", %{token: token} do
|
||||
assert {:ok, %{status: 401, headers: headers}} =
|
||||
raw_websocket_handshake("?stream=user", [
|
||||
{"sec-websocket-protocol", "invalid"}
|
||||
])
|
||||
|
||||
refute {"sec-websocket-protocol", token.token} in headers
|
||||
refute List.keymember?(headers, "sec-websocket-protocol", 0)
|
||||
end
|
||||
|
||||
test "prefers sec-websocket-protocol token over query access_token", %{
|
||||
token: token,
|
||||
user: user
|
||||
|
|
@ -450,12 +516,12 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
assert {:ok, json} = Jason.decode(json["payload"])
|
||||
|
||||
view_json =
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("show.json",
|
||||
activity: activity,
|
||||
for: reading_user
|
||||
atom_key_to_string(
|
||||
StatusView.render("show.json",
|
||||
activity: activity,
|
||||
for: reading_user
|
||||
)
|
||||
)
|
||||
|> Jason.encode!()
|
||||
|> Jason.decode!()
|
||||
|
||||
assert json == view_json
|
||||
end
|
||||
|
|
@ -478,12 +544,12 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
|||
activity = Pleroma.Activity.normalize(activity)
|
||||
|
||||
view_json =
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("show.json",
|
||||
activity: activity,
|
||||
for: reading_user
|
||||
atom_key_to_string(
|
||||
StatusView.render("show.json",
|
||||
activity: activity,
|
||||
for: reading_user
|
||||
)
|
||||
)
|
||||
|> Jason.encode!()
|
||||
|> Jason.decode!()
|
||||
|
||||
assert {:ok, %{"event" => "status.update", "payload" => ^view_json}} = decode_json(raw_json)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,12 +5,22 @@
|
|||
defmodule Pleroma.Web.RichMedia.BackfillTest do
|
||||
use Pleroma.DataCase
|
||||
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.RichMedia.Backfill
|
||||
alias Pleroma.Web.RichMedia.Card
|
||||
|
||||
import Mox
|
||||
import Pleroma.Factory
|
||||
|
||||
setup_all do: clear_config([:rich_media, :enabled], true)
|
||||
setup do
|
||||
clear_config([:rich_media, :enabled], true)
|
||||
|
||||
Mox.stub_with(Pleroma.UnstubbedConfigMock, Pleroma.Test.StaticConfig)
|
||||
Mox.stub_with(Pleroma.CachexMock, Pleroma.NullCache)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "sets a negative cache entry for an error" do
|
||||
url = "https://bad.example.com/"
|
||||
|
|
@ -23,4 +33,139 @@ defmodule Pleroma.Web.RichMedia.BackfillTest do
|
|||
|
||||
Backfill.run(%{"url" => url})
|
||||
end
|
||||
|
||||
test "sets a warm_cache entry" do
|
||||
url = "https://good.example.com/"
|
||||
url_hash = Card.url_to_hash(url)
|
||||
|
||||
Tesla.Mock.mock(fn %{url: ^url} ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: "<head><meta name=\"twitter:title\" content=\"Cofe\"></head>"
|
||||
}}
|
||||
end)
|
||||
|
||||
Pleroma.CachexMock
|
||||
|> expect(:put, fn :rich_media_cache,
|
||||
^url_hash,
|
||||
%Pleroma.Web.RichMedia.Card{url_hash: ^url_hash} ->
|
||||
{:ok, true}
|
||||
end)
|
||||
|
||||
Backfill.run(%{"url" => url})
|
||||
end
|
||||
|
||||
test "streams out update when stream == true" do
|
||||
url = "https://example.com"
|
||||
user = insert(:user)
|
||||
|
||||
Tesla.Mock.mock(fn %{url: ^url} ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: "<head><meta name=\"twitter:title\" content=\"Cofe\"></head>"
|
||||
}}
|
||||
end)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#cofe #{url}"})
|
||||
|
||||
Pleroma.CachexMock
|
||||
|> expect(:put, fn :rich_media_cache, _, _ -> {:ok, true} end)
|
||||
|
||||
Pleroma.Web.ActivityPub.ActivityPubMock
|
||||
|> expect(:stream_out, fn %Pleroma.Activity{id: id} ->
|
||||
assert id == activity.id
|
||||
:ok
|
||||
end)
|
||||
|
||||
Backfill.run(%{"url" => url, "activity_id" => activity.id, "stream" => true})
|
||||
end
|
||||
|
||||
test "does not stream out update when stream == false" do
|
||||
url = "https://example.com"
|
||||
user = insert(:user)
|
||||
|
||||
Tesla.Mock.mock(fn %{url: ^url} ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: "<head><meta name=\"twitter:title\" content=\"Cofe\"></head>"
|
||||
}}
|
||||
end)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#cofe #{url}"})
|
||||
|
||||
Pleroma.CachexMock
|
||||
|> expect(:put, fn :rich_media_cache, _, _ -> {:ok, true} end)
|
||||
|
||||
Pleroma.Web.ActivityPub.ActivityPubMock
|
||||
|> deny(:stream_out, 1)
|
||||
|
||||
Backfill.run(%{"url" => url, "activity_id" => "#{activity.data["id"]}", "stream" => false})
|
||||
end
|
||||
|
||||
# NOTE: Below two MastoAPI tests cover almost the same code paths.
|
||||
# index.json will always prefetch rich media, while show.json will try to get the card and
|
||||
# fetch it when it isn't cached (both use Card.get_by_activity in the end).
|
||||
# So if index.json doesn't fetch the rich media, show.json will when it renders the post,
|
||||
# hence why index.json test will only call ActivityPub.stream_out twice,
|
||||
# if streaming is re-enabled for in both.
|
||||
test "does not stream out in MastoAPI StatusView index" do
|
||||
url = "https://example.com"
|
||||
user = insert(:user)
|
||||
|
||||
Tesla.Mock.mock(fn %{url: ^url} ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: "<head><meta name=\"twitter:title\" content=\"Cofe\"></head>"
|
||||
}}
|
||||
end)
|
||||
|
||||
# CommonAPI federation processing will stream out once as a new post
|
||||
Pleroma.Web.ActivityPub.ActivityPubMock
|
||||
|> expect(:stream_out, 1, fn _ -> :ok end)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#cofe #{url}"})
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
# Clear cache to force backfill below
|
||||
Pleroma.Activity.HTML.invalidate_cache_for(activity.id)
|
||||
Pleroma.Web.RichMedia.Card.delete(url)
|
||||
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
|
||||
activities: [activity],
|
||||
as: :activity
|
||||
})
|
||||
|
||||
ObanHelpers.perform_all()
|
||||
end
|
||||
|
||||
test "does not stream out in MastoAPI StatusView show" do
|
||||
url = "https://example.com"
|
||||
user = insert(:user)
|
||||
|
||||
Tesla.Mock.mock(fn %{url: ^url} ->
|
||||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: "<head><meta name=\"twitter:title\" content=\"Cofe\"></head>"
|
||||
}}
|
||||
end)
|
||||
|
||||
# CommonAPI federation processing will stream out once as a new post
|
||||
Pleroma.Web.ActivityPub.ActivityPubMock
|
||||
|> expect(:stream_out, 1, fn _ -> :ok end)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "#cofe #{url}"})
|
||||
ObanHelpers.perform_all()
|
||||
|
||||
# Clear cache to force backfill below
|
||||
Pleroma.Activity.HTML.invalidate_cache_for(activity.id)
|
||||
Pleroma.Web.RichMedia.Card.delete(url)
|
||||
|
||||
Pleroma.Web.MastodonAPI.StatusView.render("show.json", activity: activity)
|
||||
ObanHelpers.perform_all()
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue