1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
6 use Pleroma.Web.ConnCase
11 @emoji_path Path.join(
12 Pleroma.Config.get!([:instance, :static_dir]),
15 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
18 admin = insert(:user, is_admin: true)
19 token = insert(:oauth_admin_token, user: admin)
23 |> assign(:user, admin)
24 |> assign(:token, token)
26 Pleroma.Emoji.reload()
27 {:ok, %{admin_conn: admin_conn}}
30 test "GET /api/pleroma/emoji/packs", %{conn: conn} do
31 resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)
33 shared = resp["test_pack"]
34 assert shared["files"] == %{"blank" => "blank.png"}
35 assert Map.has_key?(shared["pack"], "download-sha256")
36 assert shared["pack"]["can-download"]
37 assert shared["pack"]["share-files"]
39 non_shared = resp["test_pack_nonshared"]
40 assert non_shared["pack"]["share-files"] == false
41 assert non_shared["pack"]["can-download"] == false
44 describe "POST /api/pleroma/emoji/packs/list_from" do
45 test "shareable instance", %{admin_conn: admin_conn, conn: conn} do
48 |> get("/api/pleroma/emoji/packs")
52 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
53 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
55 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
56 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
58 %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} ->
63 |> post("/api/pleroma/emoji/packs/list_from", %{
64 instance_address: "https://example.com"
66 |> json_response(200) == resp
69 test "non shareable instance", %{admin_conn: admin_conn} do
71 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
72 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
74 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
75 json(%{metadata: %{features: []}})
79 |> post("/api/pleroma/emoji/packs/list_from", %{
80 instance_address: "https://example.com"
82 |> json_response(500) == %{
83 "error" => "The requested instance does not support sharing emoji packs"
88 describe "GET /api/pleroma/emoji/packs/:name/download_shared" do
89 test "download shared pack", %{conn: conn} do
92 |> get("/api/pleroma/emoji/packs/test_pack/download_shared")
95 {:ok, arch} = :zip.unzip(resp, [:memory])
97 assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end)
98 assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end)
101 test "non existing pack", %{conn: conn} do
103 |> get("/api/pleroma/emoji/packs/test_pack_for_import/download_shared")
104 |> json_response(:not_found) == %{
105 "error" => "Pack test_pack_for_import does not exist"
109 test "non downloadable pack", %{conn: conn} do
111 |> get("/api/pleroma/emoji/packs/test_pack_nonshared/download_shared")
112 |> json_response(:forbidden) == %{
114 "Pack test_pack_nonshared cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing"
119 describe "POST /api/pleroma/emoji/packs/download_from" do
120 test "shared pack from remote and non shared from fallback-src", %{
121 admin_conn: admin_conn,
125 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
126 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
128 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
129 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
133 url: "https://example.com/api/pleroma/emoji/packs/test_pack"
136 |> get("/api/pleroma/emoji/packs/test_pack")
137 |> json_response(200)
142 url: "https://example.com/api/pleroma/emoji/packs/test_pack/download_shared"
145 |> get("/api/pleroma/emoji/packs/test_pack/download_shared")
151 url: "https://example.com/api/pleroma/emoji/packs/test_pack_nonshared"
154 |> get("/api/pleroma/emoji/packs/test_pack_nonshared")
155 |> json_response(200)
160 url: "https://nonshared-pack"
162 text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))
166 |> post("/api/pleroma/emoji/packs/download_from", %{
167 instance_address: "https://example.com",
168 pack_name: "test_pack",
171 |> json_response(200) == "ok"
173 assert File.exists?("#{@emoji_path}/test_pack2/pack.json")
174 assert File.exists?("#{@emoji_path}/test_pack2/blank.png")
177 |> delete("/api/pleroma/emoji/packs/test_pack2")
178 |> json_response(200) == "ok"
180 refute File.exists?("#{@emoji_path}/test_pack2")
184 "/api/pleroma/emoji/packs/download_from",
186 instance_address: "https://example.com",
187 pack_name: "test_pack_nonshared",
188 as: "test_pack_nonshared2"
191 |> json_response(200) == "ok"
193 assert File.exists?("#{@emoji_path}/test_pack_nonshared2/pack.json")
194 assert File.exists?("#{@emoji_path}/test_pack_nonshared2/blank.png")
197 |> delete("/api/pleroma/emoji/packs/test_pack_nonshared2")
198 |> json_response(200) == "ok"
200 refute File.exists?("#{@emoji_path}/test_pack_nonshared2")
203 test "nonshareable instance", %{admin_conn: admin_conn} do
205 %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} ->
206 json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]})
208 %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} ->
209 json(%{metadata: %{features: []}})
214 "/api/pleroma/emoji/packs/download_from",
216 instance_address: "https://old-instance",
217 pack_name: "test_pack",
221 |> json_response(500) == %{
222 "error" => "The requested instance does not support sharing emoji packs"
226 test "checksum fail", %{admin_conn: admin_conn} do
228 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
229 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
231 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
232 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
236 url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha"
240 body: Pleroma.Emoji.Pack.load_pack("pack_bad_sha") |> Jason.encode!()
245 url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha/download_shared"
249 body: File.read!("test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip")
254 |> post("/api/pleroma/emoji/packs/download_from", %{
255 instance_address: "https://example.com",
256 pack_name: "pack_bad_sha",
259 |> json_response(:internal_server_error) == %{
260 "error" => "SHA256 for the pack doesn't match the one sent by the server"
264 test "other error", %{admin_conn: admin_conn} do
266 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
267 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
269 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
270 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
274 url: "https://example.com/api/pleroma/emoji/packs/test_pack"
278 body: %{"test_pack" => Pleroma.Emoji.Pack.load_pack("test_pack")} |> Jason.encode!()
283 url: "https://example.com/api/pleroma/emoji/packs/test_pack/download_shared"
287 body: File.read!("test/instance_static/emoji/test_pack/pack.json")
292 |> post("/api/pleroma/emoji/packs/download_from", %{
293 instance_address: "https://example.com",
294 pack_name: "test_pack",
297 |> json_response(:internal_server_error) == %{
299 "The pack was not set as shared and there is no fallback src to download from"
304 describe "updating pack metadata" do
306 pack_file = "#{@emoji_path}/test_pack/pack.json"
307 original_content = File.read!(pack_file)
310 File.write!(pack_file, original_content)
314 pack_file: pack_file,
316 "license" => "Test license changed",
317 "homepage" => "https://pleroma.social",
318 "description" => "Test description",
319 "share-files" => false
323 test "for a pack without a fallback source", ctx do
324 assert ctx[:admin_conn]
326 "/api/pleroma/emoji/packs/test_pack/update_metadata",
328 "new_data" => ctx[:new_data]
331 |> json_response(200) == ctx[:new_data]
333 assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data]
336 test "for a pack with a fallback source", ctx do
340 url: "https://nonshared-pack"
342 text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))
345 new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
350 "fallback-src-sha256",
351 "74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF"
354 assert ctx[:admin_conn]
356 "/api/pleroma/emoji/packs/test_pack/update_metadata",
358 "new_data" => new_data
361 |> json_response(200) == new_data_with_sha
363 assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha
366 test "when the fallback source doesn't have all the files", ctx do
370 url: "https://nonshared-pack"
372 {:ok, {'empty.zip', empty_arch}} = :zip.zip('empty.zip', [], [:memory])
376 new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
378 assert ctx[:admin_conn]
380 "/api/pleroma/emoji/packs/test_pack/update_metadata",
382 "new_data" => new_data
385 |> json_response(:bad_request) == %{
386 "error" => "The fallback archive does not have all files specified in pack.json"
391 describe "POST /api/pleroma/emoji/packs/:pack_name/update_file" do
393 pack_file = "#{@emoji_path}/test_pack/pack.json"
394 original_content = File.read!(pack_file)
397 File.write!(pack_file, original_content)
403 test "create shortcode exists", %{admin_conn: admin_conn} do
405 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
407 "shortcode" => "blank",
408 "filename" => "dir/blank.png",
409 "file" => %Plug.Upload{
410 filename: "blank.png",
411 path: "#{@emoji_path}/test_pack/blank.png"
414 |> json_response(:conflict) == %{
415 "error" => "An emoji with the \"blank\" shortcode already exists"
419 test "don't rewrite old emoji", %{admin_conn: admin_conn} do
420 on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir/") end)
423 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
425 "shortcode" => "blank2",
426 "filename" => "dir/blank.png",
427 "file" => %Plug.Upload{
428 filename: "blank.png",
429 path: "#{@emoji_path}/test_pack/blank.png"
432 |> json_response(200) == %{"blank" => "blank.png", "blank2" => "dir/blank.png"}
434 assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
437 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
438 "action" => "update",
439 "shortcode" => "blank",
440 "new_shortcode" => "blank2",
441 "new_filename" => "dir_2/blank_3.png"
443 |> json_response(:conflict) == %{
445 "New shortcode \"blank2\" is already used. If you want to override emoji use 'force' option"
449 test "rewrite old emoji with force option", %{admin_conn: admin_conn} do
450 on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir_2/") end)
453 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
455 "shortcode" => "blank2",
456 "filename" => "dir/blank.png",
457 "file" => %Plug.Upload{
458 filename: "blank.png",
459 path: "#{@emoji_path}/test_pack/blank.png"
462 |> json_response(200) == %{"blank" => "blank.png", "blank2" => "dir/blank.png"}
464 assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
467 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
468 "action" => "update",
469 "shortcode" => "blank2",
470 "new_shortcode" => "blank3",
471 "new_filename" => "dir_2/blank_3.png",
474 |> json_response(200) == %{
475 "blank" => "blank.png",
476 "blank3" => "dir_2/blank_3.png"
479 assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png")
482 test "with empty filename", %{admin_conn: admin_conn} do
484 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
486 "shortcode" => "blank2",
488 "file" => %Plug.Upload{
489 filename: "blank.png",
490 path: "#{@emoji_path}/test_pack/blank.png"
493 |> json_response(:bad_request) == %{
494 "error" => "pack name, shortcode or filename cannot be empty"
498 test "add file with not loaded pack", %{admin_conn: admin_conn} do
500 |> post("/api/pleroma/emoji/packs/not_loaded/update_file", %{
502 "shortcode" => "blank2",
503 "filename" => "dir/blank.png",
504 "file" => %Plug.Upload{
505 filename: "blank.png",
506 path: "#{@emoji_path}/test_pack/blank.png"
509 |> json_response(:bad_request) == %{
510 "error" => "pack \"not_loaded\" is not found"
514 test "remove file with not loaded pack", %{admin_conn: admin_conn} do
516 |> post("/api/pleroma/emoji/packs/not_loaded/update_file", %{
517 "action" => "remove",
518 "shortcode" => "blank3"
520 |> json_response(:bad_request) == %{"error" => "pack \"not_loaded\" is not found"}
523 test "remove file with empty shortcode", %{admin_conn: admin_conn} do
525 |> post("/api/pleroma/emoji/packs/not_loaded/update_file", %{
526 "action" => "remove",
529 |> json_response(:bad_request) == %{
530 "error" => "pack name or shortcode cannot be empty"
534 test "update file with not loaded pack", %{admin_conn: admin_conn} do
536 |> post("/api/pleroma/emoji/packs/not_loaded/update_file", %{
537 "action" => "update",
538 "shortcode" => "blank4",
539 "new_shortcode" => "blank3",
540 "new_filename" => "dir_2/blank_3.png"
542 |> json_response(:bad_request) == %{"error" => "pack \"not_loaded\" is not found"}
545 test "new with shortcode as file with update", %{admin_conn: admin_conn} do
547 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
549 "shortcode" => "blank4",
550 "filename" => "dir/blank.png",
551 "file" => %Plug.Upload{
552 filename: "blank.png",
553 path: "#{@emoji_path}/test_pack/blank.png"
556 |> json_response(200) == %{"blank" => "blank.png", "blank4" => "dir/blank.png"}
558 assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
561 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
562 "action" => "update",
563 "shortcode" => "blank4",
564 "new_shortcode" => "blank3",
565 "new_filename" => "dir_2/blank_3.png"
567 |> json_response(200) == %{"blank3" => "dir_2/blank_3.png", "blank" => "blank.png"}
569 refute File.exists?("#{@emoji_path}/test_pack/dir/")
570 assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png")
573 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
574 "action" => "remove",
575 "shortcode" => "blank3"
577 |> json_response(200) == %{"blank" => "blank.png"}
579 refute File.exists?("#{@emoji_path}/test_pack/dir_2/")
581 on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir") end)
584 test "new with shortcode from url", %{admin_conn: admin_conn} do
588 url: "https://test-blank/blank_url.png"
590 text(File.read!("#{@emoji_path}/test_pack/blank.png"))
594 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
596 "shortcode" => "blank_url",
597 "file" => "https://test-blank/blank_url.png"
599 |> json_response(200) == %{
600 "blank_url" => "blank_url.png",
601 "blank" => "blank.png"
604 assert File.exists?("#{@emoji_path}/test_pack/blank_url.png")
606 on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/blank_url.png") end)
609 test "new without shortcode", %{admin_conn: admin_conn} do
610 on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/shortcode.png") end)
613 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
615 "file" => %Plug.Upload{
616 filename: "shortcode.png",
617 path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png"
620 |> json_response(200) == %{"shortcode" => "shortcode.png", "blank" => "blank.png"}
623 test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do
625 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
626 "action" => "remove",
627 "shortcode" => "blank2"
629 |> json_response(:bad_request) == %{"error" => "Emoji \"blank2\" does not exist"}
632 test "update non existing emoji", %{admin_conn: admin_conn} do
634 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
635 "action" => "update",
636 "shortcode" => "blank2",
637 "new_shortcode" => "blank3",
638 "new_filename" => "dir_2/blank_3.png"
640 |> json_response(:bad_request) == %{"error" => "Emoji \"blank2\" does not exist"}
643 test "update with empty shortcode", %{admin_conn: admin_conn} do
645 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
646 "action" => "update",
647 "shortcode" => "blank",
648 "new_filename" => "dir_2/blank_3.png"
650 |> json_response(:bad_request) == %{
651 "error" => "new_shortcode or new_filename cannot be empty"
655 test "undefined action", %{admin_conn: admin_conn} do
657 |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
658 "action" => "undefined"
660 |> json_response(:bad_request) == %{
661 "error" => "Unknown action: undefined"
666 describe "PUT /api/pleroma/emoji/packs/:name" do
667 test "creating and deleting a pack", %{admin_conn: admin_conn} do
669 |> put("/api/pleroma/emoji/packs/test_created")
670 |> json_response(200) == "ok"
672 assert File.exists?("#{@emoji_path}/test_created/pack.json")
674 assert Jason.decode!(File.read!("#{@emoji_path}/test_created/pack.json")) == %{
680 |> delete("/api/pleroma/emoji/packs/test_created")
681 |> json_response(200) == "ok"
683 refute File.exists?("#{@emoji_path}/test_created/pack.json")
686 test "if pack exists", %{admin_conn: admin_conn} do
687 path = Path.join(@emoji_path, "test_created")
689 pack_file = Jason.encode!(%{files: %{}, pack: %{}})
690 File.write!(Path.join(path, "pack.json"), pack_file)
693 |> put("/api/pleroma/emoji/packs/test_created")
694 |> json_response(:conflict) == %{
695 "error" => "A pack named \"test_created\" already exists"
698 on_exit(fn -> File.rm_rf(path) end)
701 test "with empty name", %{admin_conn: admin_conn} do
703 |> put("/api/pleroma/emoji/packs/ ")
704 |> json_response(:bad_request) == %{"error" => "pack name cannot be empty"}
708 test "deleting nonexisting pack", %{admin_conn: admin_conn} do
710 |> delete("/api/pleroma/emoji/packs/non_existing")
711 |> json_response(:not_found) == %{"error" => "Pack non_existing does not exist"}
714 test "deleting with empty name", %{admin_conn: admin_conn} do
716 |> delete("/api/pleroma/emoji/packs/ ")
717 |> json_response(:bad_request) == %{"error" => "pack name cannot be empty"}
720 test "filesystem import", %{admin_conn: admin_conn, conn: conn} do
722 File.rm!("#{@emoji_path}/test_pack_for_import/emoji.txt")
723 File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")
726 resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)
728 refute Map.has_key?(resp, "test_pack_for_import")
731 |> post("/api/pleroma/emoji/packs/import_from_fs")
732 |> json_response(200) == ["test_pack_for_import"]
734 resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)
735 assert resp["test_pack_for_import"]["files"] == %{"blank" => "blank.png"}
737 File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")
738 refute File.exists?("#{@emoji_path}/test_pack_for_import/pack.json")
740 emoji_txt_content = """
741 blank, blank.png, Fun
743 foo, /emoji/test_pack_for_import/blank.png
747 File.write!("#{@emoji_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
750 |> post("/api/pleroma/emoji/packs/import_from_fs")
751 |> json_response(200) == ["test_pack_for_import"]
753 resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)
755 assert resp["test_pack_for_import"]["files"] == %{
756 "blank" => "blank.png",
757 "blank2" => "blank.png",
762 describe "GET /api/pleroma/emoji/packs/:name" do
763 test "shows pack.json", %{conn: conn} do
765 "files" => %{"blank" => "blank.png"},
767 "can-download" => true,
768 "description" => "Test description",
769 "download-sha256" => _,
770 "homepage" => "https://pleroma.social",
771 "license" => "Test license",
772 "share-files" => true
776 |> get("/api/pleroma/emoji/packs/test_pack")
777 |> json_response(200)
780 test "non existing pack", %{conn: conn} do
782 |> get("/api/pleroma/emoji/packs/non_existing")
783 |> json_response(:not_found) == %{"error" => "Pack non_existing does not exist"}
786 test "error name", %{conn: conn} do
788 |> get("/api/pleroma/emoji/packs/ ")
789 |> json_response(:bad_request) == %{"error" => "pack name cannot be empty"}