diff options
author | Mark Felder <feld@FreeBSD.org> | 2020-10-13 09:54:29 -0500 |
---|---|---|
committer | Mark Felder <feld@FreeBSD.org> | 2020-10-13 09:54:29 -0500 |
commit | 409f694e4f90d34285b43c7e7afc594bc386d893 (patch) | |
tree | 70d3283bcc7e565ba37b253c7cd7dbb94b9d9aa3 /test/mix | |
parent | 9968b7efedc64d0239db5578de7fc66ff4ce894d (diff) | |
parent | 8b6221d4ecd1d7e354e7de831dd46e285cb85077 (diff) | |
download | pleroma-409f694e4f90d34285b43c7e7afc594bc386d893.tar.gz |
Merge branch 'develop' into refactor/locked_user_field
Diffstat (limited to 'test/mix')
-rw-r--r-- | test/mix/pleroma_test.exs | 50 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/app_test.exs | 65 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/config_test.exs | 189 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/count_statuses_test.exs | 39 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/database_test.exs | 175 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/digest_test.exs | 60 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/ecto/migrate_test.exs | 20 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/ecto/rollback_test.exs | 20 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/ecto_test.exs | 15 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/email_test.exs | 127 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/emoji_test.exs | 243 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/frontend_test.exs | 85 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/instance_test.exs | 99 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/refresh_counter_cache_test.exs | 43 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/relay_test.exs | 180 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/robots_txt_test.exs | 45 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/uploads_test.exs | 56 | ||||
-rw-r--r-- | test/mix/tasks/pleroma/user_test.exs | 614 |
18 files changed, 2125 insertions, 0 deletions
diff --git a/test/mix/pleroma_test.exs b/test/mix/pleroma_test.exs new file mode 100644 index 000000000..c3e47b285 --- /dev/null +++ b/test/mix/pleroma_test.exs @@ -0,0 +1,50 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.PleromaTest do + use ExUnit.Case, async: true + import Mix.Pleroma + + setup_all do + Mix.shell(Mix.Shell.Process) + + on_exit(fn -> + Mix.shell(Mix.Shell.IO) + end) + + :ok + end + + describe "shell_prompt/1" do + test "input" do + send(self(), {:mix_shell_input, :prompt, "Yes"}) + + answer = shell_prompt("Do you want this?") + assert_received {:mix_shell, :prompt, [message]} + assert message =~ "Do you want this?" + assert answer == "Yes" + end + + test "with defval" do + send(self(), {:mix_shell_input, :prompt, "\n"}) + + answer = shell_prompt("Do you want this?", "defval") + + assert_received {:mix_shell, :prompt, [message]} + assert message =~ "Do you want this? [defval]" + assert answer == "defval" + end + end + + describe "get_option/3" do + test "get from options" do + assert get_option([domain: "some-domain.com"], :domain, "Promt") == "some-domain.com" + end + + test "get from prompt" do + send(self(), {:mix_shell_input, :prompt, "another-domain.com"}) + assert get_option([], :domain, "Prompt") == "another-domain.com" + end + end +end diff --git a/test/mix/tasks/pleroma/app_test.exs b/test/mix/tasks/pleroma/app_test.exs new file mode 100644 index 000000000..71a84ac8e --- /dev/null +++ b/test/mix/tasks/pleroma/app_test.exs @@ -0,0 +1,65 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.AppTest do + use Pleroma.DataCase, async: true + + setup_all do + Mix.shell(Mix.Shell.Process) + + on_exit(fn -> + Mix.shell(Mix.Shell.IO) + end) + end + + describe "creates new app" do + test "with default scopes" do + name = "Some name" + redirect = "https://example.com" + Mix.Tasks.Pleroma.App.run(["create", "-n", name, "-r", redirect]) + + assert_app(name, redirect, ["read", "write", "follow", "push"]) + end + + test "with custom scopes" do + name = "Another name" + redirect = "https://example.com" + + Mix.Tasks.Pleroma.App.run([ + "create", + "-n", + name, + "-r", + redirect, + "-s", + "read,write,follow,push,admin" + ]) + + assert_app(name, redirect, ["read", "write", "follow", "push", "admin"]) + end + end + + test "with errors" do + Mix.Tasks.Pleroma.App.run(["create"]) + {:mix_shell, :error, ["Creating failed:"]} + {:mix_shell, :error, ["name: can't be blank"]} + {:mix_shell, :error, ["redirect_uris: can't be blank"]} + end + + defp assert_app(name, redirect, scopes) do + app = Repo.get_by(Pleroma.Web.OAuth.App, client_name: name) + + assert_receive {:mix_shell, :info, [message]} + assert message == "#{name} successfully created:" + + assert_receive {:mix_shell, :info, [message]} + assert message == "App client_id: #{app.client_id}" + + assert_receive {:mix_shell, :info, [message]} + assert message == "App client_secret: #{app.client_secret}" + + assert app.scopes == scopes + assert app.redirect_uris == redirect + end +end diff --git a/test/mix/tasks/pleroma/config_test.exs b/test/mix/tasks/pleroma/config_test.exs new file mode 100644 index 000000000..f36648829 --- /dev/null +++ b/test/mix/tasks/pleroma/config_test.exs @@ -0,0 +1,189 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.ConfigTest do + use Pleroma.DataCase + + import Pleroma.Factory + + alias Pleroma.ConfigDB + alias Pleroma.Repo + + setup_all do + Mix.shell(Mix.Shell.Process) + + on_exit(fn -> + Mix.shell(Mix.Shell.IO) + Application.delete_env(:pleroma, :first_setting) + Application.delete_env(:pleroma, :second_setting) + end) + + :ok + end + + setup_all do: clear_config(:configurable_from_database, true) + + test "error if file with custom settings doesn't exist" do + Mix.Tasks.Pleroma.Config.migrate_to_db("config/not_existance_config_file.exs") + + assert_receive {:mix_shell, :info, + [ + "To migrate settings, you must define custom settings in config/not_existance_config_file.exs." + ]}, + 15 + end + + describe "migrate_to_db/1" do + setup do + initial = Application.get_env(:quack, :level) + on_exit(fn -> Application.put_env(:quack, :level, initial) end) + end + + @tag capture_log: true + test "config migration refused when deprecated settings are found" do + clear_config([:media_proxy, :whitelist], ["domain_without_scheme.com"]) + assert Repo.all(ConfigDB) == [] + + Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs") + + assert_received {:mix_shell, :error, [message]} + + assert message =~ + "Migration is not allowed until all deprecation warnings have been resolved." + end + + test "filtered settings are migrated to db" do + assert Repo.all(ConfigDB) == [] + + Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs") + + config1 = ConfigDB.get_by_params(%{group: ":pleroma", key: ":first_setting"}) + config2 = ConfigDB.get_by_params(%{group: ":pleroma", key: ":second_setting"}) + config3 = ConfigDB.get_by_params(%{group: ":quack", key: ":level"}) + refute ConfigDB.get_by_params(%{group: ":pleroma", key: "Pleroma.Repo"}) + refute ConfigDB.get_by_params(%{group: ":postgrex", key: ":json_library"}) + refute ConfigDB.get_by_params(%{group: ":pleroma", key: ":database"}) + + assert config1.value == [key: "value", key2: [Repo]] + assert config2.value == [key: "value2", key2: ["Activity"]] + assert config3.value == :info + end + + test "config table is truncated before migration" do + insert(:config, key: :first_setting, value: [key: "value", key2: ["Activity"]]) + assert Repo.aggregate(ConfigDB, :count, :id) == 1 + + Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs") + + config = ConfigDB.get_by_params(%{group: ":pleroma", key: ":first_setting"}) + assert config.value == [key: "value", key2: [Repo]] + end + end + + describe "with deletion temp file" do + setup do + temp_file = "config/temp.exported_from_db.secret.exs" + + on_exit(fn -> + :ok = File.rm(temp_file) + end) + + {:ok, temp_file: temp_file} + end + + test "settings are migrated to file and deleted from db", %{temp_file: temp_file} do + insert(:config, key: :setting_first, value: [key: "value", key2: ["Activity"]]) + insert(:config, key: :setting_second, value: [key: "value2", key2: [Repo]]) + insert(:config, group: :quack, key: :level, value: :info) + + Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "--env", "temp", "-d"]) + + assert Repo.all(ConfigDB) == [] + + file = File.read!(temp_file) + assert file =~ "config :pleroma, :setting_first," + assert file =~ "config :pleroma, :setting_second," + assert file =~ "config :quack, :level, :info" + end + + test "load a settings with large values and pass to file", %{temp_file: temp_file} do + insert(:config, + key: :instance, + value: [ + name: "Pleroma", + email: "example@example.com", + notify_email: "noreply@example.com", + description: "A Pleroma instance, an alternative fediverse server", + limit: 5_000, + chat_limit: 5_000, + remote_limit: 100_000, + upload_limit: 16_000_000, + avatar_upload_limit: 2_000_000, + background_upload_limit: 4_000_000, + banner_upload_limit: 4_000_000, + poll_limits: %{ + max_options: 20, + max_option_chars: 200, + min_expiration: 0, + max_expiration: 365 * 24 * 60 * 60 + }, + registrations_open: true, + federating: true, + federation_incoming_replies_max_depth: 100, + federation_reachability_timeout_days: 7, + federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher], + allow_relay: true, + public: true, + quarantined_instances: [], + managed_config: true, + static_dir: "instance/static/", + allowed_post_formats: ["text/plain", "text/html", "text/markdown", "text/bbcode"], + autofollowed_nicknames: [], + max_pinned_statuses: 1, + attachment_links: false, + max_report_comment_size: 1000, + safe_dm_mentions: false, + healthcheck: false, + remote_post_retention_days: 90, + skip_thread_containment: true, + limit_to_local_content: :unauthenticated, + user_bio_length: 5000, + user_name_length: 100, + max_account_fields: 10, + max_remote_account_fields: 20, + account_field_name_length: 512, + account_field_value_length: 2048, + external_user_synchronization: true, + extended_nickname_format: true, + multi_factor_authentication: [ + totp: [ + digits: 6, + period: 30 + ], + backup_codes: [ + number: 2, + length: 6 + ] + ] + ] + ) + + Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "--env", "temp", "-d"]) + + assert Repo.all(ConfigDB) == [] + assert File.exists?(temp_file) + {:ok, file} = File.read(temp_file) + + header = + if Code.ensure_loaded?(Config.Reader) do + "import Config" + else + "use Mix.Config" + end + + assert file == + "#{header}\n\nconfig :pleroma, :instance,\n name: \"Pleroma\",\n email: \"example@example.com\",\n notify_email: \"noreply@example.com\",\n description: \"A Pleroma instance, an alternative fediverse server\",\n limit: 5000,\n chat_limit: 5000,\n remote_limit: 100_000,\n upload_limit: 16_000_000,\n avatar_upload_limit: 2_000_000,\n background_upload_limit: 4_000_000,\n banner_upload_limit: 4_000_000,\n poll_limits: %{\n max_expiration: 31_536_000,\n max_option_chars: 200,\n max_options: 20,\n min_expiration: 0\n },\n registrations_open: true,\n federating: true,\n federation_incoming_replies_max_depth: 100,\n federation_reachability_timeout_days: 7,\n federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher],\n allow_relay: true,\n public: true,\n quarantined_instances: [],\n managed_config: true,\n static_dir: \"instance/static/\",\n allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n autofollowed_nicknames: [],\n max_pinned_statuses: 1,\n attachment_links: false,\n max_report_comment_size: 1000,\n safe_dm_mentions: false,\n healthcheck: false,\n remote_post_retention_days: 90,\n skip_thread_containment: true,\n limit_to_local_content: :unauthenticated,\n user_bio_length: 5000,\n user_name_length: 100,\n max_account_fields: 10,\n max_remote_account_fields: 20,\n account_field_name_length: 512,\n account_field_value_length: 2048,\n external_user_synchronization: true,\n extended_nickname_format: true,\n multi_factor_authentication: [\n totp: [digits: 6, period: 30],\n backup_codes: [number: 2, length: 6]\n ]\n" + end + end +end diff --git a/test/mix/tasks/pleroma/count_statuses_test.exs b/test/mix/tasks/pleroma/count_statuses_test.exs new file mode 100644 index 000000000..c5cd16960 --- /dev/null +++ b/test/mix/tasks/pleroma/count_statuses_test.exs @@ -0,0 +1,39 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.CountStatusesTest do + use Pleroma.DataCase + + alias Pleroma.User + alias Pleroma.Web.CommonAPI + + import ExUnit.CaptureIO, only: [capture_io: 1] + import Pleroma.Factory + + test "counts statuses" do + user = insert(:user) + {:ok, _} = CommonAPI.post(user, %{status: "test"}) + {:ok, _} = CommonAPI.post(user, %{status: "test2"}) + + user2 = insert(:user) + {:ok, _} = CommonAPI.post(user2, %{status: "test3"}) + + user = refresh_record(user) + user2 = refresh_record(user2) + + assert %{note_count: 2} = user + assert %{note_count: 1} = user2 + + {:ok, user} = User.update_note_count(user, 0) + {:ok, user2} = User.update_note_count(user2, 0) + + assert %{note_count: 0} = user + assert %{note_count: 0} = user2 + + assert capture_io(fn -> Mix.Tasks.Pleroma.CountStatuses.run([]) end) == "Done\n" + + assert %{note_count: 2} = refresh_record(user) + assert %{note_count: 1} = refresh_record(user2) + end +end diff --git a/test/mix/tasks/pleroma/database_test.exs b/test/mix/tasks/pleroma/database_test.exs new file mode 100644 index 000000000..292a5ef5f --- /dev/null +++ b/test/mix/tasks/pleroma/database_test.exs @@ -0,0 +1,175 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.DatabaseTest do + use Pleroma.DataCase + use Oban.Testing, repo: Pleroma.Repo + + alias Pleroma.Activity + alias Pleroma.Object + alias Pleroma.Repo + alias Pleroma.User + alias Pleroma.Web.CommonAPI + + import Pleroma.Factory + + setup_all do + Mix.shell(Mix.Shell.Process) + + on_exit(fn -> + Mix.shell(Mix.Shell.IO) + end) + + :ok + end + + describe "running remove_embedded_objects" do + test "it replaces objects with references" do + user = insert(:user) + {:ok, activity} = CommonAPI.post(user, %{status: "test"}) + new_data = Map.put(activity.data, "object", activity.object.data) + + {:ok, activity} = + activity + |> Activity.change(%{data: new_data}) + |> Repo.update() + + assert is_map(activity.data["object"]) + + Mix.Tasks.Pleroma.Database.run(["remove_embedded_objects"]) + + activity = Activity.get_by_id_with_object(activity.id) + assert is_binary(activity.data["object"]) + end + end + + describe "prune_objects" do + test "it prunes old objects from the database" do + insert(:note) + deadline = Pleroma.Config.get([:instance, :remote_post_retention_days]) + 1 + + date = + Timex.now() + |> Timex.shift(days: -deadline) + |> Timex.to_naive_datetime() + |> NaiveDateTime.truncate(:second) + + %{id: id} = + :note + |> insert() + |> Ecto.Changeset.change(%{inserted_at: date}) + |> Repo.update!() + + assert length(Repo.all(Object)) == 2 + + Mix.Tasks.Pleroma.Database.run(["prune_objects"]) + + assert length(Repo.all(Object)) == 1 + refute Object.get_by_id(id) + end + end + + describe "running update_users_following_followers_counts" do + test "following and followers count are updated" do + [user, user2] = insert_pair(:user) + {:ok, %User{} = user} = User.follow(user, user2) + + following = User.following(user) + + assert length(following) == 2 + assert user.follower_count == 0 + + {:ok, user} = + user + |> Ecto.Changeset.change(%{follower_count: 3}) + |> Repo.update() + + assert user.follower_count == 3 + + assert :ok == Mix.Tasks.Pleroma.Database.run(["update_users_following_followers_counts"]) + + user = User.get_by_id(user.id) + + assert length(User.following(user)) == 2 + assert user.follower_count == 0 + end + end + + describe "running fix_likes_collections" do + test "it turns OrderedCollection likes into empty arrays" do + [user, user2] = insert_pair(:user) + + {:ok, %{id: id, object: object}} = CommonAPI.post(user, %{status: "test"}) + {:ok, %{object: object2}} = CommonAPI.post(user, %{status: "test test"}) + + CommonAPI.favorite(user2, id) + + likes = %{ + "first" => + "http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes?page=1", + "id" => "http://mastodon.example.org/objects/dbdbc507-52c8-490d-9b7c-1e1d52e5c132/likes", + "totalItems" => 3, + "type" => "OrderedCollection" + } + + new_data = Map.put(object2.data, "likes", likes) + + object2 + |> Ecto.Changeset.change(%{data: new_data}) + |> Repo.update() + + assert length(Object.get_by_id(object.id).data["likes"]) == 1 + assert is_map(Object.get_by_id(object2.id).data["likes"]) + + assert :ok == Mix.Tasks.Pleroma.Database.run(["fix_likes_collections"]) + + assert length(Object.get_by_id(object.id).data["likes"]) == 1 + assert Enum.empty?(Object.get_by_id(object2.id).data["likes"]) + end + end + + describe "ensure_expiration" do + test "it adds to expiration old statuses" do + activity1 = insert(:note_activity) + + {:ok, inserted_at, 0} = DateTime.from_iso8601("2015-01-23T23:50:07Z") + activity2 = insert(:note_activity, %{inserted_at: inserted_at}) + + %{id: activity_id3} = insert(:note_activity) + + expires_at = DateTime.add(DateTime.utc_now(), 60 * 61) + + Pleroma.Workers.PurgeExpiredActivity.enqueue(%{ + activity_id: activity_id3, + expires_at: expires_at + }) + + Mix.Tasks.Pleroma.Database.run(["ensure_expiration"]) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: activity1.id}, + scheduled_at: + activity1.inserted_at + |> DateTime.from_naive!("Etc/UTC") + |> Timex.shift(days: 365) + ) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: activity2.id}, + scheduled_at: + activity2.inserted_at + |> DateTime.from_naive!("Etc/UTC") + |> Timex.shift(days: 365) + ) + + assert_enqueued( + worker: Pleroma.Workers.PurgeExpiredActivity, + args: %{activity_id: activity_id3}, + scheduled_at: expires_at + ) + end + end +end diff --git a/test/mix/tasks/pleroma/digest_test.exs b/test/mix/tasks/pleroma/digest_test.exs new file mode 100644 index 000000000..69dccb745 --- /dev/null +++ b/test/mix/tasks/pleroma/digest_test.exs @@ -0,0 +1,60 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.DigestTest do + use Pleroma.DataCase + + import Pleroma.Factory + import Swoosh.TestAssertions + + alias Pleroma.Tests.ObanHelpers + alias Pleroma.Web.CommonAPI + + setup_all do + Mix.shell(Mix.Shell.Process) + + on_exit(fn -> + Mix.shell(Mix.Shell.IO) + end) + + :ok + end + + setup do: clear_config([Pleroma.Emails.Mailer, :enabled], true) + + describe "pleroma.digest test" do + test "Sends digest to the given user" do + user1 = insert(:user) + user2 = insert(:user) + + Enum.each(0..10, fn i -> + {:ok, _activity} = + CommonAPI.post(user1, %{ + status: "hey ##{i} @#{user2.nickname}!" + }) + end) + + yesterday = + NaiveDateTime.add( + NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second), + -60 * 60 * 24, + :second + ) + + {:ok, yesterday_date} = Timex.format(yesterday, "%F", :strftime) + + :ok = Mix.Tasks.Pleroma.Digest.run(["test", user2.nickname, yesterday_date]) + + ObanHelpers.perform_all() + + assert_receive {:mix_shell, :info, [message]} + assert message =~ "Digest email have been sent" + + assert_email_sent( + to: {user2.name, user2.email}, + html_body: ~r/here is what you've missed!/i + ) + end + end +end diff --git a/test/mix/tasks/pleroma/ecto/migrate_test.exs b/test/mix/tasks/pleroma/ecto/migrate_test.exs new file mode 100644 index 000000000..43df176a1 --- /dev/null +++ b/test/mix/tasks/pleroma/ecto/migrate_test.exs @@ -0,0 +1,20 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-onl + +defmodule Mix.Tasks.Pleroma.Ecto.MigrateTest do + use Pleroma.DataCase, async: true + import ExUnit.CaptureLog + require Logger + + test "ecto.migrate info message" do + level = Logger.level() + Logger.configure(level: :warn) + + assert capture_log(fn -> + Mix.Tasks.Pleroma.Ecto.Migrate.run() + end) =~ "[info] Already up" + + Logger.configure(level: level) + end +end diff --git a/test/mix/tasks/pleroma/ecto/rollback_test.exs b/test/mix/tasks/pleroma/ecto/rollback_test.exs new file mode 100644 index 000000000..0236e35d5 --- /dev/null +++ b/test/mix/tasks/pleroma/ecto/rollback_test.exs @@ -0,0 +1,20 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.Ecto.RollbackTest do + use Pleroma.DataCase + import ExUnit.CaptureLog + require Logger + + test "ecto.rollback info message" do + level = Logger.level() + Logger.configure(level: :warn) + + assert capture_log(fn -> + Mix.Tasks.Pleroma.Ecto.Rollback.run() + end) =~ "[info] Rollback succesfully" + + Logger.configure(level: level) + end +end diff --git a/test/mix/tasks/pleroma/ecto_test.exs b/test/mix/tasks/pleroma/ecto_test.exs new file mode 100644 index 000000000..3a028df83 --- /dev/null +++ b/test/mix/tasks/pleroma/ecto_test.exs @@ -0,0 +1,15 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.EctoTest do + use ExUnit.Case, async: true + + test "raise on bad path" do + assert_raise RuntimeError, ~r/Could not find migrations directory/, fn -> + Mix.Tasks.Pleroma.Ecto.ensure_migrations_path(Pleroma.Repo, + migrations_path: "some-path" + ) + end + end +end diff --git a/test/mix/tasks/pleroma/email_test.exs b/test/mix/tasks/pleroma/email_test.exs new file mode 100644 index 000000000..9523aefd8 --- /dev/null +++ b/test/mix/tasks/pleroma/email_test.exs @@ -0,0 +1,127 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.EmailTest do + use Pleroma.DataCase + + import Swoosh.TestAssertions + + alias Pleroma.Config + alias Pleroma.Tests.ObanHelpers + + import Pleroma.Factory + + setup_all do + Mix.shell(Mix.Shell.Process) + + on_exit(fn -> + Mix.shell(Mix.Shell.IO) + end) + + :ok + end + + setup do: clear_config([Pleroma.Emails.Mailer, :enabled], true) + setup do: clear_config([:instance, :account_activation_required], true) + + describe "pleroma.email test" do + test "Sends test email with no given address" do + mail_to = Config.get([:instance, :email]) + + :ok = Mix.Tasks.Pleroma.Email.run(["test"]) + + ObanHelpers.perform_all() + + assert_receive {:mix_shell, :info, [message]} + assert message =~ "Test email has been sent" + + assert_email_sent( + to: mail_to, + html_body: ~r/a test email was requested./i + ) + end + + test "Sends test email with given address" do + mail_to = "hewwo@example.com" + + :ok = Mix.Tasks.Pleroma.Email.run(["test", "--to", mail_to]) + + ObanHelpers.perform_all() + + assert_receive {:mix_shell, :info, [message]} + assert message =~ "Test email has been sent" + + assert_email_sent( + to: mail_to, + html_body: ~r/a test email was requested./i + ) + end + + test "Sends confirmation emails" do + local_user1 = + insert(:user, %{ + confirmation_pending: true, + confirmation_token: "mytoken", + deactivated: false, + email: "local1@pleroma.com", + local: true + }) + + local_user2 = + insert(:user, %{ + confirmation_pending: true, + confirmation_token: "mytoken", + deactivated: false, + email: "local2@pleroma.com", + local: true + }) + + :ok = Mix.Tasks.Pleroma.Email.run(["resend_confirmation_emails"]) + + ObanHelpers.perform_all() + + assert_email_sent(to: {local_user1.name, local_user1.email}) + assert_email_sent(to: {local_user2.name, local_user2.email}) + end + + test "Does not send confirmation email to inappropriate users" do + # confirmed user + insert(:user, %{ + confirmation_pending: false, + confirmation_token: "mytoken", + deactivated: false, + email: "confirmed@pleroma.com", + local: true + }) + + # remote user + insert(:user, %{ + deactivated: false, + email: "remote@not-pleroma.com", + local: false + }) + + # deactivated user = + insert(:user, %{ + deactivated: true, + email: "deactivated@pleroma.com", + local: false + }) + + # invisible user + insert(:user, %{ + deactivated: false, + email: "invisible@pleroma.com", + local: true, + invisible: true + }) + + :ok = Mix.Tasks.Pleroma.Email.run(["resend_confirmation_emails"]) + + ObanHelpers.perform_all() + + refute_email_sent() + end + end +end diff --git a/test/mix/tasks/pleroma/emoji_test.exs b/test/mix/tasks/pleroma/emoji_test.exs new file mode 100644 index 000000000..0fb8603ac --- /dev/null +++ b/test/mix/tasks/pleroma/emoji_test.exs @@ -0,0 +1,243 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.EmojiTest do + use ExUnit.Case, async: true + + import ExUnit.CaptureIO + import Tesla.Mock + + alias Mix.Tasks.Pleroma.Emoji + + describe "ls-packs" do + test "with default manifest as url" do + mock(fn + %{ + method: :get, + url: "https://git.pleroma.social/pleroma/emoji-index/raw/master/index.json" + } -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/emoji/packs/default-manifest.json") + } + end) + + capture_io(fn -> Emoji.run(["ls-packs"]) end) =~ + "https://finland.fi/wp-content/uploads/2017/06/finland-emojis.zip" + end + + test "with passed manifest as file" do + capture_io(fn -> + Emoji.run(["ls-packs", "-m", "test/fixtures/emoji/packs/manifest.json"]) + end) =~ "https://git.pleroma.social/pleroma/emoji-index/raw/master/packs/blobs_gg.zip" + end + end + + describe "get-packs" do + test "download pack from default manifest" do + mock(fn + %{ + method: :get, + url: "https://git.pleroma.social/pleroma/emoji-index/raw/master/index.json" + } -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/emoji/packs/default-manifest.json") + } + + %{ + method: :get, + url: "https://finland.fi/wp-content/uploads/2017/06/finland-emojis.zip" + } -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/emoji/packs/blank.png.zip") + } + + %{ + method: :get, + url: "https://git.pleroma.social/pleroma/emoji-index/raw/master/finmoji.json" + } -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/emoji/packs/finmoji.json") + } + end) + + assert capture_io(fn -> Emoji.run(["get-packs", "finmoji"]) end) =~ "Writing pack.json for" + + emoji_path = + Path.join( + Pleroma.Config.get!([:instance, :static_dir]), + "emoji" + ) + + assert File.exists?(Path.join([emoji_path, "finmoji", "pack.json"])) + on_exit(fn -> File.rm_rf!("test/instance_static/emoji/finmoji") end) + end + + test "install local emoji pack" do + assert capture_io(fn -> + Emoji.run([ + "get-packs", + "local", + "--manifest", + "test/instance_static/local_pack/manifest.json" + ]) + end) =~ "Writing pack.json for" + + on_exit(fn -> File.rm_rf!("test/instance_static/emoji/local") end) + end + + test "pack not found" do + mock(fn + %{ + method: :get, + url: "https://git.pleroma.social/pleroma/emoji-index/raw/master/index.json" + } -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/emoji/packs/default-manifest.json") + } + end) + + assert capture_io(fn -> Emoji.run(["get-packs", "not_found"]) end) =~ + "No pack named \"not_found\" found" + end + + test "raise on bad sha256" do + mock(fn + %{ + method: :get, + url: "https://git.pleroma.social/pleroma/emoji-index/raw/master/packs/blobs_gg.zip" + } -> + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/emoji/packs/blank.png.zip") + } + end) + + assert_raise RuntimeError, ~r/^Bad SHA256 for blobs.gg/, fn -> + capture_io(fn -> + Emoji.run(["get-packs", "blobs.gg", "-m", "test/fixtures/emoji/packs/manifest.json"]) + end) + end + end + end + + describe "gen-pack" do + setup do + url = "https://finland.fi/wp-content/uploads/2017/06/finland-emojis.zip" + + mock(fn %{ + method: :get, + url: ^url + } -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/emoji/packs/blank.png.zip")} + end) + + {:ok, url: url} + end + + test "with default extensions", %{url: url} do + name = "pack1" + pack_json = "#{name}.json" + files_json = "#{name}_file.json" + refute File.exists?(pack_json) + refute File.exists?(files_json) + + captured = + capture_io(fn -> + Emoji.run([ + "gen-pack", + url, + "--name", + name, + "--license", + "license", + "--homepage", + "homepage", + "--description", + "description", + "--files", + files_json, + "--extensions", + ".png .gif" + ]) + end) + + assert captured =~ "#{pack_json} has been created with the pack1 pack" + assert captured =~ "Using .png .gif extensions" + + assert File.exists?(pack_json) + assert File.exists?(files_json) + + on_exit(fn -> + File.rm!(pack_json) + File.rm!(files_json) + end) + end + + test "with custom extensions and update existing files", %{url: url} do + name = "pack2" + pack_json = "#{name}.json" + files_json = "#{name}_file.json" + refute File.exists?(pack_json) + refute File.exists?(files_json) + + captured = + capture_io(fn -> + Emoji.run([ + "gen-pack", + url, + "--name", + name, + "--license", + "license", + "--homepage", + "homepage", + "--description", + "description", + "--files", + files_json, + "--extensions", + " .png .gif .jpeg " + ]) + end) + + assert captured =~ "#{pack_json} has been created with the pack2 pack" + assert captured =~ "Using .png .gif .jpeg extensions" + + assert File.exists?(pack_json) + assert File.exists?(files_json) + + captured = + capture_io(fn -> + Emoji.run([ + "gen-pack", + url, + "--name", + name, + "--license", + "license", + "--homepage", + "homepage", + "--description", + "description", + "--files", + files_json, + "--extensions", + " .png .gif .jpeg " + ]) + end) + + assert captured =~ "#{pack_json} has been updated with the pack2 pack" + + on_exit(fn -> + File.rm!(pack_json) + File.rm!(files_json) + end) + end + end +end diff --git a/test/mix/tasks/pleroma/frontend_test.exs b/test/mix/tasks/pleroma/frontend_test.exs new file mode 100644 index 000000000..6f9ec14cd --- /dev/null +++ b/test/mix/tasks/pleroma/frontend_test.exs @@ -0,0 +1,85 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.FrontendTest do + use Pleroma.DataCase + alias Mix.Tasks.Pleroma.Frontend + + import ExUnit.CaptureIO, only: [capture_io: 1] + + @dir "test/frontend_static_test" + + setup do + File.mkdir_p!(@dir) + clear_config([:instance, :static_dir], @dir) + + on_exit(fn -> + File.rm_rf(@dir) + end) + end + + test "it downloads and unzips a known frontend" do + clear_config([:frontends, :available], %{ + "pleroma" => %{ + "ref" => "fantasy", + "name" => "pleroma", + "build_url" => "http://gensokyo.2hu/builds/${ref}" + } + }) + + Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/builds/fantasy"} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend_dist.zip")} + end) + + capture_io(fn -> + Frontend.run(["install", "pleroma"]) + end) + + assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"])) + end + + test "it also works given a file" do + clear_config([:frontends, :available], %{ + "pleroma" => %{ + "ref" => "fantasy", + "name" => "pleroma", + "build_dir" => "" + } + }) + + folder = Path.join([@dir, "frontends", "pleroma", "fantasy"]) + previously_existing = Path.join([folder, "temp"]) + File.mkdir_p!(folder) + File.write!(previously_existing, "yey") + assert File.exists?(previously_existing) + + capture_io(fn -> + Frontend.run(["install", "pleroma", "--file", "test/fixtures/tesla_mock/frontend.zip"]) + end) + + assert File.exists?(Path.join([folder, "test.txt"])) + refute File.exists?(previously_existing) + end + + test "it downloads and unzips unknown frontends" do + Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend.zip")} + end) + + capture_io(fn -> + Frontend.run([ + "install", + "unknown", + "--ref", + "baka", + "--build-url", + "http://gensokyo.2hu/madeup.zip", + "--build-dir", + "" + ]) + end) + + assert File.exists?(Path.join([@dir, "frontends", "unknown", "baka", "test.txt"])) + end +end diff --git a/test/mix/tasks/pleroma/instance_test.exs b/test/mix/tasks/pleroma/instance_test.exs new file mode 100644 index 000000000..8a02710ee --- /dev/null +++ b/test/mix/tasks/pleroma/instance_test.exs @@ -0,0 +1,99 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.InstanceTest do + use ExUnit.Case + + setup do + File.mkdir_p!(tmp_path()) + + on_exit(fn -> + File.rm_rf(tmp_path()) + static_dir = Pleroma.Config.get([:instance, :static_dir], "test/instance_static/") + + if File.exists?(static_dir) do + File.rm_rf(Path.join(static_dir, "robots.txt")) + end + + Pleroma.Config.put([:instance, :static_dir], static_dir) + end) + + :ok + end + + defp tmp_path do + "/tmp/generated_files/" + end + + test "running gen" do + mix_task = fn -> + Mix.Tasks.Pleroma.Instance.run([ + "gen", + "--output", + tmp_path() <> "generated_config.exs", + "--output-psql", + tmp_path() <> "setup.psql", + "--domain", + "test.pleroma.social", + "--instance-name", + "Pleroma", + "--admin-email", + "admin@example.com", + "--notify-email", + "notify@example.com", + "--dbhost", + "dbhost", + "--dbname", + "dbname", + "--dbuser", + "dbuser", + "--dbpass", + "dbpass", + "--indexable", + "y", + "--db-configurable", + "y", + "--rum", + "y", + "--listen-port", + "4000", + "--listen-ip", + "127.0.0.1", + "--uploads-dir", + "test/uploads", + "--static-dir", + "./test/../test/instance/static/", + "--strip-uploads", + "y", + "--dedupe-uploads", + "n", + "--anonymize-uploads", + "n" + ]) + end + + ExUnit.CaptureIO.capture_io(fn -> + mix_task.() + end) + + generated_config = File.read!(tmp_path() <> "generated_config.exs") + assert generated_config =~ "host: \"test.pleroma.social\"" + assert generated_config =~ "name: \"Pleroma\"" + assert generated_config =~ "email: \"admin@example.com\"" + assert generated_config =~ "notify_email: \"notify@example.com\"" + assert generated_config =~ "hostname: \"dbhost\"" + assert generated_config =~ "database: \"dbname\"" + assert generated_config =~ "username: \"dbuser\"" + assert generated_config =~ "password: \"dbpass\"" + assert generated_config =~ "configurable_from_database: true" + assert generated_config =~ "http: [ip: {127, 0, 0, 1}, port: 4000]" + assert generated_config =~ "filters: [Pleroma.Upload.Filter.ExifTool]" + assert File.read!(tmp_path() <> "setup.psql") == generated_setup_psql() + assert File.exists?(Path.expand("./test/instance/static/robots.txt")) + end + + defp generated_setup_psql do + ~s(CREATE USER dbuser WITH ENCRYPTED PASSWORD 'dbpass';\nCREATE DATABASE dbname OWNER dbuser;\n\\c dbname;\n--Extensions made by ecto.migrate that need superuser access\nCREATE EXTENSION IF NOT EXISTS citext;\nCREATE EXTENSION IF NOT EXISTS pg_trgm;\nCREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";\nCREATE EXTENSION IF NOT EXISTS rum;\n) + end +end diff --git a/test/mix/tasks/pleroma/refresh_counter_cache_test.exs b/test/mix/tasks/pleroma/refresh_counter_cache_test.exs new file mode 100644 index 000000000..6a1a9ac17 --- /dev/null +++ b/test/mix/tasks/pleroma/refresh_counter_cache_test.exs @@ -0,0 +1,43 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.RefreshCounterCacheTest do + use Pleroma.DataCase + alias Pleroma.Web.CommonAPI + import ExUnit.CaptureIO, only: [capture_io: 1] + import Pleroma.Factory + + test "counts statuses" do + user = insert(:user) + other_user = insert(:user) + + CommonAPI.post(user, %{visibility: "public", status: "hey"}) + + Enum.each(0..1, fn _ -> + CommonAPI.post(user, %{ + visibility: "unlisted", + status: "hey" + }) + end) + + Enum.each(0..2, fn _ -> + CommonAPI.post(user, %{ + visibility: "direct", + status: "hey @#{other_user.nickname}" + }) + end) + + Enum.each(0..3, fn _ -> + CommonAPI.post(user, %{ + visibility: "private", + status: "hey" + }) + end) + + assert capture_io(fn -> Mix.Tasks.Pleroma.RefreshCounterCache.run([]) end) =~ "Done\n" + + assert %{"direct" => 3, "private" => 4, "public" => 1, "unlisted" => 2} = + Pleroma.Stats.get_status_visibility_count() + end +end diff --git a/test/mix/tasks/pleroma/relay_test.exs b/test/mix/tasks/pleroma/relay_test.exs new file mode 100644 index 000000000..cf48e7dda --- /dev/null +++ b/test/mix/tasks/pleroma/relay_test.exs @@ -0,0 +1,180 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.RelayTest do + alias Pleroma.Activity + alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Relay + alias Pleroma.Web.ActivityPub.Utils + use Pleroma.DataCase + + import Pleroma.Factory + + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + + Mix.shell(Mix.Shell.Process) + + on_exit(fn -> + Mix.shell(Mix.Shell.IO) + end) + + :ok + end + + describe "running follow" do + test "relay is followed" do + target_instance = "http://mastodon.example.org/users/admin" + + Mix.Tasks.Pleroma.Relay.run(["follow", target_instance]) + + local_user = Relay.get_actor() + assert local_user.ap_id =~ "/relay" + + target_user = User.get_cached_by_ap_id(target_instance) + refute target_user.local + + activity = Utils.fetch_latest_follow(local_user, target_user) + assert activity.data["type"] == "Follow" + assert activity.data["actor"] == local_user.ap_id + assert activity.data["object"] == target_user.ap_id + + :ok = Mix.Tasks.Pleroma.Relay.run(["list"]) + + assert_receive {:mix_shell, :info, + [ + "http://mastodon.example.org/users/admin - no Accept received (relay didn't follow back)" + ]} + end + end + + describe "running unfollow" do + test "relay is unfollowed" do + user = insert(:user) + target_instance = user.ap_id + + Mix.Tasks.Pleroma.Relay.run(["follow", target_instance]) + + %User{ap_id: follower_id} = local_user = Relay.get_actor() + target_user = User.get_cached_by_ap_id(target_instance) + follow_activity = Utils.fetch_latest_follow(local_user, target_user) + User.follow(local_user, target_user) + assert "#{target_instance}/followers" in User.following(local_user) + Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance]) + + cancelled_activity = Activity.get_by_ap_id(follow_activity.data["id"]) + assert cancelled_activity.data["state"] == "cancelled" + + [undo_activity] = + ActivityPub.fetch_activities([], %{ + type: "Undo", + actor_id: follower_id, + limit: 1, + skip_preload: true, + invisible_actors: true + }) + + assert undo_activity.data["type"] == "Undo" + assert undo_activity.data["actor"] == local_user.ap_id + assert undo_activity.data["object"]["id"] == cancelled_activity.data["id"] + refute "#{target_instance}/followers" in User.following(local_user) + end + + test "unfollow when relay is dead" do + user = insert(:user) + target_instance = user.ap_id + + Mix.Tasks.Pleroma.Relay.run(["follow", target_instance]) + + %User{ap_id: follower_id} = local_user = Relay.get_actor() + target_user = User.get_cached_by_ap_id(target_instance) + follow_activity = Utils.fetch_latest_follow(local_user, target_user) + User.follow(local_user, target_user) + + assert "#{target_instance}/followers" in User.following(local_user) + + Tesla.Mock.mock(fn %{method: :get, url: ^target_instance} -> + %Tesla.Env{status: 404} + end) + + Pleroma.Repo.delete(user) + Cachex.clear(:user_cache) + + Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance]) + + cancelled_activity = Activity.get_by_ap_id(follow_activity.data["id"]) + assert cancelled_activity.data["state"] == "accept" + + assert [] == + ActivityPub.fetch_activities( + [], + %{ + type: "Undo", + actor_id: follower_id, + skip_preload: true, + invisible_actors: true + } + ) + end + + test "force unfollow when relay is dead" do + user = insert(:user) + target_instance = user.ap_id + + Mix.Tasks.Pleroma.Relay.run(["follow", target_instance]) + + %User{ap_id: follower_id} = local_user = Relay.get_actor() + target_user = User.get_cached_by_ap_id(target_instance) + follow_activity = Utils.fetch_latest_follow(local_user, target_user) + User.follow(local_user, target_user) + + assert "#{target_instance}/followers" in User.following(local_user) + + Tesla.Mock.mock(fn %{method: :get, url: ^target_instance} -> + %Tesla.Env{status: 404} + end) + + Pleroma.Repo.delete(user) + Cachex.clear(:user_cache) + + Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance, "--force"]) + + cancelled_activity = Activity.get_by_ap_id(follow_activity.data["id"]) + assert cancelled_activity.data["state"] == "cancelled" + + [undo_activity] = + ActivityPub.fetch_activities( + [], + %{type: "Undo", actor_id: follower_id, skip_preload: true, invisible_actors: true} + ) + + assert undo_activity.data["type"] == "Undo" + assert undo_activity.data["actor"] == local_user.ap_id + assert undo_activity.data["object"]["id"] == cancelled_activity.data["id"] + refute "#{target_instance}/followers" in User.following(local_user) + end + end + + describe "mix pleroma.relay list" do + test "Prints relay subscription list" do + :ok = Mix.Tasks.Pleroma.Relay.run(["list"]) + + refute_receive {:mix_shell, :info, _} + + relay_user = Relay.get_actor() + + ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"] + |> Enum.each(fn ap_id -> + {:ok, user} = User.get_or_fetch_by_ap_id(ap_id) + User.follow(relay_user, user) + end) + + :ok = Mix.Tasks.Pleroma.Relay.run(["list"]) + + assert_receive {:mix_shell, :info, ["https://mstdn.io/users/mayuutann"]} + assert_receive {:mix_shell, :info, ["http://mastodon.example.org/users/admin"]} + end + end +end diff --git a/test/mix/tasks/pleroma/robots_txt_test.exs b/test/mix/tasks/pleroma/robots_txt_test.exs new file mode 100644 index 000000000..7040a0e4e --- /dev/null +++ b/test/mix/tasks/pleroma/robots_txt_test.exs @@ -0,0 +1,45 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.RobotsTxtTest do + use ExUnit.Case + use Pleroma.Tests.Helpers + alias Mix.Tasks.Pleroma.RobotsTxt + + setup do: clear_config([:instance, :static_dir]) + + test "creates new dir" do + path = "test/fixtures/new_dir/" + file_path = path <> "robots.txt" + Pleroma.Config.put([:instance, :static_dir], path) + + on_exit(fn -> + {:ok, ["test/fixtures/new_dir/", "test/fixtures/new_dir/robots.txt"]} = File.rm_rf(path) + end) + + RobotsTxt.run(["disallow_all"]) + + assert File.exists?(file_path) + {:ok, file} = File.read(file_path) + + assert file == "User-Agent: *\nDisallow: /\n" + end + + test "to existance folder" do + path = "test/fixtures/" + file_path = path <> "robots.txt" + Pleroma.Config.put([:instance, :static_dir], path) + + on_exit(fn -> + :ok = File.rm(file_path) + end) + + RobotsTxt.run(["disallow_all"]) + + assert File.exists?(file_path) + {:ok, file} = File.read(file_path) + + assert file == "User-Agent: *\nDisallow: /\n" + end +end diff --git a/test/mix/tasks/pleroma/uploads_test.exs b/test/mix/tasks/pleroma/uploads_test.exs new file mode 100644 index 000000000..d69e149a8 --- /dev/null +++ b/test/mix/tasks/pleroma/uploads_test.exs @@ -0,0 +1,56 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.UploadsTest do + alias Pleroma.Upload + use Pleroma.DataCase + + import Mock + + setup_all do + Mix.shell(Mix.Shell.Process) + + on_exit(fn -> + Mix.shell(Mix.Shell.IO) + end) + + :ok + end + + describe "running migrate_local" do + test "uploads migrated" do + with_mock Upload, + store: fn %Upload{name: _file, path: _path}, _opts -> {:ok, %{}} end do + Mix.Tasks.Pleroma.Uploads.run(["migrate_local", "S3"]) + + assert_received {:mix_shell, :info, [message]} + assert message =~ "Migrating files from local" + + assert_received {:mix_shell, :info, [message]} + + assert %{"total_count" => total_count} = + Regex.named_captures(~r"^Found (?<total_count>\d+) uploads$", message) + + assert_received {:mix_shell, :info, [message]} + + # @logevery in Mix.Tasks.Pleroma.Uploads + count = + min(50, String.to_integer(total_count)) + |> to_string() + + assert %{"count" => ^count, "total_count" => ^total_count} = + Regex.named_captures( + ~r"^Uploaded (?<count>\d+)/(?<total_count>\d+) files$", + message + ) + end + end + + test "nonexistent uploader" do + assert_raise RuntimeError, ~r/The uploader .* is not an existing/, fn -> + Mix.Tasks.Pleroma.Uploads.run(["migrate_local", "nonexistent"]) + end + end + end +end diff --git a/test/mix/tasks/pleroma/user_test.exs b/test/mix/tasks/pleroma/user_test.exs new file mode 100644 index 000000000..09e1f472e --- /dev/null +++ b/test/mix/tasks/pleroma/user_test.exs @@ -0,0 +1,614 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Mix.Tasks.Pleroma.UserTest do + alias Pleroma.Activity + alias Pleroma.MFA + alias Pleroma.Object + alias Pleroma.Repo + alias Pleroma.Tests.ObanHelpers + alias Pleroma.User + alias Pleroma.Web.CommonAPI + alias Pleroma.Web.OAuth.Authorization + alias Pleroma.Web.OAuth.Token + + use Pleroma.DataCase + use Oban.Testing, repo: Pleroma.Repo + + import ExUnit.CaptureIO + import Mock + import Pleroma.Factory + + setup_all do + Mix.shell(Mix.Shell.Process) + + on_exit(fn -> + Mix.shell(Mix.Shell.IO) + end) + + :ok + end + + describe "running new" do + test "user is created" do + # just get random data + unsaved = build(:user) + + # prepare to answer yes + send(self(), {:mix_shell_input, :yes?, true}) + + Mix.Tasks.Pleroma.User.run([ + "new", + unsaved.nickname, + unsaved.email, + "--name", + unsaved.name, + "--bio", + unsaved.bio, + "--password", + "test", + "--moderator", + "--admin" + ]) + + assert_received {:mix_shell, :info, [message]} + assert message =~ "user will be created" + + assert_received {:mix_shell, :yes?, [message]} + assert message =~ "Continue" + + assert_received {:mix_shell, :info, [message]} + assert message =~ "created" + + user = User.get_cached_by_nickname(unsaved.nickname) + assert user.name == unsaved.name + assert user.email == unsaved.email + assert user.bio == unsaved.bio + assert user.is_moderator + assert user.is_admin + end + + test "user is not created" do + unsaved = build(:user) + + # prepare to answer no + send(self(), {:mix_shell_input, :yes?, false}) + + Mix.Tasks.Pleroma.User.run(["new", unsaved.nickname, unsaved.email]) + + assert_received {:mix_shell, :info, [message]} + assert message =~ "user will be created" + + assert_received {:mix_shell, :yes?, [message]} + assert message =~ "Continue" + + assert_received {:mix_shell, :info, [message]} + assert message =~ "will not be created" + + refute User.get_cached_by_nickname(unsaved.nickname) + end + end + + describe "running rm" do + test "user is deleted" do + clear_config([:instance, :federating], true) + user = insert(:user) + + with_mock Pleroma.Web.Federator, + publish: fn _ -> nil end do + Mix.Tasks.Pleroma.User.run(["rm", user.nickname]) + ObanHelpers.perform_all() + + assert_received {:mix_shell, :info, [message]} + assert message =~ " deleted" + assert %{deactivated: true} = User.get_by_nickname(user.nickname) + + assert called(Pleroma.Web.Federator.publish(:_)) + end + end + + test "a remote user's create activity is deleted when the object has been pruned" do + user = insert(:user) + user2 = insert(:user) + + {:ok, post} = CommonAPI.post(user, %{status: "uguu"}) + {:ok, post2} = CommonAPI.post(user2, %{status: "test"}) + obj = Object.normalize(post2) + + {:ok, like_object, meta} = Pleroma.Web.ActivityPub.Builder.like(user, obj) + + {:ok, like_activity, _meta} = + Pleroma.Web.ActivityPub.Pipeline.common_pipeline( + like_object, + Keyword.put(meta, :local, true) + ) + + like_activity.data["object"] + |> Pleroma.Object.get_by_ap_id() + |> Repo.delete() + + clear_config([:instance, :federating], true) + + object = Object.normalize(post) + Object.prune(object) + + with_mock Pleroma.Web.Federator, + publish: fn _ -> nil end do + Mix.Tasks.Pleroma.User.run(["rm", user.nickname]) + ObanHelpers.perform_all() + + assert_received {:mix_shell, :info, [message]} + assert message =~ " deleted" + assert %{deactivated: true} = User.get_by_nickname(user.nickname) + + assert called(Pleroma.Web.Federator.publish(:_)) + refute Pleroma.Repo.get(Pleroma.Activity, like_activity.id) + end + + refute Activity.get_by_id(post.id) + end + + test "no user to delete" do + Mix.Tasks.Pleroma.User.run(["rm", "nonexistent"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No local user" + end + end + + describe "running toggle_activated" do + test "user is deactivated" do + user = insert(:user) + + Mix.Tasks.Pleroma.User.run(["toggle_activated", user.nickname]) + + assert_received {:mix_shell, :info, [message]} + assert message =~ " deactivated" + + user = User.get_cached_by_nickname(user.nickname) + assert user.deactivated + end + + test "user is activated" do + user = insert(:user, deactivated: true) + + Mix.Tasks.Pleroma.User.run(["toggle_activated", user.nickname]) + + assert_received {:mix_shell, :info, [message]} + assert message =~ " activated" + + user = User.get_cached_by_nickname(user.nickname) + refute user.deactivated + end + + test "no user to toggle" do + Mix.Tasks.Pleroma.User.run(["toggle_activated", "nonexistent"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No user" + end + end + + describe "running deactivate" do + test "user is unsubscribed" do + followed = insert(:user) + remote_followed = insert(:user, local: false) + user = insert(:user) + + User.follow(user, followed, :follow_accept) + User.follow(user, remote_followed, :follow_accept) + + Mix.Tasks.Pleroma.User.run(["deactivate", user.nickname]) + + assert_received {:mix_shell, :info, [message]} + assert message =~ "Deactivating" + + # Note that the task has delay :timer.sleep(500) + assert_received {:mix_shell, :info, [message]} + assert message =~ "Successfully unsubscribed" + + user = User.get_cached_by_nickname(user.nickname) + assert Enum.empty?(Enum.filter(User.get_friends(user), & &1.local)) + assert user.deactivated + end + + test "no user to deactivate" do + Mix.Tasks.Pleroma.User.run(["deactivate", "nonexistent"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No user" + end + end + + describe "running set" do + test "All statuses set" do + user = insert(:user) + + Mix.Tasks.Pleroma.User.run([ + "set", + user.nickname, + "--admin", + "--confirmed", + "--locked", + "--moderator" + ]) + + assert_received {:mix_shell, :info, [message]} + assert message =~ ~r/Admin status .* true/ + + assert_received {:mix_shell, :info, [message]} + assert message =~ ~r/Confirmation pending .* false/ + + assert_received {:mix_shell, :info, [message]} + assert message =~ ~r/Locked status .* true/ + + assert_received {:mix_shell, :info, [message]} + assert message =~ ~r/Moderator status .* true/ + + user = User.get_cached_by_nickname(user.nickname) + assert user.is_moderator + assert user.is_locked + assert user.is_admin + refute user.confirmation_pending + end + + test "All statuses unset" do + user = + insert(:user, is_locked: true, is_moderator: true, is_admin: true, confirmation_pending: true) + + Mix.Tasks.Pleroma.User.run([ + "set", + user.nickname, + "--no-admin", + "--no-confirmed", + "--no-locked", + "--no-moderator" + ]) + + assert_received {:mix_shell, :info, [message]} + assert message =~ ~r/Admin status .* false/ + + assert_received {:mix_shell, :info, [message]} + assert message =~ ~r/Confirmation pending .* true/ + + assert_received {:mix_shell, :info, [message]} + assert message =~ ~r/Locked status .* false/ + + assert_received {:mix_shell, :info, [message]} + assert message =~ ~r/Moderator status .* false/ + + user = User.get_cached_by_nickname(user.nickname) + refute user.is_moderator + refute user.is_locked + refute user.is_admin + assert user.confirmation_pending + end + + test "no user to set status" do + Mix.Tasks.Pleroma.User.run(["set", "nonexistent", "--moderator"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No local user" + end + end + + describe "running reset_password" do + test "password reset token is generated" do + user = insert(:user) + + assert capture_io(fn -> + Mix.Tasks.Pleroma.User.run(["reset_password", user.nickname]) + end) =~ "URL:" + + assert_received {:mix_shell, :info, [message]} + assert message =~ "Generated" + end + + test "no user to reset password" do + Mix.Tasks.Pleroma.User.run(["reset_password", "nonexistent"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No local user" + end + end + + describe "running reset_mfa" do + test "disables MFA" do + user = + insert(:user, + multi_factor_authentication_settings: %MFA.Settings{ + enabled: true, + totp: %MFA.Settings.TOTP{secret: "xx", confirmed: true} + } + ) + + Mix.Tasks.Pleroma.User.run(["reset_mfa", user.nickname]) + + assert_received {:mix_shell, :info, [message]} + assert message == "Multi-Factor Authentication disabled for #{user.nickname}" + + assert %{enabled: false, totp: false} == + user.nickname + |> User.get_cached_by_nickname() + |> MFA.mfa_settings() + end + + test "no user to reset MFA" do + Mix.Tasks.Pleroma.User.run(["reset_password", "nonexistent"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No local user" + end + end + + describe "running invite" do + test "invite token is generated" do + assert capture_io(fn -> + Mix.Tasks.Pleroma.User.run(["invite"]) + end) =~ "http" + + assert_received {:mix_shell, :info, [message]} + assert message =~ "Generated user invite token one time" + end + + test "token is generated with expires_at" do + assert capture_io(fn -> + Mix.Tasks.Pleroma.User.run([ + "invite", + "--expires-at", + Date.to_string(Date.utc_today()) + ]) + end) + + assert_received {:mix_shell, :info, [message]} + assert message =~ "Generated user invite token date limited" + end + + test "token is generated with max use" do + assert capture_io(fn -> + Mix.Tasks.Pleroma.User.run([ + "invite", + "--max-use", + "5" + ]) + end) + + assert_received {:mix_shell, :info, [message]} + assert message =~ "Generated user invite token reusable" + end + + test "token is generated with max use and expires date" do + assert capture_io(fn -> + Mix.Tasks.Pleroma.User.run([ + "invite", + "--max-use", + "5", + "--expires-at", + Date.to_string(Date.utc_today()) + ]) + end) + + assert_received {:mix_shell, :info, [message]} + assert message =~ "Generated user invite token reusable date limited" + end + end + + describe "running invites" do + test "invites are listed" do + {:ok, invite} = Pleroma.UserInviteToken.create_invite() + + {:ok, invite2} = + Pleroma.UserInviteToken.create_invite(%{expires_at: Date.utc_today(), max_use: 15}) + + # assert capture_io(fn -> + Mix.Tasks.Pleroma.User.run([ + "invites" + ]) + + # end) + + assert_received {:mix_shell, :info, [message]} + assert_received {:mix_shell, :info, [message2]} + assert_received {:mix_shell, :info, [message3]} + assert message =~ "Invites list:" + assert message2 =~ invite.invite_type + assert message3 =~ invite2.invite_type + end + end + + describe "running revoke_invite" do + test "invite is revoked" do + {:ok, invite} = Pleroma.UserInviteToken.create_invite(%{expires_at: Date.utc_today()}) + + assert capture_io(fn -> + Mix.Tasks.Pleroma.User.run([ + "revoke_invite", + invite.token + ]) + end) + + assert_received {:mix_shell, :info, [message]} + assert message =~ "Invite for token #{invite.token} was revoked." + end + + test "it prints an error message when invite is not exist" do + Mix.Tasks.Pleroma.User.run(["revoke_invite", "foo"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No invite found" + end + end + + describe "running delete_activities" do + test "activities are deleted" do + %{nickname: nickname} = insert(:user) + + assert :ok == Mix.Tasks.Pleroma.User.run(["delete_activities", nickname]) + assert_received {:mix_shell, :info, [message]} + assert message == "User #{nickname} statuses deleted." + end + + test "it prints an error message when user is not exist" do + Mix.Tasks.Pleroma.User.run(["delete_activities", "foo"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No local user" + end + end + + describe "running toggle_confirmed" do + test "user is confirmed" do + %{id: id, nickname: nickname} = insert(:user, confirmation_pending: false) + + assert :ok = Mix.Tasks.Pleroma.User.run(["toggle_confirmed", nickname]) + assert_received {:mix_shell, :info, [message]} + assert message == "#{nickname} needs confirmation." + + user = Repo.get(User, id) + assert user.confirmation_pending + assert user.confirmation_token + end + + test "user is not confirmed" do + %{id: id, nickname: nickname} = + insert(:user, confirmation_pending: true, confirmation_token: "some token") + + assert :ok = Mix.Tasks.Pleroma.User.run(["toggle_confirmed", nickname]) + assert_received {:mix_shell, :info, [message]} + assert message == "#{nickname} doesn't need confirmation." + + user = Repo.get(User, id) + refute user.confirmation_pending + refute user.confirmation_token + end + + test "it prints an error message when user is not exist" do + Mix.Tasks.Pleroma.User.run(["toggle_confirmed", "foo"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No local user" + end + end + + describe "search" do + test "it returns users matching" do + user = insert(:user) + moon = insert(:user, nickname: "moon", name: "fediverse expert moon") + moot = insert(:user, nickname: "moot") + kawen = insert(:user, nickname: "kawen", name: "fediverse expert moon") + + {:ok, user} = User.follow(user, moon) + + assert [moon.id, kawen.id] == User.Search.search("moon") |> Enum.map(& &1.id) + + res = User.search("moo") |> Enum.map(& &1.id) + assert Enum.sort([moon.id, moot.id, kawen.id]) == Enum.sort(res) + + assert [kawen.id, moon.id] == User.Search.search("expert fediverse") |> Enum.map(& &1.id) + + assert [moon.id, kawen.id] == + User.Search.search("expert fediverse", for_user: user) |> Enum.map(& &1.id) + end + end + + describe "signing out" do + test "it deletes all user's tokens and authorizations" do + user = insert(:user) + insert(:oauth_token, user: user) + insert(:oauth_authorization, user: user) + + assert Repo.get_by(Token, user_id: user.id) + assert Repo.get_by(Authorization, user_id: user.id) + + :ok = Mix.Tasks.Pleroma.User.run(["sign_out", user.nickname]) + + refute Repo.get_by(Token, user_id: user.id) + refute Repo.get_by(Authorization, user_id: user.id) + end + + test "it prints an error message when user is not exist" do + Mix.Tasks.Pleroma.User.run(["sign_out", "foo"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "No local user" + end + end + + describe "tagging" do + test "it add tags to a user" do + user = insert(:user) + + :ok = Mix.Tasks.Pleroma.User.run(["tag", user.nickname, "pleroma"]) + + user = User.get_cached_by_nickname(user.nickname) + assert "pleroma" in user.tags + end + + test "it prints an error message when user is not exist" do + Mix.Tasks.Pleroma.User.run(["tag", "foo"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "Could not change user tags" + end + end + + describe "untagging" do + test "it deletes tags from a user" do + user = insert(:user, tags: ["pleroma"]) + assert "pleroma" in user.tags + + :ok = Mix.Tasks.Pleroma.User.run(["untag", user.nickname, "pleroma"]) + + user = User.get_cached_by_nickname(user.nickname) + assert Enum.empty?(user.tags) + end + + test "it prints an error message when user is not exist" do + Mix.Tasks.Pleroma.User.run(["untag", "foo"]) + + assert_received {:mix_shell, :error, [message]} + assert message =~ "Could not change user tags" + end + end + + describe "bulk confirm and unconfirm" do + test "confirm all" do + user1 = insert(:user, confirmation_pending: true) + user2 = insert(:user, confirmation_pending: true) + + assert user1.confirmation_pending + assert user2.confirmation_pending + + Mix.Tasks.Pleroma.User.run(["confirm_all"]) + + user1 = User.get_cached_by_nickname(user1.nickname) + user2 = User.get_cached_by_nickname(user2.nickname) + + refute user1.confirmation_pending + refute user2.confirmation_pending + end + + test "unconfirm all" do + user1 = insert(:user, confirmation_pending: false) + user2 = insert(:user, confirmation_pending: false) + admin = insert(:user, is_admin: true, confirmation_pending: false) + mod = insert(:user, is_moderator: true, confirmation_pending: false) + + refute user1.confirmation_pending + refute user2.confirmation_pending + + Mix.Tasks.Pleroma.User.run(["unconfirm_all"]) + + user1 = User.get_cached_by_nickname(user1.nickname) + user2 = User.get_cached_by_nickname(user2.nickname) + admin = User.get_cached_by_nickname(admin.nickname) + mod = User.get_cached_by_nickname(mod.nickname) + + assert user1.confirmation_pending + assert user2.confirmation_pending + refute admin.confirmation_pending + refute mod.confirmation_pending + end + end +end |