forked from YokaiRick/akkoma
Merge branch 'openapi/search' into 'develop'
Add OpenAPI spec for SearchController See merge request pleroma/pleroma!2484
This commit is contained in:
commit
516ff945ce
6 changed files with 293 additions and 60 deletions
|
@ -556,11 +556,12 @@ defp update_creadentials_request do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp array_of_accounts do
|
def array_of_accounts do
|
||||||
%Schema{
|
%Schema{
|
||||||
title: "ArrayOfAccounts",
|
title: "ArrayOfAccounts",
|
||||||
type: :array,
|
type: :array,
|
||||||
items: Account
|
items: Account,
|
||||||
|
example: [Account.schema().example]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
207
lib/pleroma/web/api_spec/operations/search_operation.ex
Normal file
207
lib/pleroma/web/api_spec/operations/search_operation.ex
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ApiSpec.SearchOperation do
|
||||||
|
alias OpenApiSpex.Operation
|
||||||
|
alias OpenApiSpex.Schema
|
||||||
|
alias Pleroma.Web.ApiSpec.AccountOperation
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.Account
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.Status
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.Tag
|
||||||
|
|
||||||
|
import Pleroma.Web.ApiSpec.Helpers
|
||||||
|
|
||||||
|
def open_api_operation(action) do
|
||||||
|
operation = String.to_existing_atom("#{action}_operation")
|
||||||
|
apply(__MODULE__, operation, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_search_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Search"],
|
||||||
|
summary: "Search for matching accounts by username or display name",
|
||||||
|
operationId: "SearchController.account_search",
|
||||||
|
parameters: [
|
||||||
|
Operation.parameter(:q, :query, %Schema{type: :string}, "What to search for",
|
||||||
|
required: true
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:limit,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :integer, default: 40},
|
||||||
|
"Maximum number of results"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:resolve,
|
||||||
|
:query,
|
||||||
|
%Schema{allOf: [BooleanLike], default: false},
|
||||||
|
"Attempt WebFinger lookup. Use this when `q` is an exact address."
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:following,
|
||||||
|
:query,
|
||||||
|
%Schema{allOf: [BooleanLike], default: false},
|
||||||
|
"Only include accounts that the user is following"
|
||||||
|
)
|
||||||
|
],
|
||||||
|
responses: %{
|
||||||
|
200 =>
|
||||||
|
Operation.response(
|
||||||
|
"Array of Account",
|
||||||
|
"application/json",
|
||||||
|
AccountOperation.array_of_accounts()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def search_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Search"],
|
||||||
|
summary: "Search results",
|
||||||
|
security: [%{"oAuth" => ["read:search"]}],
|
||||||
|
operationId: "SearchController.search",
|
||||||
|
deprecated: true,
|
||||||
|
parameters: [
|
||||||
|
Operation.parameter(
|
||||||
|
:account_id,
|
||||||
|
:query,
|
||||||
|
FlakeID,
|
||||||
|
"If provided, statuses returned will be authored only by this account"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:type,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :string, enum: ["accounts", "hashtags", "statuses"]},
|
||||||
|
"Search type"
|
||||||
|
),
|
||||||
|
Operation.parameter(:q, :query, %Schema{type: :string}, "The search query", required: true),
|
||||||
|
Operation.parameter(
|
||||||
|
:resolve,
|
||||||
|
:query,
|
||||||
|
%Schema{allOf: [BooleanLike], default: false},
|
||||||
|
"Attempt WebFinger lookup"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:following,
|
||||||
|
:query,
|
||||||
|
%Schema{allOf: [BooleanLike], default: false},
|
||||||
|
"Only include accounts that the user is following"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:offset,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :integer},
|
||||||
|
"Offset"
|
||||||
|
)
|
||||||
|
| pagination_params()
|
||||||
|
],
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Results", "application/json", results())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def search2_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Search"],
|
||||||
|
summary: "Search results",
|
||||||
|
security: [%{"oAuth" => ["read:search"]}],
|
||||||
|
operationId: "SearchController.search2",
|
||||||
|
parameters: [
|
||||||
|
Operation.parameter(
|
||||||
|
:account_id,
|
||||||
|
:query,
|
||||||
|
FlakeID,
|
||||||
|
"If provided, statuses returned will be authored only by this account"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:type,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :string, enum: ["accounts", "hashtags", "statuses"]},
|
||||||
|
"Search type"
|
||||||
|
),
|
||||||
|
Operation.parameter(:q, :query, %Schema{type: :string}, "What to search for",
|
||||||
|
required: true
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:resolve,
|
||||||
|
:query,
|
||||||
|
%Schema{allOf: [BooleanLike], default: false},
|
||||||
|
"Attempt WebFinger lookup"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:following,
|
||||||
|
:query,
|
||||||
|
%Schema{allOf: [BooleanLike], default: false},
|
||||||
|
"Only include accounts that the user is following"
|
||||||
|
)
|
||||||
|
| pagination_params()
|
||||||
|
],
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Results", "application/json", results2())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp results2 do
|
||||||
|
%Schema{
|
||||||
|
title: "SearchResults",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
accounts: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: Account,
|
||||||
|
description: "Accounts which match the given query"
|
||||||
|
},
|
||||||
|
statuses: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: Status,
|
||||||
|
description: "Statuses which match the given query"
|
||||||
|
},
|
||||||
|
hashtags: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: Tag,
|
||||||
|
description: "Hashtags which match the given query"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
example: %{
|
||||||
|
"accounts" => [Account.schema().example],
|
||||||
|
"statuses" => [Status.schema().example],
|
||||||
|
"hashtags" => [Tag.schema().example]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp results do
|
||||||
|
%Schema{
|
||||||
|
title: "SearchResults",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
accounts: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: Account,
|
||||||
|
description: "Accounts which match the given query"
|
||||||
|
},
|
||||||
|
statuses: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: Status,
|
||||||
|
description: "Statuses which match the given query"
|
||||||
|
},
|
||||||
|
hashtags: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{type: :string},
|
||||||
|
description: "Hashtags which match the given query"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
example: %{
|
||||||
|
"accounts" => [Account.schema().example],
|
||||||
|
"statuses" => [Status.schema().example],
|
||||||
|
"hashtags" => ["cofe"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.Emoji
|
alias Pleroma.Web.ApiSpec.Schemas.Emoji
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
|
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.Poll
|
alias Pleroma.Web.ApiSpec.Schemas.Poll
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.Tag
|
||||||
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
|
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
|
||||||
|
|
||||||
require OpenApiSpex
|
require OpenApiSpex
|
||||||
|
@ -106,16 +107,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
||||||
replies_count: %Schema{type: :integer},
|
replies_count: %Schema{type: :integer},
|
||||||
sensitive: %Schema{type: :boolean},
|
sensitive: %Schema{type: :boolean},
|
||||||
spoiler_text: %Schema{type: :string},
|
spoiler_text: %Schema{type: :string},
|
||||||
tags: %Schema{
|
tags: %Schema{type: :array, items: Tag},
|
||||||
type: :array,
|
|
||||||
items: %Schema{
|
|
||||||
type: :object,
|
|
||||||
properties: %{
|
|
||||||
name: %Schema{type: :string},
|
|
||||||
url: %Schema{type: :string, format: :uri}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uri: %Schema{type: :string, format: :uri},
|
uri: %Schema{type: :string, format: :uri},
|
||||||
url: %Schema{type: :string, nullable: true, format: :uri},
|
url: %Schema{type: :string, nullable: true, format: :uri},
|
||||||
visibility: VisibilityScope
|
visibility: VisibilityScope
|
||||||
|
|
27
lib/pleroma/web/api_spec/schemas/tag.ex
Normal file
27
lib/pleroma/web/api_spec/schemas/tag.ex
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ApiSpec.Schemas.Tag do
|
||||||
|
alias OpenApiSpex.Schema
|
||||||
|
|
||||||
|
require OpenApiSpex
|
||||||
|
|
||||||
|
OpenApiSpex.schema(%{
|
||||||
|
title: "Tag",
|
||||||
|
description: "Represents a hashtag used within the content of a status",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
name: %Schema{type: :string, description: "The value of the hashtag after the # sign"},
|
||||||
|
url: %Schema{
|
||||||
|
type: :string,
|
||||||
|
format: :uri,
|
||||||
|
description: "A link to the hashtag on the instance"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
example: %{
|
||||||
|
name: "cofe",
|
||||||
|
url: "https://lain.com/tag/cofe"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
|
@ -5,7 +5,7 @@
|
||||||
defmodule Pleroma.Web.MastodonAPI.SearchController do
|
defmodule Pleroma.Web.MastodonAPI.SearchController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
import Pleroma.Web.ControllerHelper, only: [fetch_integer_param: 2, skip_relationships?: 1]
|
import Pleroma.Web.ControllerHelper, only: [skip_relationships?: 1]
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Plugs.OAuthScopesPlug
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
|
@ -18,6 +18,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||||
|
|
||||||
# Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search)
|
# Note: Mastodon doesn't allow unauthenticated access (requires read:accounts / read:search)
|
||||||
plug(OAuthScopesPlug, %{scopes: ["read:search"], fallback: :proceed_unauthenticated})
|
plug(OAuthScopesPlug, %{scopes: ["read:search"], fallback: :proceed_unauthenticated})
|
||||||
|
|
||||||
|
@ -25,7 +27,9 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
|
||||||
|
|
||||||
plug(RateLimiter, [name: :search] when action in [:search, :search2, :account_search])
|
plug(RateLimiter, [name: :search] when action in [:search, :search2, :account_search])
|
||||||
|
|
||||||
def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.SearchOperation
|
||||||
|
|
||||||
|
def account_search(%{assigns: %{user: user}} = conn, %{q: query} = params) do
|
||||||
accounts = User.search(query, search_options(params, user))
|
accounts = User.search(query, search_options(params, user))
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|
@ -36,7 +40,7 @@ def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) d
|
||||||
def search2(conn, params), do: do_search(:v2, conn, params)
|
def search2(conn, params), do: do_search(:v2, conn, params)
|
||||||
def search(conn, params), do: do_search(:v1, conn, params)
|
def search(conn, params), do: do_search(:v1, conn, params)
|
||||||
|
|
||||||
defp do_search(version, %{assigns: %{user: user}} = conn, %{"q" => query} = params) do
|
defp do_search(version, %{assigns: %{user: user}} = conn, %{q: query} = params) do
|
||||||
options = search_options(params, user)
|
options = search_options(params, user)
|
||||||
timeout = Keyword.get(Repo.config(), :timeout, 15_000)
|
timeout = Keyword.get(Repo.config(), :timeout, 15_000)
|
||||||
default_values = %{"statuses" => [], "accounts" => [], "hashtags" => []}
|
default_values = %{"statuses" => [], "accounts" => [], "hashtags" => []}
|
||||||
|
@ -44,7 +48,7 @@ defp do_search(version, %{assigns: %{user: user}} = conn, %{"q" => query} = para
|
||||||
result =
|
result =
|
||||||
default_values
|
default_values
|
||||||
|> Enum.map(fn {resource, default_value} ->
|
|> Enum.map(fn {resource, default_value} ->
|
||||||
if params["type"] in [nil, resource] do
|
if params[:type] in [nil, resource] do
|
||||||
{resource, fn -> resource_search(version, resource, query, options) end}
|
{resource, fn -> resource_search(version, resource, query, options) end}
|
||||||
else
|
else
|
||||||
{resource, fn -> default_value end}
|
{resource, fn -> default_value end}
|
||||||
|
@ -68,11 +72,11 @@ defp do_search(version, %{assigns: %{user: user}} = conn, %{"q" => query} = para
|
||||||
defp search_options(params, user) do
|
defp search_options(params, user) do
|
||||||
[
|
[
|
||||||
skip_relationships: skip_relationships?(params),
|
skip_relationships: skip_relationships?(params),
|
||||||
resolve: params["resolve"] == "true",
|
resolve: params[:resolve],
|
||||||
following: params["following"] == "true",
|
following: params[:following],
|
||||||
limit: fetch_integer_param(params, "limit"),
|
limit: params[:limit],
|
||||||
offset: fetch_integer_param(params, "offset"),
|
offset: params[:offset],
|
||||||
type: params["type"],
|
type: params[:type],
|
||||||
author: get_author(params),
|
author: get_author(params),
|
||||||
for_user: user
|
for_user: user
|
||||||
]
|
]
|
||||||
|
@ -135,7 +139,7 @@ defp with_fallback(f, fallback \\ []) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_author(%{"account_id" => account_id}) when is_binary(account_id),
|
defp get_author(%{account_id: account_id}) when is_binary(account_id),
|
||||||
do: User.get_cached_by_id(account_id)
|
do: User.get_cached_by_id(account_id)
|
||||||
|
|
||||||
defp get_author(_params), do: nil
|
defp get_author(_params), do: nil
|
||||||
|
|
|
@ -27,8 +27,8 @@ test "it returns empty result if user or status search return undefined error",
|
||||||
capture_log(fn ->
|
capture_log(fn ->
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v2/search", %{"q" => "2hu"})
|
|> get("/api/v2/search?q=2hu")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert results["accounts"] == []
|
assert results["accounts"] == []
|
||||||
assert results["statuses"] == []
|
assert results["statuses"] == []
|
||||||
|
@ -54,8 +54,8 @@ test "search", %{conn: conn} do
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v2/search", %{"q" => "2hu #private"})
|
|> get("/api/v2/search?#{URI.encode_query(%{q: "2hu #private"})}")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
[account | _] = results["accounts"]
|
[account | _] = results["accounts"]
|
||||||
assert account["id"] == to_string(user_three.id)
|
assert account["id"] == to_string(user_three.id)
|
||||||
|
@ -68,8 +68,8 @@ test "search", %{conn: conn} do
|
||||||
assert status["id"] == to_string(activity.id)
|
assert status["id"] == to_string(activity.id)
|
||||||
|
|
||||||
results =
|
results =
|
||||||
get(conn, "/api/v2/search", %{"q" => "天子"})
|
get(conn, "/api/v2/search?q=天子")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
[status] = results["statuses"]
|
[status] = results["statuses"]
|
||||||
assert status["id"] == to_string(activity.id)
|
assert status["id"] == to_string(activity.id)
|
||||||
|
@ -89,8 +89,8 @@ test "excludes a blocked users from search results", %{conn: conn} do
|
||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
|
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
|
||||||
|> get("/api/v2/search", %{"q" => "Agent"})
|
|> get("/api/v2/search?q=Agent")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
status_ids = Enum.map(results["statuses"], fn g -> g["id"] end)
|
status_ids = Enum.map(results["statuses"], fn g -> g["id"] end)
|
||||||
|
|
||||||
|
@ -107,8 +107,8 @@ test "account search", %{conn: conn} do
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/accounts/search", %{"q" => "shp"})
|
|> get("/api/v1/accounts/search?q=shp")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
result_ids = for result <- results, do: result["acct"]
|
result_ids = for result <- results, do: result["acct"]
|
||||||
|
|
||||||
|
@ -117,8 +117,8 @@ test "account search", %{conn: conn} do
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/accounts/search", %{"q" => "2hu"})
|
|> get("/api/v1/accounts/search?q=2hu")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
result_ids = for result <- results, do: result["acct"]
|
result_ids = for result <- results, do: result["acct"]
|
||||||
|
|
||||||
|
@ -130,8 +130,8 @@ test "returns account if query contains a space", %{conn: conn} do
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/accounts/search", %{"q" => "shp@shitposter.club xxx "})
|
|> get("/api/v1/accounts/search?q=shp@shitposter.club xxx")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert length(results) == 1
|
assert length(results) == 1
|
||||||
end
|
end
|
||||||
|
@ -146,8 +146,8 @@ test "it returns empty result if user or status search return undefined error",
|
||||||
capture_log(fn ->
|
capture_log(fn ->
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => "2hu"})
|
|> get("/api/v1/search?q=2hu")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert results["accounts"] == []
|
assert results["accounts"] == []
|
||||||
assert results["statuses"] == []
|
assert results["statuses"] == []
|
||||||
|
@ -173,8 +173,8 @@ test "search", %{conn: conn} do
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => "2hu"})
|
|> get("/api/v1/search?q=2hu")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
[account | _] = results["accounts"]
|
[account | _] = results["accounts"]
|
||||||
assert account["id"] == to_string(user_three.id)
|
assert account["id"] == to_string(user_three.id)
|
||||||
|
@ -194,8 +194,8 @@ test "search fetches remote statuses and prefers them over other results", %{con
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"})
|
|> get("/api/v1/search?q=https://shitposter.club/notice/2827873")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
[status, %{"id" => ^activity_id}] = results["statuses"]
|
[status, %{"id" => ^activity_id}] = results["statuses"]
|
||||||
|
|
||||||
|
@ -212,10 +212,12 @@ test "search doesn't show statuses that it shouldn't", %{conn: conn} do
|
||||||
})
|
})
|
||||||
|
|
||||||
capture_log(fn ->
|
capture_log(fn ->
|
||||||
|
q = Object.normalize(activity).data["id"]
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => Object.normalize(activity).data["id"]})
|
|> get("/api/v1/search?q=#{q}")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
[] = results["statuses"]
|
[] = results["statuses"]
|
||||||
end)
|
end)
|
||||||
|
@ -228,8 +230,8 @@ test "search fetches remote accounts", %{conn: conn} do
|
||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
|
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
|
||||||
|> get("/api/v1/search", %{"q" => "mike@osada.macgirvin.com", "resolve" => "true"})
|
|> get("/api/v1/search?q=mike@osada.macgirvin.com&resolve=true")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
[account] = results["accounts"]
|
[account] = results["accounts"]
|
||||||
assert account["acct"] == "mike@osada.macgirvin.com"
|
assert account["acct"] == "mike@osada.macgirvin.com"
|
||||||
|
@ -238,8 +240,8 @@ test "search fetches remote accounts", %{conn: conn} do
|
||||||
test "search doesn't fetch remote accounts if resolve is false", %{conn: conn} do
|
test "search doesn't fetch remote accounts if resolve is false", %{conn: conn} do
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => "mike@osada.macgirvin.com", "resolve" => "false"})
|
|> get("/api/v1/search?q=mike@osada.macgirvin.com&resolve=false")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert [] == results["accounts"]
|
assert [] == results["accounts"]
|
||||||
end
|
end
|
||||||
|
@ -254,16 +256,16 @@ test "search with limit and offset", %{conn: conn} do
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => "2hu", "limit" => 1})
|
|> get("/api/v1/search?q=2hu&limit=1")
|
||||||
|
|
||||||
assert results = json_response(result, 200)
|
assert results = json_response_and_validate_schema(result, 200)
|
||||||
assert [%{"id" => activity_id1}] = results["statuses"]
|
assert [%{"id" => activity_id1}] = results["statuses"]
|
||||||
assert [_] = results["accounts"]
|
assert [_] = results["accounts"]
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => "2hu", "limit" => 1, "offset" => 1})
|
|> get("/api/v1/search?q=2hu&limit=1&offset=1")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert [%{"id" => activity_id2}] = results["statuses"]
|
assert [%{"id" => activity_id2}] = results["statuses"]
|
||||||
assert [] = results["accounts"]
|
assert [] = results["accounts"]
|
||||||
|
@ -279,13 +281,13 @@ test "search returns results only for the given type", %{conn: conn} do
|
||||||
|
|
||||||
assert %{"statuses" => [_activity], "accounts" => [], "hashtags" => []} =
|
assert %{"statuses" => [_activity], "accounts" => [], "hashtags" => []} =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => "2hu", "type" => "statuses"})
|
|> get("/api/v1/search?q=2hu&type=statuses")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert %{"statuses" => [], "accounts" => [_user_two], "hashtags" => []} =
|
assert %{"statuses" => [], "accounts" => [_user_two], "hashtags" => []} =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => "2hu", "type" => "accounts"})
|
|> get("/api/v1/search?q=2hu&type=accounts")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "search uses account_id to filter statuses by the author", %{conn: conn} do
|
test "search uses account_id to filter statuses by the author", %{conn: conn} do
|
||||||
|
@ -297,8 +299,8 @@ test "search uses account_id to filter statuses by the author", %{conn: conn} do
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => "2hu", "account_id" => user.id})
|
|> get("/api/v1/search?q=2hu&account_id=#{user.id}")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert [%{"id" => activity_id1}] = results["statuses"]
|
assert [%{"id" => activity_id1}] = results["statuses"]
|
||||||
assert activity_id1 == activity1.id
|
assert activity_id1 == activity1.id
|
||||||
|
@ -306,8 +308,8 @@ test "search uses account_id to filter statuses by the author", %{conn: conn} do
|
||||||
|
|
||||||
results =
|
results =
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/search", %{"q" => "2hu", "account_id" => user_two.id})
|
|> get("/api/v1/search?q=2hu&account_id=#{user_two.id}")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert [%{"id" => activity_id2}] = results["statuses"]
|
assert [%{"id" => activity_id2}] = results["statuses"]
|
||||||
assert activity_id2 == activity2.id
|
assert activity_id2 == activity2.id
|
||||||
|
|
Loading…
Reference in a new issue