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:
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