zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/zenflows/vf/plan/domain.ex | 48+++++++++++++++++++++++-------------------------
Msrc/zenflows/vf/plan/resolv.ex | 2+-
Mtest/vf/plan/domain.test.exs | 56+++++++++++++++++++++++++++++++-------------------------
Mtest/vf/plan/type.test.exs | 117+++++++++++++++++++++++++++++++++++++++-----------------------------------------
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