defmodule Mobilizon.GraphQL.Resolvers.ReportTest do use Mobilizon.Web.ConnCase use Mobilizon.Tests.Helpers import Mobilizon.Factory alias Mobilizon.Actors.Actor alias Mobilizon.Config alias Mobilizon.Events.Event alias Mobilizon.Reports.{Note, Report} alias Mobilizon.Users.User alias Mobilizon.GraphQL.AbsintheHelpers describe "Resolver: Report a content" do @create_report_mutation """ mutation CreateReport($reporterId: ID!, $reportedId: ID!, $eventId: ID, $content: String) { createReport( reporterId: $reporterId, reportedId: $reportedId, eventId: $eventId, content: $content ) { content, reporter { id }, event { id }, status } } """ setup do: clear_config([:anonymous, :reports]) setup %{conn: conn} do Mobilizon.Config.clear_config_cache() anonymous_actor_id = Config.anonymous_actor_id() {:ok, conn: conn, anonymous_actor_id: anonymous_actor_id} end test "create_report/3 creates a report", %{conn: conn} do %User{} = user_reporter = insert(:user) %Actor{} = reporter = insert(:actor, user: user_reporter) %Actor{} = reported = insert(:actor) %Event{} = event = insert(:event, organizer_actor: reported) res = conn |> auth_conn(user_reporter) |> AbsintheHelpers.graphql_query( query: @create_report_mutation, variables: %{ reportedId: reported.id, reporterId: reporter.id, eventId: event.id, content: "This is an issue" } ) assert res["errors"] == nil assert res["data"]["createReport"]["content"] == "This is an issue" assert res["data"]["createReport"]["status"] == "OPEN" assert res["data"]["createReport"]["event"]["id"] == to_string(event.id) assert res["data"]["createReport"]["reporter"]["id"] == to_string(reporter.id) end test "create_report/3 without being connected doesn't create any report", %{conn: conn} do %Actor{} = reported = insert(:actor) res = conn |> AbsintheHelpers.graphql_query( query: @create_report_mutation, variables: %{ reportedId: reported.id, reporterId: 5, content: "This is an issue" } ) assert res["errors"] |> hd |> Map.get("message") == "You need to be logged-in to create reports" end test "create_report/3 anonymously creates a report if config has allowed", %{ conn: conn, anonymous_actor_id: anonymous_actor_id } do %Actor{} = reported = insert(:actor) Config.put([:anonymous, :reports, :allowed], true) res = conn |> AbsintheHelpers.graphql_query( query: @create_report_mutation, variables: %{ reportedId: reported.id, reporterId: anonymous_actor_id, content: "This is an issue" } ) assert is_nil(res["errors"]) assert res["data"]["createReport"]["content"] == "This is an issue" assert res["data"]["createReport"]["status"] == "OPEN" assert res["data"]["createReport"]["reporter"]["id"] == to_string(anonymous_actor_id) end test "create_report/3 anonymously doesn't creates a report if the anonymous actor ID is wrong", %{conn: conn} do %Actor{} = reported = insert(:actor) Config.put([:anonymous, :reports, :allowed], true) res = conn |> AbsintheHelpers.graphql_query( query: @create_report_mutation, variables: %{ reportedId: reported.id, reporterId: 53, content: "This is an issue" } ) assert res["errors"] |> hd |> Map.get("message") == "Reporter ID does not match the anonymous profile id" end end describe "Resolver: update a report" do test "update_report/3 updates the report's status", %{conn: conn} do %User{} = user_moderator = insert(:user, role: :moderator) %Actor{} = moderator = insert(:actor, user: user_moderator) %Report{} = report = insert(:report) mutation = """ mutation { updateReportStatus( report_id: #{report.id}, moderator_id: #{moderator.id}, status: RESOLVED ) { content, reporter { id }, event { id }, status } } """ res = conn |> auth_conn(user_moderator) |> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) assert json_response(res, 200)["errors"] == nil assert json_response(res, 200)["data"]["updateReportStatus"]["content"] == "This is problematic" assert json_response(res, 200)["data"]["updateReportStatus"]["status"] == "RESOLVED" assert json_response(res, 200)["data"]["updateReportStatus"]["reporter"]["id"] == to_string(report.reporter.id) end test "create_report/3 without being connected doesn't create any report", %{conn: conn} do %User{} = user_moderator = insert(:user, role: :moderator) %Actor{} = moderator = insert(:actor, user: user_moderator) %Report{} = report = insert(:report) mutation = """ mutation { updateReportStatus( report_id: #{report.id}, moderator_id: #{moderator.id}, status: RESOLVED ) { content } } """ res = conn |> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) assert json_response(res, 200)["errors"] |> hd |> Map.get("message") == "You need to be logged-in and a moderator to update a report" end end describe "Resolver: Get list of reports" do test "get an empty list of reports", %{conn: conn} do %User{} = user_moderator = insert(:user, role: :moderator) query = """ { reports { id, reported { preferredUsername } } } """ res = conn |> get("/api", AbsintheHelpers.query_skeleton(query, "report")) assert json_response(res, 200)["errors"] |> hd |> Map.get("message") == "You need to be logged-in and a moderator to list reports" res = conn |> auth_conn(user_moderator) |> get("/api", AbsintheHelpers.query_skeleton(query, "report")) assert json_response(res, 200)["errors"] == nil assert json_response(res, 200)["data"]["reports"] == [] end test "get a list of reports", %{conn: conn} do %User{} = user_moderator = insert(:user, role: :moderator) # Report don't hold millisecond information so we need to wait a bit # between each insert to keep order %Report{id: report_1_id} = insert(:report, content: "My content 1") Process.sleep(1000) %Report{id: report_2_id} = insert(:report, content: "My content 2") Process.sleep(1000) %Report{id: report_3_id} = insert(:report, content: "My content 3") %Report{} = insert(:report, status: :closed) query = """ { reports { id, reported { preferredUsername }, content, updatedAt } } """ res = conn |> auth_conn(user_moderator) |> get("/api", AbsintheHelpers.query_skeleton(query, "report")) assert json_response(res, 200)["errors"] == nil assert json_response(res, 200)["data"]["reports"] |> Enum.map(fn report -> Map.get(report, "id") end) == Enum.map([report_3_id, report_2_id, report_1_id], &to_string/1) query = """ { reports(page: 2, limit: 2) { id, reported { preferredUsername } } } """ res = conn |> auth_conn(user_moderator) |> get("/api", AbsintheHelpers.query_skeleton(query, "report")) assert json_response(res, 200)["errors"] == nil assert json_response(res, 200)["data"]["reports"] |> length == 1 query = """ { reports(page: 3, limit: 2) { id, reported { preferredUsername } } } """ res = conn |> auth_conn(user_moderator) |> get("/api", AbsintheHelpers.query_skeleton(query, "report")) assert json_response(res, 200)["errors"] == nil assert json_response(res, 200)["data"]["reports"] |> length == 0 end end describe "Resolver: View a report" do test "view a report", %{conn: conn} do %User{} = user_moderator = insert(:user, role: :moderator) %Actor{} = insert(:actor, user: user_moderator) %Actor{} = reporter = insert(:actor) %Report{} = report = insert(:report, reporter: reporter) query = """ { report (id: "#{report.id}") { id, reported { preferredUsername }, reporter { preferredUsername }, event { title }, comments { text }, content } } """ res = conn |> get("/api", AbsintheHelpers.query_skeleton(query, "report")) assert json_response(res, 200)["errors"] |> hd |> Map.get("message") == "You need to be logged-in and a moderator to view a report" res = conn |> auth_conn(user_moderator) |> get("/api", AbsintheHelpers.query_skeleton(query, "report")) assert json_response(res, 200)["errors"] == nil assert json_response(res, 200)["data"]["report"]["reported"]["preferredUsername"] == report.reported.preferred_username assert json_response(res, 200)["data"]["report"]["reporter"]["preferredUsername"] == reporter.preferred_username assert json_response(res, 200)["data"]["report"]["content"] == report.content assert json_response(res, 200)["data"]["report"]["event"]["title"] == report.event.title assert json_response(res, 200)["data"]["report"]["comments"] |> hd |> Map.get("text") == report.comments |> hd |> Map.get(:text) end end describe "Resolver: Add a note on a report" do @report_note_content "I agree with this this report" test "create_report_note/3 creates a report note", %{conn: conn} do %User{} = user_moderator = insert(:user, role: :moderator) %Actor{id: moderator_id} = moderator = insert(:actor, user: user_moderator) %Report{id: report_id} = insert(:report) mutation = """ mutation { createReportNote( moderator_id: #{moderator_id}, report_id: #{report_id}, content: "#{@report_note_content}" ) { content, moderator { preferred_username }, report { id } } } """ res = conn |> auth_conn(user_moderator) |> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) assert json_response(res, 200)["errors"] == nil assert json_response(res, 200)["data"]["createReportNote"]["content"] == @report_note_content assert json_response(res, 200)["data"]["createReportNote"]["moderator"][ "preferred_username" ] == moderator.preferred_username assert json_response(res, 200)["data"]["createReportNote"]["report"]["id"] == to_string(report_id) end test "delete_report_note deletes a report note", %{conn: conn} do %User{} = user_moderator = insert(:user, role: :moderator) %Actor{id: moderator_id} = moderator = insert(:actor, user: user_moderator) %Note{id: report_note_id} = insert(:report_note, moderator: moderator) mutation = """ mutation { deleteReportNote( moderator_id: #{moderator_id}, note_id: #{report_note_id}, ) { id } } """ res = conn |> auth_conn(user_moderator) |> post("/api", AbsintheHelpers.mutation_skeleton(mutation)) assert json_response(res, 200)["errors"] == nil assert json_response(res, 200)["data"]["deleteReportNote"]["id"] == to_string(report_note_id) end end end