commit 761bdaabe3cbd6495289bf10054b892647a5c65a
parent 2ae2f0164ab1eaf6194f4c52d442df0c2c69230a
Author: srfsh <dev@srf.sh>
Date: Tue, 23 Aug 2022 10:43:58 +0300
Zenflows{Test,}.VF.RecipeProcess: add paging support and small improvements
Diffstat:
5 files changed, 206 insertions(+), 222 deletions(-)
diff --git a/src/zenflows/vf/recipe_process/domain.ex b/src/zenflows/vf/recipe_process/domain.ex
@@ -20,35 +20,48 @@ defmodule Zenflows.VF.RecipeProcess.Domain do
alias Ecto.Multi
alias Zenflows.DB.Repo
+alias Zenflows.GQL.Paging
alias Zenflows.VF.{Duration, RecipeProcess}
@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()) :: RecipeProcess.t() | nil
-def by_id(repo \\ Repo, id) do
- repo.get(RecipeProcess, id)
+@spec one(repo(), id() | map() | Keyword.t())
+ :: {:ok, RecipeProcess.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(RecipeProcess, clauses) do
+ nil -> {:error, "not found"}
+ found -> {:ok, found}
+ end
+end
+
+@spec all(Paging.params()) :: Paging.result(RecipeProcess.t())
+def all(params) do
+ Paging.page(RecipeProcess, params)
end
@spec create(params()) :: {:ok, RecipeProcess.t()} | {:error, chgset()}
def create(params) do
Multi.new()
- |> Multi.insert(:rec_proc, RecipeProcess.chgset(params))
+ |> Multi.insert(:insert, RecipeProcess.chgset(params))
|> Repo.transaction()
|> case do
- {:ok, %{rec_proc: rp}} -> {:ok, rp}
+ {:ok, %{insert: rp}} -> {:ok, rp}
{:error, _, cset, _} -> {:error, cset}
end
end
-@spec update(id(), params()) :: {:ok, RecipeProcess.t()} | {:error, chgset()}
+@spec update(id(), params())
+ :: {:ok, RecipeProcess.t()} | {:error, String.t() | chgset()}
def update(id, params) do
Multi.new()
- |> Multi.run(:get, multi_get(id))
- |> Multi.update(:update, &RecipeProcess.chgset(&1.get, params))
+ |> Multi.put(:id, id)
+ |> Multi.run(:one, &one/2)
+ |> Multi.update(:update, &RecipeProcess.chgset(&1.one, params))
|> Repo.transaction()
|> case do
{:ok, %{update: rp}} -> {:ok, rp}
@@ -56,11 +69,13 @@ def update(id, params) do
end
end
-@spec delete(id()) :: {:ok, RecipeProcess.t()} | {:error, chgset()}
+@spec delete(id())
+ :: {:ok, RecipeProcess.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: rp}} -> {:ok, rp}
@@ -77,16 +92,4 @@ end
def preload(rec_proc, :process_conforms_to) do
Repo.preload(rec_proc, :process_conforms_to)
end
-
-# Returns a RecipeProcess 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, RecipeProcess.t()} | {:error, String.t()})
-defp multi_get(id) do
- fn repo, _ ->
- case by_id(repo, id) do
- nil -> {:error, "not found"}
- rp -> {:ok, rp}
- end
- end
-end
end
diff --git a/src/zenflows/vf/recipe_process/resolv.ex b/src/zenflows/vf/recipe_process/resolv.ex
@@ -20,36 +20,40 @@ defmodule Zenflows.VF.RecipeProcess.Resolv do
use Absinthe.Schema.Notation
-alias Zenflows.VF.{RecipeProcess, RecipeProcess.Domain}
+alias Zenflows.VF.RecipeProcess.Domain
-def recipe_process(%{id: id}, _info) do
- {:ok, Domain.by_id(id)}
+def recipe_process(params, _) do
+ Domain.one(params)
end
-def create_recipe_process(%{recipe_process: params}, _info) do
+def recipe_processes(params, _) do
+ Domain.all(params)
+end
+
+def create_recipe_process(%{recipe_process: params}, _) do
with {:ok, rec_proc} <- Domain.create(params) do
{:ok, %{recipe_process: rec_proc}}
end
end
-def update_recipe_process(%{recipe_process: %{id: id} = params}, _info) do
+def update_recipe_process(%{recipe_process: %{id: id} = params}, _) do
with {:ok, rec_proc} <- Domain.update(id, params) do
{:ok, %{recipe_process: rec_proc}}
end
end
-def delete_recipe_process(%{id: id}, _info) do
+def delete_recipe_process(%{id: id}, _) do
with {:ok, _} <- Domain.delete(id) do
{:ok, true}
end
end
-def has_duration(%RecipeProcess{} = rec_proc, _args, _info) do
+def has_duration(rec_proc, _, _) do
rec_proc = Domain.preload(rec_proc, :has_duration)
{:ok, rec_proc.has_duration}
end
-def process_conforms_to(%RecipeProcess{} = rec_proc, _args, _info) do
+def process_conforms_to(rec_proc, _, _) do
rec_proc = Domain.preload(rec_proc, :process_conforms_to)
{:ok, rec_proc.process_conforms_to}
end
diff --git a/src/zenflows/vf/recipe_process/type.ex b/src/zenflows/vf/recipe_process/type.ex
@@ -37,6 +37,7 @@ for purposes of categorization.
@process_conforms_to """
The standard specification or definition of a process.
"""
+@process_conforms_to_id "(`ProcesssSpecification`) #{@process_conforms_to}"
@note "A textual description or comment."
@desc "Specifies a process in a recipe for use in planning from recipe."
@@ -60,10 +61,6 @@ object :recipe_process do
field :note, :string
end
-object :recipe_process_response do
- field :recipe_process, non_null(:recipe_process)
-end
-
input_object :recipe_process_create_params do
@desc @name
field :name, non_null(:string)
@@ -74,10 +71,7 @@ input_object :recipe_process_create_params do
@desc @process_classified_as
field :process_classified_as, list_of(non_null(:uri))
- # TODO: When
- # https://github.com/absinthe-graphql/absinthe/issues/1126 results,
- # apply the correct changes if any.
- @desc "(`ProcessSpecification`) " <> @process_conforms_to
+ @desc @process_conforms_to_id
field :process_conforms_to_id, non_null(:id), name: "process_conforms_to"
@desc @note
@@ -96,20 +90,40 @@ input_object :recipe_process_update_params do
@desc @process_classified_as
field :process_classified_as, list_of(non_null(:uri))
- @desc "(`ProcessSpecification`) " <> @process_conforms_to
+ @desc @process_conforms_to_id
field :process_conforms_to_id, :id, name: "process_conforms_to"
@desc @note
field :note, :string
end
+object :recipe_process_response do
+ field :recipe_process, non_null(:recipe_process)
+end
+
+object :recipe_process_edge do
+ field :cursor, non_null(:id)
+ field :node, non_null(:recipe_process)
+end
+
+object :recipe_process_connection do
+ field :page_info, non_null(:page_info)
+ field :edges, non_null(list_of(non_null(:recipe_process_edge)))
+end
+
object :query_recipe_process do
field :recipe_process, :recipe_process do
arg :id, non_null(:id)
resolve &Resolv.recipe_process/2
end
- #recipeProcesses(start: ID, limit: Int): [RecipeProcess!]
+ field :recipe_processes, :recipe_process_connection do
+ arg :first, :integer
+ arg :after, :id
+ arg :last, :integer
+ arg :before, :id
+ resolve &Resolv.recipe_processes/2
+ end
end
object :mutation_recipe_process do
diff --git a/test/vf/recipe_process/domain.test.exs b/test/vf/recipe_process/domain.test.exs
@@ -26,69 +26,63 @@ alias Zenflows.VF.{
RecipeProcess.Domain,
}
-setup ctx do
- params = %{
- name: Factory.uniq("name"),
- note: Factory.uniq("note"),
- process_classified_as: Factory.uniq_list("uri"),
- process_conforms_to_id: Factory.insert!(:process_specification).id,
- has_duration: Factory.build(:iduration),
- }
-
- if ctx[:no_insert] do
- %{params: params}
- else
- %{params: params, inserted: Factory.insert!(:recipe_process)}
- end
+setup do
+ %{
+ params: %{
+ name: Factory.uniq("name"),
+ note: Factory.uniq("note"),
+ process_classified_as: Factory.uniq_list("uri"),
+ process_conforms_to_id: Factory.insert!(:process_specification).id,
+ has_duration: Factory.build(:iduration),
+ },
+ inserted: Factory.insert!(:recipe_process),
+ }
end
-test "by_id/1 returns a RecipeProcess", %{inserted: rec_proc} do
- assert %RecipeProcess{} = Domain.by_id(rec_proc.id)
+describe "one/1" do
+ test "with good id: finds the RecipeProcess", %{inserted: %{id: id}} do
+ assert {:ok, %RecipeProcess{}} = Domain.one(id)
+ end
+
+ test "with bad id: doesn't find the RecipeProcess" do
+ assert {:error, "not found"} = Domain.one(Factory.id())
+ end
end
describe "create/1" do
- @tag :no_insert
- test "creates a RecipeProcess with valid params without :has_duration", %{params: params} do
- params = Map.delete(params, :has_duration)
-
- assert {:ok, %RecipeProcess{} = rec_proc} = Domain.create(params)
-
- assert rec_proc.name == params.name
- assert rec_proc.note == params.note
- assert rec_proc.process_classified_as == params.process_classified_as
- assert rec_proc.process_conforms_to_id == params.process_conforms_to_id
- assert rec_proc.has_duration_unit_type == nil
- assert rec_proc.has_duration_numeric_duration == nil
+ test "with good params (with :has_duration): creates a RecipeProcess", %{params: params} do
+ assert {:ok, %RecipeProcess{} = new} = Domain.create(params)
+ assert new.name == params.name
+ assert new.note == params.note
+ assert new.process_classified_as == params.process_classified_as
+ assert new.process_conforms_to_id == params.process_conforms_to_id
+ assert new.has_duration_unit_type == params.has_duration.unit_type
+ assert new.has_duration_numeric_duration == params.has_duration.numeric_duration
end
- @tag :no_insert
- test "creates a RecipeProcess with valid params with :has_duration", %{params: params} do
- assert {:ok, %RecipeProcess{} = rec_proc} = Domain.create(params)
-
- assert rec_proc.name == params.name
- assert rec_proc.note == params.note
- assert rec_proc.process_classified_as == params.process_classified_as
- assert rec_proc.process_conforms_to_id == params.process_conforms_to_id
- assert rec_proc.has_duration_unit_type == params.has_duration.unit_type
- assert rec_proc.has_duration_numeric_duration == params.has_duration.numeric_duration
+ test "with good params (without :has_duration): creates a RecipeProcess", %{params: params} do
+ params = Map.delete(params, :has_duration)
+ assert {:ok, %RecipeProcess{} = new} = Domain.create(params)
+ assert new.name == params.name
+ assert new.note == params.note
+ assert new.process_classified_as == params.process_classified_as
+ assert new.process_conforms_to_id == params.process_conforms_to_id
+ assert new.has_duration_unit_type == nil
+ assert new.has_duration_numeric_duration == nil
end
- @tag :no_insert
- test "creates a RecipeProcess with valid params with :has_duration set to nil", %{params: params} do
+ test "with good params (with :has_duration set to nil): creates a RecipeProcess", %{params: params} do
params = Map.put(params, :has_duration, nil)
-
- assert {:ok, %RecipeProcess{} = rec_proc} = Domain.create(params)
-
- assert rec_proc.name == params.name
- assert rec_proc.note == params.note
- assert rec_proc.process_classified_as == params.process_classified_as
- assert rec_proc.process_conforms_to_id == params.process_conforms_to_id
- assert rec_proc.has_duration_unit_type == nil
- assert rec_proc.has_duration_numeric_duration == nil
+ assert {:ok, %RecipeProcess{} = new} = Domain.create(params)
+ assert new.name == params.name
+ assert new.note == params.note
+ assert new.process_classified_as == params.process_classified_as
+ assert new.process_conforms_to_id == params.process_conforms_to_id
+ assert new.has_duration_unit_type == nil
+ assert new.has_duration_numeric_duration == nil
end
- @tag :no_insert
- test "doesn't create a RecipeProcess with valid invalid :has_duration fields", %{params: params} do
+ test "with bad params (with bad :has_duration): doesn't create a RecipeProcess", %{params: params} do
params = Map.put(params, :has_duration, %{unit_type: nil, numeric_duration: nil})
assert {:error, %Changeset{errors: errs}} = Domain.create(params)
assert length(Keyword.get_values(errs, :has_duration)) == 2
@@ -110,15 +104,14 @@ describe "create/1" do
assert Keyword.has_key?(errs, :has_duration)
end
- test "doesn't create a RecipeProcess with invalid params" do
+ test "with bad params: doesn't create a RecipeProcess" do
assert {:error, %Changeset{}} = Domain.create(%{})
end
end
describe "update/2" do
- test "updates a RecipeProcess with valid params with :has_duration", %{params: params, inserted: old} do
+ test "with good params (with :has_duration): updates the RecipeProcess", %{params: params, inserted: old} do
assert {:ok, %RecipeProcess{} = new} = Domain.update(old.id, params)
-
assert new.name == params.name
assert new.note == params.note
assert new.process_classified_as == params.process_classified_as
@@ -127,11 +120,9 @@ describe "update/2" do
assert new.has_duration_numeric_duration == params.has_duration.numeric_duration
end
- test "updates a RecipeProcess with valid params with :has_duration set to nil", %{params: params, inserted: old} do
+ test "with good params (with :has_duration set to nil): updates the RecipeProcess", %{params: params, inserted: old} do
params = Map.put(params, :has_duration, nil)
-
assert {:ok, %RecipeProcess{} = new} = Domain.update(old.id, params)
-
assert new.name == params.name
assert new.note == params.note
assert new.process_classified_as == params.process_classified_as
@@ -140,15 +131,14 @@ describe "update/2" do
assert new.has_duration_unit_type == nil
end
- test "doesn't update a RecipeProcess with valid params with :has_duration fields set to nil", %{params: params, inserted: old} do
+ test "with bad params (with :has_duration fields set to nil): doesn't update the RecipeProcess", %{params: params, inserted: old} do
params = Map.put(params, :has_duration, %{unit_type: nil, numeric_duration: nil})
assert {:error, %Changeset{errors: errs}} = Domain.update(old.id, params)
assert length(Keyword.get_values(errs, :has_duration)) == 2
end
- test "doesn't update a RecipeProcess", %{inserted: old} do
+ test "with bad params: doesn't update the RecipeProcess", %{inserted: old} do
assert {:ok, %RecipeProcess{} = new} = Domain.update(old.id, %{})
-
assert new.name == old.name
assert new.note == old.note
assert new.process_classified_as == old.process_classified_as
@@ -158,9 +148,15 @@ describe "update/2" do
end
end
-test "delete/1 deletes a RecipeProcess", %{inserted: %{id: id}} do
- assert {:ok, %RecipeProcess{id: ^id}} = Domain.delete(id)
- assert Domain.by_id(id) == nil
+describe "delete/1" do
+ test "with good id: deletes the RecipeProcess", %{inserted: %{id: id}} do
+ assert {:ok, %RecipeProcess{id: ^id}} = Domain.delete(id)
+ assert {:error, "not found"} = Domain.one(id)
+ end
+
+ test "with bad id: doesn't delete the RecipeProcess" do
+ assert {:error, "not found"} = Domain.delete(Factory.id())
+ end
end
describe "preload/2" do
diff --git a/test/vf/recipe_process/type.test.exs b/test/vf/recipe_process/type.test.exs
@@ -21,156 +21,123 @@ use ZenflowsTest.Help.AbsinCase, async: true
setup do
%{
params: %{
- name: Factory.uniq("name"),
- has_duration: Factory.build(:iduration),
- process_classified_as: Factory.uniq_list("uri"),
- process_conforms_to_id: Factory.insert!(:process_specification).id,
- note: Factory.uniq("note"),
+ "name" => Factory.uniq("name"),
+ "hasDuration" => %{
+ "unitType" => Factory.build(:time_unit) |> to_string(),
+ "numericDuration" => Factory.float(),
+ },
+ "processClassifiedAs" => Factory.uniq_list("uri"),
+ "processConformsTo" => Factory.insert!(:process_specification).id,
+ "note" => Factory.uniq("note"),
},
inserted: Factory.insert!(:recipe_process),
}
end
+@frag """
+fragment recipeProcess on RecipeProcess {
+ id
+ name
+ note
+ processClassifiedAs
+ processConformsTo {id}
+ hasDuration {
+ unitType
+ numericDuration
+ }
+}
+"""
+
describe "Query" do
- test "recipeProcess()", %{inserted: rec_proc} do
+ test "recipeProcess", %{inserted: new} do
assert %{data: %{"recipeProcess" => data}} =
- query!("""
- recipeProcess(id: "#{rec_proc.id}") {
- id
- name
- note
- processClassifiedAs
- processConformsTo { id }
- hasDuration {
- unitType
- numericDuration
- }
+ run!("""
+ #{@frag}
+ query ($id: ID!) {
+ recipeProcess(id: $id) {...recipeProcess}
}
- """)
+ """, vars: %{"id" => new.id})
- assert data["id"] == rec_proc.id
- assert data["name"] == rec_proc.name
- assert data["note"] == rec_proc.note
- assert data["processClassifiedAs"] == rec_proc.process_classified_as
- assert data["processConformsTo"]["id"] == rec_proc.process_conforms_to_id
- assert data["hasDuration"]["unitType"] == to_string(rec_proc.has_duration_unit_type)
- assert data["hasDuration"]["numericDuration"] == rec_proc.has_duration_numeric_duration
+ assert data["id"] == new.id
+ assert data["name"] == new.name
+ assert data["note"] == new.note
+ assert data["processClassifiedAs"] == new.process_classified_as
+ assert data["processConformsTo"]["id"] == new.process_conforms_to_id
+ assert data["hasDuration"]["unitType"] == to_string(new.has_duration_unit_type)
+ assert data["hasDuration"]["numericDuration"] == new.has_duration_numeric_duration
end
end
describe "Mutation" do
- test "createRecipeProcess()", %{params: params} do
+ test "createRecipeProcess", %{params: params} do
assert %{data: %{"createRecipeProcess" => %{"recipeProcess" => data}}} =
- mutation!("""
- createRecipeProcess(recipeProcess: {
- name: "#{params.name}"
- note: "#{params.note}"
- processClassifiedAs: #{inspect(params.process_classified_as)}
- processConformsTo: "#{params.process_conforms_to_id}"
- hasDuration: {
- unitType: #{params.has_duration.unit_type}
- numericDuration: #{params.has_duration.numeric_duration}
- }
- }) {
- recipeProcess {
- id
- name
- note
- processClassifiedAs
- processConformsTo { id }
- hasDuration {
- unitType
- numericDuration
- }
+ run!("""
+ #{@frag}
+ mutation ($recipeProcess: RecipeProcessCreateParams!) {
+ createRecipeProcess(recipeProcess: $recipeProcess) {
+ recipeProcess {...recipeProcess}
}
}
- """)
+ """, vars: %{"recipeProcess" => params})
assert {:ok, _} = Zenflows.DB.ID.cast(data["id"])
- assert data["name"] == params.name
- assert data["note"] == params.note
- assert data["processClassifiedAs"] == params.process_classified_as
- assert data["processConformsTo"]["id"] == params.process_conforms_to_id
- assert data["hasDuration"]["unitType"] == to_string(params.has_duration.unit_type)
- assert data["hasDuration"]["numericDuration"] == params.has_duration.numeric_duration
+ assert data["name"] == params["name"]
+ assert data["note"] == params["note"]
+ assert data["processClassifiedAs"] == params["processClassifiedAs"]
+ assert data["processConformsTo"]["id"] == params["processConformsTo"]
+ assert data["hasDuration"] == params["hasDuration"]
end
- test "updateRecipeProcess()", %{params: params, inserted: rec_proc} do
+ test "updateRecipeProcess", %{params: params, inserted: old} do
assert %{data: %{"updateRecipeProcess" => %{"recipeProcess" => data}}} =
- mutation!("""
- updateRecipeProcess(recipeProcess: {
- id: "#{rec_proc.id}"
- name: "#{params.name}"
- note: "#{params.note}"
- processClassifiedAs: #{inspect(params.process_classified_as)}
- processConformsTo: "#{params.process_conforms_to_id}"
- hasDuration: {
- unitType: #{params.has_duration.unit_type}
- numericDuration: #{params.has_duration.numeric_duration}
- }
- }) {
- recipeProcess {
- id
- name
- note
- processClassifiedAs
- processConformsTo { id }
- hasDuration {
- unitType
- numericDuration
- }
+ run!("""
+ #{@frag}
+ mutation ($recipeProcess: RecipeProcessUpdateParams!) {
+ updateRecipeProcess(recipeProcess: $recipeProcess) {
+ recipeProcess {...recipeProcess}
}
}
- """)
+ """, vars: %{"recipeProcess" => Map.put(params, "id", old.id)})
- assert data["id"] == rec_proc.id
- assert data["name"] == params.name
- assert data["note"] == params.note
- assert data["processClassifiedAs"] == params.process_classified_as
- assert data["processConformsTo"]["id"] == params.process_conforms_to_id
- assert data["hasDuration"]["unitType"] == to_string(params.has_duration.unit_type)
- assert data["hasDuration"]["numericDuration"] == params.has_duration.numeric_duration
+ assert data["id"] == old.id
+ assert data["name"] == params["name"]
+ assert data["note"] == params["note"]
+ assert data["processClassifiedAs"] == params["processClassifiedAs"]
+ assert data["processConformsTo"]["id"] == params["processConformsTo"]
+ assert data["hasDuration"] == params["hasDuration"]
end
- test "updateRecipeProcess(), set hasDuration to null", %{params: params, inserted: rec_proc} do
+ test "updateRecipeProcess: hasDuration set null", %{params: params, inserted: old} do
assert %{data: %{"updateRecipeProcess" => %{"recipeProcess" => data}}} =
- mutation!("""
- updateRecipeProcess(recipeProcess: {
- id: "#{rec_proc.id}"
- name: "#{params.name}"
- note: "#{params.note}"
- processClassifiedAs: #{inspect(params.process_classified_as)}
- processConformsTo: "#{params.process_conforms_to_id}"
- hasDuration: null
- }) {
- recipeProcess {
- id
- name
- note
- processClassifiedAs
- processConformsTo { id }
- hasDuration {
- unitType
- numericDuration
- }
+ run!("""
+ #{@frag}
+ mutation ($recipeProcess: RecipeProcessUpdateParams!) {
+ updateRecipeProcess(recipeProcess: $recipeProcess) {
+ recipeProcess {...recipeProcess}
}
}
- """)
+ """, vars: %{
+ "recipeProcess" =>
+ params
+ |> Map.put("id", old.id)
+ |> Map.put("hasDuration", nil)
+ })
- assert data["id"] == rec_proc.id
- assert data["name"] == params.name
- assert data["note"] == params.note
- assert data["processClassifiedAs"] == params.process_classified_as
- assert data["processConformsTo"]["id"] == params.process_conforms_to_id
- assert data["hasDuration"]["unitType"] == nil
- assert data["hasDuration"]["numericDuration"] == nil
+ assert data["id"] == old.id
+ assert data["name"] == params["name"]
+ assert data["note"] == params["note"]
+ assert data["processClassifiedAs"] == params["processClassifiedAs"]
+ assert data["processConformsTo"]["id"] == params["processConformsTo"]
+ assert data["hasDuration"] == nil
end
- test "deleteRecipeProcess()", %{inserted: %{id: id}} do
+ test "deleteRecipeProcess", %{inserted: %{id: id}} do
assert %{data: %{"deleteRecipeProcess" => true}} =
- mutation!("""
- deleteRecipeProcess(id: "#{id}")
- """)
+ run!("""
+ mutation ($id: ID!) {
+ deleteRecipeProcess(id: $id)
+ }
+ """, vars: %{"id" => id})
end
end
end