diff options
author | Tusooa Zhu <tusooa@kazv.moe> | 2022-07-03 22:24:57 +0000 |
---|---|---|
committer | Tusooa Zhu <tusooa@kazv.moe> | 2022-07-03 22:24:57 +0000 |
commit | 4edc867b87362475a8cd749257e5d29c431467b4 (patch) | |
tree | 8805651d07c82f48c2935dcdf598016045a1813d /test | |
parent | 014096aeefe88348323db74e2ab7f81e0184bfee (diff) | |
parent | c50ade26ba9f63802512a745107de66aba59e9fe (diff) | |
download | pleroma-4edc867b87362475a8cd749257e5d29c431467b4.tar.gz pleroma-4edc867b87362475a8cd749257e5d29c431467b4.zip |
Merge branch 'develop' into 'from/upstream-develop/tusooa/edits'
# Conflicts:
# lib/pleroma/constants.ex
Diffstat (limited to 'test')
16 files changed, 828 insertions, 9 deletions
diff --git a/test/fixtures/image_with_caption-abstract.jpg b/test/fixtures/image_with_caption-abstract.jpg Binary files differnew file mode 100644 index 000000000..f982ffa81 --- /dev/null +++ b/test/fixtures/image_with_caption-abstract.jpg diff --git a/test/fixtures/image_with_imagedescription_and_caption-abstract.jpg b/test/fixtures/image_with_imagedescription_and_caption-abstract.jpg Binary files differnew file mode 100644 index 000000000..c82a269ef --- /dev/null +++ b/test/fixtures/image_with_imagedescription_and_caption-abstract.jpg diff --git a/test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg b/test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg Binary files differnew file mode 100644 index 000000000..a232fd2a1 --- /dev/null +++ b/test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg diff --git a/test/fixtures/image_with_no_description.jpg b/test/fixtures/image_with_no_description.jpg Binary files differnew file mode 100644 index 000000000..ec6fc4be8 --- /dev/null +++ b/test/fixtures/image_with_no_description.jpg diff --git a/test/mix/tasks/pleroma/instance_test.exs b/test/mix/tasks/pleroma/instance_test.exs index 249689ec6..b1c10e03c 100644 --- a/test/mix/tasks/pleroma/instance_test.exs +++ b/test/mix/tasks/pleroma/instance_test.exs @@ -67,7 +67,9 @@ defmodule Mix.Tasks.Pleroma.InstanceTest do "test/uploads", "--static-dir", "./test/../test/instance/static/", - "--strip-uploads", + "--strip-uploads-location", + "y", + "--read-uploads-description", "y", "--dedupe-uploads", "n", @@ -91,7 +93,10 @@ defmodule Mix.Tasks.Pleroma.InstanceTest do 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 generated_config =~ + "filters: [Pleroma.Upload.Filter.Exiftool.StripLocation, Pleroma.Upload.Filter.Exiftool.ReadDescription]" + assert File.read!(tmp_path() <> "setup.psql") == generated_setup_psql() assert File.exists?(Path.expand("./test/instance/static/robots.txt")) end diff --git a/test/pleroma/announcement_read_relationship_test.exs b/test/pleroma/announcement_read_relationship_test.exs new file mode 100644 index 000000000..5fd4ffbef --- /dev/null +++ b/test/pleroma/announcement_read_relationship_test.exs @@ -0,0 +1,40 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.AnnouncementReadRelationshipTest do + alias Pleroma.AnnouncementReadRelationship + + use Pleroma.DataCase, async: true + + import Pleroma.Factory + + setup do + {:ok, user: insert(:user), announcement: insert(:announcement)} + end + + describe "mark_read/2" do + test "should insert relationship", %{user: user, announcement: announcement} do + {:ok, _} = AnnouncementReadRelationship.mark_read(user, announcement) + + assert AnnouncementReadRelationship.exists?(user, announcement) + end + end + + describe "mark_unread/2" do + test "should delete relationship", %{user: user, announcement: announcement} do + {:ok, _} = AnnouncementReadRelationship.mark_read(user, announcement) + + assert :ok = AnnouncementReadRelationship.mark_unread(user, announcement) + refute AnnouncementReadRelationship.exists?(user, announcement) + end + + test "should not fail if relationship does not exist", %{ + user: user, + announcement: announcement + } do + assert :ok = AnnouncementReadRelationship.mark_unread(user, announcement) + refute AnnouncementReadRelationship.exists?(user, announcement) + end + end +end diff --git a/test/pleroma/announcement_test.exs b/test/pleroma/announcement_test.exs new file mode 100644 index 000000000..a007c3718 --- /dev/null +++ b/test/pleroma/announcement_test.exs @@ -0,0 +1,98 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.AnnouncementTest do + alias Pleroma.Announcement + + use Pleroma.DataCase, async: true + + import Pleroma.Factory + + describe "list_all_visible_when/1" do + setup do: {:ok, time: NaiveDateTime.utc_now()} + + test "with no start or end time", %{time: time} do + _announcement = insert(:announcement) + + assert [_] = Announcement.list_all_visible_when(time) + end + + test "with start time before current", %{time: time} do + before_now = NaiveDateTime.add(time, -10, :second) + + _announcement = insert(:announcement, %{starts_at: before_now}) + + assert [_] = Announcement.list_all_visible_when(time) + end + + test "with start time after current", %{time: time} do + after_now = NaiveDateTime.add(time, 10, :second) + + _announcement = insert(:announcement, %{starts_at: after_now}) + + assert [] = Announcement.list_all_visible_when(time) + end + + test "with end time after current", %{time: time} do + after_now = NaiveDateTime.add(time, 10, :second) + + _announcement = insert(:announcement, %{ends_at: after_now}) + + assert [_] = Announcement.list_all_visible_when(time) + end + + test "with end time before current", %{time: time} do + before_now = NaiveDateTime.add(time, -10, :second) + + _announcement = insert(:announcement, %{ends_at: before_now}) + + assert [] = Announcement.list_all_visible_when(time) + end + + test "with both start and end time", %{time: time} do + before_now = NaiveDateTime.add(time, -10, :second) + after_now = NaiveDateTime.add(time, 10, :second) + + _announcement = insert(:announcement, %{starts_at: before_now, ends_at: after_now}) + + assert [_] = Announcement.list_all_visible_when(time) + end + + test "with both start and end time, current not in the range", %{time: time} do + before_now = NaiveDateTime.add(time, -10, :second) + after_now = NaiveDateTime.add(time, 10, :second) + + _announcement = insert(:announcement, %{starts_at: after_now, ends_at: before_now}) + + assert [] = Announcement.list_all_visible_when(time) + end + end + + describe "announcements formatting" do + test "it formats links" do + raw = "something on https://pleroma.social ." + announcement = insert(:announcement, %{data: %{"content" => raw}}) + + assert announcement.rendered["content"] =~ ~r(<a.+?https://pleroma.social) + assert announcement.data["content"] == raw + end + + test "it formats mentions" do + user = insert(:user) + raw = "something on @#{user.nickname} ." + announcement = insert(:announcement, %{data: %{"content" => raw}}) + + assert announcement.rendered["content"] =~ ~r(<a.+?#{user.nickname}) + assert announcement.data["content"] == raw + end + + test "it formats tags" do + raw = "something on #mew ." + announcement = insert(:announcement, %{data: %{"content" => raw}}) + + assert announcement.rendered["content"] =~ ~r(<a.+?#mew) + assert announcement.data["content"] == raw + end + end +end diff --git a/test/pleroma/config/deprecation_warnings_test.exs b/test/pleroma/config/deprecation_warnings_test.exs index 202ec4b90..f3453ddb0 100644 --- a/test/pleroma/config/deprecation_warnings_test.exs +++ b/test/pleroma/config/deprecation_warnings_test.exs @@ -11,6 +11,62 @@ defmodule Pleroma.Config.DeprecationWarningsTest do alias Pleroma.Config alias Pleroma.Config.DeprecationWarnings + describe "filter exiftool" do + test "gives warning when still used" do + clear_config( + [Pleroma.Upload, :filters], + [Pleroma.Upload.Filter.Exiftool] + ) + + assert capture_log(fn -> DeprecationWarnings.check_exiftool_filter() end) =~ + """ + !!!DEPRECATION WARNING!!! + Your config is using Exiftool as a filter instead of Exiftool.StripLocation. This should work for now, but you are advised to change to the new configuration to prevent possible issues later: + + ``` + config :pleroma, Pleroma.Upload, + filters: [Pleroma.Upload.Filter.Exiftool] + ``` + + Is now + + + ``` + config :pleroma, Pleroma.Upload, + filters: [Pleroma.Upload.Filter.Exiftool.StripLocation] + ``` + """ + end + + test "changes setting to exiftool strip location" do + clear_config( + [Pleroma.Upload, :filters], + [Pleroma.Upload.Filter.Exiftool, Pleroma.Upload.Filter.Exiftool.ReadDescription] + ) + + expected_config = [ + Pleroma.Upload.Filter.Exiftool.StripLocation, + Pleroma.Upload.Filter.Exiftool.ReadDescription + ] + + capture_log(fn -> DeprecationWarnings.warn() end) + + assert Config.get([Pleroma.Upload]) |> Keyword.get(:filters, []) == expected_config + end + + test "doesn't give a warning with correct config" do + clear_config( + [Pleroma.Upload, :filters], + [ + Pleroma.Upload.Filter.Exiftool.StripLocation, + Pleroma.Upload.Filter.Exiftool.ReadDescription + ] + ) + + assert capture_log(fn -> DeprecationWarnings.check_exiftool_filter() end) == "" + end + end + describe "simple policy tuples" do test "gives warning when there are still strings" do clear_config([:mrf_simple], diff --git a/test/pleroma/config_db_test.exs b/test/pleroma/config_db_test.exs index ea44b716f..ba7c615e2 100644 --- a/test/pleroma/config_db_test.exs +++ b/test/pleroma/config_db_test.exs @@ -238,10 +238,11 @@ defmodule Pleroma.ConfigDBTest do end test "ssl options" do - assert ConfigDB.to_elixir_types([":tlsv1", ":tlsv1.1", ":tlsv1.2"]) == [ + assert ConfigDB.to_elixir_types([":tlsv1", ":tlsv1.1", ":tlsv1.2", ":tlsv1.3"]) == [ :tlsv1, :"tlsv1.1", - :"tlsv1.2" + :"tlsv1.2", + :"tlsv1.3" ] end diff --git a/test/pleroma/docs/generator_test.exs b/test/pleroma/docs/generator_test.exs index 92b4d13e4..5e41d6ccb 100644 --- a/test/pleroma/docs/generator_test.exs +++ b/test/pleroma/docs/generator_test.exs @@ -86,7 +86,7 @@ defmodule Pleroma.Docs.GeneratorTest do key: :versions, type: {:list, :atom}, description: "List of TLS version to use", - suggestions: [:tlsv1, ":tlsv1.1", ":tlsv1.2"] + suggestions: [:tlsv1, ":tlsv1.1", ":tlsv1.2", ":tlsv1.3"] } ] }, @@ -213,7 +213,7 @@ defmodule Pleroma.Docs.GeneratorTest do test "suggestion for tls versions" do [%{children: children} | _] = Generator.convert_to_strings(@descriptions) child = Enum.at(children, 8) - assert child[:suggestions] == [":tlsv1", ":tlsv1.1", ":tlsv1.2"] + assert child[:suggestions] == [":tlsv1", ":tlsv1.1", ":tlsv1.2", ":tlsv1.3"] end test "subgroup with module name" do diff --git a/test/pleroma/upload/filter/exiftool/read_description_test.exs b/test/pleroma/upload/filter/exiftool/read_description_test.exs new file mode 100644 index 000000000..7389fda47 --- /dev/null +++ b/test/pleroma/upload/filter/exiftool/read_description_test.exs @@ -0,0 +1,117 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Upload.Filter.Exiftool.ReadDescriptionTest do + use Pleroma.DataCase, async: true + alias Pleroma.Upload.Filter + + @uploads %Pleroma.Upload{ + name: "image_with_imagedescription_and_caption-abstract.jpg", + content_type: "image/jpeg", + path: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"), + tempfile: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"), + description: nil + } + + test "keeps description when not empty" do + uploads = %Pleroma.Upload{ + name: "image_with_imagedescription_and_caption-abstract.jpg", + content_type: "image/jpeg", + path: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"), + tempfile: + Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"), + description: "Some description" + } + + assert Filter.Exiftool.ReadDescription.filter(uploads) == + {:ok, :noop} + end + + test "otherwise returns ImageDescription when present" do + uploads_after = %Pleroma.Upload{ + name: "image_with_imagedescription_and_caption-abstract.jpg", + content_type: "image/jpeg", + path: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"), + tempfile: + Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"), + description: "a descriptive white pixel" + } + + assert Filter.Exiftool.ReadDescription.filter(@uploads) == + {:ok, :filtered, uploads_after} + end + + test "otherwise returns iptc:Caption-Abstract when present" do + upload = %Pleroma.Upload{ + name: "image_with_caption-abstract.jpg", + content_type: "image/jpeg", + path: Path.absname("test/fixtures/image_with_caption-abstract.jpg"), + tempfile: Path.absname("test/fixtures/image_with_caption-abstract.jpg"), + description: nil + } + + upload_after = %Pleroma.Upload{ + name: "image_with_caption-abstract.jpg", + content_type: "image/jpeg", + path: Path.absname("test/fixtures/image_with_caption-abstract.jpg"), + tempfile: Path.absname("test/fixtures/image_with_caption-abstract.jpg"), + description: "an abstract white pixel" + } + + assert Filter.Exiftool.ReadDescription.filter(upload) == + {:ok, :filtered, upload_after} + end + + test "otherwise returns nil" do + uploads = %Pleroma.Upload{ + name: "image_with_no_description.jpg", + content_type: "image/jpeg", + path: Path.absname("test/fixtures/image_with_no_description.jpg"), + tempfile: Path.absname("test/fixtures/image_with_no_description.jpg"), + description: nil + } + + assert Filter.Exiftool.ReadDescription.filter(uploads) == + {:ok, :filtered, uploads} + end + + test "Return nil when image description from EXIF data exceeds the maximum length" do + clear_config([:instance, :description_limit], 5) + + assert Filter.Exiftool.ReadDescription.filter(@uploads) == + {:ok, :filtered, @uploads} + end + + test "Ignores content with only whitespace" do + uploads = %Pleroma.Upload{ + name: "non-existant.jpg", + content_type: "image/jpeg", + path: + Path.absname( + "test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg" + ), + tempfile: + Path.absname( + "test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg" + ), + description: nil + } + + assert Filter.Exiftool.ReadDescription.filter(uploads) == + {:ok, :filtered, uploads} + end + + test "Return nil when image description from EXIF data can't be read" do + uploads = %Pleroma.Upload{ + name: "non-existant.jpg", + content_type: "image/jpeg", + path: Path.absname("test/fixtures/non-existant.jpg"), + tempfile: Path.absname("test/fixtures/non-existant_tmp.jpg"), + description: nil + } + + assert Filter.Exiftool.ReadDescription.filter(uploads) == + {:ok, :filtered, uploads} + end +end diff --git a/test/pleroma/upload/filter/exiftool_test.exs b/test/pleroma/upload/filter/exiftool/strip_location_test.exs index 0a0ef2bdf..7e1541f60 100644 --- a/test/pleroma/upload/filter/exiftool_test.exs +++ b/test/pleroma/upload/filter/exiftool/strip_location_test.exs @@ -2,7 +2,7 @@ # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> # SPDX-License-Identifier: AGPL-3.0-only -defmodule Pleroma.Upload.Filter.ExiftoolTest do +defmodule Pleroma.Upload.Filter.Exiftool.StripLocationTest do use Pleroma.DataCase, async: true alias Pleroma.Upload.Filter @@ -21,7 +21,7 @@ defmodule Pleroma.Upload.Filter.ExiftoolTest do tempfile: Path.absname("test/fixtures/DSCN0010_tmp.jpg") } - assert Filter.Exiftool.filter(upload) == {:ok, :filtered} + assert Filter.Exiftool.StripLocation.filter(upload) == {:ok, :filtered} {exif_original, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010.jpg"]) {exif_filtered, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010_tmp.jpg"]) @@ -37,6 +37,6 @@ defmodule Pleroma.Upload.Filter.ExiftoolTest do content_type: "image/webp" } - assert Filter.Exiftool.filter(upload) == {:ok, :noop} + assert Filter.Exiftool.StripLocation.filter(upload) == {:ok, :noop} end end diff --git a/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs index b07011b76..9a17e277e 100644 --- a/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs +++ b/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs @@ -27,6 +27,46 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do assert attachment.mediaType == "application/octet-stream" end + test "works with an unknown but valid mime type" do + attachment = %{ + "mediaType" => "x-custom/x-type", + "type" => "Document", + "url" => "https://example.org" + } + + assert {:ok, attachment} = + AttachmentValidator.cast_and_validate(attachment) + |> Ecto.Changeset.apply_action(:insert) + + assert attachment.mediaType == "x-custom/x-type" + end + + test "works with invalid mime types" do + attachment = %{ + "mediaType" => "x-customx-type", + "type" => "Document", + "url" => "https://example.org" + } + + assert {:ok, attachment} = + AttachmentValidator.cast_and_validate(attachment) + |> Ecto.Changeset.apply_action(:insert) + + assert attachment.mediaType == "application/octet-stream" + + attachment = %{ + "mediaType" => "https://example.org", + "type" => "Document", + "url" => "https://example.org" + } + + assert {:ok, attachment} = + AttachmentValidator.cast_and_validate(attachment) + |> Ecto.Changeset.apply_action(:insert) + + assert attachment.mediaType == "application/octet-stream" + end + test "it turns mastodon attachments into our attachments" do attachment = %{ "url" => diff --git a/test/pleroma/web/admin_api/controllers/announcement_controller_test.exs b/test/pleroma/web/admin_api/controllers/announcement_controller_test.exs new file mode 100644 index 000000000..5b8148c05 --- /dev/null +++ b/test/pleroma/web/admin_api/controllers/announcement_controller_test.exs @@ -0,0 +1,281 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.AnnouncementControllerTest do + use Pleroma.Web.ConnCase + + import Pleroma.Factory + + setup do + admin = insert(:user, is_admin: true) + token = insert(:oauth_admin_token, user: admin) + + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, token) + + {:ok, %{admin: admin, token: token, conn: conn}} + end + + describe "GET /api/v1/pleroma/admin/announcements" do + test "it lists all announcements", %{conn: conn} do + %{id: id} = insert(:announcement) + + response = + conn + |> get("/api/v1/pleroma/admin/announcements") + |> json_response_and_validate_schema(:ok) + + assert [%{"id" => ^id}] = response + end + + test "it paginates announcements", %{conn: conn} do + _announcements = Enum.map(0..20, fn _ -> insert(:announcement) end) + + response = + conn + |> get("/api/v1/pleroma/admin/announcements") + |> json_response_and_validate_schema(:ok) + + assert length(response) == 20 + end + + test "it paginates announcements with custom params", %{conn: conn} do + announcements = Enum.map(0..20, fn _ -> insert(:announcement) end) + + response = + conn + |> get("/api/v1/pleroma/admin/announcements", limit: 5, offset: 7) + |> json_response_and_validate_schema(:ok) + + assert length(response) == 5 + assert Enum.at(response, 0)["id"] == Enum.at(announcements, 7).id + end + + test "it returns empty list with out-of-bounds offset", %{conn: conn} do + _announcements = Enum.map(0..20, fn _ -> insert(:announcement) end) + + response = + conn + |> get("/api/v1/pleroma/admin/announcements", offset: 21) + |> json_response_and_validate_schema(:ok) + + assert [] = response + end + + test "it rejects invalid pagination params", %{conn: conn} do + conn + |> get("/api/v1/pleroma/admin/announcements", limit: 0) + |> json_response_and_validate_schema(400) + + conn + |> get("/api/v1/pleroma/admin/announcements", limit: -1) + |> json_response_and_validate_schema(400) + + conn + |> get("/api/v1/pleroma/admin/announcements", offset: -1) + |> json_response_and_validate_schema(400) + end + end + + describe "GET /api/v1/pleroma/admin/announcements/:id" do + test "it displays one announcement", %{conn: conn} do + %{id: id} = insert(:announcement) + + response = + conn + |> get("/api/v1/pleroma/admin/announcements/#{id}") + |> json_response_and_validate_schema(:ok) + + assert %{"id" => ^id} = response + end + + test "it returns not found for non-existent id", %{conn: conn} do + %{id: id} = insert(:announcement) + + _response = + conn + |> get("/api/v1/pleroma/admin/announcements/#{id}xxx") + |> json_response_and_validate_schema(:not_found) + end + end + + describe "DELETE /api/v1/pleroma/admin/announcements/:id" do + test "it deletes specified announcement", %{conn: conn} do + %{id: id} = insert(:announcement) + + _response = + conn + |> delete("/api/v1/pleroma/admin/announcements/#{id}") + |> json_response_and_validate_schema(:ok) + end + + test "it returns not found for non-existent id", %{conn: conn} do + %{id: id} = insert(:announcement) + + _response = + conn + |> delete("/api/v1/pleroma/admin/announcements/#{id}xxx") + |> json_response_and_validate_schema(:not_found) + + assert %{id: ^id} = Pleroma.Announcement.get_by_id(id) + end + end + + describe "PATCH /api/v1/pleroma/admin/announcements/:id" do + test "it returns not found for non-existent id", %{conn: conn} do + %{id: id} = insert(:announcement) + + _response = + conn + |> put_req_header("content-type", "application/json") + |> patch("/api/v1/pleroma/admin/announcements/#{id}xxx", %{}) + |> json_response_and_validate_schema(:not_found) + + assert %{id: ^id} = Pleroma.Announcement.get_by_id(id) + end + + test "it updates a field", %{conn: conn} do + %{id: id} = insert(:announcement) + + now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + starts_at = NaiveDateTime.add(now, -10, :second) + + _response = + conn + |> put_req_header("content-type", "application/json") + |> patch("/api/v1/pleroma/admin/announcements/#{id}", %{ + starts_at: NaiveDateTime.to_iso8601(starts_at) + }) + |> json_response_and_validate_schema(:ok) + + new = Pleroma.Announcement.get_by_id(id) + + assert NaiveDateTime.compare(new.starts_at, starts_at) == :eq + end + + test "it updates with time with utc timezone", %{conn: conn} do + %{id: id} = insert(:announcement) + + now = DateTime.now("Etc/UTC") |> elem(1) |> DateTime.truncate(:second) + starts_at = DateTime.add(now, -10, :second) + + _response = + conn + |> put_req_header("content-type", "application/json") + |> patch("/api/v1/pleroma/admin/announcements/#{id}", %{ + starts_at: DateTime.to_iso8601(starts_at) + }) + |> json_response_and_validate_schema(:ok) + + new = Pleroma.Announcement.get_by_id(id) + + assert DateTime.compare(new.starts_at, starts_at) == :eq + end + + test "it updates a data field", %{conn: conn} do + %{id: id} = announcement = insert(:announcement, data: %{"all_day" => true}) + + assert announcement.data["all_day"] == true + + new_content = "new content" + + response = + conn + |> put_req_header("content-type", "application/json") + |> patch("/api/v1/pleroma/admin/announcements/#{id}", %{ + content: new_content + }) + |> json_response_and_validate_schema(:ok) + + assert response["content"] == new_content + assert response["all_day"] == true + + new = Pleroma.Announcement.get_by_id(id) + + assert new.data["content"] == new_content + assert new.data["all_day"] == true + end + + test "it nullifies a nullable field", %{conn: conn} do + now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + starts_at = NaiveDateTime.add(now, -10, :second) + + %{id: id} = insert(:announcement, starts_at: starts_at) + + response = + conn + |> put_req_header("content-type", "application/json") + |> patch("/api/v1/pleroma/admin/announcements/#{id}", %{ + starts_at: nil + }) + |> json_response_and_validate_schema(:ok) + + assert response["starts_at"] == nil + + new = Pleroma.Announcement.get_by_id(id) + + assert new.starts_at == nil + end + end + + describe "POST /api/v1/pleroma/admin/announcements" do + test "it creates an announcement", %{conn: conn} do + content = "test post announcement api" + + now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + starts_at = NaiveDateTime.add(now, -10, :second) + ends_at = NaiveDateTime.add(now, 10, :second) + + response = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/pleroma/admin/announcements", %{ + "content" => content, + "starts_at" => NaiveDateTime.to_iso8601(starts_at), + "ends_at" => NaiveDateTime.to_iso8601(ends_at), + "all_day" => true + }) + |> json_response_and_validate_schema(:ok) + + assert %{"content" => ^content, "all_day" => true} = response + + announcement = Pleroma.Announcement.get_by_id(response["id"]) + + assert not is_nil(announcement) + + assert NaiveDateTime.compare(announcement.starts_at, starts_at) == :eq + assert NaiveDateTime.compare(announcement.ends_at, ends_at) == :eq + end + + test "creating with time with utc timezones", %{conn: conn} do + content = "test post announcement api" + + now = DateTime.now("Etc/UTC") |> elem(1) |> DateTime.truncate(:second) + starts_at = DateTime.add(now, -10, :second) + ends_at = DateTime.add(now, 10, :second) + + response = + conn + |> put_req_header("content-type", "application/json") + |> post("/api/v1/pleroma/admin/announcements", %{ + "content" => content, + "starts_at" => DateTime.to_iso8601(starts_at), + "ends_at" => DateTime.to_iso8601(ends_at), + "all_day" => true + }) + |> json_response_and_validate_schema(:ok) + + assert %{"content" => ^content, "all_day" => true} = response + + announcement = Pleroma.Announcement.get_by_id(response["id"]) + + assert not is_nil(announcement) + + assert DateTime.compare(announcement.starts_at, starts_at) == :eq + assert DateTime.compare(announcement.ends_at, ends_at) == :eq + end + end +end diff --git a/test/pleroma/web/mastodon_api/controllers/announcement_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/announcement_controller_test.exs new file mode 100644 index 000000000..60c9978c2 --- /dev/null +++ b/test/pleroma/web/mastodon_api/controllers/announcement_controller_test.exs @@ -0,0 +1,169 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.AnnouncementControllerTest do + use Pleroma.Web.ConnCase + + import Pleroma.Factory + + alias Pleroma.Announcement + alias Pleroma.AnnouncementReadRelationship + + describe "GET /api/v1/announcements" do + setup do + %{conn: conn} = oauth_access([]) + {:ok, conn: conn} + end + + test "it does not allow guests", %{conn: conn} do + _response = + conn + |> assign(:token, nil) + |> get("/api/v1/announcements") + |> json_response_and_validate_schema(:forbidden) + end + + test "it allows users with scopes" do + %{conn: conn} = oauth_access(["read:accounts"]) + + _response = + conn + |> get("/api/v1/announcements") + |> json_response_and_validate_schema(:ok) + end + + test "it lists all announcements", %{conn: conn} do + %{id: id} = insert(:announcement) + + response = + conn + |> get("/api/v1/announcements") + |> json_response_and_validate_schema(:ok) + + assert [%{"id" => ^id}] = response + end + + test "it returns time with utc timezone", %{conn: conn} do + start_time = + NaiveDateTime.utc_now() + |> NaiveDateTime.add(-999_999, :second) + |> NaiveDateTime.truncate(:second) + + end_time = + NaiveDateTime.utc_now() + |> NaiveDateTime.add(999_999, :second) + |> NaiveDateTime.truncate(:second) + + %{id: id} = insert(:announcement, %{starts_at: start_time, ends_at: end_time}) + + response = + conn + |> get("/api/v1/announcements") + |> json_response_and_validate_schema(:ok) + + assert [%{"id" => ^id}] = [announcement] = response + + assert String.ends_with?(announcement["starts_at"], "Z") + assert String.ends_with?(announcement["ends_at"], "Z") + end + + test "it does not list announcements starting after current time", %{conn: conn} do + time = NaiveDateTime.utc_now() |> NaiveDateTime.add(999_999, :second) + insert(:announcement, starts_at: time) + + response = + conn + |> get("/api/v1/announcements") + |> json_response_and_validate_schema(:ok) + + assert [] = response + end + + test "it does not list announcements ending before current time", %{conn: conn} do + time = NaiveDateTime.utc_now() |> NaiveDateTime.add(-999_999, :second) + insert(:announcement, ends_at: time) + + response = + conn + |> get("/api/v1/announcements") + |> json_response_and_validate_schema(:ok) + + assert [] = response + end + + test "when authenticated, also expose read property", %{conn: conn} do + %{id: id} = insert(:announcement) + + response = + conn + |> get("/api/v1/announcements") + |> json_response_and_validate_schema(:ok) + + assert [%{"id" => ^id, "read" => false}] = response + end + + test "when authenticated and announcement is read by user" do + %{id: id} = announcement = insert(:announcement) + user = insert(:user) + + AnnouncementReadRelationship.mark_read(user, announcement) + + %{conn: conn} = oauth_access(["read:accounts"], user: user) + + response = + conn + |> get("/api/v1/announcements") + |> json_response_and_validate_schema(:ok) + + assert [%{"id" => ^id, "read" => true}] = response + end + end + + describe "POST /api/v1/announcements/:id/dismiss" do + setup do: oauth_access(["write:accounts"]) + + test "it requires auth", %{conn: conn} do + %{id: id} = insert(:announcement) + + _response = + conn + |> assign(:token, nil) + |> post("/api/v1/announcements/#{id}/dismiss") + |> json_response_and_validate_schema(:forbidden) + end + + test "it requires write:accounts oauth scope" do + %{id: id} = insert(:announcement) + + %{conn: conn} = oauth_access(["read:accounts"]) + + _response = + conn + |> post("/api/v1/announcements/#{id}/dismiss") + |> json_response_and_validate_schema(:forbidden) + end + + test "it gives 404 for non-existent announcements", %{conn: conn} do + %{id: id} = insert(:announcement) + + _response = + conn + |> post("/api/v1/announcements/#{id}xxx/dismiss") + |> json_response_and_validate_schema(:not_found) + end + + test "it marks announcement as read", %{user: user, conn: conn} do + %{id: id} = announcement = insert(:announcement) + + refute Announcement.read_by?(announcement, user) + + _response = + conn + |> post("/api/v1/announcements/#{id}/dismiss") + |> json_response_and_validate_schema(:ok) + + assert Announcement.read_by?(announcement, user) + end + end +end diff --git a/test/support/factory.ex b/test/support/factory.ex index aaadae9bd..b01aff3ab 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -639,4 +639,16 @@ defmodule Pleroma.Factory do context: ["home"] } end + + def announcement_factory(params \\ %{}) do + data = Map.get(params, :data, %{}) + + {_, params} = Map.pop(params, :data) + + %Pleroma.Announcement{ + data: Map.merge(%{"content" => "test announcement", "all_day" => false}, data) + } + |> Map.merge(params) + |> Pleroma.Announcement.add_rendered_properties() + end end |