forked from AkkomaGang/akkoma
Merge branch 'tests/web/mastodon_api/search_controller' into 'develop'
add test for search_controller/ 100% coverage See merge request pleroma/pleroma!1377
This commit is contained in:
commit
42422f3ff2
3 changed files with 176 additions and 102 deletions
|
@ -4,29 +4,27 @@
|
||||||
|
|
||||||
defmodule Pleroma.Web.MastodonAPI.SearchController do
|
defmodule Pleroma.Web.MastodonAPI.SearchController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.Plugs.RateLimiter
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web
|
alias Pleroma.Web
|
||||||
|
alias Pleroma.Web.ControllerHelper
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
|
|
||||||
alias Pleroma.Web.ControllerHelper
|
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
plug(RateLimiter, :search when action in [:search, :search2, :account_search])
|
||||||
plug(Pleroma.Plugs.RateLimiter, :search when action in [:search, :search2, :account_search])
|
|
||||||
|
|
||||||
def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
||||||
accounts = with_fallback(fn -> User.search(query, search_options(params, user)) end, [])
|
accounts = with_fallback(fn -> User.search(query, search_options(params, user)) end, [])
|
||||||
statuses = with_fallback(fn -> Activity.search(user, query) end, [])
|
statuses = with_fallback(fn -> Activity.search(user, query) end, [])
|
||||||
|
|
||||||
tags_path = Web.base_url() <> "/tag/"
|
tags_path = Web.base_url() <> "/tag/"
|
||||||
|
|
||||||
tags =
|
tags =
|
||||||
query
|
query
|
||||||
|> String.split()
|
|> prepare_tags
|
||||||
|> Enum.uniq()
|
|
||||||
|> Enum.filter(fn tag -> String.starts_with?(tag, "#") end)
|
|
||||||
|> Enum.map(fn tag -> String.slice(tag, 1..-1) end)
|
|
||||||
|> Enum.map(fn tag -> %{name: tag, url: tags_path <> tag} end)
|
|> Enum.map(fn tag -> %{name: tag, url: tags_path <> tag} end)
|
||||||
|
|
||||||
res = %{
|
res = %{
|
||||||
|
@ -40,15 +38,10 @@ def search2(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
||||||
accounts = with_fallback(fn -> User.search(query, search_options(params, user)) end, [])
|
accounts = with_fallback(fn -> User.search(query, search_options(params, user)) end)
|
||||||
statuses = with_fallback(fn -> Activity.search(user, query) end, [])
|
statuses = with_fallback(fn -> Activity.search(user, query) end)
|
||||||
|
|
||||||
tags =
|
tags = prepare_tags(query)
|
||||||
query
|
|
||||||
|> String.split()
|
|
||||||
|> Enum.uniq()
|
|
||||||
|> Enum.filter(fn tag -> String.starts_with?(tag, "#") end)
|
|
||||||
|> Enum.map(fn tag -> String.slice(tag, 1..-1) end)
|
|
||||||
|
|
||||||
res = %{
|
res = %{
|
||||||
"accounts" => AccountView.render("accounts.json", users: accounts, for: user, as: :user),
|
"accounts" => AccountView.render("accounts.json", users: accounts, for: user, as: :user),
|
||||||
|
@ -67,6 +60,14 @@ def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) d
|
||||||
json(conn, res)
|
json(conn, res)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp prepare_tags(query) do
|
||||||
|
query
|
||||||
|
|> String.split()
|
||||||
|
|> Enum.uniq()
|
||||||
|
|> Enum.filter(fn tag -> String.starts_with?(tag, "#") end)
|
||||||
|
|> Enum.map(fn tag -> String.slice(tag, 1..-1) end)
|
||||||
|
end
|
||||||
|
|
||||||
defp search_options(params, user) do
|
defp search_options(params, user) do
|
||||||
[
|
[
|
||||||
resolve: params["resolve"] == "true",
|
resolve: params["resolve"] == "true",
|
||||||
|
@ -77,7 +78,7 @@ defp search_options(params, user) do
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
defp with_fallback(f, fallback) do
|
defp with_fallback(f, fallback \\ []) do
|
||||||
try do
|
try do
|
||||||
f.()
|
f.()
|
||||||
rescue
|
rescue
|
||||||
|
|
|
@ -19,6 +19,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
||||||
import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1]
|
import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1]
|
||||||
|
|
||||||
# TODO: Add cached version.
|
# TODO: Add cached version.
|
||||||
|
defp get_replied_to_activities([]), do: %{}
|
||||||
|
|
||||||
defp get_replied_to_activities(activities) do
|
defp get_replied_to_activities(activities) do
|
||||||
activities
|
activities
|
||||||
|> Enum.map(fn
|
|> Enum.map(fn
|
||||||
|
|
|
@ -6,123 +6,194 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
|
||||||
use Pleroma.Web.ConnCase
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Web
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
import ExUnit.CaptureLog
|
import ExUnit.CaptureLog
|
||||||
import Tesla.Mock
|
import Tesla.Mock
|
||||||
|
import Mock
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
test "account search", %{conn: conn} do
|
describe ".search2" do
|
||||||
user = insert(:user)
|
test "it returns empty result if user or status search return undefined error", %{conn: conn} do
|
||||||
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
|
with_mocks [
|
||||||
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
{Pleroma.User, [], [search: fn _q, _o -> raise "Oops" end]},
|
||||||
|
{Pleroma.Activity, [], [search: fn _u, _q -> raise "Oops" end]}
|
||||||
|
] do
|
||||||
|
conn = get(conn, "/api/v2/search", %{"q" => "2hu"})
|
||||||
|
|
||||||
results =
|
assert results = json_response(conn, 200)
|
||||||
conn
|
|
||||||
|> assign(:user, user)
|
|
||||||
|> get("/api/v1/accounts/search", %{"q" => "shp"})
|
|
||||||
|> json_response(200)
|
|
||||||
|
|
||||||
result_ids = for result <- results, do: result["acct"]
|
assert results["accounts"] == []
|
||||||
|
assert results["statuses"] == []
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
assert user_two.nickname in result_ids
|
test "search", %{conn: conn} do
|
||||||
assert user_three.nickname in result_ids
|
user = insert(:user)
|
||||||
|
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
|
||||||
|
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
||||||
|
|
||||||
results =
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu private"})
|
||||||
conn
|
|
||||||
|> assign(:user, user)
|
|
||||||
|> get("/api/v1/accounts/search", %{"q" => "2hu"})
|
|
||||||
|> json_response(200)
|
|
||||||
|
|
||||||
result_ids = for result <- results, do: result["acct"]
|
{:ok, _activity} =
|
||||||
|
CommonAPI.post(user, %{
|
||||||
|
"status" => "This is about 2hu, but private",
|
||||||
|
"visibility" => "private"
|
||||||
|
})
|
||||||
|
|
||||||
assert user_three.nickname in result_ids
|
{:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
|
||||||
end
|
|
||||||
|
|
||||||
test "search", %{conn: conn} do
|
conn = get(conn, "/api/v2/search", %{"q" => "2hu #private"})
|
||||||
user = insert(:user)
|
|
||||||
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
|
|
||||||
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
|
|
||||||
|
|
||||||
{:ok, _activity} =
|
|
||||||
CommonAPI.post(user, %{
|
|
||||||
"status" => "This is about 2hu, but private",
|
|
||||||
"visibility" => "private"
|
|
||||||
})
|
|
||||||
|
|
||||||
{:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
|
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
|
||||||
|> get("/api/v1/search", %{"q" => "2hu"})
|
|
||||||
|
|
||||||
assert results = json_response(conn, 200)
|
|
||||||
|
|
||||||
[account | _] = results["accounts"]
|
|
||||||
assert account["id"] == to_string(user_three.id)
|
|
||||||
|
|
||||||
assert results["hashtags"] == []
|
|
||||||
|
|
||||||
[status] = results["statuses"]
|
|
||||||
assert status["id"] == to_string(activity.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "search fetches remote statuses", %{conn: conn} do
|
|
||||||
capture_log(fn ->
|
|
||||||
conn =
|
|
||||||
conn
|
|
||||||
|> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
|
|
||||||
|
|
||||||
assert results = json_response(conn, 200)
|
assert results = json_response(conn, 200)
|
||||||
|
# IO.inspect results
|
||||||
|
|
||||||
|
[account | _] = results["accounts"]
|
||||||
|
assert account["id"] == to_string(user_three.id)
|
||||||
|
|
||||||
|
assert results["hashtags"] == [
|
||||||
|
%{"name" => "private", "url" => "#{Web.base_url()}/tag/private"}
|
||||||
|
]
|
||||||
|
|
||||||
[status] = results["statuses"]
|
[status] = results["statuses"]
|
||||||
assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
|
assert status["id"] == to_string(activity.id)
|
||||||
end)
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "search doesn't show statuses that it shouldn't", %{conn: conn} do
|
describe ".account_search" do
|
||||||
{:ok, activity} =
|
test "account search", %{conn: conn} do
|
||||||
CommonAPI.post(insert(:user), %{
|
user = insert(:user)
|
||||||
"status" => "This is about 2hu, but private",
|
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
|
||||||
"visibility" => "private"
|
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
||||||
})
|
|
||||||
|
results =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/accounts/search", %{"q" => "shp"})
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
result_ids = for result <- results, do: result["acct"]
|
||||||
|
|
||||||
|
assert user_two.nickname in result_ids
|
||||||
|
assert user_three.nickname in result_ids
|
||||||
|
|
||||||
|
results =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/accounts/search", %{"q" => "2hu"})
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
result_ids = for result <- results, do: result["acct"]
|
||||||
|
|
||||||
|
assert user_three.nickname in result_ids
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".search" do
|
||||||
|
test "it returns empty result if user or status search return undefined error", %{conn: conn} do
|
||||||
|
with_mocks [
|
||||||
|
{Pleroma.User, [], [search: fn _q, _o -> raise "Oops" end]},
|
||||||
|
{Pleroma.Activity, [], [search: fn _u, _q -> raise "Oops" end]}
|
||||||
|
] do
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/search", %{"q" => "2hu"})
|
||||||
|
|
||||||
|
assert results = json_response(conn, 200)
|
||||||
|
|
||||||
|
assert results["accounts"] == []
|
||||||
|
assert results["statuses"] == []
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "search", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
|
||||||
|
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
|
||||||
|
|
||||||
|
{:ok, _activity} =
|
||||||
|
CommonAPI.post(user, %{
|
||||||
|
"status" => "This is about 2hu, but private",
|
||||||
|
"visibility" => "private"
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
|
||||||
|
|
||||||
capture_log(fn ->
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => Object.normalize(activity).data["id"]})
|
|> get("/api/v1/search", %{"q" => "2hu"})
|
||||||
|
|
||||||
assert results = json_response(conn, 200)
|
assert results = json_response(conn, 200)
|
||||||
|
|
||||||
[] = results["statuses"]
|
[account | _] = results["accounts"]
|
||||||
end)
|
assert account["id"] == to_string(user_three.id)
|
||||||
end
|
|
||||||
|
|
||||||
test "search fetches remote accounts", %{conn: conn} do
|
assert results["hashtags"] == []
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
conn =
|
[status] = results["statuses"]
|
||||||
conn
|
assert status["id"] == to_string(activity.id)
|
||||||
|> assign(:user, user)
|
end
|
||||||
|> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
|
|
||||||
|
|
||||||
assert results = json_response(conn, 200)
|
test "search fetches remote statuses", %{conn: conn} do
|
||||||
[account] = results["accounts"]
|
capture_log(fn ->
|
||||||
assert account["acct"] == "shp@social.heldscal.la"
|
conn =
|
||||||
end
|
conn
|
||||||
|
|> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
|
||||||
|
|
||||||
test "search doesn't fetch remote accounts if resolve is false", %{conn: conn} do
|
assert results = json_response(conn, 200)
|
||||||
conn =
|
|
||||||
conn
|
|
||||||
|> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "false"})
|
|
||||||
|
|
||||||
assert results = json_response(conn, 200)
|
[status] = results["statuses"]
|
||||||
assert [] == results["accounts"]
|
|
||||||
|
assert status["uri"] ==
|
||||||
|
"tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "search doesn't show statuses that it shouldn't", %{conn: conn} do
|
||||||
|
{:ok, activity} =
|
||||||
|
CommonAPI.post(insert(:user), %{
|
||||||
|
"status" => "This is about 2hu, but private",
|
||||||
|
"visibility" => "private"
|
||||||
|
})
|
||||||
|
|
||||||
|
capture_log(fn ->
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/search", %{"q" => Object.normalize(activity).data["id"]})
|
||||||
|
|
||||||
|
assert results = json_response(conn, 200)
|
||||||
|
|
||||||
|
[] = results["statuses"]
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "search fetches remote accounts", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"})
|
||||||
|
|
||||||
|
assert results = json_response(conn, 200)
|
||||||
|
[account] = results["accounts"]
|
||||||
|
assert account["acct"] == "shp@social.heldscal.la"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "search doesn't fetch remote accounts if resolve is false", %{conn: conn} do
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "false"})
|
||||||
|
|
||||||
|
assert results = json_response(conn, 200)
|
||||||
|
assert [] == results["accounts"]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue