Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 82 additions & 9 deletions lib/liquid_voting_web/resolvers/delegations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,51 @@ defmodule LiquidVotingWeb.Resolvers.Delegations do
def delegation(_, %{id: id}, %{context: %{organization_id: organization_id}}),
do: {:ok, Delegations.get_delegation!(id, organization_id)}

# Will add participants to the db if they don't exist yet, or fetch them if they do.
# Their ids are used for delegator_id and delegate_id when inserting the delegation
# with create_delegation_with_valid_arguments/1
@doc """
Creates a delegation.

Adds participants to the db if they don't exist, or fetches them if they do.

Valid arguments (args) must include 2 ids (delegator_id and delegate_id)
OR 2 emails (delegator_email and delegate_email).

Valid arguments (args) may include a proposal_url.
Without a proposal_url, an attempt to create a global delegation will occur.

The participant ids, either directly taken from delegator_id and
delegate_id, or via searching the db for participants with the emails
provided, are used when inserting the delegation with
LiquidVoting.Delegations.create_delegation/1.

## Examples

iex> create_delegation(
%{},
%{delegator_email: "alice@somemail.com",
delegate_email: "bob@somemail.com",
proposal_url: "https://proposalplace/proposal63"},
%{context: %{organization_id: "b212ef83-d3df-4a7a-8875-36cca613e8d6"}})
%Delegation{}

iex> create_delegation(
%{},
%{delegator_email: "alice@somemail.com"},
%{context: %{organization_id: "b212ef83-d3df-4a7a-8875-36cca613e8d6"}})
{:error,
%{
details: %{delegate_email: ["can't be blank"]},
message: "Could not create delegation"
}}
"""
def create_delegation(_, args, %{context: %{organization_id: organization_id}}) do
args
|> Map.put(:organization_id, organization_id)
|> Delegations.create_delegation()
|> case do
{:ok, delegation} ->
{:ok, delegation}
args = Map.put(args, :organization_id, organization_id)

with {:ok, args} <- validate_participant_args(args),
{:ok, delegation} <- Delegations.create_delegation(args) do
{:ok, delegation}
else
{:error, %{message: message, details: details}} ->
{:error, %{message: message, details: details}}

{:error, changeset} ->
{:error,
Expand All @@ -29,6 +64,44 @@ defmodule LiquidVotingWeb.Resolvers.Delegations do
end
end

defp validate_participant_args(args) do
case args do
%{delegator_email: _, delegate_email: _} ->
{:ok, args}

%{delegator_id: _, delegate_id: _} ->
{:ok, args}

# delegator_email field provided, but no delegate_email field provided
%{delegator_email: _} ->
field_not_found_error(%{delegate_email: ["can't be blank"]})

# delegate_email field provided, but no delegator_email field provided
%{delegate_email: _} ->
field_not_found_error(%{delegator_email: ["can't be blank"]})

# delegator_id field provided, but no delegate_id field provided
%{delegator_id: _} ->
field_not_found_error(%{delegate_id: ["can't be blank"]})

# delegate_id field provided, but no delegator_id field provided
%{delegate_id: _} ->
field_not_found_error(%{delegator_id: ["can't be blank"]})

# no id or email fields provided for delegator and delegate
_ ->
field_not_found_error("emails or ids identifying delegator and delegate can't be blank")
end
end

defp field_not_found_error(details) do
{:error,
%{
message: "Could not create delegation",
details: details
}}
end

# Delete proposal-specific delegations
def delete_delegation(
_,
Expand Down
3 changes: 1 addition & 2 deletions test/liquid_voting/delegations_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ defmodule LiquidVoting.DelegationsTest do
assert {:error, %Ecto.Changeset{}} = Delegations.create_delegation(context[:invalid_attrs])
end

test "create_delegation/1 with same participant as delegator and delegate returns error changeset",
context do
test "create_delegation/1 with same participant as delegator and delegate returns error changeset" do
participant = insert(:participant)

args = %{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ defmodule LiquidVotingWeb.Absinthe.Mutations.CreateDelegationTest do
assert delegation["votingResult"]["against"] == 0
end

test "with missing fields" do
test "with missing delegate email field" do
query = """
mutation {
createDelegation(delegatorEmail: "#{@delegator_email}") {
Expand All @@ -109,7 +109,7 @@ defmodule LiquidVotingWeb.Absinthe.Mutations.CreateDelegationTest do
Absinthe.run(query, Schema, context: %{organization_id: Ecto.UUID.generate()})

assert message == "Could not create delegation"
assert details == %{delegate_id: ["can't be blank"], delegator_id: ["can't be blank"]}
assert details == %{delegate_email: ["can't be blank"]}
end
end

Expand Down Expand Up @@ -170,7 +170,28 @@ defmodule LiquidVotingWeb.Absinthe.Mutations.CreateDelegationTest do
assert delegation["delegate"]["email"] == context[:delegate].email
end

test "with missing field", context do
test "with proposal url, but missing delegate and delegator id fields" do
query = """
mutation {
createDelegation(proposalUrl: "#{@proposal_url}") {
delegator {
email
}
delegate {
email
}
}
}
"""

{:ok, %{errors: [%{message: message, details: details}]}} =
Absinthe.run(query, Schema, context: %{organization_id: Ecto.UUID.generate()})

assert message == "Could not create delegation"
assert details == "emails or ids identifying delegator and delegate can't be blank"
end

test "with missing delegate id field", context do
query = """
mutation {
createDelegation(delegatorId: "#{context[:delegator].id}") {
Expand Down