commit d1417e74e07fe90116885c594ba96db78f8e360f
parent 1ac24e4737c38cb9aa34c21607193a3661c60dd0
Author: srfsh <dev@srf.sh>
Date: Mon, 22 Aug 2022 19:54:08 +0300
Zenflows{Test,}.VF.AgentRelationship: add paging support and small improvements
Diffstat:
5 files changed, 171 insertions(+), 144 deletions(-)
diff --git a/src/zenflows/vf/agent_relationship/domain.ex b/src/zenflows/vf/agent_relationship/domain.ex
@@ -20,55 +20,71 @@ defmodule Zenflows.VF.AgentRelationship.Domain do
alias Ecto.Multi
alias Zenflows.DB.Repo
+alias Zenflows.GQL.Paging
alias Zenflows.VF.AgentRelationship
@typep repo() :: Ecto.Repo.t()
@typep chgset() :: Ecto.Changeset.t()
-@typep changes() :: Ecto.Multi.changes()
@typep id() :: Zenflows.DB.Schema.id()
@typep params() :: Zenflows.DB.Schema.params()
-@spec by_id(repo(), id()) :: AgentRelationship.t() | nil
-def by_id(repo \\ Repo, id) do
- repo.get(AgentRelationship, id)
+@spec one(repo(), id() | map() | Keyword.t())
+ :: {:ok, AgentRelationship.t()} | {:error, String.t()}
+def one(repo \\ Repo, _)
+def one(repo, id) when is_binary(id), do: one(repo, id: id)
+def one(repo, clauses) do
+ case repo.get_by(AgentRelationship, clauses) do
+ nil -> {:error, "not found"}
+ found -> {:ok, found}
+ end
+end
+
+@spec all(Paging.params()) :: Paging.result(AgentRelationship.t())
+def all(params) do
+ Paging.page(AgentRelationship, params)
end
@spec create(params()) :: {:ok, AgentRelationship.t()} | {:error, chgset()}
def create(params) do
Multi.new()
- |> Multi.insert(:rel, AgentRelationship.chgset(params))
+ |> Multi.insert(:insert, AgentRelationship.chgset(params))
|> Repo.transaction()
|> case do
- {:ok, %{rel: rel}} -> {:ok, rel}
+ {:ok, %{insert: ar}} -> {:ok, ar}
{:error, _, cset, _} -> {:error, cset}
end
end
-@spec update(id(), params()) :: {:ok, AgentRelationship.t()} | {:error, chgset()}
+@spec update(id(), params())
+ :: {:ok, AgentRelationship.t()} | {:error, String.t() | chgset()}
def update(id, params) do
Multi.new()
- |> Multi.run(:get, multi_get(id))
- |> Multi.update(:update, &AgentRelationship.chgset(&1.get, params))
+ |> Multi.put(:id, id)
+ |> Multi.run(:one, &one/2)
+ |> Multi.update(:update, &AgentRelationship.chgset(&1.one, params))
|> Repo.transaction()
|> case do
- {:ok, %{update: rel}} -> {:ok, rel}
+ {:ok, %{update: ar}} -> {:ok, ar}
{:error, _, msg_or_cset, _} -> {:error, msg_or_cset}
end
end
-@spec delete(id()) :: {:ok, AgentRelationship.t()} | {:error, chgset()}
+@spec delete(id())
+ :: {:ok, AgentRelationship.t()} | {:error, String.t() | chgset()}
def delete(id) do
Multi.new()
- |> Multi.run(:get, multi_get(id))
- |> Multi.delete(:delete, &(&1.get))
+ |> Multi.put(:id, id)
+ |> Multi.run(:one, &one/2)
+ |> Multi.delete(:delete, &(&1.one))
|> Repo.transaction()
|> case do
- {:ok, %{delete: rel}} -> {:ok, rel}
+ {:ok, %{delete: ar}} -> {:ok, ar}
{:error, _, msg_or_cset, _} -> {:error, msg_or_cset}
end
end
-@spec preload(AgentRelationship.t(), :subject | :object | :relationship) :: AgentRelationship.t()
+@spec preload(AgentRelationship.t(), :subject | :object | :relationship)
+ :: AgentRelationship.t()
def preload(rel, :subject) do
Repo.preload(rel, :subject)
end
@@ -80,16 +96,4 @@ end
def preload(rel, :relationship) do
Repo.preload(rel, :relationship)
end
-
-# Returns an AgentRelationship in ok-err tuple from given ID. Used inside
-# Ecto.Multi.run/5 to get a record in transaction.
-@spec multi_get(id()) :: (repo(), changes() -> {:ok, AgentRelationship.t()} | {:error, String.t()})
-defp multi_get(id) do
- fn repo, _ ->
- case by_id(repo, id) do
- nil -> {:error, "not found"}
- rel -> {:ok, rel}
- end
- end
-end
end
diff --git a/src/zenflows/vf/agent_relationship/resolv.ex b/src/zenflows/vf/agent_relationship/resolv.ex
@@ -20,40 +20,45 @@ defmodule Zenflows.VF.AgentRelationship.Resolv do
alias Zenflows.VF.{AgentRelationship, AgentRelationship.Domain}
-def subject(%AgentRelationship{} = rel, _params, _info) do
- rel = Domain.preload(rel, :subject)
- {:ok, rel.subject}
-end
-
-def object(%AgentRelationship{} = rel, _params, _info) do
- rel = Domain.preload(rel, :object)
- {:ok, rel.object}
+def agent_relationship(params, _) do
+ Domain.one(params)
end
-def relationship(%AgentRelationship{} = rel, _params, _info) do
- rel = Domain.preload(rel, :relationship)
- {:ok, rel.relationship}
-end
-
-def agent_relationship(%{id: id}, _info) do
- {:ok, Domain.by_id(id)}
+def agent_relationships(params, _) do
+ Domain.all(params)
end
-def create_agent_relationship(%{relationship: params}, _info) do
+def create_agent_relationship(%{relationship: params}, _) do
with {:ok, rel} <- Domain.create(params) do
{:ok, %{agent_relationship: rel}}
end
end
-def update_agent_relationship(%{relationship: %{id: id} = params}, _info) do
+def update_agent_relationship(%{relationship: %{id: id} = params}, _) do
with {:ok, rel} <- Domain.update(id, params) do
{:ok, %{agent_relationship: rel}}
end
end
-def delete_agent_relationship(%{id: id}, _info) do
+def delete_agent_relationship(%{id: id}, _) do
with {:ok, _rel} <- Domain.delete(id) do
{:ok, true}
end
end
+
+def subject(%AgentRelationship{} = rel, _, _) do
+ rel = Domain.preload(rel, :subject)
+ {:ok, rel.subject}
+end
+
+def object(%AgentRelationship{} = rel, _, _) do
+ rel = Domain.preload(rel, :object)
+ {:ok, rel.object}
+end
+
+def relationship(%AgentRelationship{} = rel, _, _) do
+ rel = Domain.preload(rel, :relationship)
+ {:ok, rel.relationship}
+end
+
end
diff --git a/src/zenflows/vf/agent_relationship/type.ex b/src/zenflows/vf/agent_relationship/type.ex
@@ -26,11 +26,14 @@ alias Zenflows.VF.AgentRelationship.Resolv
The subject of a relationship between two agents. For example, if Mary
is a member of a group, then Mary is the subject.
"""
+@subject_id "(`Agent`) #{@subject}"
@object """
The object of a relationship between two agents. For example, if Mary
is a member of a group, then the group is the object.
"""
+@object_id "(`Agent`) #{@object}"
@relationship "A kind of relationship that exists between two agents."
+@relationship_id "(`AgentRelationshipRole`) #{@relationship}"
#@in_scope_of """
#Grouping around something to create a boundary or context, used for
#documenting, accounting, planning.
@@ -61,18 +64,14 @@ object :agent_relationship do
field :note, :string
end
-object :agent_relationship_response do
- field :agent_relationship, non_null(:agent_relationship)
-end
-
input_object :agent_relationship_create_params do
- @desc "(`Agent`) " <> @subject
+ @desc @subject_id
field :subject_id, non_null(:id), name: "subject"
- @desc "(`Agent`) " <> @object
+ @desc @object_id
field :object_id, non_null(:id), name: "object"
- @desc "(`AgentRelationshipRole`) " <> @relationship
+ @desc @relationship_id
field :relationship_id, non_null(:id), name: "relationship"
#@desc @in_scope_of
@@ -85,13 +84,13 @@ end
input_object :agent_relationship_update_params do
field :id, non_null(:id)
- @desc "(`Agent`) " <> @subject
+ @desc @subject_id
field :subject_id, :id, name: "subject"
- @desc "(`Agent`) " <> @object
+ @desc @object_id
field :object_id, :id, name: "object"
- @desc "(`AgentRelationshipRole`) " <> @relationship
+ @desc @relationship_id
field :relationship_id, :id, name: "relationship"
#@desc @in_scope_of
@@ -101,6 +100,20 @@ input_object :agent_relationship_update_params do
field :note, :string
end
+object :agent_relationship_response do
+ field :agent_relationship, non_null(:agent_relationship)
+end
+
+object :agent_relationship_edge do
+ field :cursor, non_null(:id)
+ field :node, non_null(:agent_relationship)
+end
+
+object :agent_relationship_connection do
+ field :page_info, non_null(:page_info)
+ field :edges, non_null(list_of(non_null(:agent_relationship_edge)))
+end
+
object :query_agent_relationship do
@desc "Retrieve details of an agent relationship by its ID."
field :agent_relationship, :agent_relationship do
@@ -108,11 +121,17 @@ object :query_agent_relationship do
resolve &Resolv.agent_relationship/2
end
- #@desc """
- #Retrieve details of all the relationships between all agents
- #registered in this collaboration space.
- #"""
- #agentRelationships(start: ID, limit: Int): [AgentRelationship!]
+ @desc """
+ Retrieve details of all the relationships between all agents
+ registered in this collaboration space.
+ """
+ field :agent_relationships, :agent_relationship_connection do
+ arg :first, :integer
+ arg :after, :id
+ arg :last, :integer
+ arg :before, :id
+ resolve &Resolv.agent_relationships/2
+ end
end
object :mutation_agent_relationship do
diff --git a/test/vf/agent_relationship/domain.test.exs b/test/vf/agent_relationship/domain.test.exs
@@ -30,42 +30,45 @@ setup do
# in_scope_of:
note: Factory.uniq("note"),
},
- agent_relationship: Factory.insert!(:agent_relationship),
+ inserted: Factory.insert!(:agent_relationship),
}
end
-test "by_id/1 returns an AgentRelationship", %{agent_relationship: rel} do
- assert %AgentRelationship{} = Domain.by_id(rel.id)
+describe "one/1" do
+ test "with good id: finds the AgentRelationship", %{inserted: %{id: id}} do
+ assert {:ok, %AgentRelationship{}} = Domain.one(id)
+ end
+
+ test "with bad id: doesn't find the AgentRelationship"do
+ assert {:error, "not found"} = Domain.one(Factory.id())
+ end
end
describe "create/1" do
- test "creates an AgentRelationship with valid params", %{params: params} do
- assert {:ok, %AgentRelationship{} = rel} = Domain.create(params)
-
- assert rel.subject_id == params.subject_id
- assert rel.object_id == params.object_id
- assert rel.relationship_id == params.relationship_id
- assert rel.note == params.note
+ test "with good params: creates an AgentRelationship", %{params: params} do
+ assert {:ok, %AgentRelationship{} = new} = Domain.create(params)
+ assert new.subject_id == params.subject_id
+ assert new.object_id == params.object_id
+ assert new.relationship_id == params.relationship_id
+ assert new.note == params.note
end
- test "doesn't create a AgentRelationship with invalid params" do
+ test "with bad params: doesn't create an AgentRelationship" do
assert {:error, %Changeset{}} = Domain.create(%{})
end
end
describe "update/2" do
- test "updates an AgentRelationship with valid params", %{params: params, agent_relationship: old} do
+ test "with good params: updates the AgentRelationship", %{params: params, inserted: old} do
assert {:ok, %AgentRelationship{} = new} = Domain.update(old.id, params)
-
assert new.subject_id == params.subject_id
assert new.object_id == params.object_id
assert new.relationship_id == params.relationship_id
assert new.note == params.note
end
- test "doesn't update a AgentRelationship", %{agent_relationship: old} do
+ test "with bad params: doesn't update the AgentRelationship", %{inserted: old} do
assert {:ok, %AgentRelationship{} = new} = Domain.update(old.id, %{})
-
assert new.subject_id == old.subject_id
assert new.object_id == old.object_id
assert new.relationship_id == old.relationship_id
@@ -73,8 +76,14 @@ describe "update/2" do
end
end
-test "delete/1 deletes an AgentRelationship", %{agent_relationship: %{id: id}} do
- assert {:ok, %AgentRelationship{id: ^id}} = Domain.delete(id)
- assert Domain.by_id(id) == nil
+describe "delete/1" do
+ test "with good id: deletes the AgentRelationship", %{inserted: %{id: id}} do
+ assert {:ok, %AgentRelationship{id: ^id}} = Domain.delete(id)
+ assert {:error, "not found"} = Domain.one(id)
+ end
+
+ test "with bad id: doesn't delete the AgentRelationship" do
+ assert {:error, "not found"} = Domain.delete(Factory.id())
+ end
end
end
diff --git a/test/vf/agent_relationship/type.test.exs b/test/vf/agent_relationship/type.test.exs
@@ -21,98 +21,88 @@ use ZenflowsTest.Help.AbsinCase, async: true
setup do
%{
params: %{
- subject_id: Factory.insert!(:agent).id,
- object_id: Factory.insert!(:agent).id,
- relationship_id: Factory.insert!(:agent_relationship_role).id,
- # in_scope_of:
- note: Factory.uniq("note"),
+ "subject" => Factory.insert!(:agent).id,
+ "object" => Factory.insert!(:agent).id,
+ "relationship" => Factory.insert!(:agent_relationship_role).id,
+ # inScopeOf:
+ "note" => Factory.uniq("note"),
},
- agent_relationship: Factory.insert!(:agent_relationship),
+ inserted: Factory.insert!(:agent_relationship),
}
end
+@frag """
+fragment agentRelationship on AgentRelationship {
+ id
+ subject { id }
+ object { id }
+ relationship { id }
+ note
+}
+"""
+
describe "Query" do
- test "agentRelationship()", %{agent_relationship: rel} do
+ test "agentRelationship", %{inserted: new} do
assert %{data: %{"agentRelationship" => data}} =
- query!("""
- agentRelationship(id: "#{rel.id}") {
- id
- subject { id }
- object { id }
- relationship {
- id
- }
- note
+ run!("""
+ #{@frag}
+ query ($id: ID!) {
+ agentRelationship(id: $id) {...agentRelationship}
}
- """)
+ """, vars: %{"id" => new.id})
- assert data["id"] == rel.id
- assert data["subject"]["id"] == rel.subject_id
- assert data["object"]["id"] == rel.object_id
- assert data["relationship"]["id"] == rel.relationship_id
- assert data["note"] == rel.note
+ assert data["id"] == new.id
+ assert data["subject"]["id"] == new.subject_id
+ assert data["object"]["id"] == new.object_id
+ assert data["relationship"]["id"] == new.relationship_id
+ assert data["note"] == new.note
end
end
describe "Mutation" do
- test "createAgentRelationship()", %{params: params} do
+ test "createAgentRelationship", %{params: params} do
assert %{data: %{"createAgentRelationship" => %{"agentRelationship" => data}}} =
- mutation!("""
- createAgentRelationship(relationship: {
- subject: "#{params.subject_id}"
- object: "#{params.object_id}"
- relationship: "#{params.relationship_id}"
- note: "#{params.note}"
- }) {
- agentRelationship {
- id
- subject { id }
- object { id }
- relationship { id }
- note
+ run!("""
+ #{@frag}
+ mutation ($relationship: AgentRelationshipCreateParams!) {
+ createAgentRelationship(relationship: $relationship) {
+ agentRelationship {...agentRelationship}
}
}
- """)
+ """, vars: %{"relationship" => params})
assert {:ok, _} = Zenflows.DB.ID.cast(data["id"])
- assert data["subject"]["id"] == params.subject_id
- assert data["object"]["id"] == params.object_id
- assert data["relationship"]["id"] == params.relationship_id
- assert data["note"] == params.note
+ assert data["subject"]["id"] == params["subject"]
+ assert data["object"]["id"] == params["object"]
+ assert data["relationship"]["id"] == params["relationship"]
+ assert data["note"] == params["note"]
end
- test "updateAgentRelationship()", %{params: params, agent_relationship: rel} do
+ test "updateAgentRelationship", %{params: params, inserted: old} do
assert %{data: %{"updateAgentRelationship" => %{"agentRelationship" => data}}} =
- mutation!("""
- updateAgentRelationship(relationship: {
- id: "#{rel.id}"
- subject: "#{params.subject_id}"
- object: "#{params.object_id}"
- relationship: "#{params.relationship_id}"
- note: "#{params.note}"
- }) {
- agentRelationship {
- id
- subject { id }
- object { id }
- relationship { id }
- note
+ run!("""
+ #{@frag}
+ mutation ($relationship: AgentRelationshipUpdateParams!) {
+ updateAgentRelationship(relationship: $relationship) {
+ agentRelationship {...agentRelationship}
}
}
- """)
+ """, vars: %{"relationship" => Map.put(params, "id", old.id)})
- assert data["id"] == rel.id
- assert data["subject"]["id"] == params.subject_id
- assert data["object"]["id"] == params.object_id
- assert data["relationship"]["id"] == params.relationship_id
- assert data["note"] == params.note
+ assert data["id"] == old.id
+ assert data["subject"]["id"] == params["subject"]
+ assert data["object"]["id"] == params["object"]
+ assert data["relationship"]["id"] == params["relationship"]
+ assert data["note"] == params["note"]
end
- test "deleteAgentRelationship()", %{agent_relationship: %{id: id}} do
+ test "deleteAgentRelationship", %{inserted: %{id: id}} do
assert %{data: %{"deleteAgentRelationship" => true}} =
- mutation!("""
- deleteAgentRelationship(id: "#{id}")
- """)
+ run!("""
+ mutation ($id: ID!) {
+ deleteAgentRelationship(id: $id)
+ }
+ """, vars: %{"id" => id})
end
end
end