<%= for scope <- @available_scopes do %>
- <%# Note: using hidden input with `unchecked_value` in order to distinguish user's empty selection from `scope` param being omitted %>
+ <% # Note: using hidden input with `unchecked_value` in order to distinguish user's empty selection from `scope` param being omitted %>
<%= if scope in @scopes do %>
<%= checkbox @form, :"scope_#{scope}", value: scope in @scopes && scope, checked_value: scope, unchecked_value: "", name: "authorization[scope][]" %>
diff --git a/lib/pleroma/web/web_finger/web_finger_controller.ex b/lib/pleroma/web/web_finger/web_finger_controller.ex
index 021df9bc5..8a291e28e 100644
--- a/lib/pleroma/web/web_finger/web_finger_controller.ex
+++ b/lib/pleroma/web/web_finger/web_finger_controller.ex
@@ -41,5 +41,10 @@ defmodule Pleroma.Web.WebFinger.WebFingerController do
end
end
+ # Default to JSON when no format is specified or format is not recognized
+ def webfinger(%{assigns: %{format: _format}} = conn, %{"resource" => _resource} = params) do
+ webfinger(put_in(conn.assigns.format, "json"), params)
+ end
+
def webfinger(conn, _params), do: send_resp(conn, 400, "Bad Request")
end
diff --git a/lib/pleroma/workers/mute_expire_worker.ex b/lib/pleroma/workers/mute_expire_worker.ex
index 8356a775d..9a04fc486 100644
--- a/lib/pleroma/workers/mute_expire_worker.ex
+++ b/lib/pleroma/workers/mute_expire_worker.ex
@@ -5,9 +5,13 @@
defmodule Pleroma.Workers.MuteExpireWorker do
use Oban.Worker, queue: :background
+ alias Pleroma.User
+
@impl true
- def perform(%Job{args: %{"op" => "unmute_user", "muter_id" => muter_id, "mutee_id" => mutee_id}}) do
- Pleroma.User.unmute(muter_id, mutee_id)
+ def perform(%Job{
+ args: %{"op" => "unmute_user", "muter_id" => muter_id, "mutee_id" => mutee_id}
+ }) do
+ User.unmute(muter_id, mutee_id)
:ok
end
@@ -18,6 +22,17 @@ defmodule Pleroma.Workers.MuteExpireWorker do
:ok
end
+ def perform(%Job{
+ args: %{"op" => "unblock_user", "blocker_id" => blocker_id, "blocked_id" => blocked_id}
+ }) do
+ Pleroma.Web.CommonAPI.unblock(
+ User.get_cached_by_id(blocked_id),
+ User.get_cached_by_id(blocker_id)
+ )
+
+ :ok
+ end
+
@impl true
def timeout(_job), do: :timer.seconds(5)
end
diff --git a/mix.exs b/mix.exs
index 808a2b12c..971084f94 100644
--- a/mix.exs
+++ b/mix.exs
@@ -37,22 +37,13 @@ defmodule Pleroma.Mixfile do
pleroma: [
include_executables_for: [:unix],
applications: [ex_syslogger: :load, syslog: :load, eldap: :transient],
- steps: [:assemble, &put_otp_version/1, ©_files/1, ©_nginx_config/1],
+ steps: [:assemble, ©_files/1, ©_nginx_config/1],
config_providers: [{Pleroma.Config.ReleaseRuntimeProvider, []}]
]
]
]
end
- def put_otp_version(%{path: target_path} = release) do
- File.write!(
- Path.join([target_path, "OTP_VERSION"]),
- Pleroma.OTPVersion.version()
- )
-
- release
- end
-
def copy_files(%{path: target_path} = release) do
File.cp_r!("./rel/files", target_path)
release
@@ -213,7 +204,7 @@ defmodule Pleroma.Mixfile do
{:poison, "~> 3.0", only: :test},
{:ex_doc, "~> 0.22", only: :dev, runtime: false},
{:ex_machina, "~> 2.4", only: :test},
- {:credo, "~> 1.6", only: [:dev, :test], runtime: false},
+ {:credo, "~> 1.7", only: [:dev, :test], runtime: false},
{:mock, "~> 0.3.5", only: :test},
{:covertool, "~> 2.0", only: :test},
{:hackney, "~> 1.18.0", override: true},
@@ -236,7 +227,7 @@ defmodule Pleroma.Mixfile do
"ecto.rollback": ["pleroma.ecto.rollback"],
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
"ecto.reset": ["ecto.drop", "ecto.setup"],
- test: ["ecto.create --quiet", "ecto.migrate", "test"],
+ test: ["ecto.create --quiet", "ecto.migrate", "test --warnings-as-errors"],
docs: ["pleroma.docs", "docs"],
analyze: ["credo --strict --only=warnings,todo,fixme,consistency,readability"],
copyright: &add_copyright/1,
diff --git a/mix.lock b/mix.lock
index 9b53ede62..f7f37b7e1 100644
--- a/mix.lock
+++ b/mix.lock
@@ -23,7 +23,7 @@
"cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
"cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"},
- "credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"},
+ "credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"},
"crontab": {:hex, :crontab, "1.1.8", "2ce0e74777dfcadb28a1debbea707e58b879e6aa0ffbf9c9bb540887bce43617", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
"custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"},
"db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
diff --git a/priv/repo/migrations/20240904142434_assign_app_user.exs b/priv/repo/migrations/20240904142434_assign_app_user.exs
index 11bec529b..74740220d 100644
--- a/priv/repo/migrations/20240904142434_assign_app_user.exs
+++ b/priv/repo/migrations/20240904142434_assign_app_user.exs
@@ -1,20 +1,24 @@
defmodule Pleroma.Repo.Migrations.AssignAppUser do
use Ecto.Migration
+ import Ecto.Query
+
alias Pleroma.Repo
alias Pleroma.Web.OAuth.App
alias Pleroma.Web.OAuth.Token
def up do
- Repo.all(Token)
- |> Enum.group_by(fn x -> Map.get(x, :app_id) end)
- |> Enum.each(fn {_app_id, tokens} ->
- token =
- Enum.filter(tokens, fn x -> not is_nil(x.user_id) end)
- |> List.first()
-
+ Token
+ |> where([t], not is_nil(t.user_id))
+ |> group_by([t], t.app_id)
+ |> select([t], %{app_id: t.app_id, id: min(t.id)})
+ |> order_by(asc: :app_id)
+ |> Repo.stream()
+ |> Stream.each(fn %{id: id} ->
+ token = Token.Query.get_by_id(id) |> Repo.one()
App.maybe_update_owner(token)
end)
+ |> Stream.run()
end
def down, do: :ok
diff --git a/priv/repo/migrations/20250314153704_add_activities_actor_type_index.exs b/priv/repo/migrations/20250314153704_add_activities_actor_type_index.exs
new file mode 100644
index 000000000..a0fac28a8
--- /dev/null
+++ b/priv/repo/migrations/20250314153704_add_activities_actor_type_index.exs
@@ -0,0 +1,14 @@
+defmodule Pleroma.Repo.Migrations.AddActivitiesActorTypeIndex do
+ use Ecto.Migration
+ @disable_ddl_transaction true
+
+ def change do
+ create(
+ index(
+ :activities,
+ ["actor", "(data ->> 'type'::text)", "id DESC NULLS LAST"],
+ concurrently: true
+ )
+ )
+ end
+end
diff --git a/test/fixtures/friendica-dislike-undo.json b/test/fixtures/friendica-dislike-undo.json
new file mode 100644
index 000000000..b258e00be
--- /dev/null
+++ b/test/fixtures/friendica-dislike-undo.json
@@ -0,0 +1,76 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {
+ "Hashtag": "as:Hashtag",
+ "PropertyValue": "schema:PropertyValue",
+ "conversation": "ostatus:conversation",
+ "dfrn": "http://purl.org/macgirvin/dfrn/1.0/",
+ "diaspora": "https://diasporafoundation.org/ns/",
+ "directMessage": "litepub:directMessage",
+ "discoverable": "toot:discoverable",
+ "featured": {
+ "@id": "toot:featured",
+ "@type": "@id"
+ },
+ "litepub": "http://litepub.social/ns#",
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "ostatus": "http://ostatus.org#",
+ "quoteUrl": "as:quoteUrl",
+ "schema": "http://schema.org#",
+ "sensitive": "as:sensitive",
+ "toot": "http://joinmastodon.org/ns#",
+ "value": "schema:value",
+ "vcard": "http://www.w3.org/2006/vcard/ns#"
+ }
+ ],
+ "actor": "https://my-place.social/profile/vaartis",
+ "cc": [
+ "https://my-place.social/followers/vaartis"
+ ],
+ "id": "https://my-place.social/objects/e599373b-1368-4b20-cd24-837166957182/Undo",
+ "instrument": {
+ "id": "https://my-place.social/friendica",
+ "name": "Friendica 'Interrupted Fern' 2024.12-1576",
+ "type": "Application",
+ "url": "https://my-place.social"
+ },
+ "object": {
+ "actor": "https://my-place.social/profile/vaartis",
+ "cc": [
+ "https://my-place.social/followers/vaartis"
+ ],
+ "diaspora:guid": "e599373b-1968-4b20-cd24-80d340160302",
+ "diaspora:like": "{\"author\":\"vaartis@my-place.social\",\"guid\":\"e599373b-1968-4b20-cd24-80d340160302\",\"parent_guid\":\"cd36feba-c31f3ed3fd5c064a-17c31593\",\"parent_type\":\"Post\",\"positive\":\"false\",\"author_signature\":\"xR2zLJNfc9Nhx1n8LLMWM1kde12my4cqamIsrH\\/UntKzuDwO4DuHBL0fkFhgC\\/dylxm4HqsHD45MQbtwQCVGq6WhC96TrbMuYEK61HIO23dTr3m+qJVtfdH4wyhUNHgiiYPhZpkLDfnR1JiRWmFTlmZC8q8JEkOB5IQsrWia2eOR6IsqDcdKO\\/Urgns9\\/BdQi8KnchBKSEFc1iUtcOEruvhunKGyW5zI\\/Rltfdz3xGH8tlw+YlMXeWXPnqgOJ9GzNA0lwG4U421L6yylYagW7oxIznnBLB4bO46vYZbgXZV1hiI9ZyveHOinLMY1QkmTj5CNvnx3\\/VJwLovd0v+0Nr2vu\\/3ftbpBXc6L1bsNjlRqtsfwJlcgl+tH1DC4W8tKf+Y3tdtzVw0CHXCuacxHLyq5wZd\\/5YfYR9SJQ\\/jInU4PHA5+hIE3PGqNUp5QfFE0umq56H7MQKsIPgM5mMV4fPAA8OpltuMVDvQYUxalrnvoTf00k90x1wCTK71\\/jQGh7r7PmGvSdfPr+65eVTjITD8\\/lTGIb8850v1fl3\\/i2R8Dv17jQIRyX5o9MXPSO6jHo4Swma5RzPA\\/0bRj6qRTyPkM1L9qEIr+2H2I7KKhT2ZE5GhAU7yI9A3VLBWzpTrUPMGbfpd1OjVTEqXAdMjpLDYI3Mh5zQ58p8xCzt+W+t0=\"}",
+ "id": "https://my-place.social/objects/e599373b-1368-4b20-cd24-837166957182",
+ "instrument": {
+ "id": "https://my-place.social/friendica",
+ "name": "Friendica 'Interrupted Fern' 2024.12-1576",
+ "type": "Application",
+ "url": "https://my-place.social"
+ },
+ "object": "https://pl.kotobank.ch/objects/301bce65-8a1b-4c49-a65c-fe2ce861a213",
+ "published": "2025-06-12T18:47:41Z",
+ "to": [
+ "https://pl.kotobank.ch/users/vaartis",
+ "https://mitra.social/users/silverpill",
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "type": "Dislike"
+ },
+ "published": "2025-06-12T18:41:25Z",
+ "signature": {
+ "created": "2025-06-12T18:44:16Z",
+ "creator": "https://my-place.social/profile/vaartis#main-key",
+ "nonce": "2d67847d4bd4b1b83a30d61eac6cdc7ad6b980df06a8b9b97217e1d8f7b6cf20",
+ "signatureValue": "LnoRMZuQGDvTICkShGBq28ynaj2lF1bViJFGS6n4gKn3IbxPWATHxao43gxWRc+HCTrHNg7quzgaW4+PYM7UVUz3jO+bjNKsN845nijOVdyFrPOXbuaij3KQh2OoHhFJWoV/ZQQTFF0kRK1qT4BwG+P8NqOOKAMv+Cw7ruQH+f2w7uDgcNIbCD1gLcwb6cw7WVe5qu8yMkKqp2kBdqW3RCsI85RmmFgwehDgH5nrX7ER1qbeLWrqy7echwD9/fO3rqAu13xDNyiGZHDT7JB3RUt0AyMm0XCfjbwSQ0n+MkYXgE4asvFz81+iiPCLt+6gePWAFc5odF1FxdySBpSuUOs4p92NzP9OhQ0c0qrqrzYI7aYklY7oMfxjkva+X+0bm3up+2IRJdnZa/pXlmwdcqTpyMr1sgzaexMUNBp3dq7zA51eEaakLDX3i2onXJowfmze3+6XgPAFHYamR+pRNtuEoY4uyYEK3fj5GgwJ4RtFJMYVoEs/Q8h3OgYRcK1FE9UlDjSqbQ7QIRn2Ib4wjgmkeM0vrHIwh/1CtqA/M/6WuYFzCaJBc8O9ykpK9ZMbw64ToQXKf2SqhZsDoyTWRWTO1PXOk1XCAAElUh8/WCyeghvgqLXn0LHov4lmBsHA5iMUcLqBKD3GJIHd+ExrOFxMZs4mBLLGyz0p5joJ3NY=",
+ "type": "RsaSignature2017"
+ },
+ "to": [
+ "https://pl.kotobank.ch/users/vaartis",
+ "https://mitra.social/users/silverpill",
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "type": "Undo"
+}
diff --git a/test/fixtures/friendica-dislike.json b/test/fixtures/friendica-dislike.json
new file mode 100644
index 000000000..c75939073
--- /dev/null
+++ b/test/fixtures/friendica-dislike.json
@@ -0,0 +1,56 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {
+ "Hashtag": "as:Hashtag",
+ "PropertyValue": "schema:PropertyValue",
+ "conversation": "ostatus:conversation",
+ "dfrn": "http://purl.org/macgirvin/dfrn/1.0/",
+ "diaspora": "https://diasporafoundation.org/ns/",
+ "directMessage": "litepub:directMessage",
+ "discoverable": "toot:discoverable",
+ "featured": {
+ "@id": "toot:featured",
+ "@type": "@id"
+ },
+ "litepub": "http://litepub.social/ns#",
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "ostatus": "http://ostatus.org#",
+ "quoteUrl": "as:quoteUrl",
+ "schema": "http://schema.org#",
+ "sensitive": "as:sensitive",
+ "toot": "http://joinmastodon.org/ns#",
+ "value": "schema:value",
+ "vcard": "http://www.w3.org/2006/vcard/ns#"
+ }
+ ],
+ "actor": "https://my-place.social/profile/vaartis",
+ "cc": [
+ "https://my-place.social/followers/vaartis"
+ ],
+ "diaspora:guid": "e599373b-1968-4b20-cd24-80d340160302",
+ "diaspora:like": "{\"author\":\"vaartis@my-place.social\",\"guid\":\"e599373b-1968-4b20-cd24-80d340160302\",\"parent_guid\":\"cd36feba-c31f3ed3fd5c064a-17c31593\",\"parent_type\":\"Post\",\"positive\":\"false\",\"author_signature\":\"xR2zLJNfc9Nhx1n8LLMWM1kde12my4cqamIsrH\\/UntKzuDwO4DuHBL0fkFhgC\\/dylxm4HqsHD45MQbtwQCVGq6WhC96TrbMuYEK61HIO23dTr3m+qJVtfdH4wyhUNHgiiYPhZpkLDfnR1JiRWmFTlmZC8q8JEkOB5IQsrWia2eOR6IsqDcdKO\\/Urgns9\\/BdQi8KnchBKSEFc1iUtcOEruvhunKGyW5zI\\/Rltfdz3xGH8tlw+YlMXeWXPnqgOJ9GzNA0lwG4U421L6yylYagW7oxIznnBLB4bO46vYZbgXZV1hiI9ZyveHOinLMY1QkmTj5CNvnx3\\/VJwLovd0v+0Nr2vu\\/3ftbpBXc6L1bsNjlRqtsfwJlcgl+tH1DC4W8tKf+Y3tdtzVw0CHXCuacxHLyq5wZd\\/5YfYR9SJQ\\/jInU4PHA5+hIE3PGqNUp5QfFE0umq56H7MQKsIPgM5mMV4fPAA8OpltuMVDvQYUxalrnvoTf00k90x1wCTK71\\/jQGh7r7PmGvSdfPr+65eVTjITD8\\/lTGIb8850v1fl3\\/i2R8Dv17jQIRyX5o9MXPSO6jHo4Swma5RzPA\\/0bRj6qRTyPkM1L9qEIr+2H2I7KKhT2ZE5GhAU7yI9A3VLBWzpTrUPMGbfpd1OjVTEqXAdMjpLDYI3Mh5zQ58p8xCzt+W+t0=\"}",
+ "id": "https://my-place.social/objects/e599373b-1368-4b20-cd24-837166957182",
+ "instrument": {
+ "id": "https://my-place.social/friendica",
+ "name": "Friendica 'Interrupted Fern' 2024.12-1576",
+ "type": "Application",
+ "url": "https://my-place.social"
+ },
+ "object": "https://pl.kotobank.ch/objects/301bce65-8a1b-4c49-a65c-fe2ce861a213",
+ "published": "2025-06-12T18:47:41Z",
+ "signature": {
+ "created": "2025-06-12T18:47:42Z",
+ "creator": "https://my-place.social/profile/vaartis#main-key",
+ "nonce": "84e496f80b09d7a299c5cc89e8cadd13abf621b3a0a321684fa74278b68a6dd8",
+ "signatureValue": "qe2WxY+j7daIYLRadCctgal6A1s9XgoiMfM/8KjJm15w0sSizYYqruyQ5gS44e+cj5GHc9v5gP2ieod5v7eHAPzlcDI4bfkcyHVapAXTqU67ZebW+v6Q+21IMDgqrkYCv5TbV7LTxltW59dlqovpHE4TEe/M7xLKWJ3vVchRUcWqH9kDmak0nacoqYVAb5E9jYnQhUWPTCfPV82qQpeWQPOZ4iIvPw6rDkSSY5jL6bCogBZblHGpUjXfe/FPlacaCWiTQdoga3yOBXB1RYPw9nh5FI5Xkv/oi+52WmJrECinlD6AL8/BpiYvKz236zy7p/TR4BXlCx9RR/msjOnSabkQ4kmYFrRr80UDCGF+CdkdzLl8K9rSE3PbF1+nEqD7X0GOWn/DdtixqXJw6IR4bh32YW2SlcrSRBvI1p82Mv68BeqRaYqL6FAhKFwLhX5JpXngZ3k0g7rWWxc498voPWnFZDyCTRNxO9VIIUavDDEQ0BdFk6WDb8zx9tsAg8JoK57eVDcFly7tfVQffYiHpve06d8ag1DtzipqguRsURmuqpGNMq28XBTxwtrP2LnXXHKxoYN/YQ9cDnCKclbx7/uKmOVMLkLZlM0wAVoZpm5z2fG4voKqFiGZ1PoiFY2sN4URMArJtygV3PlTX4ASAQrak0ksvEo9msrBUD0Su9c=",
+ "type": "RsaSignature2017"
+ },
+ "to": [
+ "https://pl.kotobank.ch/users/vaartis",
+ "https://mitra.social/users/silverpill",
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "type": "Dislike"
+}
diff --git a/test/fixtures/misskey-custom-emoji-like.json b/test/fixtures/misskey-custom-emoji-like.json
new file mode 100644
index 000000000..51a825d42
--- /dev/null
+++ b/test/fixtures/misskey-custom-emoji-like.json
@@ -0,0 +1,54 @@
+ {
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {
+ "Emoji": "toot:Emoji",
+ "Hashtag": "as:Hashtag",
+ "PropertyValue": "schema:PropertyValue",
+ "_misskey_content": "misskey:_misskey_content",
+ "_misskey_quote": "misskey:_misskey_quote",
+ "_misskey_reaction": "misskey:_misskey_reaction",
+ "_misskey_summary": "misskey:_misskey_summary",
+ "_misskey_votes": "misskey:_misskey_votes",
+ "backgroundUrl": "sharkey:backgroundUrl",
+ "discoverable": "toot:discoverable",
+ "featured": "toot:featured",
+ "fedibird": "http://fedibird.com/ns#",
+ "firefish": "https://joinfirefish.org/ns#",
+ "isCat": "misskey:isCat",
+ "listenbrainz": "sharkey:listenbrainz",
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "misskey": "https://misskey-hub.net/ns#",
+ "quoteUri": "fedibird:quoteUri",
+ "quoteUrl": "as:quoteUrl",
+ "schema": "http://schema.org#",
+ "sensitive": "as:sensitive",
+ "sharkey": "https://joinsharkey.org/ns#",
+ "speakAsCat": "firefish:speakAsCat",
+ "toot": "http://joinmastodon.org/ns#",
+ "value": "schema:value",
+ "vcard": "http://www.w3.org/2006/vcard/ns#"
+ }
+ ],
+ "_misskey_reaction": ":blobwtfnotlikethis:",
+ "actor": "https://mai.waifuism.life/users/9otxaeemjqy70001",
+ "content": ":blobwtfnotlikethis:",
+ "id": "https://mai.waifuism.life/likes/9q2xifhrdnb0001b",
+ "object": "https://bungle.online/notes/9q2xi2sy4k",
+ "tag": [
+ {
+ "icon": {
+ "mediaType": "image/png",
+ "type": "Image",
+ "url": "https://mai.waifuism.life/files/1b0510f2-1fb4-43f5-a399-10053bbd8f0f"
+ },
+ "id": "https://mai.waifuism.life/emojis/blobwtfnotlikethis",
+ "name": ":blobwtfnotlikethis:",
+ "type": "Emoji",
+ "updated": "2024-02-07T02:21:46.497Z"
+ }
+ ],
+ "type": "Like"
+}
+
diff --git a/test/fixtures/mitra-custom-emoji-like.json b/test/fixtures/mitra-custom-emoji-like.json
new file mode 100644
index 000000000..4d727febd
--- /dev/null
+++ b/test/fixtures/mitra-custom-emoji-like.json
@@ -0,0 +1,46 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ "https://w3id.org/security/data-integrity/v1",
+ {
+ "Emoji": "toot:Emoji",
+ "Hashtag": "as:Hashtag",
+ "sensitive": "as:sensitive",
+ "toot": "http://joinmastodon.org/ns#"
+ }
+ ],
+ "actor": "https://mitra.social/users/silverpill",
+ "cc": [],
+ "content": ":ablobcatheartsqueeze:",
+ "id": "https://mitra.social/activities/like/0195a89a-a3a0-ead4-3a1c-aa6311397cfd",
+ "object": "https://framapiaf.org/users/peertube/statuses/114182703352270287",
+ "proof": {
+ "created": "2025-03-18T09:34:21.610678375Z",
+ "cryptosuite": "eddsa-jcs-2022",
+ "proofPurpose": "assertionMethod",
+ "proofValue": "z5AvpwkXQGFpTneRVDNeF48Jo9qYG6PgrE5HaPPpQNdNyc31ULMN4Vxd4aFXELo4Rk5Y9hd9nDy254xP8v5uGGWp1",
+ "type": "DataIntegrityProof",
+ "verificationMethod": "https://mitra.social/users/silverpill#ed25519-key"
+ },
+ "tag": [
+ {
+ "attributedTo": "https://mitra.social/actor",
+ "icon": {
+ "mediaType": "image/png",
+ "type": "Image",
+ "url": "https://mitra.social/media/a08e153441b25e512ab1b2e8922f5d8cd928322c8b79958cd48297ac722a4117.png"
+ },
+ "id": "https://mitra.social/objects/emojis/ablobcatheartsqueeze",
+ "name": ":ablobcatheartsqueeze:",
+ "type": "Emoji",
+ "updated": "1970-01-01T00:00:00Z"
+ }
+ ],
+ "to": [
+ "https://framapiaf.org/users/peertube",
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "type": "Like"
+}
+
diff --git a/test/fixtures/rich_media/instagram_longtext.html b/test/fixtures/rich_media/instagram_longtext.html
new file mode 100644
index 000000000..e833f408c
--- /dev/null
+++ b/test/fixtures/rich_media/instagram_longtext.html
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
CAPTURE THE ATLAS | ✨ A Once-in-a-Lifetime Shot: Total Lunar Eclipse + Aurora Substorm! 🔴💚
+
+Last Thursday night, under the freezing skies of Northern Alaska, I... | Instagram
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/fixtures/tesla_mock/deepl-languages-list.json b/test/fixtures/tesla_mock/deepl-languages-list.json
new file mode 100644
index 000000000..03d47d2ec
--- /dev/null
+++ b/test/fixtures/tesla_mock/deepl-languages-list.json
@@ -0,0 +1 @@
+[{"language":"BG","name":"Bulgarian","supports_formality":false},{"language":"CS","name":"Czech","supports_formality":false},{"language":"DA","name":"Danish","supports_formality":false},{"language":"DE","name":"German","supports_formality":true},{"language":"EL","name":"Greek","supports_formality":false},{"language":"EN-GB","name":"English (British)","supports_formality":false},{"language":"EN-US","name":"English (American)","supports_formality":false},{"language":"ES","name":"Spanish","supports_formality":true},{"language":"ET","name":"Estonian","supports_formality":false},{"language":"FI","name":"Finnish","supports_formality":false},{"language":"FR","name":"French","supports_formality":true},{"language":"HU","name":"Hungarian","supports_formality":false},{"language":"ID","name":"Indonesian","supports_formality":false},{"language":"IT","name":"Italian","supports_formality":true},{"language":"JA","name":"Japanese","supports_formality":false},{"language":"LT","name":"Lithuanian","supports_formality":false},{"language":"LV","name":"Latvian","supports_formality":false},{"language":"NL","name":"Dutch","supports_formality":true},{"language":"PL","name":"Polish","supports_formality":true},{"language":"PT-BR","name":"Portuguese (Brazilian)","supports_formality":true},{"language":"PT-PT","name":"Portuguese (European)","supports_formality":true},{"language":"RO","name":"Romanian","supports_formality":false},{"language":"RU","name":"Russian","supports_formality":true},{"language":"SK","name":"Slovak","supports_formality":false},{"language":"SL","name":"Slovenian","supports_formality":false},{"language":"SV","name":"Swedish","supports_formality":false},{"language":"TR","name":"Turkish","supports_formality":false},{"language":"UK","name":"Ukrainian","supports_formality":false},{"language":"ZH","name":"Chinese (simplified)","supports_formality":false}]
\ No newline at end of file
diff --git a/test/fixtures/tesla_mock/deepl-translation.json b/test/fixtures/tesla_mock/deepl-translation.json
new file mode 100644
index 000000000..fef7bb215
--- /dev/null
+++ b/test/fixtures/tesla_mock/deepl-translation.json
@@ -0,0 +1 @@
+{"translations":[{"detected_source_language":"PL","text":"REMOVE THE FOLLOWER!Paste this on your follower. If we get 70% of nk users...they will remove the follower!!!"}]}
\ No newline at end of file
diff --git a/test/fixtures/warnings/otp_version/21.1 b/test/fixtures/warnings/otp_version/21.1
deleted file mode 100644
index 90cd64c4f..000000000
--- a/test/fixtures/warnings/otp_version/21.1
+++ /dev/null
@@ -1 +0,0 @@
-21.1
\ No newline at end of file
diff --git a/test/fixtures/warnings/otp_version/22.1 b/test/fixtures/warnings/otp_version/22.1
deleted file mode 100644
index d9b314368..000000000
--- a/test/fixtures/warnings/otp_version/22.1
+++ /dev/null
@@ -1 +0,0 @@
-22.1
\ No newline at end of file
diff --git a/test/fixtures/warnings/otp_version/22.4 b/test/fixtures/warnings/otp_version/22.4
deleted file mode 100644
index 1da8ccd28..000000000
--- a/test/fixtures/warnings/otp_version/22.4
+++ /dev/null
@@ -1 +0,0 @@
-22.4
\ No newline at end of file
diff --git a/test/fixtures/warnings/otp_version/23.0 b/test/fixtures/warnings/otp_version/23.0
deleted file mode 100644
index 4266d8634..000000000
--- a/test/fixtures/warnings/otp_version/23.0
+++ /dev/null
@@ -1 +0,0 @@
-23.0
\ No newline at end of file
diff --git a/test/mix/tasks/pleroma/frontend_test.exs b/test/mix/tasks/pleroma/frontend_test.exs
index 6d09f8e36..59ebcec92 100644
--- a/test/mix/tasks/pleroma/frontend_test.exs
+++ b/test/mix/tasks/pleroma/frontend_test.exs
@@ -11,7 +11,7 @@ defmodule Mix.Tasks.Pleroma.FrontendTest do
@dir "test/frontend_static_test"
setup do
- File.mkdir_p!(@dir)
+ Pleroma.Backports.mkdir_p!(@dir)
clear_config([:instance, :static_dir], @dir)
on_exit(fn ->
@@ -50,7 +50,7 @@ defmodule Mix.Tasks.Pleroma.FrontendTest do
folder = Path.join([@dir, "frontends", "pleroma", "fantasy"])
previously_existing = Path.join([folder, "temp"])
- File.mkdir_p!(folder)
+ Pleroma.Backports.mkdir_p!(folder)
File.write!(previously_existing, "yey")
assert File.exists?(previously_existing)
diff --git a/test/mix/tasks/pleroma/instance_test.exs b/test/mix/tasks/pleroma/instance_test.exs
index b1c10e03c..5ecb6e445 100644
--- a/test/mix/tasks/pleroma/instance_test.exs
+++ b/test/mix/tasks/pleroma/instance_test.exs
@@ -7,7 +7,7 @@ defmodule Mix.Tasks.Pleroma.InstanceTest do
use Pleroma.DataCase
setup do
- File.mkdir_p!(tmp_path())
+ Pleroma.Backports.mkdir_p!(tmp_path())
on_exit(fn ->
File.rm_rf(tmp_path())
diff --git a/test/mix/tasks/pleroma/uploads_test.exs b/test/mix/tasks/pleroma/uploads_test.exs
index f3d5aa64f..0aa24807e 100644
--- a/test/mix/tasks/pleroma/uploads_test.exs
+++ b/test/mix/tasks/pleroma/uploads_test.exs
@@ -62,7 +62,7 @@ defmodule Mix.Tasks.Pleroma.UploadsTest do
upload_dir = Config.get([Pleroma.Uploaders.Local, :uploads])
if not File.exists?(upload_dir) || File.ls!(upload_dir) == [] do
- File.mkdir_p(upload_dir)
+ Pleroma.Backports.mkdir_p(upload_dir)
Path.join([upload_dir, "file.txt"])
|> File.touch()
diff --git a/test/pleroma/emoji/pack_test.exs b/test/pleroma/emoji/pack_test.exs
index 6ab3e657e..b458401a7 100644
--- a/test/pleroma/emoji/pack_test.exs
+++ b/test/pleroma/emoji/pack_test.exs
@@ -58,7 +58,7 @@ defmodule Pleroma.Emoji.PackTest do
test "skips existing emojis when adding from zip file", %{pack: pack} do
# First, let's create a test pack with a "bear" emoji
test_pack_path = Path.join(@emoji_path, "test_bear_pack")
- File.mkdir_p(test_pack_path)
+ Pleroma.Backports.mkdir_p(test_pack_path)
# Create a pack.json file
File.write!(Path.join(test_pack_path, "pack.json"), """
diff --git a/test/pleroma/frontend_test.exs b/test/pleroma/frontend_test.exs
index c89c56c8c..22e0ffb9a 100644
--- a/test/pleroma/frontend_test.exs
+++ b/test/pleroma/frontend_test.exs
@@ -9,7 +9,7 @@ defmodule Pleroma.FrontendTest do
@dir "test/frontend_static_test"
setup do
- File.mkdir_p!(@dir)
+ Pleroma.Backports.mkdir_p!(@dir)
clear_config([:instance, :static_dir], @dir)
on_exit(fn ->
@@ -46,7 +46,7 @@ defmodule Pleroma.FrontendTest do
folder = Path.join([@dir, "frontends", "pleroma", "fantasy"])
previously_existing = Path.join([folder, "temp"])
- File.mkdir_p!(folder)
+ Pleroma.Backports.mkdir_p!(folder)
File.write!(previously_existing, "yey")
assert File.exists?(previously_existing)
diff --git a/test/pleroma/language/language_detector_test.exs b/test/pleroma/language/language_detector_test.exs
new file mode 100644
index 000000000..ccb81d5bd
--- /dev/null
+++ b/test/pleroma/language/language_detector_test.exs
@@ -0,0 +1,56 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Language.LanguageDetectorTest do
+ use Pleroma.DataCase, async: true
+
+ alias Pleroma.Language.LanguageDetector
+ alias Pleroma.Language.LanguageDetectorMock
+ alias Pleroma.StaticStubbedConfigMock
+
+ import Mox
+
+ setup do
+ # Stub the StaticStubbedConfigMock to return our mock for the provider
+ StaticStubbedConfigMock
+ |> stub(:get, fn
+ [Pleroma.Language.LanguageDetector, :provider] -> LanguageDetectorMock
+ _other -> nil
+ end)
+
+ # Stub the LanguageDetectorMock with default implementations
+ LanguageDetectorMock
+ |> stub(:missing_dependencies, fn -> [] end)
+ |> stub(:configured?, fn -> true end)
+
+ :ok
+ end
+
+ test "it detects text language" do
+ LanguageDetectorMock
+ |> expect(:detect, fn _text -> "fr" end)
+
+ detected_language = LanguageDetector.detect("Je viens d'atterrir en Tchéquie.")
+
+ assert detected_language == "fr"
+ end
+
+ test "it returns nil if text is not long enough" do
+ # No need to set expectations as the word count check happens before the provider is called
+
+ detected_language = LanguageDetector.detect("it returns nil")
+
+ assert detected_language == nil
+ end
+
+ test "it returns nil if no provider specified" do
+ # Override the stub to return nil for the provider
+ StaticStubbedConfigMock
+ |> expect(:get, fn [Pleroma.Language.LanguageDetector, :provider] -> nil end)
+
+ detected_language = LanguageDetector.detect("this should also return nil")
+
+ assert detected_language == nil
+ end
+end
diff --git a/test/pleroma/language/translation/deepl_test.exs b/test/pleroma/language/translation/deepl_test.exs
new file mode 100644
index 000000000..3a7265622
--- /dev/null
+++ b/test/pleroma/language/translation/deepl_test.exs
@@ -0,0 +1,37 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Language.Translation.DeeplTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Language.Translation.Deepl
+
+ test "it translates text" do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ clear_config([Pleroma.Language.Translation.Deepl, :base_url], "https://api-free.deepl.com")
+ clear_config([Pleroma.Language.Translation.Deepl, :api_key], "API_KEY")
+
+ {:ok, res} =
+ Deepl.translate(
+ "USUNĄĆ ŚLEDZIKA!Wklej to na swojego śledzika. Jeżeli uzbieramy 70% użytkowników nk...to usuną śledzika!!!",
+ "pl",
+ "en"
+ )
+
+ assert %{
+ detected_source_language: "PL",
+ provider: "DeepL"
+ } = res
+ end
+
+ test "it returns languages list" do
+ Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+ clear_config([Pleroma.Language.Translation.Deepl, :base_url], "https://api-free.deepl.com")
+ clear_config([Pleroma.Language.Translation.Deepl, :api_key], "API_KEY")
+
+ assert {:ok, [language | _languages]} = Deepl.supported_languages(:target)
+
+ assert is_binary(language)
+ end
+end
diff --git a/test/pleroma/language/translation_test.exs b/test/pleroma/language/translation_test.exs
new file mode 100644
index 000000000..0be7a8d60
--- /dev/null
+++ b/test/pleroma/language/translation_test.exs
@@ -0,0 +1,28 @@
+defmodule Pleroma.Language.TranslationTest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Language.Translation
+
+ setup do: clear_config([Pleroma.Language.Translation, :provider], TranslationMock)
+
+ test "it translates text" do
+ assert {:ok,
+ %{
+ content: "txet emos",
+ detected_source_language: _,
+ provider: _
+ }} = Translation.translate("some text", "en", "uk")
+ end
+
+ test "it stores translation result in cache" do
+ Translation.translate("some text", "en", "uk")
+
+ assert {:ok, result} =
+ Cachex.get(
+ :translations_cache,
+ "en/uk/#{:crypto.hash(:sha256, "some text") |> Base.encode64()}"
+ )
+
+ assert result.content == "txet emos"
+ end
+end
diff --git a/test/pleroma/object_test.exs b/test/pleroma/object_test.exs
index ed5c2b6c8..13e941e4d 100644
--- a/test/pleroma/object_test.exs
+++ b/test/pleroma/object_test.exs
@@ -156,7 +156,7 @@ defmodule Pleroma.ObjectTest do
uploads_dir = Pleroma.Config.get!([Pleroma.Uploaders.Local, :uploads])
- File.mkdir_p!(uploads_dir)
+ Pleroma.Backports.mkdir_p!(uploads_dir)
file = %Plug.Upload{
content_type: "image/jpeg",
diff --git a/test/pleroma/otp_version_test.exs b/test/pleroma/otp_version_test.exs
deleted file mode 100644
index 21701d5a8..000000000
--- a/test/pleroma/otp_version_test.exs
+++ /dev/null
@@ -1,42 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2022 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.OTPVersionTest do
- use ExUnit.Case, async: true
-
- alias Pleroma.OTPVersion
-
- describe "check/1" do
- test "22.4" do
- assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/22.4"]) ==
- "22.4"
- end
-
- test "22.1" do
- assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/22.1"]) ==
- "22.1"
- end
-
- test "21.1" do
- assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/21.1"]) ==
- "21.1"
- end
-
- test "23.0" do
- assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/23.0"]) ==
- "23.0"
- end
-
- test "with nonexistent file" do
- assert OTPVersion.get_version_from_files([
- "test/fixtures/warnings/otp_version/non-exising",
- "test/fixtures/warnings/otp_version/22.4"
- ]) == "22.4"
- end
-
- test "empty paths" do
- assert OTPVersion.get_version_from_files([]) == nil
- end
- end
-end
diff --git a/test/pleroma/safe_zip_test.exs b/test/pleroma/safe_zip_test.exs
index 3312d4e63..f07b25675 100644
--- a/test/pleroma/safe_zip_test.exs
+++ b/test/pleroma/safe_zip_test.exs
@@ -9,12 +9,12 @@ defmodule Pleroma.SafeZipTest do
setup do
# Ensure tmp directory exists
- File.mkdir_p!(@tmp_dir)
+ Pleroma.Backports.mkdir_p!(@tmp_dir)
on_exit(fn ->
# Clean up any files created during tests
File.rm_rf!(@tmp_dir)
- File.mkdir_p!(@tmp_dir)
+ Pleroma.Backports.mkdir_p!(@tmp_dir)
end)
:ok
@@ -89,7 +89,7 @@ defmodule Pleroma.SafeZipTest do
# For this test, we'll manually check if the file exists in the archive
# by extracting it and verifying it exists
extract_dir = Path.join(@tmp_dir, "extract_check")
- File.mkdir_p!(extract_dir)
+ Pleroma.Backports.mkdir_p!(extract_dir)
{:ok, files} = SafeZip.unzip_file(zip_path, extract_dir)
# Verify the root file was extracted
@@ -145,7 +145,7 @@ defmodule Pleroma.SafeZipTest do
test "can create zip with directories" do
# Create a directory structure
dir_path = Path.join(@tmp_dir, "test_dir")
- File.mkdir_p!(dir_path)
+ Pleroma.Backports.mkdir_p!(dir_path)
file_in_dir_path = Path.join(dir_path, "file_in_dir.txt")
File.write!(file_in_dir_path, "file in directory")
@@ -428,7 +428,7 @@ defmodule Pleroma.SafeZipTest do
# Create a directory and a file in it
dir_path = Path.join(@tmp_dir, "file_in_dir")
- File.mkdir_p!(dir_path)
+ Pleroma.Backports.mkdir_p!(dir_path)
file_in_dir_path = Path.join(dir_path, "test_file.txt")
File.write!(file_in_dir_path, "file in directory content")
diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs
index 176e70ef9..0b4dc9197 100644
--- a/test/pleroma/user_test.exs
+++ b/test/pleroma/user_test.exs
@@ -2669,8 +2669,12 @@ defmodule Pleroma.UserTest do
assert {:ok, user} = User.update_last_active_at(user)
- assert user.last_active_at >= test_started_at
- assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
+ assert NaiveDateTime.compare(user.last_active_at, test_started_at) in [:gt, :eq]
+
+ assert NaiveDateTime.compare(
+ user.last_active_at,
+ NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
+ ) in [:lt, :eq]
last_active_at =
NaiveDateTime.utc_now()
@@ -2682,10 +2686,15 @@ defmodule Pleroma.UserTest do
|> cast(%{last_active_at: last_active_at}, [:last_active_at])
|> User.update_and_set_cache()
- assert user.last_active_at == last_active_at
+ assert NaiveDateTime.compare(user.last_active_at, last_active_at) == :eq
+
assert {:ok, user} = User.update_last_active_at(user)
- assert user.last_active_at >= test_started_at
- assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
+ assert NaiveDateTime.compare(user.last_active_at, test_started_at) in [:gt, :eq]
+
+ assert NaiveDateTime.compare(
+ user.last_active_at,
+ NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
+ ) in [:lt, :eq]
end
test "active_user_count/1" do
@@ -2783,6 +2792,15 @@ defmodule Pleroma.UserTest do
assert user_updated.also_known_as |> length() == 1
assert user2.ap_id in user_updated.also_known_as
end
+
+ test "should tolerate non-http(s) aliases" do
+ user =
+ insert(:user, %{
+ also_known_as: ["at://did:plc:xgvzy7ni6ig6ievcbls5jaxe"]
+ })
+
+ assert "at://did:plc:xgvzy7ni6ig6ievcbls5jaxe" in user.also_known_as
+ end
end
describe "alias_users/1" do
diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs
index dbc3aa532..c16f081f6 100644
--- a/test/pleroma/web/activity_pub/activity_pub_test.exs
+++ b/test/pleroma/web/activity_pub/activity_pub_test.exs
@@ -826,7 +826,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
assert object.data["repliesCount"] == 2
end
- test "increates quotes count", %{user: user} do
+ test "increases quotes count", %{user: user} do
user2 = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{status: "1", visibility: "public"})
diff --git a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
index 829598246..3c7ff0eeb 100644
--- a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
+++ b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
@@ -5,12 +5,33 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest do
use Pleroma.DataCase, async: true
+ alias Pleroma.Language.LanguageDetectorMock
+ alias Pleroma.StaticStubbedConfigMock
alias Pleroma.Web.ActivityPub.ObjectValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator
alias Pleroma.Web.ActivityPub.Utils
+ import Mox
import Pleroma.Factory
+ # Setup for all tests
+ setup do
+ # Stub the StaticStubbedConfigMock to return our mock for the provider
+ StaticStubbedConfigMock
+ |> stub(:get, fn
+ [Pleroma.Language.LanguageDetector, :provider] -> LanguageDetectorMock
+ _other -> nil
+ end)
+
+ # Stub the LanguageDetectorMock with default implementations
+ LanguageDetectorMock
+ |> stub(:missing_dependencies, fn -> [] end)
+ |> stub(:configured?, fn -> true end)
+ |> stub(:detect, fn _text -> nil end)
+
+ :ok
+ end
+
describe "Notes" do
setup do
user = insert(:user)
@@ -234,6 +255,37 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
assert object.language == "pl"
end
+ test "it doesn't call LanguageDetector when language is specified" do
+ # Set up expectation that detect should not be called
+ LanguageDetectorMock
+ |> expect(:detect, 0, fn _ -> flunk("LanguageDetector.detect should not be called") end)
+ |> stub(:missing_dependencies, fn -> [] end)
+ |> stub(:configured?, fn -> true end)
+
+ # Stub the StaticStubbedConfigMock to return our mock for the provider
+ StaticStubbedConfigMock
+ |> stub(:get, fn
+ [Pleroma.Language.LanguageDetector, :provider] -> LanguageDetectorMock
+ _other -> nil
+ end)
+
+ user = insert(:user)
+
+ note = %{
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "id" => Utils.generate_object_id(),
+ "type" => "Note",
+ "content" => "a post in English",
+ "contentMap" => %{
+ "en" => "a post in English"
+ },
+ "attributedTo" => user.ap_id
+ }
+
+ ArticleNotePageValidator.cast_and_apply(note)
+ end
+
test "it adds contentMap if language is specified" do
user = insert(:user)
diff --git a/test/pleroma/web/activity_pub/publisher_test.exs b/test/pleroma/web/activity_pub/publisher_test.exs
index 99ed42877..b7ff0ed5f 100644
--- a/test/pleroma/web/activity_pub/publisher_test.exs
+++ b/test/pleroma/web/activity_pub/publisher_test.exs
@@ -520,4 +520,105 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
assert decoded["cc"] == []
end
+
+ test "unlisted activities retain public address in cc" do
+ user = insert(:user)
+
+ # simulate unlistd activity by only having
+ # public address in cc
+ activity =
+ insert(:note_activity,
+ user: user,
+ data_attrs: %{
+ "cc" => [@as_public],
+ "to" => [user.follower_address]
+ }
+ )
+
+ assert @as_public in activity.data["cc"]
+
+ prepared =
+ Publisher.prepare_one(%{
+ inbox: "https://remote.instance/users/someone/inbox",
+ activity_id: activity.id
+ })
+
+ {:ok, decoded} = Jason.decode(prepared.json)
+
+ assert @as_public in decoded["cc"]
+
+ # maybe we also have another inbox in cc
+ # during Publishing
+ activity =
+ insert(:note_activity,
+ user: user,
+ data_attrs: %{
+ "cc" => [@as_public],
+ "to" => [user.follower_address]
+ }
+ )
+
+ prepared =
+ Publisher.prepare_one(%{
+ inbox: "https://remote.instance/users/someone/inbox",
+ activity_id: activity.id,
+ cc: ["https://remote.instance/users/someone_else/inbox"]
+ })
+
+ {:ok, decoded} = Jason.decode(prepared.json)
+
+ assert decoded["cc"] == [@as_public, "https://remote.instance/users/someone_else/inbox"]
+ end
+
+ test "public address in cc parameter is preserved" do
+ user = insert(:user)
+
+ cc_with_public = [@as_public, "https://example.org/users/other"]
+
+ activity =
+ insert(:note_activity,
+ user: user,
+ data_attrs: %{
+ "cc" => cc_with_public,
+ "to" => [user.follower_address]
+ }
+ )
+
+ assert @as_public in activity.data["cc"]
+
+ prepared =
+ Publisher.prepare_one(%{
+ inbox: "https://remote.instance/users/someone/inbox",
+ activity_id: activity.id,
+ cc: cc_with_public
+ })
+
+ {:ok, decoded} = Jason.decode(prepared.json)
+
+ assert cc_with_public == decoded["cc"]
+ end
+
+ test "cc parameter is preserved" do
+ user = insert(:user)
+
+ activity =
+ insert(:note_activity,
+ user: user,
+ data_attrs: %{
+ "cc" => ["https://example.com/specific/user"],
+ "to" => [user.follower_address]
+ }
+ )
+
+ prepared =
+ Publisher.prepare_one(%{
+ inbox: "https://remote.instance/users/someone/inbox",
+ activity_id: activity.id,
+ cc: ["https://example.com/specific/user"]
+ })
+
+ {:ok, decoded} = Jason.decode(prepared.json)
+
+ assert decoded["cc"] == ["https://example.com/specific/user"]
+ end
end
diff --git a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs
index c02f66d77..27f8522ce 100644
--- a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs
+++ b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do
use Pleroma.DataCase, async: true
alias Pleroma.Activity
+ alias Pleroma.Object
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.CommonAPI
@@ -75,4 +76,107 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do
assert activity_data["object"] == activity.data["object"]
assert activity_data["content"] == "⭐"
end
+
+ test "it works for misskey likes with custom emoji" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
+
+ data =
+ File.read!("test/fixtures/misskey-custom-emoji-like.json")
+ |> Jason.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ _actor = insert(:user, ap_id: data["actor"], local: false)
+
+ {:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert activity_data["actor"] == data["actor"]
+ assert activity_data["type"] == "EmojiReact"
+ assert activity_data["id"] == data["id"]
+ assert activity_data["object"] == activity.data["object"]
+ assert activity_data["content"] == ":blobwtfnotlikethis:"
+
+ assert [["blobwtfnotlikethis", _, _]] =
+ Object.get_by_ap_id(activity.data["object"])
+ |> Object.get_emoji_reactions()
+ end
+
+ test "it works for mitra likes with custom emoji" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
+
+ data =
+ File.read!("test/fixtures/mitra-custom-emoji-like.json")
+ |> Jason.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ _actor = insert(:user, ap_id: data["actor"], local: false)
+
+ {:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert activity_data["actor"] == data["actor"]
+ assert activity_data["type"] == "EmojiReact"
+ assert activity_data["id"] == data["id"]
+ assert activity_data["object"] == activity.data["object"]
+ assert activity_data["content"] == ":ablobcatheartsqueeze:"
+
+ assert [["ablobcatheartsqueeze", _, _]] =
+ Object.get_by_ap_id(activity.data["object"])
+ |> Object.get_emoji_reactions()
+ end
+
+ test "it works for likes with wrong content" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
+
+ data =
+ File.read!("test/fixtures/mitra-custom-emoji-like.json")
+ |> Jason.decode!()
+ |> Map.put("object", activity.data["object"])
+ |> Map.put("content", 1)
+
+ _actor = insert(:user, ap_id: data["actor"], local: false)
+
+ assert {:ok, activity} = Transmogrifier.handle_incoming(data)
+ assert activity.data["type"] == "Like"
+ end
+
+ test "it changes incoming dislikes into emoji reactions" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{status: "hello"})
+
+ data =
+ File.read!("test/fixtures/friendica-dislike.json")
+ |> Jason.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ _actor = insert(:user, ap_id: data["actor"], local: false)
+
+ {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
+
+ refute Enum.empty?(activity.recipients)
+
+ assert data["actor"] == "https://my-place.social/profile/vaartis"
+ assert data["type"] == "EmojiReact"
+ assert data["content"] == "👎"
+ assert data["id"] == "https://my-place.social/objects/e599373b-1368-4b20-cd24-837166957182"
+ assert data["object"] == activity.data["object"]
+
+ data =
+ File.read!("test/fixtures/friendica-dislike-undo.json")
+ |> Jason.decode!()
+ |> put_in(["object", "object"], activity.data["object"])
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "https://my-place.social/profile/vaartis"
+ assert data["type"] == "Undo"
+
+ assert data["object"] ==
+ "https://my-place.social/objects/e599373b-1368-4b20-cd24-837166957182"
+ end
end
diff --git a/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs
index 0d1a4999e..a6b8dba46 100644
--- a/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs
+++ b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.AdminAPI.FrontendControllerTest do
setup do
clear_config([:instance, :static_dir], @dir)
- File.mkdir_p!(Pleroma.Frontend.dir())
+ Pleroma.Backports.mkdir_p!(Pleroma.Frontend.dir())
on_exit(fn ->
File.rm_rf(@dir)
diff --git a/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs b/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs
index 9511dccea..344c908fe 100644
--- a/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs
+++ b/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs
@@ -10,7 +10,7 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentControllerTest do
@default_instance_panel ~s(
Welcome to Pleroma!
)
setup do
- File.mkdir_p!(@dir)
+ Pleroma.Backports.mkdir_p!(@dir)
on_exit(fn -> File.rm_rf(@dir) end)
end
diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs
index 73230a58c..6b5d31537 100644
--- a/test/pleroma/web/common_api_test.exs
+++ b/test/pleroma/web/common_api_test.exs
@@ -111,6 +111,17 @@ defmodule Pleroma.Web.CommonAPITest do
end
end
+ test "add expiring block", %{blocker: blocker, blocked: blocked} do
+ {:ok, _} = CommonAPI.block(blocked, blocker, %{expires_in: 60})
+ assert User.blocks?(blocker, blocked)
+
+ worker = Pleroma.Workers.MuteExpireWorker
+ args = %{"op" => "unblock_user", "blocker_id" => blocker.id, "blocked_id" => blocked.id}
+
+ assert :ok = perform_job(worker, args)
+ refute User.blocks?(blocker, blocked)
+ end
+
test "it blocks and does not federate if outgoing blocks are disabled", %{
blocker: blocker,
blocked: blocked
diff --git a/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs
index 373a84303..8a0fe5259 100644
--- a/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs
+++ b/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs
@@ -152,4 +152,46 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
}
] = result["rules"]
end
+
+ test "translation languages matrix", %{conn: conn} do
+ clear_config([Pleroma.Language.Translation, :provider], TranslationMock)
+
+ assert %{"en" => ["pl"], "pl" => ["en"]} =
+ conn
+ |> get("/api/v1/instance/translation_languages")
+ |> json_response_and_validate_schema(200)
+ end
+
+ test "base_urls in pleroma metadata", %{conn: conn} do
+ media_proxy_base_url = "https://media.example.org"
+ upload_base_url = "https://uploads.example.org"
+
+ clear_config([:media_proxy, :enabled], true)
+ clear_config([:media_proxy, :base_url], media_proxy_base_url)
+ clear_config([Pleroma.Upload, :base_url], upload_base_url)
+
+ conn = get(conn, "/api/v1/instance")
+
+ assert result = json_response_and_validate_schema(conn, 200)
+ assert result["pleroma"]["metadata"]["base_urls"]["media_proxy"] == media_proxy_base_url
+ assert result["pleroma"]["metadata"]["base_urls"]["upload"] == upload_base_url
+
+ # Test when media_proxy is disabled
+ clear_config([:media_proxy, :enabled], false)
+
+ conn = get(conn, "/api/v1/instance")
+
+ assert result = json_response_and_validate_schema(conn, 200)
+ refute Map.has_key?(result["pleroma"]["metadata"]["base_urls"], "media_proxy")
+ assert result["pleroma"]["metadata"]["base_urls"]["upload"] == upload_base_url
+
+ # Test when upload base_url is not set
+ clear_config([Pleroma.Upload, :base_url], nil)
+
+ conn = get(conn, "/api/v1/instance")
+
+ assert result = json_response_and_validate_schema(conn, 200)
+ refute Map.has_key?(result["pleroma"]["metadata"]["base_urls"], "media_proxy")
+ refute Map.has_key?(result["pleroma"]["metadata"]["base_urls"], "upload")
+ end
end
diff --git a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs
index a4bca6cf9..25a17d5c1 100644
--- a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs
+++ b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs
@@ -2483,4 +2483,62 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|> json_response_and_validate_schema(:not_found)
end
end
+
+ describe "translating statuses" do
+ setup do: clear_config([Pleroma.Language.Translation, :provider], TranslationMock)
+
+ test "it translates a status to user language" do
+ user = insert(:user, language: "fr")
+ %{conn: conn} = oauth_access(["read:statuses"], user: user)
+ another_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(another_user, %{
+ status: "Cześć!",
+ visibility: "public",
+ language: "pl"
+ })
+
+ response =
+ conn
+ |> post("/api/v1/statuses/#{activity.id}/translate")
+ |> json_response_and_validate_schema(200)
+
+ assert response == %{
+ "content" => "!ćśezC",
+ "detected_source_language" => "pl",
+ "provider" => "TranslationMock"
+ }
+ end
+
+ test "it returns an error if no target language provided" do
+ %{conn: conn} = oauth_access(["read:statuses"])
+ another_user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(another_user, %{
+ status: "Cześć!",
+ language: "pl"
+ })
+
+ assert conn
+ |> post("/api/v1/statuses/#{activity.id}/translate")
+ |> json_response_and_validate_schema(400)
+ end
+
+ test "it doesn't translate non-public statuses" do
+ %{conn: conn, user: user} = oauth_access(["read:statuses"])
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ status: "Cześć!",
+ visibility: "private",
+ language: "pl"
+ })
+
+ assert conn
+ |> post("/api/v1/statuses/#{activity.id}/translate")
+ |> json_response_and_validate_schema(404)
+ end
+ end
end
diff --git a/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs
index be94a02ad..bcc25b83e 100644
--- a/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs
+++ b/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs
@@ -19,10 +19,33 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do
"artist" => "lain",
"album" => "lain radio",
"length" => "180000",
- "externalLink" => "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+1"
+ "external_link" => "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+1"
})
- assert %{"title" => "lain radio episode 1"} = json_response_and_validate_schema(conn, 200)
+ assert %{
+ "title" => "lain radio episode 1",
+ "external_link" => "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+1"
+ } = json_response_and_validate_schema(conn, 200)
+ end
+
+ test "external_link fallback" do
+ %{conn: conn} = oauth_access(["write"])
+
+ conn =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/pleroma/scrobble", %{
+ "title" => "lain radio episode 2",
+ "artist" => "lain",
+ "album" => "lain radio",
+ "length" => "180000",
+ "externalLink" => "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+2"
+ })
+
+ assert %{
+ "title" => "lain radio episode 2",
+ "external_link" => "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+2"
+ } = json_response_and_validate_schema(conn, 200)
end
end
@@ -35,7 +58,7 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do
title: "lain radio episode 1",
artist: "lain",
album: "lain radio",
- externalLink: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+1"
+ external_link: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+1"
})
{:ok, _activity} =
@@ -43,7 +66,7 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do
title: "lain radio episode 2",
artist: "lain",
album: "lain radio",
- externalLink: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+2"
+ external_link: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+2"
})
{:ok, _activity} =
@@ -51,7 +74,7 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do
title: "lain radio episode 3",
artist: "lain",
album: "lain radio",
- externalLink: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+3"
+ external_link: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+3"
})
conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/scrobbles")
diff --git a/test/pleroma/web/plugs/frontend_static_plug_test.exs b/test/pleroma/web/plugs/frontend_static_plug_test.exs
index 6f4d24d9e..a7af3e74e 100644
--- a/test/pleroma/web/plugs/frontend_static_plug_test.exs
+++ b/test/pleroma/web/plugs/frontend_static_plug_test.exs
@@ -13,7 +13,7 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do
@dir "test/tmp/instance_static"
setup do
- File.mkdir_p!(@dir)
+ Pleroma.Backports.mkdir_p!(@dir)
on_exit(fn -> File.rm_rf(@dir) end)
end
@@ -38,7 +38,7 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do
clear_config([:frontends, :primary], %{"name" => name, "ref" => ref})
path = "#{@dir}/frontends/#{name}/#{ref}"
- File.mkdir_p!(path)
+ Pleroma.Backports.mkdir_p!(path)
File.write!("#{path}/index.html", "from frontend plug")
index = get(conn, "/")
@@ -52,7 +52,7 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do
clear_config([:frontends, :admin], %{"name" => name, "ref" => ref})
path = "#{@dir}/frontends/#{name}/#{ref}"
- File.mkdir_p!(path)
+ Pleroma.Backports.mkdir_p!(path)
File.write!("#{path}/index.html", "from frontend plug")
index = get(conn, "/pleroma/admin/")
@@ -67,7 +67,7 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do
clear_config([:frontends, :primary], %{"name" => name, "ref" => ref})
path = "#{@dir}/frontends/#{name}/#{ref}"
- File.mkdir_p!("#{path}/proxy/rr/ss")
+ Pleroma.Backports.mkdir_p!("#{path}/proxy/rr/ss")
File.write!("#{path}/proxy/rr/ss/Ek7w8WPVcAApOvN.jpg:large", "FB image")
ConfigMock
diff --git a/test/pleroma/web/plugs/instance_static_test.exs b/test/pleroma/web/plugs/instance_static_test.exs
index 33b74dcf0..b5a5a3334 100644
--- a/test/pleroma/web/plugs/instance_static_test.exs
+++ b/test/pleroma/web/plugs/instance_static_test.exs
@@ -8,7 +8,7 @@ defmodule Pleroma.Web.Plugs.InstanceStaticTest do
@dir "test/tmp/instance_static"
setup do
- File.mkdir_p!(@dir)
+ Pleroma.Backports.mkdir_p!(@dir)
on_exit(fn -> File.rm_rf(@dir) end)
end
@@ -34,7 +34,7 @@ defmodule Pleroma.Web.Plugs.InstanceStaticTest do
refute html_response(bundled_index, 200) == "from frontend plug"
path = "#{@dir}/frontends/#{name}/#{ref}"
- File.mkdir_p!(path)
+ Pleroma.Backports.mkdir_p!(path)
File.write!("#{path}/index.html", "from frontend plug")
index = get(conn, "/")
diff --git a/test/pleroma/web/plugs/user_tracking_plug_test.exs b/test/pleroma/web/plugs/user_tracking_plug_test.exs
index 742f04fea..cd9c66448 100644
--- a/test/pleroma/web/plugs/user_tracking_plug_test.exs
+++ b/test/pleroma/web/plugs/user_tracking_plug_test.exs
@@ -21,8 +21,12 @@ defmodule Pleroma.Web.Plugs.UserTrackingPlugTest do
|> assign(:user, user)
|> UserTrackingPlug.call(%{})
- assert user.last_active_at >= test_started_at
- assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
+ assert NaiveDateTime.compare(user.last_active_at, test_started_at) in [:gt, :eq]
+
+ assert NaiveDateTime.compare(
+ user.last_active_at,
+ NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
+ ) in [:lt, :eq]
end
test "doesn't update last_active_at if it was updated recently", %{conn: conn} do
@@ -38,7 +42,7 @@ defmodule Pleroma.Web.Plugs.UserTrackingPlugTest do
|> assign(:user, user)
|> UserTrackingPlug.call(%{})
- assert user.last_active_at == last_active_at
+ assert NaiveDateTime.compare(user.last_active_at, last_active_at) == :eq
end
test "skips updating last_active_at if user ID is nil", %{conn: conn} do
diff --git a/test/pleroma/web/rich_media/parser_test.exs b/test/pleroma/web/rich_media/parser_test.exs
index 20f61badc..1f01d657a 100644
--- a/test/pleroma/web/rich_media/parser_test.exs
+++ b/test/pleroma/web/rich_media/parser_test.exs
@@ -61,6 +61,13 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
}}
end
+ test "truncates title and description fields" do
+ {:ok, parsed} = Parser.parse("https://instagram.com/longtext")
+
+ assert String.length(parsed["title"]) == 120
+ assert String.length(parsed["description"]) == 200
+ end
+
test "parses OEmbed and filters HTML tags" do
assert Parser.parse("https://example.com/oembed") ==
{:ok,
diff --git a/test/pleroma/web/web_finger/web_finger_controller_test.exs b/test/pleroma/web/web_finger/web_finger_controller_test.exs
index 80e072163..be44e3a8b 100644
--- a/test/pleroma/web/web_finger/web_finger_controller_test.exs
+++ b/test/pleroma/web/web_finger/web_finger_controller_test.exs
@@ -5,7 +5,6 @@
defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do
use Pleroma.Web.ConnCase
- import ExUnit.CaptureLog
import Pleroma.Factory
import Tesla.Mock
@@ -55,6 +54,26 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do
]
end
+ test "Webfinger defaults to JSON when no Accept header is provided" do
+ user =
+ insert(:user,
+ ap_id: "https://hyrule.world/users/zelda",
+ also_known_as: ["https://mushroom.kingdom/users/toad"]
+ )
+
+ response =
+ build_conn()
+ |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost")
+ |> json_response(200)
+
+ assert response["subject"] == "acct:#{user.nickname}@localhost"
+
+ assert response["aliases"] == [
+ "https://hyrule.world/users/zelda",
+ "https://mushroom.kingdom/users/toad"
+ ]
+ end
+
test "reach user on tld, while pleroma is running on subdomain" do
clear_config([Pleroma.Web.Endpoint, :url, :host], "sub.example.com")
@@ -109,16 +128,25 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do
assert result == "Couldn't find user"
end
- test "Sends a 404 when invalid format" do
- user = insert(:user)
+ test "Returns JSON when format is not supported" do
+ user =
+ insert(:user,
+ ap_id: "https://hyrule.world/users/zelda",
+ also_known_as: ["https://mushroom.kingdom/users/toad"]
+ )
- assert capture_log(fn ->
- assert_raise Phoenix.NotAcceptableError, fn ->
- build_conn()
- |> put_req_header("accept", "text/html")
- |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost")
- end
- end) =~ "no supported media type in accept header"
+ response =
+ build_conn()
+ |> put_req_header("accept", "text/html")
+ |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost")
+ |> json_response(200)
+
+ assert response["subject"] == "acct:#{user.nickname}@localhost"
+
+ assert response["aliases"] == [
+ "https://hyrule.world/users/zelda",
+ "https://mushroom.kingdom/users/toad"
+ ]
end
test "Sends a 400 when resource param is missing" do
diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex
index 1c472fca9..f8d11e602 100644
--- a/test/support/http_request_mock.ex
+++ b/test/support/http_request_mock.ex
@@ -1494,6 +1494,11 @@ defmodule HttpRequestMock do
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/twitter_card.html")}}
end
+ def get("https://instagram.com/longtext", _, _, _) do
+ {:ok,
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/instagram_longtext.html")}}
+ end
+
def get("https://example.com/non-ogp", _, _, _) do
{:ok,
%Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/non_ogp_embed.html")}}
@@ -1701,6 +1706,24 @@ defmodule HttpRequestMock do
}}
end
+ def post("https://api-free.deepl.com/v2/translate" <> _, _, _, _) do
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/deepl-translation.json"),
+ headers: [{"content-type", "application/json"}]
+ }}
+ end
+
+ def post("https://api-free.deepl.com/v2/languages" <> _, _, _, _) do
+ {:ok,
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/fixtures/tesla_mock/deepl-languages-list.json"),
+ headers: [{"content-type", "application/json"}]
+ }}
+ end
+
def post(url, query, body, headers) do
{:error,
"Mock response not implemented for POST #{inspect(url)}, #{query}, #{inspect(body)}, #{inspect(headers)}"}
@@ -1720,7 +1743,8 @@ defmodule HttpRequestMock do
"https://example.com/twitter-card",
"https://google.com/",
"https://pleroma.local/notice/9kCP7V",
- "https://yahoo.com/"
+ "https://yahoo.com/",
+ "https://instagram.com/longtext"
]
def head(url, _query, _body, _headers) when url in @rich_media_mocks do
diff --git a/test/support/mocks.ex b/test/support/mocks.ex
index ca2974504..b26834871 100644
--- a/test/support/mocks.ex
+++ b/test/support/mocks.ex
@@ -34,5 +34,9 @@ Mox.defmock(Pleroma.LoggerMock, for: Pleroma.Logging)
Mox.defmock(Pleroma.Uploaders.S3.ExAwsMock, for: Pleroma.Uploaders.S3.ExAwsAPI)
+Mox.defmock(Pleroma.Language.LanguageDetectorMock,
+ for: Pleroma.Language.LanguageDetector.Provider
+)
+
Mox.defmock(Pleroma.DateTimeMock, for: Pleroma.DateTime)
Mox.defmock(Pleroma.MogrifyMock, for: Pleroma.MogrifyBehaviour)
diff --git a/test/support/translation_mock.ex b/test/support/translation_mock.ex
new file mode 100644
index 000000000..84ed8f696
--- /dev/null
+++ b/test/support/translation_mock.ex
@@ -0,0 +1,43 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule TranslationMock do
+ alias Pleroma.Language.Translation.Provider
+
+ use Provider
+
+ @behaviour Provider
+
+ @name "TranslationMock"
+
+ @impl Provider
+ def configured?, do: true
+
+ @impl Provider
+ def translate(content, source_language, _target_language) do
+ {:ok,
+ %{
+ content: content |> String.reverse(),
+ detected_source_language: source_language,
+ provider: @name
+ }}
+ end
+
+ @impl Provider
+ def supported_languages(_) do
+ {:ok, ["en", "pl"]}
+ end
+
+ @impl Provider
+ def languages_matrix do
+ {:ok,
+ %{
+ "en" => ["pl"],
+ "pl" => ["en"]
+ }}
+ end
+
+ @impl Provider
+ def name, do: @name
+end
diff --git a/test/test_helper.exs b/test/test_helper.exs
index 94661353b..dc6c05a74 100644
--- a/test/test_helper.exs
+++ b/test/test_helper.exs
@@ -2,8 +2,6 @@
# Copyright © 2017-2022 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
-Code.put_compiler_option(:warnings_as_errors, true)
-
ExUnit.configure(capture_log: true, max_cases: System.schedulers_online())
ExUnit.start(exclude: [:federated])