commit 2c8deac62dbd767a4aa4bf99cedec63dc8a2c7f2
parent bd1f61de42b733a35982299c5247a14d853ea914
Author: srfsh <dev@srf.sh>
Date: Tue, 16 Aug 2022 13:31:06 +0300
Zenflows{Test,}.VF.ProposedIntent: init
Diffstat:
4 files changed, 281 insertions(+), 0 deletions(-)
diff --git a/src/zenflows/vf/proposed_intent/domain.ex b/src/zenflows/vf/proposed_intent/domain.ex
@@ -0,0 +1,78 @@
+# Zenflows is designed to implement the Valueflows vocabulary,
+# written and maintained by srfsh <info@dyne.org>.
+# Copyright (C) 2021-2022 Dyne.org foundation <foundation@dyne.org>.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+defmodule Zenflows.VF.ProposedIntent.Domain do
+@moduledoc "Domain logic of ProposedIntents."
+
+alias Ecto.Multi
+alias Zenflows.DB.Repo
+alias Zenflows.VF.ProposedIntent
+
+@typep repo() :: Ecto.Repo.t()
+@typep chgset() :: Ecto.Changeset.t()
+@typep id() :: Zenflows.DB.Schema.id()
+@typep params() :: Zenflows.DB.Schema.params()
+
+@spec one(repo(), id()) :: {:ok, ProposedIntent.t()} | {:error, String.t()}
+def one(repo \\ Repo, id) do
+ one_by(repo, id: id)
+end
+
+@spec one_by(repo(), map() | Keyword.t())
+ :: {:ok, ProposedIntent.t()} | {:error, String.t()}
+def one_by(repo \\ Repo, clauses) do
+ case repo.get_by(ProposedIntent, clauses) do
+ nil -> {:error, "not found"}
+ found -> {:ok, found}
+ end
+end
+
+@spec create(params()) :: {:ok, ProposedIntent.t()} | {:error, chgset()}
+def create(params) do
+ Multi.new()
+ |> Multi.insert(:insert, ProposedIntent.chgset(params))
+ |> Repo.transaction()
+ |> case do
+ {:ok, %{insert: pi}} -> {:ok, pi}
+ {:error, _, cset, _} -> {:error, cset}
+ end
+end
+
+@spec delete(id())
+ :: {:ok, ProposedIntent.t()} | {:error, String.t() | chgset()}
+def delete(id) do
+ Multi.new()
+ |> Multi.put(:id, id)
+ |> Multi.run(:one, &one_by/2)
+ |> Multi.delete(:delete, &(&1.one))
+ |> Repo.transaction()
+ |> case do
+ {:ok, %{delete: pi}} -> {:ok, pi}
+ {:error, _, msg_or_cset, _} -> {:error, msg_or_cset}
+ end
+end
+
+@spec preload(ProposedIntent.t(), :published_in | :publishes)
+ :: ProposedIntent.t()
+def preload(prop_int, :published_in) do
+ Repo.preload(prop_int, :published_in)
+end
+
+def preload(prop_int, :publishes) do
+ Repo.preload(prop_int, :publishes)
+end
+end
diff --git a/src/zenflows/vf/proposed_intent/resolv.ex b/src/zenflows/vf/proposed_intent/resolv.ex
@@ -0,0 +1,44 @@
+# Zenflows is designed to implement the Valueflows vocabulary,
+# written and maintained by srfsh <info@dyne.org>.
+# Copyright (C) 2021-2022 Dyne.org foundation <foundation@dyne.org>.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+defmodule Zenflows.VF.ProposedIntent.Resolv do
+@moduledoc "Resolvers of ProposedIntent."
+
+alias Zenflows.VF.ProposedIntent.Domain
+
+def published_in(prop_int, _, _) do
+ prop_int = Domain.preload(prop_int, :published_in)
+ {:ok, prop_int.published_in}
+end
+
+def publishes(prop_int, _, _) do
+ prop_int = Domain.preload(prop_int, :publishes)
+ {:ok, prop_int.publishes}
+end
+
+def propose_intent(params, _) do
+ with {:ok, prop_int} <- Domain.create(params) do
+ {:ok, %{proposed_intent: prop_int}}
+ end
+end
+
+def delete_proposed_intent(%{id: id}, _) do
+ with {:ok, _} <- Domain.delete(id) do
+ {:ok, true}
+ end
+end
+end
diff --git a/test/vf/proposed_intent/domain.test.exs b/test/vf/proposed_intent/domain.test.exs
@@ -0,0 +1,88 @@
+# Zenflows is designed to implement the Valueflows vocabulary,
+# written and maintained by srfsh <info@dyne.org>.
+# Copyright (C) 2021-2022 Dyne.org foundation <foundation@dyne.org>.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+defmodule ZenflowsTest.VF.ProposedIntent.Domain do
+use ZenflowsTest.Help.EctoCase, async: true
+
+alias Ecto.Changeset
+alias Zenflows.VF.{
+ Intent,
+ Proposal,
+ ProposedIntent,
+ ProposedIntent.Domain,
+}
+
+setup do
+ %{
+ params: %{
+ reciprocal: Factory.bool(),
+ publishes_id: Factory.insert!(:intent).id,
+ published_in_id: Factory.insert!(:proposal).id,
+ },
+ inserted: Factory.insert!(:proposed_intent),
+ id: Factory.id(),
+ }
+end
+
+describe "one/1" do
+ test "with good id: finds the ProposedIntent", %{inserted: %{id: id}} do
+ assert {:ok, %ProposedIntent{}} = Domain.one(id)
+ end
+
+ test "with bad id: doesn't find the ProposedIntent", %{id: id} do
+ assert {:error, "not found"} = Domain.one(id)
+ end
+end
+
+describe "create/1" do
+ test "with good params: creates a ProposedIntent", %{params: params} do
+ assert {:ok, %ProposedIntent{} = prop_int} = Domain.create(params)
+ assert prop_int.reciprocal == params.reciprocal
+ assert prop_int.publishes_id == params.publishes_id
+ assert prop_int.published_in_id == params.published_in_id
+ end
+
+ test "with bad params: doesn't create a ProposedIntent" do
+ assert {:error, %Changeset{}} = Domain.create(%{})
+ end
+end
+
+describe "delete/1" do
+ test "with good id: deletes the ProposedIntent", %{inserted: %{id: id}} do
+ assert {:ok, %ProposedIntent{id: ^id}} = Domain.delete(id)
+ assert {:error, "not found"} = Domain.one(id)
+ end
+
+ test "with bad id: doesn't delete the ProposedIntent", %{id: id} do
+ assert {:error, "not found"} = Domain.delete(id)
+ end
+end
+
+describe "preload/2" do
+ test "preloads `:published_in`", %{inserted: %{id: id}} do
+ assert {:ok, prop} = Domain.one(id)
+ prop = Domain.preload(prop, :published_in)
+ assert %Proposal{} = prop.published_in
+ end
+
+ test "preloads `:publishes`", %{inserted: %{id: id}} do
+ assert {:ok, prop} = Domain.one(id)
+ prop = Domain.preload(prop, :publishes)
+ assert %Intent{} = prop.publishes
+ end
+end
+end
diff --git a/test/vf/proposed_intent/type.test.exs b/test/vf/proposed_intent/type.test.exs
@@ -0,0 +1,71 @@
+# Zenflows is designed to implement the Valueflows vocabulary,
+# written and maintained by srfsh <info@dyne.org>.
+# Copyright (C) 2021-2022 Dyne.org foundation <foundation@dyne.org>.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+defmodule ZenflowsTest.VF.ProposedIntent.Type do
+use ZenflowsTest.Help.AbsinCase, async: true
+
+setup do
+ %{
+ params: %{
+ "reciprocal" => Factory.bool(),
+ "publishedIn" => Factory.insert!(:proposal).id,
+ "publishes" => Factory.insert!(:intent).id
+ },
+ inserted: Factory.insert!(:proposed_intent),
+ }
+end
+
+describe "Mutation" do
+ test "proposeIntent", %{params: params} do
+ assert %{data: %{"proposeIntent" => %{"proposedIntent" => data}}} =
+ run!("""
+ mutation (
+ $reciprocal: Boolean!
+ $publishedIn: ID!
+ $publishes: ID!
+ ) {
+ proposeIntent(
+ reciprocal: $reciprocal
+ publishedIn: $publishedIn
+ publishes: $publishes
+ ) {
+ proposedIntent {
+ id
+ reciprocal
+ publishedIn {id}
+ publishes {id}
+ }
+ }
+ }
+ """, vars: params)
+
+ assert {:ok, _} = Zenflows.DB.ID.cast(data["id"])
+ assert data["reciprocal"] == params["reciprocal"]
+ assert data["publishedIn"]["id"] == params["publishedIn"]
+ assert data["publishes"]["id"] == params["publishes"]
+ end
+
+ test "deleteProposedIntent", %{inserted: %{id: id}} do
+ assert %{data: %{"deleteProposedIntent" => true}} =
+ run!("""
+ mutation ($id: ID!) {
+ deleteProposedIntent(id: $id)
+ }
+ """, vars: %{"id" => id})
+ end
+end
+end