commit 22030ea1ddeeddc4b2344c3216616e7b427640c5
parent d3158f6dffc659538955faf0254575a3f144951a
Author: srfsh <dev@srf.sh>
Date: Sun, 14 Aug 2022 13:11:10 +0300
Zenflows{Test,}.VF.Plan.{Domain,Resolv}: refactor
I think it is easier to read the code this way.
Diffstat:
4 files changed, 112 insertions(+), 111 deletions(-)
diff --git a/src/zenflows/vf/plan/domain.ex b/src/zenflows/vf/plan/domain.ex
@@ -24,31 +24,41 @@ alias Zenflows.VF.Plan
@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()) :: Plan.t() | nil
-def by_id(repo \\ Repo, id) do
- repo.get(Plan, id)
+@spec one(repo(), id()) :: {:ok, Plan.t()} | {:error, String.t()}
+def one(repo \\ Repo, id) do
+ one_by(repo, id: id)
+end
+
+@spec one_by(repo(), map() | Keyword.t())
+ :: {:ok, Plan.t()} | {:error, String.t()}
+def one_by(repo \\ Repo, clauses) do
+ case repo.get_by(Plan, clauses) do
+ nil -> {:error, "not found"}
+ found -> {:ok, found}
+ end
end
@spec create(params()) :: {:ok, Plan.t()} | {:error, chgset()}
def create(params) do
Multi.new()
- |> Multi.insert(:plan, Plan.chgset(params))
+ |> Multi.insert(:insert, Plan.chgset(params))
|> Repo.transaction()
|> case do
- {:ok, %{plan: p}} -> {:ok, p}
+ {:ok, %{insert: p}} -> {:ok, p}
{:error, _, cset, _} -> {:error, cset}
end
end
-@spec update(id(), params()) :: {:ok, Plan.t()} | {:error, chgset()}
+@spec update(id(), params()) ::
+ {:ok, Plan.t()} | {:error, String.t() | chgset()}
def update(id, params) do
Multi.new()
- |> Multi.run(:get, multi_get(id))
- |> Multi.update(:update, &Plan.chgset(&1.get, params))
+ |> Multi.put(:id, id)
+ |> Multi.run(:one, &one_by/2)
+ |> Multi.update(:update, &Plan.chgset(&1.one, params))
|> Repo.transaction()
|> case do
{:ok, %{update: p}} -> {:ok, p}
@@ -56,11 +66,12 @@ def update(id, params) do
end
end
-@spec delete(id()) :: {:ok, Plan.t()} | {:error, chgset()}
+@spec delete(id()) :: {:ok, Plan.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_by/2)
+ |> Multi.delete(:delete, &(&1.one))
|> Repo.transaction()
|> case do
{:ok, %{delete: p}} -> {:ok, p}
@@ -72,17 +83,4 @@ end
def preload(plan, :refinement_of) do
Repo.preload(plan, :refinement_of)
end
-
-# Returns a Plan 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, Plan.t()} | {:error, String.t()})
-defp multi_get(id) do
- fn repo, _ ->
- case by_id(repo, id) do
- nil -> {:error, "not found"}
- p -> {:ok, p}
- end
- end
-end
end
diff --git a/src/zenflows/vf/plan/resolv.ex b/src/zenflows/vf/plan/resolv.ex
@@ -23,7 +23,7 @@ use Absinthe.Schema.Notation
alias Zenflows.VF.{Plan, Plan.Domain}
def plan(%{id: id}, _info) do
- {:ok, Domain.by_id(id)}
+ Domain.one(id)
end
def create_plan(%{plan: params}, _info) do
diff --git a/test/vf/plan/domain.test.exs b/test/vf/plan/domain.test.exs
@@ -21,54 +21,54 @@ use ZenflowsTest.Help.EctoCase, async: true
alias Ecto.Changeset
alias Zenflows.VF.{Plan, Plan.Domain, Scenario}
-setup ctx do
- params = %{
- name: Factory.uniq("name"),
- note: Factory.uniq("note"),
- due: DateTime.utc_now(),
- refinement_of_id: Factory.insert!(:scenario).id,
- }
+setup do
+ %{
+ params: %{
+ name: Factory.str("name"),
+ note: Factory.str("note"),
+ due: Factory.now(),
+ refinement_of_id: Factory.insert!(:scenario).id,
+ },
+ inserted: Factory.insert!(:plan),
+ id: Factory.id(),
+ }
+end
- if ctx[:no_insert] do
- %{params: params}
- else
- %{params: params, inserted: Factory.insert!(:plan)}
+describe "one/1" do
+ test "with good id: finds the Plan", %{inserted: %{id: id}} do
+ assert {:ok, %Plan{}} = Domain.one(id)
end
-end
-test "by_id/1 returns a Plan", %{inserted: plan} do
- assert %Plan{} = Domain.by_id(plan.id)
+ test "with bad id: doesn't find the Plan", %{id: id} do
+ assert {:error, "not found"} = Domain.one(id)
+ end
end
describe "create/1" do
- @tag :no_insert
- test "creates a Plan with valid params", %{params: params} do
+ test "with good params: creates a Plan", %{params: params} do
assert {:ok, %Plan{} = plan} = Domain.create(params)
-
assert plan.name == params.name
assert plan.note == params.note
assert plan.due == params.due
assert plan.refinement_of_id == params.refinement_of_id
end
- test "doesn't create a Plan with invalid params" do
+ test "with bad params: doesn't create an" do
assert {:error, %Changeset{}} = Domain.create(%{})
end
end
describe "update/2" do
- test "updates a Plan with valid params", %{params: params, inserted: old} do
+ test "with good params: updates the Plan", %{params: params, inserted: old} do
assert {:ok, %Plan{} = new} = Domain.update(old.id, params)
-
assert new.name == params.name
assert new.note == params.note
assert new.due == params.due
assert new.refinement_of_id == params.refinement_of_id
end
- test "doesn't update a Plan", %{inserted: old} do
+ test "with bad params: doesn't update the Plan", %{inserted: old} do
assert {:ok, %Plan{} = new} = Domain.update(old.id, %{})
-
assert new.name == old.name
assert new.note == old.note
assert new.due == old.due
@@ -76,9 +76,15 @@ describe "update/2" do
end
end
-test "delete/1 deletes a Plan", %{inserted: %{id: id}} do
- assert {:ok, %Plan{id: ^id}} = Domain.delete(id)
- assert Domain.by_id(id) == nil
+describe "delete/1" do
+ test "with good id: deletes the Plan", %{inserted: %{id: id}} do
+ assert {:ok, %Plan{id: ^id}} = Domain.delete(id)
+ assert {:error, "not found"} = Domain.one(id)
+ end
+
+ test "with bad id: doesn't delete the Plan", %{id: id} do
+ assert {:error, "not found"} = Domain.delete(id)
+ end
end
describe "preload/2" do
diff --git a/test/vf/plan/type.test.exs b/test/vf/plan/type.test.exs
@@ -16,104 +16,101 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
defmodule ZenflowsTest.VF.Plan.Type do
+@moduledoc "A man, a plan, a canal: panama."
+
use ZenflowsTest.Help.AbsinCase, async: true
setup do
%{
params: %{
- name: Factory.uniq("name"),
- note: Factory.uniq("note"),
- due: DateTime.utc_now(),
- refinement_of_id: Factory.insert!(:scenario).id,
+ "name" => Factory.uniq("name"),
+ "note" => Factory.uniq("note"),
+ "due" => Factory.iso_now(),
+ "refinementOf" => Factory.insert!(:scenario).id,
},
inserted: Factory.insert!(:plan),
}
end
+@frag """
+fragment plan on Plan {
+ id
+ name
+ note
+ created
+ due
+ refinementOf {id}
+}
+"""
+
describe "Query" do
- test "plan()", %{inserted: plan} do
+ test "plan", %{inserted: plan} do
assert %{data: %{"plan" => data}} =
- query!("""
- plan(id: "#{plan.id}") {
- id
- name
- note
- created
- due
- refinementOf {id}
+ run!("""
+ #{@frag}
+ query ($id: ID!) {
+ plan(id: $id) {...plan}
}
- """)
+ """, vars: %{"id" => plan.id})
assert data["id"] == plan.id
assert data["name"] == plan.name
assert data["note"] == plan.note
- assert data["created"] == DateTime.to_iso8601(plan.created)
assert data["due"] == DateTime.to_iso8601(plan.due)
assert data["refinementOf"]["id"] == plan.refinement_of_id
+ assert {:ok, created, 0} = DateTime.from_iso8601(data["created"])
+ assert DateTime.compare(DateTime.utc_now(), created) != :lt
end
end
describe "Mutation" do
- test "createPlan()", %{params: params} do
+ test "createPlan", %{params: params} do
assert %{data: %{"createPlan" => %{"plan" => data}}} =
- mutation!("""
- createPlan(plan: {
- name: "#{params.name}"
- note: "#{params.note}"
- due: "#{params.due}"
- refinementOf: "#{params.refinement_of_id}"
- }) {
- plan {
- id
- name
- note
- created
- due
- refinementOf {id}
+ run!("""
+ #{@frag}
+ mutation ($plan: PlanCreateParams!) {
+ createPlan(plan: $plan) {
+ plan {...plan}
}
}
- """)
+ """, vars: %{"plan" => params})
assert {:ok, _} = Zenflows.DB.ID.cast(data["id"])
- assert data["name"] == params.name
- assert data["note"] == params.note
- assert data["due"] == DateTime.to_iso8601(params.due)
- assert data["refinementOf"]["id"] == params.refinement_of_id
+ assert data["name"] == params["name"]
+ assert data["note"] == params["note"]
+ assert data["due"] == params["due"]
+ assert data["refinementOf"]["id"] == params["refinementOf"]
+ assert {:ok, created, 0} = DateTime.from_iso8601(data["created"])
+ assert DateTime.compare(DateTime.utc_now(), created) != :lt
end
- test "updatePlan()", %{params: params, inserted: plan} do
+ test "updatePlan", %{params: params, inserted: plan} do
assert %{data: %{"updatePlan" => %{"plan" => data}}} =
- mutation!("""
- updatePlan(plan: {
- id: "#{plan.id}"
- name: "#{params.name}"
- note: "#{params.note}"
- due: "#{params.due}"
- refinementOf: "#{params.refinement_of_id}"
- }) {
- plan {
- id
- name
- note
- created
- due
- refinementOf {id}
+ run!("""
+ #{@frag}
+ mutation ($plan: PlanUpdateParams!) {
+ updatePlan(plan: $plan) {
+ plan {...plan}
}
}
- """)
+ """, vars: %{"plan" => params |> Map.put("id", plan.id)})
assert data["id"] == plan.id
- assert data["name"] == params.name
- assert data["note"] == params.note
- assert data["due"] == DateTime.to_iso8601(params.due)
- assert data["refinementOf"]["id"] == params.refinement_of_id
+ assert data["name"] == params["name"]
+ assert data["note"] == params["note"]
+ assert data["due"] == params["due"]
+ assert data["refinementOf"]["id"] == params["refinementOf"]
+ assert {:ok, created, 0} = DateTime.from_iso8601(data["created"])
+ assert DateTime.compare(DateTime.utc_now(), created) != :lt
end
- test "deletePlan()", %{inserted: %{id: id}} do
+ test "deletePlan", %{inserted: %{id: id}} do
assert %{data: %{"deletePlan" => true}} =
- mutation!("""
- deletePlan(id: "#{id}")
- """)
+ run!("""
+ mutation ($id: ID!) {
+ deletePlan(id: $id)
+ }
+ """, vars: %{"id" => id})
end
end
end