mobilizon.chapril.org-mobil.../test/graphql/resolvers/post_test.exs
Thomas Citharel b849a63cc6 Make GraphQL parameters strict following Absinthe 1.7 validating
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
2022-03-29 13:58:58 +02:00

656 lines
15 KiB
Elixir

defmodule Mobilizon.GraphQL.Resolvers.PostTest do
use Mobilizon.Web.ConnCase
import Mobilizon.Factory
alias Mobilizon.Actors.{Actor, Member}
alias Mobilizon.Posts.Post
alias Mobilizon.Users.User
alias Mobilizon.GraphQL.AbsintheHelpers
@post_fragment """
fragment PostFragment on Post {
id
title
slug
url
body
author {
id
preferredUsername
name
avatar {
url
}
}
attributedTo {
id
preferredUsername
name
avatar {
url
}
}
visibility
insertedAt
updatedAt
draft
}
"""
@get_group_posts """
query($name: String!, $page: Int, $limit: Int) {
group(preferredUsername: $name) {
id
posts(page: $page, limit: $limit) {
elements {
id,
title,
},
total
},
}
}
"""
@post_query """
query Post($slug: String!) {
post(slug: $slug) {
...PostFragment
}
}
#{@post_fragment}
"""
@create_post """
mutation CreatePost($title: String!, $body: String!, $attributedToId: ID!, $draft: Boolean) {
createPost(title: $title, body: $body, attributedToId: $attributedToId, draft: $draft) {
...PostFragment
}
}
#{@post_fragment}
"""
@update_post """
mutation UpdatePost($id: ID!, $title: String, $body: String, $attributedToId: ID, $draft: Boolean) {
updatePost(id: $id, title: $title, body: $body, attributedToId: $attributedToId, draft: $draft) {
...PostFragment
}
}
#{@post_fragment}
"""
@delete_post """
mutation DeletePost($id: ID!) {
deletePost(id: $id) {
id
}
}
"""
@post_title "my post"
@updated_post_title "my updated post"
setup do
%User{} = user = insert(:user)
%Actor{} = actor = insert(:actor, user: user)
%Actor{} = group = insert(:group)
%Post{} = post = insert(:post, attributed_to: group, author: actor)
%Post{} =
post_unlisted = insert(:post, attributed_to: group, author: actor, visibility: :unlisted)
%Post{} = post_draft = insert(:post, attributed_to: group, author: actor, draft: true)
%Member{} = insert(:member, parent: group, actor: actor, role: :member)
%Post{} =
post_private = insert(:post, attributed_to: group, author: actor, visibility: :private)
insert(:follower, target_actor: group, approved: true)
{:ok,
user: user,
group: group,
post: post,
post_unlisted: post_unlisted,
post_draft: post_draft,
post_private: post_private}
end
describe "Resolver: Get group's posts" do
test "find_posts_for_group/3", %{
conn: conn,
user: user,
group: group,
post: post,
post_unlisted: post_unlisted,
post_draft: post_draft,
post_private: post_private
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_group_posts,
variables: %{
name: group.preferred_username
}
)
assert is_nil(res["errors"])
assert res["data"]["group"]["posts"]["total"] == 4
assert res["data"]["group"]["posts"]["elements"] |> Enum.map(& &1["id"]) |> MapSet.new() ==
MapSet.new([
post.id,
post_unlisted.id,
post_draft.id,
post_private.id
])
end
test "find_posts_for_group/3 when not member of group", %{
conn: conn,
group: group,
post: post
} do
%User{} = user = insert(:user)
%Actor{} = insert(:actor, user: user)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_group_posts,
variables: %{
name: group.preferred_username
}
)
assert is_nil(res["errors"])
assert res["data"]["group"]["posts"]["total"] == 1
assert res["data"]["group"]["posts"]["elements"] |> Enum.map(& &1["id"]) == [post.id]
end
test "find_posts_for_group/3 when not connected", %{
conn: conn,
group: group,
post: post
} do
res =
conn
|> AbsintheHelpers.graphql_query(
query: @get_group_posts,
variables: %{
name: group.preferred_username
}
)
assert is_nil(res["errors"])
assert res["data"]["group"]["posts"]["total"] == 1
assert res["data"]["group"]["posts"]["elements"] |> Enum.map(& &1["id"]) == [post.id]
end
end
describe "Resolver: Get a specific post" do
test "get_post/3 for a public post", %{
conn: conn,
user: user,
post: post
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post.slug
}
)
assert is_nil(res["errors"])
assert res["data"]["post"]["title"] == post.title
end
test "get_post/3 for a non-existing post", %{
conn: conn,
user: user
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: "not existing"
}
)
assert hd(res["errors"])["message"] == "Post not found"
end
test "get_post/3 for an unlisted post", %{
conn: conn,
user: user,
post_unlisted: post_unlisted
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post_unlisted.slug
}
)
assert is_nil(res["errors"])
assert res["data"]["post"]["title"] == post_unlisted.title
assert res["data"]["post"]["visibility"] ==
post_unlisted.visibility |> to_string() |> String.upcase()
end
test "get_post/3 for a private post", %{
conn: conn,
user: user,
post_private: post_private
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post_private.slug
}
)
assert is_nil(res["errors"])
assert res["data"]["post"]["title"] == post_private.title
assert res["data"]["post"]["visibility"] ==
post_private.visibility |> to_string() |> String.upcase()
end
test "get_post/3 for a draft post", %{
conn: conn,
user: user,
post_draft: post_draft
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post_draft.slug
}
)
assert res["errors"] == nil
assert res["data"]["post"]["title"] == post_draft.title
assert res["data"]["post"]["draft"] == true
end
test "get_post/3 without being a member for a public post", %{
conn: conn,
post: post
} do
%User{} = user = insert(:user)
%Actor{} = insert(:actor, user: user)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post.slug
}
)
assert is_nil(res["errors"])
assert res["data"]["post"]["title"] == post.title
end
test "get_post/3 without being connected for a public post", %{
conn: conn,
post: post
} do
res =
conn
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post.slug
}
)
assert is_nil(res["errors"])
assert res["data"]["post"]["title"] == post.title
end
test "get_post/3 without being a member for an unlisted post", %{
conn: conn,
post_unlisted: post_unlisted
} do
%User{} = user = insert(:user)
%Actor{} = insert(:actor, user: user)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post_unlisted.slug
}
)
assert is_nil(res["errors"])
assert res["data"]["post"]["title"] == post_unlisted.title
assert res["data"]["post"]["visibility"] ==
post_unlisted.visibility |> to_string() |> String.upcase()
end
test "get_post/3 without being a member for a private post", %{
conn: conn,
post_private: post_private
} do
%User{} = user = insert(:user)
%Actor{} = insert(:actor, user: user)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post_private.slug
}
)
assert hd(res["errors"])["message"] == "Post not found"
end
test "get_post/3 without being connected for an unlisted post still gives the post", %{
conn: conn,
post_unlisted: post_unlisted
} do
res =
conn
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post_unlisted.slug
}
)
assert is_nil(res["errors"])
assert res["data"]["post"]["title"] == post_unlisted.title
assert res["data"]["post"]["visibility"] ==
post_unlisted.visibility |> to_string() |> String.upcase()
end
test "get_post/3 without being connected for a private post", %{
conn: conn,
post_private: post_private
} do
res =
conn
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post_private.slug
}
)
assert hd(res["errors"])["message"] == "Post not found"
end
test "get_post/3 without being a member for a draft post", %{
conn: conn,
post_draft: post_draft
} do
%User{} = user = insert(:user)
%Actor{} = insert(:actor, user: user)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post_draft.slug
}
)
assert hd(res["errors"])["message"] == "Post not found"
end
test "get_post/3 without being connected for a draft post", %{
conn: conn,
post_draft: post_draft
} do
res =
conn
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post_draft.slug
}
)
assert hd(res["errors"])["message"] == "Post not found"
end
end
describe "Resolver: Create a post" do
test "create_post/3 creates a post for a group", %{
conn: conn,
user: user,
group: group
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_post,
variables: %{
title: @post_title,
body: "My new post is here",
attributedToId: group.id
}
)
assert is_nil(res["errors"])
assert res["data"]["createPost"]["title"] == @post_title
id = res["data"]["createPost"]["id"]
assert res["data"]["createPost"]["slug"] == "my-post-#{ShortUUID.encode!(id)}"
end
test "create_post/3 creates a draft post for a group", %{
conn: conn,
user: user,
group: group
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_post,
variables: %{
title: @post_title,
body: "My new post is here",
attributedToId: group.id,
draft: true
}
)
assert is_nil(res["errors"])
assert res["data"]["createPost"]["title"] == @post_title
id = res["data"]["createPost"]["id"]
assert res["data"]["createPost"]["slug"] == "my-post-#{ShortUUID.encode!(id)}"
assert res["data"]["createPost"]["draft"] == true
end
test "create_post/3 doesn't create a post if no group is defined", %{
conn: conn,
user: user
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_post,
variables: %{
title: @post_title,
body: "some body",
attributedToId: nil
}
)
assert Enum.map(res["errors"], & &1["message"]) == [
"Argument \"attributedToId\" has invalid value $attributedToId.",
"Variable \"attributedToId\": Expected non-null, found null."
]
end
test "create_post/3 doesn't create a post if the actor is not a member of the group",
%{
conn: conn,
group: group
} do
%User{} = user = insert(:user)
%Actor{} = insert(:actor, user: user)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_post,
variables: %{
title: @post_title,
body: "My body",
attributedToId: group.id
}
)
assert Enum.map(res["errors"], & &1["message"]) == [
"Profile is not member of group"
]
end
end
describe "Resolver: Update a post" do
test "update_post/3 updates a post for a group", %{
conn: conn,
user: user,
group: group
} do
%Post{id: post_id} = insert(:post, attributed_to: group)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @update_post,
variables: %{
id: post_id,
title: @updated_post_title
}
)
assert is_nil(res["errors"])
assert res["data"]["updatePost"]["title"] == @updated_post_title
end
end
describe "Resolver: Delete a post" do
test "delete_post/3 deletes a post", %{
conn: conn,
user: user,
group: group
} do
%Post{id: post_id, slug: post_slug} =
insert(:post,
attributed_to: group
)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @delete_post,
variables: %{
id: post_id
}
)
assert is_nil(res["errors"])
assert res["data"]["deletePost"]["id"] == post_id
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @post_query,
variables: %{
slug: post_slug
}
)
assert hd(res["errors"])["message"] == "Post not found"
end
test "delete_post/3 deletes a post not found", %{
conn: conn,
user: user
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @delete_post,
variables: %{
id: "not found"
}
)
assert hd(res["errors"])["message"] == "Post ID is not a valid ID"
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @delete_post,
variables: %{
id: "d276ef98-8433-48d7-890e-c24eda0dcdbe"
}
)
assert hd(res["errors"])["message"] == "Post doesn't exist"
end
end
end