mobilizon/test/graphql/resolvers/resource_test.exs

865 lines
22 KiB
Elixir

defmodule Mobilizon.GraphQL.Resolvers.ResourceTest do
use Mobilizon.Web.ConnCase
import Mobilizon.Factory
alias Mobilizon.Actors.{Actor, Member}
alias Mobilizon.Resources.Resource
alias Mobilizon.Users.User
alias Mobilizon.GraphQL.AbsintheHelpers
@metadata_fragment """
fragment ResourceMetadataBasicFields on ResourceMetadata {
imageRemoteUrl,
height,
width,
type,
faviconUrl
}
"""
@get_group_resources """
query($name: String!) {
group(preferredUsername: $name) {
id,
url,
name,
domain,
summary,
preferredUsername,
resources(page: 1, limit: 3) {
elements {
id,
title,
resourceUrl,
summary,
updatedAt,
type,
path,
metadata {
...ResourceMetadataBasicFields
}
},
total
},
}
}
#{@metadata_fragment}
"""
@get_resource """
query GetResource($path: String, $username: String) {
resource(path: $path, username: $username) {
id,
title,
summary,
url,
path,
type,
metadata {
...ResourceMetadataBasicFields
authorName,
authorUrl,
providerName,
providerUrl,
html
},
parent {
id
},
actor {
id,
preferredUsername
},
children {
total,
elements {
id,
title,
summary,
url,
type,
path,
resourceUrl,
metadata {
...ResourceMetadataBasicFields
}
}
}
}
}
#{@metadata_fragment}
"""
@create_resource """
mutation CreateResource($title: String!, $parentId: ID, $summary: String, $actorId: ID!, $resourceUrl: String, $type: String) {
createResource(title: $title, parentId: $parentId, summary: $summary, actorId: $actorId, resourceUrl: $resourceUrl, type: $type) {
id,
title,
summary,
url,
resourceUrl,
updatedAt,
path,
type,
metadata {
...ResourceMetadataBasicFields
authorName,
authorUrl,
providerName,
providerUrl,
html
}
}
}
#{@metadata_fragment}
"""
@update_resource """
mutation UpdateResource($id: ID!, $title: String, $summary: String, $parentId: ID, $resourceUrl: String) {
updateResource(id: $id, title: $title, parentId: $parentId, summary: $summary, resourceUrl: $resourceUrl) {
id,
title,
summary,
url,
path,
resourceUrl,
type,
children {
total,
elements {
id,
title,
summary,
url,
type,
path,
resourceUrl,
metadata {
...ResourceMetadataBasicFields
}
}
}
}
}
#{@metadata_fragment}
"""
@delete_resource """
mutation DeleteResource($id: ID!) {
deleteResource(id: $id) {
id
}
}
"""
@resource_url "https://framasoft.org/fr/full"
@resource_title "my resource"
@updated_resource_title "my updated resource"
@folder_title "my folder"
setup do
%User{} = user = insert(:user)
%Actor{} = actor = insert(:actor, user: user)
%Actor{} = group = insert(:group)
%Member{} = insert(:member, parent: group, actor: actor, role: :member)
resource_in_root = %Resource{} = insert(:resource, actor: group)
folder_in_root =
%Resource{id: parent_id, path: parent_path} =
insert(:resource,
type: :folder,
resource_url: nil,
actor: group,
title: "root folder",
path: "/root folder"
)
resource_in_folder =
%Resource{} =
insert(:resource,
resource_url: nil,
actor: group,
parent_id: parent_id,
path: "#{parent_path}/titre",
title: "titre"
)
{:ok,
user: user,
group: group,
root_resources: [folder_in_root, resource_in_root],
resource_in_folder: resource_in_folder}
end
describe "Resolver: Get group's resources" do
test "find_resources_for_group/3", %{
conn: conn,
user: user,
group: group,
root_resources: root_resources,
resource_in_folder: resource_in_folder
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_group_resources,
variables: %{
name: group.preferred_username
}
)
assert is_nil(res["errors"])
assert res["data"]["group"]["resources"]["total"] == 3
assert res["data"]["group"]["resources"]["elements"]
|> Enum.map(&{&1["path"], &1["type"]})
|> MapSet.new() ==
(root_resources ++ [resource_in_folder])
|> Enum.map(&{&1.path, Atom.to_string(&1.type)})
|> MapSet.new()
end
test "find_resources_for_group/3 when not member of group", %{
conn: conn,
group: group
} do
%User{} = user = insert(:user)
%Actor{} = insert(:actor, user: user)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_group_resources,
variables: %{
name: group.preferred_username
}
)
assert is_nil(res["errors"])
assert res["data"]["group"]["resources"]["total"] == 0
assert res["data"]["group"]["resources"]["elements"] == []
end
test "find_resources_for_group/3 when not connected", %{
conn: conn,
group: group
} do
res =
conn
|> AbsintheHelpers.graphql_query(
query: @get_group_resources,
variables: %{
name: group.preferred_username
}
)
assert is_nil(res["errors"])
assert res["data"]["group"]["resources"]["total"] == 0
assert res["data"]["group"]["resources"]["elements"] == []
end
end
describe "Resolver: Get a specific resource" do
test "get_resource/3 for the root path", %{
conn: conn,
user: user,
group: group,
root_resources: root_resources
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_resource,
variables: %{
path: "/",
username: group.preferred_username
}
)
assert is_nil(res["errors"])
assert res["data"]["resource"]["path"] == "/"
assert String.starts_with?(res["data"]["resource"]["id"], "root_")
assert res["data"]["resource"]["children"]["elements"]
|> Enum.map(& &1["id"])
|> MapSet.new() == root_resources |> Enum.map(& &1.id) |> MapSet.new()
end
test "get_resource/3 for a folder path", %{
conn: conn,
user: user,
group: group,
root_resources: [root_folder, _],
resource_in_folder: resource_in_folder
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_resource,
variables: %{
path: root_folder.path,
username: group.preferred_username
}
)
assert is_nil(res["errors"])
assert res["data"]["resource"]["type"] == "folder"
assert res["data"]["resource"]["path"] == root_folder.path
assert is_nil(res["data"]["resource"]["parent"]["id"])
assert res["data"]["resource"]["children"]["total"] == 1
assert res["data"]["resource"]["children"]["elements"]
|> Enum.map(& &1["id"])
|> MapSet.new() == [resource_in_folder] |> Enum.map(& &1.id) |> MapSet.new()
end
test "get_resource/3 for a non-existing path", %{
conn: conn,
user: user,
group: group
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_resource,
variables: %{
path: "/non existing",
username: group.preferred_username
}
)
assert hd(res["errors"])["message"] == "No such resource"
end
test "get_resource/3 for a non-existing group", %{
conn: conn,
user: user
} do
%Actor{preferred_username: group_name} = insert(:group)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_resource,
variables: %{
path: "/non existing",
username: group_name
}
)
assert hd(res["errors"])["message"] == "Actor is not member of group"
end
test "get_resource/3 when not connected", %{
conn: conn,
group: group,
resource_in_folder: resource_in_folder
} do
res =
conn
|> AbsintheHelpers.graphql_query(
query: @get_resource,
variables: %{
path: resource_in_folder.path,
username: group.preferred_username
}
)
assert hd(res["errors"])["message"] == "You need to be logged-in to access resources"
end
end
describe "Resolver: Create a resource" do
test "create_resource/3 creates a resource for a group", %{
conn: conn,
user: user,
group: group
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_resource,
variables: %{
title: @resource_title,
parentId: nil,
actorId: group.id,
resourceUrl: @resource_url
}
)
assert is_nil(res["errors"])
assert res["data"]["createResource"]["metadata"]["faviconUrl"] ==
"https://framasoft.org/icons/favicon.png"
assert res["data"]["createResource"]["metadata"]["imageRemoteUrl"] ==
"https://framasoft.org/img/opengraph/full.jpg"
assert res["data"]["createResource"]["path"] == "/#{@resource_title}"
assert res["data"]["createResource"]["resourceUrl"] == @resource_url
assert res["data"]["createResource"]["title"] == @resource_title
assert res["data"]["createResource"]["type"] == "link"
end
test "create_resource/3 creates a folder", %{conn: conn, user: user, group: group} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_resource,
variables: %{
title: @folder_title,
parentId: nil,
actorId: group.id,
type: "folder"
}
)
assert is_nil(res["errors"])
assert res["data"]["createResource"]["path"] == "/#{@folder_title}"
assert res["data"]["createResource"]["title"] == @folder_title
assert res["data"]["createResource"]["type"] == "folder"
end
test "create_resource/3 creates a resource in a folder", %{
conn: conn,
user: user,
group: group
} do
%Resource{id: parent_id, path: parent_path} =
insert(:resource, type: :folder, resource_url: nil, actor: group)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_resource,
variables: %{
title: @resource_title,
parentId: parent_id,
actorId: group.id,
resourceUrl: @resource_url
}
)
assert is_nil(res["errors"])
assert res["data"]["createResource"]["metadata"]["faviconUrl"] ==
"https://framasoft.org/icons/favicon.png"
assert res["data"]["createResource"]["metadata"]["imageRemoteUrl"] ==
"https://framasoft.org/img/opengraph/full.jpg"
assert res["data"]["createResource"]["path"] == "#{parent_path}/#{@resource_title}"
assert res["data"]["createResource"]["resourceUrl"] == @resource_url
assert res["data"]["createResource"]["title"] == @resource_title
assert res["data"]["createResource"]["type"] == "link"
end
test "create_resource/3 doesn't create a resource in a folder if no group is defined", %{
conn: conn,
user: user
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_resource,
variables: %{
title: @resource_title,
parentId: nil,
resourceUrl: @resource_url
}
)
assert Enum.map(res["errors"], & &1["message"]) == [
"In argument \"actorId\": Expected type \"ID!\", found null.",
"Variable \"actorId\": Expected non-null, found null."
]
end
test "create_resource/3 doesn't create a resource 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_resource,
variables: %{
title: @resource_title,
parentId: nil,
actorId: group.id,
resourceUrl: @resource_url
}
)
assert Enum.map(res["errors"], & &1["message"]) == [
"Actor id is not member of group"
]
end
test "create_resource/3 doesn't create a resource if the referenced parent folder is not owned by the group",
%{
conn: conn,
user: user,
group: group
} do
%Actor{} = group2 = insert(:group)
%Resource{id: parent_id} =
insert(:resource, type: :folder, resource_url: nil, actor: group2)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @create_resource,
variables: %{
title: @resource_title,
parentId: parent_id,
actorId: group.id,
resourceUrl: @resource_url
}
)
assert Enum.map(res["errors"], & &1["message"]) == [
"Parent resource doesn't match this group"
]
end
end
describe "Resolver: Update a resource" do
test "update_resource/3 renames a resource for a group", %{
conn: conn,
user: user,
group: group
} do
%Resource{id: resource_id} = insert(:resource, resource_url: @resource_url, actor: group)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @update_resource,
variables: %{
id: resource_id,
title: @updated_resource_title
}
)
assert is_nil(res["errors"])
assert res["data"]["updateResource"]["path"] == "/#{@updated_resource_title}"
assert res["data"]["updateResource"]["resourceUrl"] == @resource_url
assert res["data"]["updateResource"]["title"] == @updated_resource_title
assert res["data"]["updateResource"]["type"] == "link"
end
test "update_resource/3 moves and renames a resource for a group", %{
conn: conn,
user: user,
group: group,
root_resources: [root_folder, _]
} do
%Resource{id: resource_id} = insert(:resource, resource_url: @resource_url, actor: group)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @update_resource,
variables: %{
id: resource_id,
title: @updated_resource_title,
parentId: root_folder.id
}
)
assert is_nil(res["errors"])
assert res["data"]["updateResource"]["path"] ==
"#{root_folder.path}/#{@updated_resource_title}"
assert res["data"]["updateResource"]["resourceUrl"] == @resource_url
assert res["data"]["updateResource"]["title"] == @updated_resource_title
assert res["data"]["updateResource"]["type"] == "link"
end
test "update_resource/3 moves a resource in a subfolder for a group", %{
conn: conn,
user: user,
group: group,
root_resources: [root_folder, _]
} do
%Resource{id: resource_id} =
resource = insert(:resource, resource_url: @resource_url, actor: group)
folder =
insert(:resource,
parent_id: root_folder.id,
actor: group,
path: "#{root_folder.path}/subfolder",
title: "subfolder"
)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @update_resource,
variables: %{
id: resource_id,
parentId: folder.id
}
)
assert is_nil(res["errors"])
assert res["data"]["updateResource"]["path"] ==
"#{folder.path}/#{resource.title}"
assert res["data"]["updateResource"]["resourceUrl"] == @resource_url
assert res["data"]["updateResource"]["title"] == resource.title
assert res["data"]["updateResource"]["type"] == "link"
end
test "update_resource/3 renames a folder and all the paths for it's children", %{
conn: conn,
user: user,
group: group,
root_resources: [root_folder, _]
} do
folder =
insert(:resource,
parent_id: root_folder.id,
actor: group,
path: "#{root_folder.path}/subfolder",
title: "subfolder",
type: :folder
)
%Resource{} =
insert(:resource,
resource_url: @resource_url,
actor: group,
parent_id: folder.id,
path: "#{folder.path}/titre",
title: "titre"
)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @update_resource,
variables: %{
id: folder.id,
title: "updated subfolder"
}
)
assert is_nil(res["errors"])
assert res["data"]["updateResource"]["path"] ==
"#{root_folder.path}/updated subfolder"
assert res["data"]["updateResource"]["title"] == "updated subfolder"
assert res["data"]["updateResource"]["type"] == "folder"
assert hd(res["data"]["updateResource"]["children"]["elements"])["path"] ==
"#{root_folder.path}/updated subfolder/titre"
end
test "update_resource/3 moves a folder and updates all the paths for it's children", %{
conn: conn,
user: user,
group: group,
root_resources: [root_folder, _]
} do
folder =
insert(:resource,
parent_id: nil,
actor: group,
path: "/subfolder",
title: "subfolder",
type: :folder
)
%Resource{} =
insert(:resource,
resource_url: @resource_url,
actor: group,
parent_id: folder.id,
path: "#{folder.path}/titre",
title: "titre"
)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @update_resource,
variables: %{
id: folder.id,
parentId: root_folder.id,
title: "updated subfolder"
}
)
assert is_nil(res["errors"])
assert res["data"]["updateResource"]["path"] ==
"#{root_folder.path}/updated subfolder"
assert res["data"]["updateResource"]["title"] == "updated subfolder"
assert res["data"]["updateResource"]["type"] == "folder"
assert hd(res["data"]["updateResource"]["children"]["elements"])["path"] ==
"#{root_folder.path}/updated subfolder/titre"
end
end
describe "Resolver: Delete a resource" do
test "delete_resource/3 deletes a resource", %{
conn: conn,
user: user,
group: group
} do
%Resource{id: resource_id, path: resource_path} =
insert(:resource,
resource_url: @resource_url,
actor: group,
parent_id: nil
)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @delete_resource,
variables: %{
id: resource_id
}
)
assert is_nil(res["errors"])
assert res["data"]["deleteResource"]["id"] == resource_id
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_resource,
variables: %{
path: resource_path,
username: group.preferred_username
}
)
assert hd(res["errors"])["message"] == "No such resource"
end
test "delete_resource/3 deletes a folder and children", %{
conn: conn,
user: user,
group: group
} do
%Resource{id: folder_id, path: folder_path} =
insert(:resource,
parent_id: nil,
actor: group,
path: "/subfolder",
title: "subfolder",
type: :folder
)
%Resource{path: resource_path} =
insert(:resource,
resource_url: @resource_url,
actor: group,
parent_id: folder_id,
path: "#{folder_path}/titre",
title: "titre"
)
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @delete_resource,
variables: %{
id: folder_id
}
)
assert is_nil(res["errors"])
assert res["data"]["deleteResource"]["id"] == folder_id
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_resource,
variables: %{
path: folder_path,
username: group.preferred_username
}
)
assert hd(res["errors"])["message"] == "No such resource"
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @get_resource,
variables: %{
path: resource_path,
username: group.preferred_username
}
)
assert hd(res["errors"])["message"] == "No such resource"
end
test "delete_resource/3 deletes a resource not found", %{
conn: conn,
user: user
} do
res =
conn
|> auth_conn(user)
|> AbsintheHelpers.graphql_query(
query: @delete_resource,
variables: %{
id: "58869b5b-2beb-423a-b483-1585d847e2cc"
}
)
assert hd(res["errors"])["message"] == "Resource doesn't exist"
end
end
end