zf

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

commit c0287c8f5d4d9803c17b13b96722774696e523ea
parent f98ddcfa7b8fa92da701eadb79fbac03626c0e51
Author: srfsh <dev@srf.sh>
Date:   Tue, 23 Aug 2022 08:51:35 +0300

Zenflows{Test,}.VF.ProductBatch: add paging support and small improvements

Diffstat:
Msrc/zenflows/vf/product_batch/domain.ex | 52+++++++++++++++++++++++++++-------------------------
Msrc/zenflows/vf/product_batch/resolv.ex | 14+++++++++-----
Msrc/zenflows/vf/product_batch/type.ex | 26++++++++++++++++++++++----
Mtest/vf/product_batch/domain.test.exs | 41+++++++++++++++++++++++++----------------
Mtest/vf/product_batch/type.test.exs | 98+++++++++++++++++++++++++++++++++++++------------------------------------------
5 files changed, 129 insertions(+), 102 deletions(-)

diff --git a/src/zenflows/vf/product_batch/domain.ex b/src/zenflows/vf/product_batch/domain.ex @@ -20,17 +20,28 @@ defmodule Zenflows.VF.ProductBatch.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.ProductBatch @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()) :: ProductBatch.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(ProductBatch, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, ProductBatch.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(ProductBatch, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(ProductBatch.t()) +def all(params) do + Paging.page(ProductBatch, params) end @spec create(params()) :: {:ok, ProductBatch.t()} | {:error, chgset()} @@ -39,44 +50,35 @@ def create(params) do |> Multi.insert(:insert, ProductBatch.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{insert: b}} -> {:ok, b} + {:ok, %{insert: pb}} -> {:ok, pb} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, ProductBatch.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, ProductBatch.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &ProductBatch.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &ProductBatch.chgset(&1.one, params)) |> Repo.transaction() |> case do - {:ok, %{update: b}} -> {:ok, b} + {:ok, %{update: pb}} -> {:ok, pb} {:error, _, msg_or_cset, _} -> {:error, msg_or_cset} end end -@spec delete(id()) :: {:ok, ProductBatch.t()} | {:error, chgset()} +@spec delete(id()) :: {:ok, ProductBatch.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: b}} -> {:ok, b} + {:ok, %{delete: pb}} -> {:ok, pb} {:error, _, msg_or_cset, _} -> {:error, msg_or_cset} end end - -# Returns a ProductBatch 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, ProductBatch.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - b -> {:ok, b} - end - end -end end diff --git a/src/zenflows/vf/product_batch/resolv.ex b/src/zenflows/vf/product_batch/resolv.ex @@ -22,23 +22,27 @@ use Absinthe.Schema.Notation alias Zenflows.VF.ProductBatch.Domain -def product_batch(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def product_batch(params, _) do + Domain.one(params) end -def create_product_batch(%{product_batch: params}, _info) do +def product_batches(params, _) do + Domain.all(params) +end + +def create_product_batch(%{product_batch: params}, _) do with {:ok, batch} <- Domain.create(params) do {:ok, %{product_batch: batch}} end end -def update_product_batch(%{product_batch: %{id: id} = params}, _info) do +def update_product_batch(%{product_batch: %{id: id} = params}, _) do with {:ok, batch} <- Domain.update(id, params) do {:ok, %{product_batch: batch}} end end -def delete_product_batch(%{id: id}, _info) do +def delete_product_batch(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end diff --git a/src/zenflows/vf/product_batch/type.ex b/src/zenflows/vf/product_batch/type.ex @@ -47,10 +47,6 @@ object :product_batch do field :production_date, :datetime end -object :product_batch_response do - field :product_batch, non_null(:product_batch) -end - input_object :product_batch_create_params do @desc @batch_number field :batch_number, non_null(:string) @@ -75,11 +71,33 @@ input_object :product_batch_update_params do field :production_date, :datetime end +object :product_batch_response do + field :product_batch, non_null(:product_batch) +end + +object :product_batch_edge do + field :cursor, non_null(:id) + field :node, non_null(:product_batch) +end + +object :product_batch_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:product_batch_edge))) +end + object :query_product_batch do field :product_batch, :product_batch do arg :id, non_null(:id) resolve &Resolv.product_batch/2 end + + field :product_batches, :product_batch_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.product_batches/2 + end end object :mutation_product_batch do diff --git a/test/vf/product_batch/domain.test.exs b/test/vf/product_batch/domain.test.exs @@ -32,44 +32,53 @@ setup do } end -test "by_id/1 returns a ProductBatch", %{inserted: batch} do - assert %ProductBatch{} = Domain.by_id(batch.id) +describe "one/1" do + test "with good id: finds the ProductBatch", %{inserted: %{id: id}} do + assert {:ok, %ProductBatch{}} = Domain.one(id) + end + + test "with bad id: doesn't find the ProductBatch" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - test "creates a ProductBatch with valid params", %{params: params} do - assert {:ok, %ProductBatch{} = batch} = Domain.create(params) - - assert batch.batch_number == params.batch_number - assert batch.expiry_date == params.expiry_date - assert batch.production_date == params.production_date + test "with good params: creates a ProductBatch", %{params: params} do + assert {:ok, %ProductBatch{} = new} = Domain.create(params) + assert new.batch_number == params.batch_number + assert new.expiry_date == params.expiry_date + assert new.production_date == params.production_date end - test "doesn't create a ProductBatch with invalid params" do + test "with bad params: doesn't create a ProductBatch" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates a ProductBatch with valid params", %{params: params, inserted: old} do + test "with good params: updates the ProductBatch", %{params: params, inserted: old} do assert {:ok, %ProductBatch{} = new} = Domain.update(old.id, params) - assert new.batch_number == params.batch_number assert new.expiry_date == params.expiry_date assert new.production_date == params.production_date end - test "doesn't update a ProductBatch", %{inserted: old} do + test "with bad params: doesn't update the ProductBatch", %{inserted: old} do assert {:ok, %ProductBatch{} = new} = Domain.update(old.id, %{}) - assert new.batch_number == old.batch_number assert new.expiry_date == old.expiry_date assert new.production_date == old.production_date end end -test "delete/1 deletes a ProductBatch", %{inserted: %{id: id}} do - assert {:ok, %ProductBatch{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the ProductBatch", %{inserted: %{id: id}} do + assert {:ok, %ProductBatch{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the ProductBatch" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end end diff --git a/test/vf/product_batch/type.test.exs b/test/vf/product_batch/type.test.exs @@ -21,86 +21,80 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - batch_number: Factory.uniq("batch number"), - expiry_date: DateTime.utc_now(), - production_date: DateTime.utc_now(), + "batchNumber" => Factory.uniq("batch number"), + "expiryDate" => Factory.iso_now(), + "productionDate" => Factory.iso_now(), }, inserted: Factory.insert!(:product_batch), } end +@frag """ +fragment productBatch on ProductBatch { + id + batchNumber + expiryDate + productionDate +} +""" + describe "Query" do - test "productBatch()", %{inserted: batch} do + test "productBatch", %{inserted: new} do assert %{data: %{"productBatch" => data}} = - query!(""" - productBatch(id: "#{batch.id}") { - id - batchNumber - expiryDate - productionDate + run!(""" + #{@frag} + query ($id: ID!) { + productBatch(id: $id) {...productBatch} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == batch.id - assert data["batchNumber"] == batch.batch_number - assert data["expiryDate"] == DateTime.to_iso8601(batch.expiry_date) - assert data["productionDate"] == DateTime.to_iso8601(batch.production_date) + assert data["id"] == new.id + assert data["batchNumber"] == new.batch_number + assert data["expiryDate"] == DateTime.to_iso8601(new.expiry_date) + assert data["productionDate"] == DateTime.to_iso8601(new.production_date) end end describe "Mutation" do - test "createProductBatch()", %{params: params} do + test "createProductBatch", %{params: params} do assert %{data: %{"createProductBatch" => %{"productBatch" => data}}} = - mutation!(""" - createProductBatch(productBatch: { - batchNumber: "#{params.batch_number}" - expiryDate: "#{params.expiry_date}" - productionDate: "#{params.production_date}" - }) { - productBatch { - id - batchNumber - expiryDate - productionDate + run!(""" + #{@frag} + mutation ($productBatch: ProductBatchCreateParams!) { + createProductBatch(productBatch: $productBatch) { + productBatch {...productBatch} } } - """) + """, vars: %{"productBatch" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["batchNumber"] == params.batch_number - assert data["expiryDate"] == DateTime.to_iso8601(params.expiry_date) - assert data["productionDate"] == DateTime.to_iso8601(params.production_date) + data = Map.delete(data, "id") + assert data == params end - test "updateProductBatch()", %{params: params, inserted: batch} do + test "updateProductBatch", %{params: params, inserted: old} do assert %{data: %{"updateProductBatch" => %{"productBatch" => data}}} = - mutation!(""" - updateProductBatch(productBatch: { - id: "#{batch.id}" - batchNumber: "#{params.batch_number}" - expiryDate: "#{params.expiry_date}" - productionDate: "#{params.production_date}" - }) { - productBatch { - id - batchNumber - expiryDate - productionDate + run!(""" + #{@frag} + mutation ($productBatch: ProductBatchUpdateParams!) { + updateProductBatch(productBatch: $productBatch) { + productBatch {...productBatch} } } - """) + """, vars: %{"productBatch" => Map.put(params, "id", old.id)}) - assert data["id"] == batch.id - assert data["batchNumber"] == params.batch_number - assert data["expiryDate"] == DateTime.to_iso8601(params.expiry_date) - assert data["productionDate"] == DateTime.to_iso8601(params.production_date) + assert data["id"] == old.id + data = Map.delete(data, "id") + assert data == params end test "deleteProductBatch()", %{inserted: %{id: id}} do assert %{data: %{"deleteProductBatch" => true}} = - mutation!(""" - deleteProductBatch(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteProductBatch(id: $id) + } + """, vars: %{"id" => id}) end end end