zf

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

commit f8109ba2045a364b90b21882cf83552bb4c71c74
parent 1ec3042ecb11b6421d76353d89c627e582bea115
Author: sir fish <dev@srf.sh>
Date:   Tue, 23 Aug 2022 12:32:16 +0300

Merge pull request #6 from dyne/srfsh/paging


Diffstat:
Mconf/.env.templ | 4++++
Mconf/runtime.exs | 13+++++++++++++
Mdevop/.docker-compose.templ | 3+++
Mdocs/configuration-guide.md | 6++++++
Msrc/zenflows/gql/mw/sign.ex | 2+-
Asrc/zenflows/gql/paging.ex | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/zenflows/keypairoom/domain.ex | 4++--
Msrc/zenflows/vf/agent/domain.ex | 17++++++++++++++---
Msrc/zenflows/vf/agent/resolv.ex | 12++++++++----
Msrc/zenflows/vf/agent/type.ex | 23+++++++++++++++++++++--
Msrc/zenflows/vf/agent_relationship/domain.ex | 58+++++++++++++++++++++++++++++++---------------------------
Msrc/zenflows/vf/agent_relationship/resolv.ex | 41+++++++++++++++++++++++------------------
Msrc/zenflows/vf/agent_relationship/type.ex | 49++++++++++++++++++++++++++++++++++---------------
Msrc/zenflows/vf/agent_relationship_role/domain.ex | 51+++++++++++++++++++++++++++------------------------
Msrc/zenflows/vf/agent_relationship_role/resolv.ex | 21+++++++++++++--------
Msrc/zenflows/vf/agent_relationship_role/type.ex | 42++++++++++++++++++++++++++++--------------
Msrc/zenflows/vf/agreement/domain.ex | 21++++++++++++---------
Msrc/zenflows/vf/agreement/resolv.ex | 12++++++++----
Msrc/zenflows/vf/agreement/type.ex | 26++++++++++++++++++++++----
Msrc/zenflows/vf/economic_event/domain.ex | 44++++++++++++++++++++++----------------------
Msrc/zenflows/vf/economic_event/resolv.ex | 45+++++++++++++++++++++++----------------------
Msrc/zenflows/vf/economic_event/type.ex | 67+++++++++++++++++++++++--------------------------------------------
Msrc/zenflows/vf/economic_resource/domain.ex | 45+++++++++++++++++++++++----------------------
Msrc/zenflows/vf/economic_resource/resolv.ex | 39++++++++++++++++++++-------------------
Msrc/zenflows/vf/economic_resource/type.ex | 26+++++++++++++++++++++-----
Msrc/zenflows/vf/intent/domain.ex | 21++++++++++++---------
Msrc/zenflows/vf/intent/resolv.ex | 58++++++++++++++++++++++++++--------------------------------
Msrc/zenflows/vf/intent/type.ex | 32++++++++++++++++----------------
Msrc/zenflows/vf/organization.ex | 1+
Msrc/zenflows/vf/organization/domain.ex | 55++++++++++++++++++++++++++-----------------------------
Msrc/zenflows/vf/organization/resolv.ex | 20++++++++++++--------
Msrc/zenflows/vf/organization/type.ex | 39++++++++++++++++++++++++++++-----------
Msrc/zenflows/vf/person/domain.ex | 74++++++++++++++++++++++++++++----------------------------------------------
Msrc/zenflows/vf/person/resolv.ex | 24++++++++++++++----------
Msrc/zenflows/vf/person/type.ex | 38+++++++++++++++++++++++++++++---------
Msrc/zenflows/vf/plan/domain.ex | 23+++++++++++++----------
Msrc/zenflows/vf/plan/resolv.ex | 30+++++++++++++++++-------------
Msrc/zenflows/vf/plan/type.ex | 37++++++++++++++++++++++++-------------
Msrc/zenflows/vf/process/domain.ex | 51++++++++++++++++++++++++++-------------------------
Msrc/zenflows/vf/process/resolv.ex | 22+++++++++++++---------
Msrc/zenflows/vf/process/type.ex | 59++++++++++++++++++++++++++++++-----------------------------
Msrc/zenflows/vf/process_specification/domain.ex | 55+++++++++++++++++++++++++++++--------------------------
Msrc/zenflows/vf/process_specification/resolv.ex | 14+++++++++-----
Msrc/zenflows/vf/process_specification/type.ex | 26++++++++++++++++++++++----
Msrc/zenflows/vf/product_batch/domain.ex | 52+++++++++++++++++++++++++++-------------------------
Msrc/zenflows/vf/product_batch/resolv.ex | 14+++++++++-----
Msrc/zenflows/vf/product_batch/type.ex | 26++++++++++++++++++++++----
Msrc/zenflows/vf/proposal/domain.ex | 23+++++++++++++----------
Msrc/zenflows/vf/proposal/resolv.ex | 54++++++++++++++++++++++++------------------------------
Msrc/zenflows/vf/proposal/type.ex | 42++++++++++++++++++++----------------------
Msrc/zenflows/vf/proposed_intent/domain.ex | 21++++++++++++---------
Msrc/zenflows/vf/proposed_intent/resolv.ex | 20++++++++++----------
Msrc/zenflows/vf/recipe_exchange/domain.ex | 51+++++++++++++++++++++++++++------------------------
Msrc/zenflows/vf/recipe_exchange/resolv.ex | 14+++++++++-----
Msrc/zenflows/vf/recipe_exchange/type.ex | 26++++++++++++++++++++++----
Msrc/zenflows/vf/recipe_flow/domain.ex | 50++++++++++++++++++++++++++------------------------
Msrc/zenflows/vf/recipe_flow/resolv.ex | 33+++++++++++++++++----------------
Msrc/zenflows/vf/recipe_flow/type.ex | 75++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/zenflows/vf/recipe_process/domain.ex | 51+++++++++++++++++++++++++++------------------------
Msrc/zenflows/vf/recipe_process/resolv.ex | 20++++++++++++--------
Msrc/zenflows/vf/recipe_process/type.ex | 34++++++++++++++++++++++++----------
Msrc/zenflows/vf/recipe_resource/domain.ex | 51+++++++++++++++++++++++++++------------------------
Msrc/zenflows/vf/recipe_resource/resolv.ex | 25+++++++++++++------------
Msrc/zenflows/vf/recipe_resource/type.ex | 44++++++++++++++++++++++++++++++--------------
Msrc/zenflows/vf/resource_specification/domain.ex | 26+++++++++++++++-----------
Msrc/zenflows/vf/resource_specification/resolv.ex | 23++++++++++++-----------
Msrc/zenflows/vf/resource_specification/type.ex | 39+++++++++++++++++++++++++++------------
Msrc/zenflows/vf/role_behavior/domain.ex | 48+++++++++++++++++++++++++-----------------------
Msrc/zenflows/vf/role_behavior/resolv.ex | 8++++++--
Msrc/zenflows/vf/role_behavior/type.ex | 26++++++++++++++++++++++----
Msrc/zenflows/vf/scenario/domain.ex | 47++++++++++++++++++++++++-----------------------
Msrc/zenflows/vf/scenario/resolv.ex | 20++++++++++++--------
Msrc/zenflows/vf/scenario/type.ex | 48+++++++++++++++++++++++++++---------------------
Msrc/zenflows/vf/scenario_definition/domain.ex | 52+++++++++++++++++++++++++++-------------------------
Msrc/zenflows/vf/scenario_definition/resolv.ex | 18+++++++++++-------
Msrc/zenflows/vf/scenario_definition/type.ex | 26+++++++++++++++++++++-----
Msrc/zenflows/vf/spatial_thing/domain.ex | 50++++++++++++++++++++++++++------------------------
Msrc/zenflows/vf/spatial_thing/resolv.ex | 14+++++++++-----
Msrc/zenflows/vf/spatial_thing/type.ex | 26+++++++++++++++++++++-----
Msrc/zenflows/vf/unit/domain.ex | 29+++++++++++++++++------------
Msrc/zenflows/vf/unit/resolv.ex | 14+++++++++-----
Msrc/zenflows/vf/unit/type.ex | 26+++++++++++++++++++++-----
Msrc/zenflows/vf/validate.ex | 2+-
Atest/gql/paging.test.exs | 298+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/help/factory.ex | 149+++++++++++++++++++++++++++++++++++--------------------------------------------
Mtest/vf/agent/domain.test.exs | 24+++++++++---------------
Mtest/vf/agent_relationship/domain.test.exs | 47++++++++++++++++++++++++++++-------------------
Mtest/vf/agent_relationship/type.test.exs | 122++++++++++++++++++++++++++++++++++++-------------------------------------------
Mtest/vf/agent_relationship_role/domain.test.exs | 50++++++++++++++++++++++++++++++--------------------
Mtest/vf/agent_relationship_role/type.test.exs | 119+++++++++++++++++++++++++++++++++++++------------------------------------------
Mtest/vf/agreement/domain.test.exs | 15+++++++--------
Mtest/vf/agreement/type.test.exs | 10+++++-----
Mtest/vf/appreciation.test.exs | 2+-
Mtest/vf/claim.test.exs | 6+++---
Mtest/vf/commitment.test.exs | 6+++---
Mtest/vf/economic_event/domain.test.exs | 180+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mtest/vf/economic_resource/domain.test.exs | 13++++++-------
Mtest/vf/economic_resource/type.test.exs | 209++++++++++++++++++++++++++++++++++++-------------------------------------------
Mtest/vf/fulfillment.test.exs | 2+-
Mtest/vf/intent/domain.test.exs | 17++++++++---------
Mtest/vf/intent/type.test.exs | 8++++----
Mtest/vf/organization/domain.test.exs | 85++++++++++++++++++++++++++++++++++---------------------------------------------
Mtest/vf/organization/type.test.exs | 74++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/vf/person/domain.test.exs | 113++++++++++++++++++++++++++++++++++++-------------------------------------------
Mtest/vf/person/type.test.exs | 169+++++++++++++++++++++++++++++++++----------------------------------------------
Mtest/vf/plan/domain.test.exs | 19+++++++++----------
Mtest/vf/plan/type.test.exs | 4++--
Mtest/vf/process/domain.test.exs | 91++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mtest/vf/process/type.test.exs | 183++++++++++++++++++++++++++++++++-----------------------------------------------
Mtest/vf/process_specification/domain.test.exs | 45+++++++++++++++++++++++++++------------------
Mtest/vf/process_specification/type.test.exs | 90++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/vf/product_batch/domain.test.exs | 43++++++++++++++++++++++++++-----------------
Mtest/vf/product_batch/type.test.exs | 98+++++++++++++++++++++++++++++++++++++------------------------------------------
Mtest/vf/proposal.test.exs | 4++--
Mtest/vf/proposal/domain.test.exs | 39++++++++++++++++++---------------------
Mtest/vf/proposal/type.test.exs | 55+++++++++++--------------------------------------------
Mtest/vf/proposed_intent/domain.test.exs | 17++++++++---------
Mtest/vf/recipe_exchange/domain.test.exs | 45+++++++++++++++++++++++++++------------------
Mtest/vf/recipe_exchange/type.test.exs | 90++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/vf/recipe_flow/domain.test.exs | 229++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mtest/vf/recipe_flow/type.test.exs | 275++++++++++++++++++++++++++-----------------------------------------------------
Mtest/vf/recipe_process/domain.test.exs | 122++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mtest/vf/recipe_process/type.test.exs | 201+++++++++++++++++++++++++++++++++----------------------------------------------
Mtest/vf/recipe_resource/domain.test.exs | 63++++++++++++++++++++++++++++++++++++---------------------------
Mtest/vf/recipe_resource/type.test.exs | 93++++++++++++++++++++++++++++++++++---------------------------------------------
Mtest/vf/resource_specification/domain.test.exs | 29++++++++++++++---------------
Mtest/vf/resource_specification/type.test.exs | 83++++++++++++++++++++++++++++++++++---------------------------------------------
Mtest/vf/role_behavior/domain.test.exs | 45+++++++++++++++++++++++++++------------------
Mtest/vf/role_behavior/type.test.exs | 90++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/vf/satisfaction.test.exs | 2+-
Mtest/vf/scenario/domain.test.exs | 73+++++++++++++++++++++++++++++++++++++++----------------------------------
Mtest/vf/scenario/type.test.exs | 140++++++++++++++++++++++++++++++++++---------------------------------------------
Mtest/vf/scenario_definition/domain.test.exs | 63++++++++++++++++++++++++++++++++++-----------------------------
Mtest/vf/scenario_definition/type.test.exs | 125+++++++++++++++++++++++++++++++++++--------------------------------------------
Mtest/vf/settlement.test.exs | 2+-
Mtest/vf/spatial_thing/domain.test.exs | 55++++++++++++++++++++++++++++++++-----------------------
Mtest/vf/spatial_thing/type.test.exs | 138+++++++++++++++++++++++++++++++++----------------------------------------------
Mtest/vf/unit/domain.test.exs | 9++++-----
Mtest/vf/unit/type.test.exs | 90++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/vf/validate.test.exs | 2+-
140 files changed, 3929 insertions(+), 3328 deletions(-)

diff --git a/conf/.env.templ b/conf/.env.templ @@ -33,3 +33,7 @@ export ROOM_SALT=@ROOM_SALT ## admin export ADMIN_KEY=@ADMIN_KEY + +## gql +export GQL_DEF_PAGE_SIZE=50 +export GQL_MAX_PAGE_SIZE=100 diff --git a/conf/runtime.exs b/conf/runtime.exs @@ -81,3 +81,16 @@ if byte_size(admin_key) != 64, do: raise "ADMIN_KEY must be a 64-octect long, lowercase-base16-encoded string" config :zenflows, Zenflows.Admin, admin_key: admin_key + +# +# gql +# +def_page_size = get_env_int.("GQL_DEF_PAGE_SIZE", 50) +if def_page_size < 1, + do: raise "GQL_DEF_PAGE_SIZE must be greater than 1" +max_page_size = get_env_int.("GQL_MAX_PAGE_SIZE", 100) +if max_page_size < def_page_size, + do: raise "GQL_MAX_PAGE_SIZE can't be less than GQL_DEF_PAGE_SIZE" +config :zenflows, Zenflows.GQL, + def_page_size: def_page_size, + max_page_size: max_page_size diff --git a/devop/.docker-compose.templ b/devop/.docker-compose.templ @@ -39,6 +39,9 @@ services: ROOM_HOST: zvmlet ROOM_PORT: &room_port 3000 ROOM_SALT: @ROOM_SALT + + GQL_DEF_PAGE_SIZE: 50 + GQL_MAX_PAGE_SIZE: 100 depends_on: - zvmlet - db diff --git a/docs/configuration-guide.md b/docs/configuration-guide.md @@ -47,6 +47,12 @@ also see the [Required Options](#required-options). `openssl rand -hex 64`. It is automatically generated when you run `mann env.setup`. +* `GQL_DEF_PAGE_SIZE`: A non-negative integer. It is used for the + default GraphQL page size if the client doesn't provide one. +* `GQL_MAX_PAGE_SIZE`: A non-negative integer. It is used for the + maximum GraphQL page size if client provides a too-large value. + It must be greater than `GQL_DEF_PAGE_SIZE`. + ## Required Options diff --git a/src/zenflows/gql/mw/sign.ex b/src/zenflows/gql/mw/sign.ex @@ -29,7 +29,7 @@ alias Zenflows.VF.Person def call(res, _opts) do if res.context.authenticate_calls? do with %{gql_user: user, gql_sign: sign, gql_body: body} <- res.context, - per when not is_nil(per) <- Person.Domain.by_user(user), + per when not is_nil(per) <- Person.Domain.one(user: user), true <- Restroom.verify_graphql?(body, sign, per.eddsa_public_key) do put_in(res.context[:req_user], per) else _ -> diff --git a/src/zenflows/gql/paging.ex b/src/zenflows/gql/paging.ex @@ -0,0 +1,169 @@ +# Zenflows is designed to implement the Valueflows vocabulary, +# written and maintained by srfsh <info@dyne.org>. +# Copyright (C) 2021-2022 Dyne.org foundation <foundation@dyne.org>. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +defmodule Zenflows.GQL.Paging do +@moduledoc "Paging helpers for Resolv modules." + +import Ecto.Query + +alias Zenflows.DB.{ID, Repo, Schema} + +@type result(schema) :: {:ok, t(schema)} | {:error, String.t()} + +@type t(schema) :: %{ + page_info: page_info(), + edges: [edges(schema)], +} + +@type page_info() :: %{ + start_cursor: ID.t() | nil, + end_cursor: ID.t() | nil, + has_previous_page: boolean(), + has_next_page: boolean(), + total_count: non_neg_integer(), + page_limit: non_neg_integer(), +} + +@type edges(schema) :: %{ + cursor: ID.t(), + node: schema, +} + +@type params() :: %{first: non_neg_integer(), after: ID.t()} + | %{last: non_neg_integer, before: ID.t()} + +@spec def_page_size() :: non_neg_integer() +def def_page_size() do + conf()[:def_page_size] +end + +@spec def_page_size() :: non_neg_integer() +def max_page_size() do + conf()[:max_page_size] +end + +@spec conf() :: Keyword.t() +defp conf() do + Application.fetch_env!(:zenflows, Zenflows.GQL) +end + +@spec parse(params()) :: {:error, String.t()} | {:ok, {:forw | :back, ID.t() | nil, non_neg_integer()}} +def parse(%{first: _, last: _}), do: {:error, "first and last can't be provided at the same time"} +def parse(%{after: _, before: _}), do: {:error, "after and before can't be provided at the same time"} + +def parse(%{after: _, last: _}), do: {:error, "after and last can't be provided at the same time"} +def parse(%{before: _, first: _}), do: {:error, "before and first can't be provided at the same time"} + +def parse(%{first: num}) when num < 0, do: {:error, "first must be positive"} +def parse(%{last: num}) when num < 0, do: {:error, "last must be positive"} + +def parse(%{after: cur, first: num}), do: {:ok, {:forw, cur, normalize(num)}} +def parse(%{after: cur}), do: {:ok, {:forw, cur, def_page_size()}} + +def parse(%{before: cur, last: num}), do: {:ok, {:back, cur, normalize(num)}} +def parse(%{before: cur}), do: {:ok, {:back, cur, def_page_size()}} + +def parse(%{first: num}), do: {:ok, {:forw, nil, normalize(num)}} +def parse(%{last: num}), do: {:ok, {:back, nil, normalize(num)}} + +def parse(_), do: {:ok, {:forw, nil, def_page_size()}} + +@spec normalize(integer()) :: non_neg_integer() +defp normalize(num) do + # credo:disable-for-next-line Credo.Check.Refactor.MatchInCondition + if num > (max = max_page_size()), + do: max, + else: num +end + +@doc """ +Page Ecto schemas. + +Only supports forward or backward paging with or without cursors. +""" +@spec page(Schema.t() | Ecto.Query.t(), params()) :: result(Schema.t()) +def page(schema_or_query, params) do + with {:ok, {dir, cur, num}} <- parse(params) do + {page_fun, order_by} = + case dir do + :forw -> {&forw/3, [asc: :id]} + :back -> {&back/3, [desc: :id]} + _ -> raise ArgumentError # impossible + end + where = + case {dir, cur} do + {_, nil} -> [] + {:forw, cur} -> dynamic([s], s.id > ^cur) + {:back, cur} -> dynamic([s], s.id < ^cur) + _ -> raise ArgumentError # impossible + end + {:ok, + from(s in schema_or_query, + where: ^where, + order_by: ^order_by, + limit: ^num + 1, + select: %{cursor: s.id, node: s}) + |> Repo.all() + |> page_fun.(cur, num)} + end +end + +@spec forw(edges(Schema.t()), ID.t() | nil, non_neg_integer()) :: t(Schema.t()) +def forw(edges, cur, num) do + {edges, count} = + Enum.reduce(edges, {[], 0}, fn e, {edges, count} -> + {[e | edges], count + 1} + end) + + {edges, has_next?, count} = + # we indeed have fetched num+1 records + if count - 1 == num do + [_ | edges] = edges + {edges, true, count - 1} + else + {edges, false, count} + end + + {edges, first, last} = + case edges do + [] -> {[], nil, nil} + _ -> + [last | _] = edges + [first | _] = edges = Enum.reverse(edges) + {edges, first, last} + end + + %{ + edges: edges, + page_info: %{ + start_cursor: first[:cursor], + end_cursor: last[:cursor], + has_next_page: has_next?, + has_previous_page: cur != nil, + total_count: count, + page_limit: num, + }, + } +end + +@spec back(edges(Schema.t()), ID.t() | nil, non_neg_integer()) :: t(Schema.t()) +def back(edges, cur, num) do + # Currently, this part of the algorithm doesn't care about + # whether we do forward or backward paging. + forw(edges, cur, num) +end +end diff --git a/src/zenflows/keypairoom/domain.ex b/src/zenflows/keypairoom/domain.ex @@ -25,13 +25,13 @@ alias Zenflows.Restroom alias Zenflows.VF.Person def keypairoom_server(false, data) do - if Person.Domain.exists_email(Map.fetch!(data, "email")), + if Person.Domain.exists?(email: Map.fetch!(data, "email")), do: Restroom.keypairoom_server(data), else: {:error, "email doesn't exists"} end def keypairoom_server(true, data) do - if Person.Domain.exists_email(Map.fetch!(data, "email")), + if Person.Domain.exists?(email: Map.fetch!(data, "email")), do: {:error, "email exists"}, else: Restroom.keypairoom_server(data) end diff --git a/src/zenflows/vf/agent/domain.ex b/src/zenflows/vf/agent/domain.ex @@ -21,11 +21,22 @@ defmodule Zenflows.VF.Agent.Domain do alias Zenflows.DB.Repo alias Zenflows.VF.Agent +@typep repo() :: Ecto.Repo.t() @typep id() :: Zenflows.DB.Schema.id() -@spec by_id(id) :: Agent.t() | nil -def by_id(id) do - Repo.get(Agent, id) +@spec one(repo(), id() | map() | Keyword.t()) :: {:ok, Agent.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(Agent, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(Agent.t()) +def all(params) do + Paging.page(Agent, params) end @spec preload(Agent.t(), :primary_location) :: Agent.t() diff --git a/src/zenflows/vf/agent/resolv.ex b/src/zenflows/vf/agent/resolv.ex @@ -20,15 +20,19 @@ defmodule Zenflows.VF.Agent.Resolv do alias Zenflows.VF.{Agent, Agent.Domain} -def my_agent(_args, %{context: %{req_user: user}}) do +def my_agent(_, %{context: %{req_user: user}}) do {:ok, user} end -def agent(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def agent(params, _) do + Domain.one(params) end -def primary_location(%Agent{} = agent, _args, _info) do +def agents(params, _) do + Domain.all(params) +end + +def primary_location(%Agent{} = agent, _, _) do agent = Domain.preload(agent, :primary_location) {:ok, agent.primary_location} end diff --git a/src/zenflows/vf/agent/type.ex b/src/zenflows/vf/agent/type.ex @@ -61,6 +61,16 @@ interface :agent do end end +object :agent_edge do + field :cursor, non_null(:id) + field :node, non_null(:agent) +end + +object :agent_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:agent_edge))) +end + object :query_agent do @desc "Loads details of the currently authenticated agent." field :my_agent, :agent do @@ -73,8 +83,17 @@ object :query_agent do resolve &Resolv.agent/2 end - #"Loads all agents publicly registered within this collaboration space." - #agents(start: ID, limit: Int): [Agent!] + @desc """ + Loads all agents publicly registered within this collaboration + space. + """ + field :agents, :agent_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.agents/2 + end end # object :mutation_agent diff --git a/src/zenflows/vf/agent_relationship/domain.ex b/src/zenflows/vf/agent_relationship/domain.ex @@ -20,55 +20,71 @@ defmodule Zenflows.VF.AgentRelationship.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.AgentRelationship @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()) :: AgentRelationship.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(AgentRelationship, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, AgentRelationship.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(AgentRelationship, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(AgentRelationship.t()) +def all(params) do + Paging.page(AgentRelationship, params) end @spec create(params()) :: {:ok, AgentRelationship.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:rel, AgentRelationship.chgset(params)) + |> Multi.insert(:insert, AgentRelationship.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{rel: rel}} -> {:ok, rel} + {:ok, %{insert: ar}} -> {:ok, ar} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, AgentRelationship.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, AgentRelationship.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &AgentRelationship.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &AgentRelationship.chgset(&1.one, params)) |> Repo.transaction() |> case do - {:ok, %{update: rel}} -> {:ok, rel} + {:ok, %{update: ar}} -> {:ok, ar} {:error, _, msg_or_cset, _} -> {:error, msg_or_cset} end end -@spec delete(id()) :: {:ok, AgentRelationship.t()} | {:error, chgset()} +@spec delete(id()) + :: {:ok, AgentRelationship.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: rel}} -> {:ok, rel} + {:ok, %{delete: ar}} -> {:ok, ar} {:error, _, msg_or_cset, _} -> {:error, msg_or_cset} end end -@spec preload(AgentRelationship.t(), :subject | :object | :relationship) :: AgentRelationship.t() +@spec preload(AgentRelationship.t(), :subject | :object | :relationship) + :: AgentRelationship.t() def preload(rel, :subject) do Repo.preload(rel, :subject) end @@ -80,16 +96,4 @@ end def preload(rel, :relationship) do Repo.preload(rel, :relationship) end - -# Returns an AgentRelationship 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, AgentRelationship.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - rel -> {:ok, rel} - end - end -end end diff --git a/src/zenflows/vf/agent_relationship/resolv.ex b/src/zenflows/vf/agent_relationship/resolv.ex @@ -20,40 +20,45 @@ defmodule Zenflows.VF.AgentRelationship.Resolv do alias Zenflows.VF.{AgentRelationship, AgentRelationship.Domain} -def subject(%AgentRelationship{} = rel, _params, _info) do - rel = Domain.preload(rel, :subject) - {:ok, rel.subject} -end - -def object(%AgentRelationship{} = rel, _params, _info) do - rel = Domain.preload(rel, :object) - {:ok, rel.object} +def agent_relationship(params, _) do + Domain.one(params) end -def relationship(%AgentRelationship{} = rel, _params, _info) do - rel = Domain.preload(rel, :relationship) - {:ok, rel.relationship} -end - -def agent_relationship(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def agent_relationships(params, _) do + Domain.all(params) end -def create_agent_relationship(%{relationship: params}, _info) do +def create_agent_relationship(%{relationship: params}, _) do with {:ok, rel} <- Domain.create(params) do {:ok, %{agent_relationship: rel}} end end -def update_agent_relationship(%{relationship: %{id: id} = params}, _info) do +def update_agent_relationship(%{relationship: %{id: id} = params}, _) do with {:ok, rel} <- Domain.update(id, params) do {:ok, %{agent_relationship: rel}} end end -def delete_agent_relationship(%{id: id}, _info) do +def delete_agent_relationship(%{id: id}, _) do with {:ok, _rel} <- Domain.delete(id) do {:ok, true} end end + +def subject(%AgentRelationship{} = rel, _, _) do + rel = Domain.preload(rel, :subject) + {:ok, rel.subject} +end + +def object(%AgentRelationship{} = rel, _, _) do + rel = Domain.preload(rel, :object) + {:ok, rel.object} +end + +def relationship(%AgentRelationship{} = rel, _, _) do + rel = Domain.preload(rel, :relationship) + {:ok, rel.relationship} +end + end diff --git a/src/zenflows/vf/agent_relationship/type.ex b/src/zenflows/vf/agent_relationship/type.ex @@ -26,11 +26,14 @@ alias Zenflows.VF.AgentRelationship.Resolv The subject of a relationship between two agents. For example, if Mary is a member of a group, then Mary is the subject. """ +@subject_id "(`Agent`) #{@subject}" @object """ The object of a relationship between two agents. For example, if Mary is a member of a group, then the group is the object. """ +@object_id "(`Agent`) #{@object}" @relationship "A kind of relationship that exists between two agents." +@relationship_id "(`AgentRelationshipRole`) #{@relationship}" #@in_scope_of """ #Grouping around something to create a boundary or context, used for #documenting, accounting, planning. @@ -61,18 +64,14 @@ object :agent_relationship do field :note, :string end -object :agent_relationship_response do - field :agent_relationship, non_null(:agent_relationship) -end - input_object :agent_relationship_create_params do - @desc "(`Agent`) " <> @subject + @desc @subject_id field :subject_id, non_null(:id), name: "subject" - @desc "(`Agent`) " <> @object + @desc @object_id field :object_id, non_null(:id), name: "object" - @desc "(`AgentRelationshipRole`) " <> @relationship + @desc @relationship_id field :relationship_id, non_null(:id), name: "relationship" #@desc @in_scope_of @@ -85,13 +84,13 @@ end input_object :agent_relationship_update_params do field :id, non_null(:id) - @desc "(`Agent`) " <> @subject + @desc @subject_id field :subject_id, :id, name: "subject" - @desc "(`Agent`) " <> @object + @desc @object_id field :object_id, :id, name: "object" - @desc "(`AgentRelationshipRole`) " <> @relationship + @desc @relationship_id field :relationship_id, :id, name: "relationship" #@desc @in_scope_of @@ -101,6 +100,20 @@ input_object :agent_relationship_update_params do field :note, :string end +object :agent_relationship_response do + field :agent_relationship, non_null(:agent_relationship) +end + +object :agent_relationship_edge do + field :cursor, non_null(:id) + field :node, non_null(:agent_relationship) +end + +object :agent_relationship_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:agent_relationship_edge))) +end + object :query_agent_relationship do @desc "Retrieve details of an agent relationship by its ID." field :agent_relationship, :agent_relationship do @@ -108,11 +121,17 @@ object :query_agent_relationship do resolve &Resolv.agent_relationship/2 end - #@desc """ - #Retrieve details of all the relationships between all agents - #registered in this collaboration space. - #""" - #agentRelationships(start: ID, limit: Int): [AgentRelationship!] + @desc """ + Retrieve details of all the relationships between all agents + registered in this collaboration space. + """ + field :agent_relationships, :agent_relationship_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.agent_relationships/2 + end end object :mutation_agent_relationship do diff --git a/src/zenflows/vf/agent_relationship_role/domain.ex b/src/zenflows/vf/agent_relationship_role/domain.ex @@ -20,35 +20,48 @@ defmodule Zenflows.VF.AgentRelationshipRole.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.AgentRelationshipRole @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()) :: AgentRelationshipRole.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(AgentRelationshipRole, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, AgentRelationshipRole.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(AgentRelationshipRole, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(AgentRelationshipRole.t()) +def all(params) do + Paging.page(AgentRelationshipRole, params) end @spec create(params()) :: {:ok, AgentRelationshipRole.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:rel_role, AgentRelationshipRole.chgset(params)) + |> Multi.insert(:insert, AgentRelationshipRole.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{rel_role: rr}} -> {:ok, rr} + {:ok, %{insert: rr}} -> {:ok, rr} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, AgentRelationshipRole.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, AgentRelationshipRole.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &AgentRelationshipRole.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &AgentRelationshipRole.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: rr}} -> {:ok, rr} @@ -56,11 +69,13 @@ def update(id, params) do end end -@spec delete(id()) :: {:ok, AgentRelationshipRole.t()} | {:error, chgset()} +@spec delete(id()) + :: {:ok, AgentRelationshipRole.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: rr}} -> {:ok, rr} @@ -72,16 +87,4 @@ end def preload(rel_role, :role_behavior) do Repo.preload(rel_role, :role_behavior) end - -# Returns an AgentRelationshipRole 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, AgentRelationshipRole.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - rr -> {:ok, rr} - end - end -end end diff --git a/src/zenflows/vf/agent_relationship_role/resolv.ex b/src/zenflows/vf/agent_relationship_role/resolv.ex @@ -20,30 +20,35 @@ defmodule Zenflows.VF.AgentRelationshipRole.Resolv do alias Zenflows.VF.{AgentRelationshipRole, AgentRelationshipRole.Domain} -def role_behavior(%AgentRelationshipRole{} = rel_role, _args, _info) do - rel_role = Domain.preload(rel_role, :role_behavior) - {:ok, rel_role.role_behavior} +def agent_relationship_role(params, _) do + Domain.one(params) end -def agent_relationship_role(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def agent_relationship_roles(params, _) do + Domain.all(params) end -def create_agent_relationship_role(%{agent_relationship_role: params}, _info) do +def create_agent_relationship_role(%{agent_relationship_role: params}, _) do with {:ok, rel_role} <- Domain.create(params) do {:ok, %{agent_relationship_role: rel_role}} end end -def update_agent_relationship_role(%{agent_relationship_role: %{id: id} = params}, _info) do +def update_agent_relationship_role(%{agent_relationship_role: %{id: id} = params}, _) do with {:ok, rel_role} <- Domain.update(id, params) do {:ok, %{agent_relationship_role: rel_role}} end end -def delete_agent_relationship_role(%{id: id}, _info) do +def delete_agent_relationship_role(%{id: id}, _) do with {:ok, _rel_role} <- Domain.delete(id) do {:ok, true} end end + +def role_behavior(%AgentRelationshipRole{} = rel_role, _, _) do + rel_role = Domain.preload(rel_role, :role_behavior) + {:ok, rel_role.role_behavior} +end + end diff --git a/src/zenflows/vf/agent_relationship_role/type.ex b/src/zenflows/vf/agent_relationship_role/type.ex @@ -25,6 +25,7 @@ alias Zenflows.VF.AgentRelationshipRole.Resolv @role_behavior """ The general shape or behavior grouping of an agent relationship role. """ +@role_behavior_id "(`RoleBehavior`) #{@role_behavior}" @role_label """ The human readable name of the role, from the subject to the object. """ @@ -50,15 +51,8 @@ object :agent_relationship_role do field :note, :string end -object :agent_relationship_role_response do - field :agent_relationship_role, non_null(:agent_relationship_role) -end - input_object :agent_relationship_role_create_params do - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`RoleBhavior`) " <> @role_behavior + @desc @role_behavior_id field :role_behavior_id, :id, name: "role_behavior" @desc @role_label @@ -74,7 +68,7 @@ end input_object :agent_relationship_role_update_params do field :id, non_null(:id) - @desc "(`RoleBhavior`) " <> @role_behavior + @desc @role_behavior_id field :role_behavior_id, :id, name: "role_behavior" @desc @role_label @@ -87,6 +81,20 @@ input_object :agent_relationship_role_update_params do field :note, :string end +object :agent_relationship_role_response do + field :agent_relationship_role, non_null(:agent_relationship_role) +end + +object :agent_relationship_role_edge do + field :cursor, non_null(:id) + field :node, non_null(:agent_relationship_role) +end + +object :agent_relationship_role_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:agent_relationship_role_edge))) +end + object :query_agent_relationship_role do @desc "Retrieve details of an agent relationship role by its ID." field :agent_relationship_role, :agent_relationship_role do @@ -94,11 +102,17 @@ object :query_agent_relationship_role do resolve &Resolv.agent_relationship_role/2 end - # @desc """ - # Retrieve possible kinds of associations that agents may have - # with one another in this collaboration space. - # """ - # agentRelationshipRoles(start: ID, limit: Int): [AgentRelationshipRole!] + @desc """ + Retrieve possible kinds of associations that agents may have + with one another in this collaboration space. + """ + field :agent_relationship_roles, :agent_relationship_role_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.agent_relationship_roles/2 + end end object :mutation_agent_relationship_role do diff --git a/src/zenflows/vf/agreement/domain.ex b/src/zenflows/vf/agreement/domain.ex @@ -20,6 +20,7 @@ defmodule Zenflows.VF.Agreement.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.Agreement @typep repo() :: Ecto.Repo.t() @@ -27,20 +28,22 @@ alias Zenflows.VF.Agreement @typep id() :: Zenflows.DB.Schema.id() @typep params() :: Zenflows.DB.Schema.params() -@spec one(repo(), id()) :: {:ok, Agreement.t()} | {:error, String.t()} -def one(repo \\ Repo, id) do - one_by(repo, id: id) -end - -@spec one_by(repo(), map() | Keyword.t()) +@spec one(repo(), id() | map() | Keyword.t()) :: {:ok, Agreement.t()} | {:error, String.t()} -def one_by(repo \\ Repo, clauses) do +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(Agreement, clauses) do nil -> {:error, "not found"} found -> {:ok, found} end end +@spec all(Paging.params()) :: Paging.result(Agreement.t()) +def all(params) do + Paging.page(Agreement, params) +end + @spec create(params()) :: {:ok, Agreement.t()} | {:error, chgset()} def create(params) do Multi.new() @@ -57,7 +60,7 @@ end def update(id, params) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) + |> Multi.run(:one, &one/2) |> Multi.update(:update, &Agreement.chgset(&1.one, params)) |> Repo.transaction() |> case do @@ -70,7 +73,7 @@ end def delete(id) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) + |> Multi.run(:one, &one/2) |> Multi.delete(:delete, &(&1.one)) |> Repo.transaction() |> case do diff --git a/src/zenflows/vf/agreement/resolv.ex b/src/zenflows/vf/agreement/resolv.ex @@ -20,12 +20,12 @@ defmodule Zenflows.VF.Agreement.Resolv do alias Zenflows.VF.Agreement.Domain -def created(%{id: id}, _, _) do - Zenflows.DB.ID.ts(id) +def agreement(params, _info) do + Domain.one(params) end -def agreement(%{id: id}, _info) do - Domain.one(id) +def agreements(params, _) do + Domain.all(params) end def create_agreement(%{agreement: params}, _info) do @@ -45,4 +45,8 @@ def delete_agreement(%{id: id}, _info) do {:ok, true} end end + +def created(%{id: id}, _, _) do + Zenflows.DB.ID.ts(id) +end end diff --git a/src/zenflows/vf/agreement/type.ex b/src/zenflows/vf/agreement/type.ex @@ -43,10 +43,6 @@ object :agreement do field :created, non_null(:datetime), resolve: &Resolv.created/3 end -object :agreement_response do - field :agreement, non_null(:agreement) -end - input_object :agreement_create_params do @desc @name field :name, non_null(:string) @@ -65,11 +61,33 @@ input_object :agreement_update_params do field :note, :string end +object :agreement_response do + field :agreement, non_null(:agreement) +end + +object :agreement_edge do + field :cursor, non_null(:id) + field :node, non_null(:agreement) +end + +object :agreement_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:agreement_edge))) +end + object :query_agreement do field :agreement, :agreement do arg :id, non_null(:id) resolve &Resolv.agreement/2 end + + field :agreements, :agreement_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.agreements/2 + end end object :mutation_agreement do diff --git a/src/zenflows/vf/economic_event/domain.ex b/src/zenflows/vf/economic_event/domain.ex @@ -22,6 +22,7 @@ import Ecto.Query alias Ecto.{Changeset, Multi} alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.{ Action, EconomicEvent, @@ -30,19 +31,29 @@ alias Zenflows.VF.{ } @typep repo() :: Ecto.Repo.t() -@typep error() :: Ecto.Changeset.t() | String.t() -@typep changes() :: Ecto.Multi.changes() +@typep chgset() :: Ecto.Changeset.t() @typep id() :: Zenflows.DB.Schema.id() @typep params() :: Zenflows.DB.Schema.params() -@spec by_id(repo(), id()) :: EconomicEvent.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(EconomicEvent, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, EconomicEvent.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(EconomicEvent, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(EconomicEvent.t()) +def all(params) do + Paging.page(EconomicEvent, params) end @spec create(params(), params()) :: {:ok, EconomicEvent.t(), EconomicResource.t(), nil} | {:ok, EconomicEvent.t(), nil, EconomicResource.t()} - | {:ok, EconomicEvent.t()} | {:error, error()} + | {:ok, EconomicEvent.t()} | {:error, String.t() | chgset()} def create(evt_params, res_params) do Multi.new() |> Multi.insert(:created_evt, EconomicEvent.chgset(evt_params)) @@ -976,11 +987,13 @@ defp handle_multi("move", evt, res_params) do end) end -@spec update(id(), params()) :: {:ok, EconomicEvent.t()} | {:error, error()} +@spec update(id(), params()) + :: {:ok, EconomicEvent.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &EconomicEvent.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &EconomicEvent.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: ee}} -> {:ok, ee} @@ -1049,17 +1062,4 @@ end def preload(eco_evt, :triggered_by) do Repo.preload(eco_evt, :triggered_by) end - -# Returns a EconomicEvent 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, EconomicEvent.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - ee -> {:ok, ee} - end - end -end end diff --git a/src/zenflows/vf/economic_event/resolv.ex b/src/zenflows/vf/economic_event/resolv.ex @@ -20,16 +20,17 @@ defmodule Zenflows.VF.EconomicEvent.Resolv do use Absinthe.Schema.Notation -alias Zenflows.VF.{ - EconomicEvent, - EconomicEvent.Domain, -} +alias Zenflows.VF.EconomicEvent.Domain -def economic_event(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def economic_event(params, _) do + Domain.one(params) end -def create_economic_event(%{event: evt_params} = params, _info) do +def economic_events(params, _) do + Domain.all(params) +end + +def create_economic_event(%{event: evt_params} = params, _) do res_params = params[:new_inventoried_resource] case Domain.create(evt_params, res_params) do {:ok, evt, res, nil} -> @@ -48,78 +49,78 @@ def create_economic_event(%{event: evt_params} = params, _info) do end end -def update_economic_event(%{economic_event: %{id: id} = params}, _info) do +def update_economic_event(%{economic_event: %{id: id} = params}, _) do with {:ok, eco_evt} <- Domain.update(id, params) do {:ok, %{economic_event: eco_evt}} end end -def action(%EconomicEvent{} = eco_evt, _args, _info) do +def action(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :action) {:ok, eco_evt.action} end -def input_of(%EconomicEvent{} = eco_evt, _args, _info) do +def input_of(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :input_of) {:ok, eco_evt.input_of} end -def output_of(%EconomicEvent{} = eco_evt, _args, _info) do +def output_of(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :output_of) {:ok, eco_evt.output_of} end -def provider(%EconomicEvent{} = eco_evt, _args, _info) do +def provider(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :provider) {:ok, eco_evt.provider} end -def receiver(%EconomicEvent{} = eco_evt, _args, _info) do +def receiver(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :receiver) {:ok, eco_evt.receiver} end -def resource_inventoried_as(%EconomicEvent{} = eco_evt, _args, _info) do +def resource_inventoried_as(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :resource_inventoried_as) {:ok, eco_evt.resource_inventoried_as} end -def to_resource_inventoried_as(%EconomicEvent{} = eco_evt, _args, _info) do +def to_resource_inventoried_as(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :to_resource_inventoried_as) {:ok, eco_evt.to_resource_inventoried_as} end -def resource_quantity(%EconomicEvent{} = eco_evt, _args, _info) do +def resource_quantity(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :resource_quantity) {:ok, eco_evt.resource_quantity} end -def effort_quantity(%EconomicEvent{} = eco_evt, _args, _info) do +def effort_quantity(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :effort_quantity) {:ok, eco_evt.effort_quantity} end -def resource_conforms_to(%EconomicEvent{} = eco_evt, _args, _info) do +def resource_conforms_to(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :resource_conforms_to) {:ok, eco_evt.resource_conforms_to} end -def to_location(%EconomicEvent{} = eco_evt, _args, _info) do +def to_location(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :to_location) {:ok, eco_evt.to_location} end -def at_location(%EconomicEvent{} = eco_evt, _args, _info) do +def at_location(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :at_location) {:ok, eco_evt.at_location} end -def realization_of(%EconomicEvent{} = eco_evt, _args, _info) do +def realization_of(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :realization_of) {:ok, eco_evt.realization_of} end -def triggered_by(%EconomicEvent{} = eco_evt, _args, _info) do +def triggered_by(eco_evt, _, _) do eco_evt = Domain.preload(eco_evt, :triggered_by) {:ok, eco_evt.triggered_by} end diff --git a/src/zenflows/vf/economic_event/type.ex b/src/zenflows/vf/economic_event/type.ex @@ -173,30 +173,13 @@ object :economic_event do resolve: &Resolv.triggered_by/3 end -object :economic_event_response do - @desc "Details of the newly created event." - field :economic_event, non_null(:economic_event) - - #@desc """ - #Details of any newly created `EconomicResource`, for events that - #create new resources. - #""" - #field :economic_resource, :economic_resource -end - input_object :economic_event_create_params do @desc @action field :action_id, non_null(:string), name: "action" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. @desc @input_of_id field :input_of_id, :id, name: "input_of" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. @desc @output_of_id field :output_of_id, :id, name: "output_of" @@ -206,24 +189,15 @@ input_object :economic_event_create_params do @desc @receiver_id field :receiver_id, :id, name: "receiver" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. @desc @resource_inventoried_as_id field :resource_inventoried_as_id, :id, name: "resource_inventoried_as" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. @desc @to_resource_inventoried_as_id field :to_resource_inventoried_as_id, :id, name: "to_resource_inventoried_as" @desc @resource_classified_as field :resource_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 @resource_conforms_to_id field :resource_conforms_to_id, :id, name: "resource_conforms_to" @@ -245,30 +219,18 @@ input_object :economic_event_create_params do @desc @note field :note, :string - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. @desc @to_location_id field :to_location_id, :id, name: "to_location" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. @desc @at_location_id field :at_location_id, :id, name: "at_location" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. @desc @realization_of_id field :realization_of_id, :id, name: "realization_of" @desc @agreed_in field :agreed_in, :string - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. @desc @triggered_by_id field :triggered_by_id, :id, name: "triggered_by" end @@ -279,28 +241,45 @@ input_object :economic_event_update_params do @desc @note field :note, :string - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. @desc @realization_of_id field :realization_of_id, :id, name: "realization_of" @desc @agreed_in field :agreed_in, :string - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. @desc @triggered_by_id field :triggered_by_id, :id, name: "triggered_by" end +object :economic_event_response do + @desc "Details of the newly created event." + field :economic_event, non_null(:economic_event) +end + +object :economic_event_edge do + field :cursor, non_null(:id) + field :node, non_null(:economic_event) +end + +object :economic_event_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:economic_event_edge))) +end + object :query_economic_event do field :economic_event, :economic_event do arg :id, non_null(:id) resolve &Resolv.economic_event/2 end + field :economic_events, :economic_event_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.economic_events/2 + end + #recipeFlow(start: ID, limit: Int): [EconomicEvent!] end diff --git a/src/zenflows/vf/economic_resource/domain.ex b/src/zenflows/vf/economic_resource/domain.ex @@ -20,6 +20,7 @@ defmodule Zenflows.VF.EconomicResource.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.{ Action, EconomicResource, @@ -28,20 +29,31 @@ alias Zenflows.VF.{ @typep repo() :: Ecto.Repo.t() @typep error() :: Ecto.Changeset.t() | String.t() -@typep changes() :: Ecto.Multi.changes() @typep id() :: Zenflows.DB.Schema.id() @typep params() :: Zenflows.DB.Schema.params() -@spec by_id(repo(), id()) :: EconomicResource.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(EconomicResource, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, EconomicResource.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(EconomicResource, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(EconomicResource.t()) +def all(params) do + Paging.page(EconomicResource, params) end -@spec update(id(), params()) :: {:ok, EconomicResource.t()} | {:error, error} +@spec update(id(), params()) :: {:ok, EconomicResource.t()} | {:error, error()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &EconomicResource.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &EconomicResource.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: er}} -> {:ok, er} @@ -49,11 +61,12 @@ def update(id, params) do end end -@spec delete(id()) :: {:ok, EconomicResource.t()} | {:error, error} +@spec delete(id()) :: {:ok, EconomicResource.t()} | {:error, error()} 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: er}} -> {:ok, er} @@ -109,16 +122,4 @@ end def preload(eco_res, :unit_of_effort) do Repo.preload(eco_res, :unit_of_effort) end - -# Returns a EconomicResource 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, EconomicResource.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - er -> {:ok, er} - end - end -end end diff --git a/src/zenflows/vf/economic_resource/resolv.ex b/src/zenflows/vf/economic_resource/resolv.ex @@ -20,78 +20,79 @@ defmodule Zenflows.VF.EconomicResource.Resolv do use Absinthe.Schema.Notation -alias Zenflows.VF.{ - EconomicResource, - EconomicResource.Domain, -} +alias Zenflows.VF.EconomicResource.Domain -def economic_resource(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def economic_resource(params, _) do + Domain.one(params) end -def update_economic_resource(%{resource: %{id: id} = params}, _info) do +def economic_resources(params, _) do + Domain.all(params) +end + +def update_economic_resource(%{resource: %{id: id} = params}, _) do with {:ok, eco_res} <- Domain.update(id, params) do {:ok, %{economic_resource: eco_res}} end end -def delete_economic_resource(%{id: id}, _info) do +def delete_economic_resource(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end end -def conforms_to(%EconomicResource{} = eco_res, _args, _info) do +def conforms_to(eco_res, _, _) do eco_res = Domain.preload(eco_res, :conforms_to) {:ok, eco_res.conforms_to} end -def accounting_quantity(%EconomicResource{} = eco_res, _args, _info) do +def accounting_quantity(eco_res, _, _) do eco_res = Domain.preload(eco_res, :accounting_quantity) {:ok, eco_res.accounting_quantity} end -def onhand_quantity(%EconomicResource{} = eco_res, _args, _info) do +def onhand_quantity(eco_res, _, _) do eco_res = Domain.preload(eco_res, :onhand_quantity) {:ok, eco_res.onhand_quantity} end -def primary_accountable(%EconomicResource{} = eco_res, _args, _info) do +def primary_accountable(eco_res, _, _) do eco_res = Domain.preload(eco_res, :primary_accountable) {:ok, eco_res.primary_accountable} end -def custodian(%EconomicResource{} = eco_res, _args, _info) do +def custodian(eco_res, _, _) do eco_res = Domain.preload(eco_res, :custodian) {:ok, eco_res.custodian} end -def stage(%EconomicResource{} = eco_res, _args, _info) do +def stage(eco_res, _, _) do eco_res = Domain.preload(eco_res, :stage) {:ok, eco_res.stage} end -def state(%EconomicResource{} = eco_res, _args, _info) do +def state(eco_res, _, _) do eco_res = Domain.preload(eco_res, :state) {:ok, eco_res.state} end -def current_location(%EconomicResource{} = eco_res, _args, _info) do +def current_location(eco_res, _, _) do eco_res = Domain.preload(eco_res, :current_location) {:ok, eco_res.current_location} end -def lot(%EconomicResource{} = eco_res, _args, _info) do +def lot(eco_res, _, _) do eco_res = Domain.preload(eco_res, :lot) {:ok, eco_res.lot} end -def contained_in(%EconomicResource{} = eco_res, _args, _info) do +def contained_in(eco_res, _, _) do eco_res = Domain.preload(eco_res, :contained_in) {:ok, eco_res.contained_in} end -def unit_of_effort(%EconomicResource{} = eco_res, _args, _info) do +def unit_of_effort(eco_res, _, _) do eco_res = Domain.preload(eco_res, :unit_of_effort) {:ok, eco_res.unit_of_effort} end diff --git a/src/zenflows/vf/economic_resource/type.ex b/src/zenflows/vf/economic_resource/type.ex @@ -155,10 +155,6 @@ object :economic_resource do field :unit_of_effort, :unit, resolve: &Resolv.unit_of_effort/3 end -object :economic_resource_response do - field :economic_resource, non_null(:economic_resource) -end - input_object :economic_resource_create_params do @desc @name field :name, non_null(:string) @@ -176,6 +172,20 @@ input_object :economic_resource_create_params do field :lot_id, :id, name: "lot" end +object :economic_resource_response do + field :economic_resource, non_null(:economic_resource) +end + +object :economic_resource_edge do + field :cursor, non_null(:id) + field :node, non_null(:economic_resource) +end + +object :economic_resource_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:economic_resource_edge))) +end + input_object :economic_resource_update_params do field :id, non_null(:id) @@ -192,7 +202,13 @@ object :query_economic_resource do resolve &Resolv.economic_resource/2 end - #economicResources(start: ID, limit: Int): [EconomicResource!] + field :economic_resources, :economic_resource_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.economic_resources/2 + end end object :mutation_economic_resource do diff --git a/src/zenflows/vf/intent/domain.ex b/src/zenflows/vf/intent/domain.ex @@ -20,6 +20,7 @@ defmodule Zenflows.VF.Intent.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.{ Action, Intent, @@ -31,20 +32,22 @@ alias Zenflows.VF.{ @typep id() :: Zenflows.DB.Schema.id() @typep params() :: Zenflows.DB.Schema.params() -@spec one(repo(), id()) :: {:ok, Intent.t()} | {:error, String.t()} -def one(repo \\ Repo, id) do - one_by(repo, id: id) -end - -@spec one_by(repo(), map() | Keyword.t()) +@spec one(repo(), id() | map() | Keyword.t()) :: {:ok, Intent.t()} | {:error, String.t()} -def one_by(repo \\ Repo, clauses) do +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(Intent, clauses) do nil -> {:error, "not found"} found -> {:ok, found} end end +@spec all(Paging.params()) :: Paging.result(Intent.t()) +def all(params) do + Paging.page(Intent, params) +end + @spec create(params()) :: {:ok, Intent.t()} | {:error, chgset()} def create(params) do Multi.new() @@ -61,7 +64,7 @@ end def update(id, params) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) + |> Multi.run(:one, &one/2) |> Multi.update(:update, &Intent.chgset(&1.one, params)) |> Repo.transaction() |> case do @@ -74,7 +77,7 @@ end def delete(id) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) + |> Multi.run(:one, &one/2) |> Multi.delete(:delete, &(&1.one)) |> Repo.transaction() |> case do diff --git a/src/zenflows/vf/intent/resolv.ex b/src/zenflows/vf/intent/resolv.ex @@ -20,6 +20,32 @@ defmodule Zenflows.VF.Intent.Resolv do alias Zenflows.VF.Intent.Domain +def intent(params, _) do + Domain.one(params) +end + +def intents(params, _) do + Domain.all(params) +end + +def create_intent(%{intent: params}, _) do + with {:ok, int} <- Domain.create(params) do + {:ok, %{intent: int}} + end +end + +def update_intent(%{intent: %{id: id} = params}, _) do + with {:ok, int} <- Domain.update(id, params) do + {:ok, %{intent: int}} + end +end + +def delete_intent(%{id: id}, _) do + with {:ok, _} <- Domain.delete(id) do + {:ok, true} + end +end + def action(int, _, _) do int = Domain.preload(int, :action) {:ok, int.action} @@ -79,36 +105,4 @@ def published_in(int, _, _) do int = Domain.preload(int, :published_in) {:ok, int.published_in} end - -def intent(%{id: id}, _) do - Domain.one(id) -end - -def intents(_, _) do - {:ok, %{ - edges: [], - page_info: %{ - has_previous_page: false, - has_next_page: false, - }, - }} -end - -def create_intent(%{intent: params}, _) do - with {:ok, int} <- Domain.create(params) do - {:ok, %{intent: int}} - end -end - -def update_intent(%{intent: %{id: id} = params}, _) do - with {:ok, int} <- Domain.update(id, params) do - {:ok, %{intent: int}} - end -end - -def delete_intent(%{id: id}, _) do - with {:ok, _} <- Domain.delete(id) do - {:ok, true} - end -end end diff --git a/src/zenflows/vf/intent/type.ex b/src/zenflows/vf/intent/type.ex @@ -175,20 +175,6 @@ object :intent do resolve: &Resolv.published_in/3 end -object :intent_response do - field :intent, non_null(:intent) -end - -object :intent_edge do - field :cursor, non_null(:string) - field :node, non_null(:intent) -end - -object :intent_connection do - field :page_info, non_null(:page_info) - field :edges, non_null(list_of(non_null(:intent_edge))) -end - input_object :intent_create_params do @desc @action_id field :action_id, non_null(:string), name: "action" @@ -321,6 +307,20 @@ input_object :intent_update_params do field :agreed_in, :uri end +object :intent_response do + field :intent, non_null(:intent) +end + +object :intent_edge do + field :cursor, non_null(:id) + field :node, non_null(:intent) +end + +object :intent_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:intent_edge))) +end + object :query_intent do field :intent, :intent do arg :id, non_null(:id) @@ -329,9 +329,9 @@ object :query_intent do field :intents, non_null(:intent_connection) do arg :first, :integer - arg :after, :string + arg :after, :id arg :last, :integer - arg :before, :string + arg :before, :id resolve &Resolv.intents/2 end end diff --git a/src/zenflows/vf/organization.ex b/src/zenflows/vf/organization.ex @@ -29,6 +29,7 @@ alias Zenflows.VF.{SpatialThing, Validate} note: String.t() | nil, primary_location: SpatialThing.t() | nil, classified_as: [String.t()] | nil, + updated_at: DateTime.t(), } schema "vf_agent" do diff --git a/src/zenflows/vf/organization/domain.ex b/src/zenflows/vf/organization/domain.ex @@ -22,43 +22,51 @@ import Ecto.Query alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.Organization @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()) :: Organization.t() | nil -def by_id(repo \\ Repo, id) do - repo.get_by(Organization, id: id, type: :org) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, Organization.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 + clauses = if(is_map(clauses), + do: Map.put(clauses, :type, :org), + else: Keyword.put(clauses, :type, :org)) + case repo.get_by(Organization, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end end -@spec all() :: [Organization.t()] -def all() do - Organization - |> from() - |> where(type: :org) - |> Repo.all() +@spec all(Paging.params()) :: Paging.result(Organization.t()) +def all(params) do + Paging.page(where(Organization, type: :org), params) end @spec create(params()) :: {:ok, Organization.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:org, Organization.chgset(params)) + |> Multi.insert(:insert, Organization.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{org: o}} -> {:ok, o} + {:ok, %{insert: o}} -> {:ok, o} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, Organization.t()} | {:error, String.t() | chgset()} +@spec update(id(), params()) + :: {:ok, Organization.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &Organization.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &Organization.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: o}} -> {:ok, o} @@ -69,8 +77,9 @@ end @spec delete(id()) :: {:ok, Organization.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: o}} -> {:ok, o} @@ -82,16 +91,4 @@ end def preload(org, :primary_location) do Repo.preload(org, :primary_location) end - -# Returns an Organization 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, Organization.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - org -> {:ok, org} - end - end -end end diff --git a/src/zenflows/vf/organization/resolv.ex b/src/zenflows/vf/organization/resolv.ex @@ -20,36 +20,40 @@ defmodule Zenflows.VF.Organization.Resolv do alias Zenflows.VF.{Agent, Organization, Organization.Domain} -def organization(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def organization(params, _) do + Domain.one(params) end -def create_organization(%{organization: params}, _info) do +def organizations(params, _) do + Domain.all(params) +end + +def create_organization(%{organization: params}, _) do with {:ok, org} <- Domain.create(params) do {:ok, %{agent: org}} end end -def update_organization(%{organization: %{id: id} = params}, _info) do +def update_organization(%{organization: %{id: id} = params}, _) do with {:ok, org} <- Domain.update(id, params) do {:ok, %{agent: org}} end end -def delete_organization(%{id: id}, _info) do +def delete_organization(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end end -def primary_location(%Organization{} = org, _args, _info) do +def primary_location(%Organization{} = org, _, _) do org = Domain.preload(org, :primary_location) {:ok, org.primary_location} end # For some reason, Absinthe calls this one instead of the one on # Zenflows.VF.Agent.Type for queries to Agent itself. -def primary_location(%Agent{} = agent, args, info) do - Agent.Resolv.primary_location(agent, args, info) +def primary_location(%Agent{} = agent, params, info) do + Agent.Resolv.primary_location(agent, params, info) end end diff --git a/src/zenflows/vf/organization/type.ex b/src/zenflows/vf/organization/type.ex @@ -33,6 +33,7 @@ occur and mail can be sent. This is usually a mappable geographic location. It also could be a website address, as in the case of agents who have no physical location. """ +@primary_location_id "(`SpatialThing`) #{@primary_location}" @note "A textual description or comment." @classified_as """ References one or more concepts in a common taxonomy or other @@ -62,10 +63,6 @@ object :organization do field :classified_as, list_of(non_null(:string)) end -object :organization_response do - field :agent, non_null(:organization) -end - input_object :organization_create_params do @desc @name field :name, non_null(:string) @@ -76,10 +73,7 @@ input_object :organization_create_params do @desc @note field :note, :string - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`SpatialThing`) " <> @primary_location + @desc @primary_location_id field :primary_location_id, :id, name: "primary_location" @desc @classified_as @@ -98,13 +92,27 @@ input_object :organization_update_params do @desc @note field :note, :string - @desc "(`SpatialThing`) " <> @primary_location + @desc @primary_location_id field :primary_location_id, :id, name: "primary_location" @desc @classified_as field :classified_as, list_of(non_null(:string)) end +object :organization_response do + field :agent, non_null(:organization) +end + +object :organization_edge do + field :cursor, non_null(:id) + field :node, non_null(:organization) +end + +object :organization_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:organization_edge))) +end + object :query_organization do @desc "Find an organization (group) agent by its ID." field :organization, :organization do @@ -112,8 +120,17 @@ object :query_organization do resolve &Resolv.organization/2 end - #"Loads all organizations publicly registered within this collaboration space" - #organizations(start: ID, limit: Int): [Organization!] + @desc """ + Loads all organizations publicly registered within this + collaboration space. + """ + field :organizations, :organization_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.organizations/2 + end end object :mutation_organization do diff --git a/src/zenflows/vf/person/domain.ex b/src/zenflows/vf/person/domain.ex @@ -22,62 +22,55 @@ import Ecto.Query alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.Person @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(repo(), Keyword.t() | map()) :: Person.t() | nil -def by(repo \\ Repo, clauses) -def by(repo, clauses) when is_map(clauses) do - repo.get_by(Person, Map.put(clauses, :type, :per)) -end -def by(repo, clauses) when is_list(clauses) do - repo.get_by(Person, Keyword.put(clauses, :type, :per)) -end - -@spec by_id(repo(), id()) :: Person.t() | nil -def by_id(repo \\ Repo, id) do - by(repo, id: id) -end - -@spec by_user(repo(), String.t()) :: Person.t() | nil -def by_user(repo \\ Repo, user) do - by(repo, user: user) +@spec one(repo(), id() | map() | Keyword.t()) :: {:ok, Person.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 + clauses = if(is_map(clauses), + do: Map.put(clauses, :type, :per), + else: Keyword.put(clauses, :type, :per)) + case repo.get_by(Person, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end end -@spec exists_email(String.t()) :: boolean() -def exists_email(email) do - where(Person, email: ^email) |> Repo.exists?() +@spec all(Paging.params()) :: Paging.result(Person.t()) +def all(params) do + Paging.page(where(Person, type: :per), params) end -@spec all() :: [Person.t()] -def all() do - Person - |> from() - |> where(type: :per) - |> Repo.all() +@spec exists?(Keyword.t()) :: boolean() +def exists?(conds) do + where(Person, ^conds) |> Repo.exists?() end @spec create(params()) :: {:ok, Person.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:per, Person.chgset(params)) + |> Multi.insert(:insert, Person.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{per: p}} -> {:ok, p} + {:ok, %{insert: p}} -> {:ok, p} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, Person.t()} | {:error, String.t() | chgset()} +@spec update(id(), params()) + :: {:ok, Person.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &Person.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &Person.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: p}} -> {:ok, p} @@ -88,8 +81,9 @@ end @spec delete(id()) :: {:ok, Person.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: p}} -> {:ok, p} @@ -101,16 +95,4 @@ end def preload(per, :primary_location) do Repo.preload(per, :primary_location) end - -# Returns a Person 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, Person.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - per -> {:ok, per} - end - end -end end diff --git a/src/zenflows/vf/person/resolv.ex b/src/zenflows/vf/person/resolv.ex @@ -20,40 +20,44 @@ defmodule Zenflows.VF.Person.Resolv do alias Zenflows.VF.{Agent, Person, Person.Domain} -def person(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def person(params, _) do + Domain.one(params) end -def person_exists(params, _info) do - {:ok, Domain.by(params)} +def people(params, _) do + Domain.all(params) end -def create_person(%{person: params}, _info) do +def person_exists(params, _) do + Domain.one(params) +end + +def create_person(%{person: params}, _) do with {:ok, per} <- Domain.create(params) do {:ok, %{agent: per}} end end -def update_person(%{person: %{id: id} = params}, _info) do +def update_person(%{person: %{id: id} = params}, _) do with {:ok, per} <- Domain.update(id, params) do {:ok, %{agent: per}} end end -def delete_person(%{id: id}, _info) do +def delete_person(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end end -def primary_location(%Person{} = per, _args, _info) do +def primary_location(%Person{} = per, _, _) do per = Domain.preload(per, :primary_location) {:ok, per.primary_location} end # For some reason, Absinthe calls this one instead of the one on # Zenflows.VF.Agent.Type for queries to Agent itself. -def primary_location(%Agent{} = agent, args, info) do - Agent.Resolv.primary_location(agent, args, info) +def primary_location(%Agent{} = agent, params, info) do + Agent.Resolv.primary_location(agent, params, info) end end diff --git a/src/zenflows/vf/person/type.ex b/src/zenflows/vf/person/type.ex @@ -34,6 +34,7 @@ occur and mail can be sent. This is usually a mappable geographic location. It also could be a website address, as in the case of agents who have no physical location. """ +@primary_location_id "(`SpatialThing`) #{@primary_location}" @user "Username of the agent. Implies uniqueness." @email "Email address of the agent. Implies uniqueness." @ecdh_public_key "ecdh public key, encoded by zenroom" @@ -83,10 +84,6 @@ object :person do field :schnorr_public_key, :string end -object :person_response do - field :agent, non_null(:person) -end - input_object :person_create_params do @desc @name field :name, non_null(:string) @@ -100,7 +97,7 @@ input_object :person_create_params do # TODO: When # https://github.com/absinthe-graphql/absinthe/issues/1126 results, # apply the correct changes if any. - @desc "(`SpatialThing`) " <> @primary_location + @desc @primary_location_id field :primary_location_id, :id, name: "primary_location" @desc @user @@ -137,13 +134,27 @@ input_object :person_update_params do @desc @note field :note, :string - @desc "(`SpatialThing`) " <> @primary_location + @desc @primary_location_id field :primary_location_id, :id, name: "primary_location" @desc @user field :user, :string end +object :person_response do + field :agent, non_null(:person) +end + +object :person_edge do + field :cursor, non_null(:id) + field :node, non_null(:person) +end + +object :person_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:person_edge))) +end + object :query_person do @desc "Find a person by their ID." field :person, :person do @@ -151,6 +162,18 @@ object :query_person do resolve &Resolv.person/2 end + @desc """ + Loads all people who have publicly registered with this collaboration + space. + """ + field :people, :person_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.people/2 + end + @desc "Find if a person exists by email and eddsa-public-key." field :person_exists, :person do meta only_guest?: true @@ -158,9 +181,6 @@ object :query_person do arg :eddsa_public_key, non_null(:string) resolve &Resolv.person_exists/2 end - - #"Loads all people who have publicly registered with this collaboration space." - #people(start: ID, limit: Int): [Person!] end object :mutation_person do diff --git a/src/zenflows/vf/plan/domain.ex b/src/zenflows/vf/plan/domain.ex @@ -20,6 +20,7 @@ defmodule Zenflows.VF.Plan.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.Plan @typep repo() :: Ecto.Repo.t() @@ -27,20 +28,22 @@ alias Zenflows.VF.Plan @typep id() :: Zenflows.DB.Schema.id() @typep params() :: Zenflows.DB.Schema.params() -@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()) +@spec one(repo(), id() | map() | Keyword.t()) :: {:ok, Plan.t()} | {:error, String.t()} -def one_by(repo \\ Repo, clauses) do +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(Plan, clauses) do nil -> {:error, "not found"} found -> {:ok, found} end end +@spec all(Paging.params()) :: Paging.result(Plan.t()) +def all(params) do + Paging.page(Plan, params) +end + @spec create(params()) :: {:ok, Plan.t()} | {:error, chgset()} def create(params) do Multi.new() @@ -57,7 +60,7 @@ end def update(id, params) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) + |> Multi.run(:one, &one/2) |> Multi.update(:update, &Plan.chgset(&1.one, params)) |> Repo.transaction() |> case do @@ -70,8 +73,8 @@ end def delete(id) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) - |> Multi.delete(:delete, &(&1.one)) + |> Multi.run(:one, &one/2) + |> Multi.delete(:delete, & &1.one) |> Repo.transaction() |> case do {:ok, %{delete: p}} -> {:ok, p} diff --git a/src/zenflows/vf/plan/resolv.ex b/src/zenflows/vf/plan/resolv.ex @@ -20,36 +20,40 @@ defmodule Zenflows.VF.Plan.Resolv do use Absinthe.Schema.Notation -alias Zenflows.VF.{Plan, Plan.Domain} +alias Zenflows.VF.Plan.Domain -def created(%{id: id}, _, _) do - Zenflows.DB.ID.ts(id) +def plan(params, _) do + Domain.one(params) end -def refinement_of(%Plan{} = plan, _args, _info) do - plan = Domain.preload(plan, :refinement_of) - {:ok, plan.refinement_of} +def plans(params, _) do + Domain.all(params) end -def plan(%{id: id}, _info) do - Domain.one(id) -end - -def create_plan(%{plan: params}, _info) do +def create_plan(%{plan: params}, _) do with {:ok, plan} <- Domain.create(params) do {:ok, %{plan: plan}} end end -def update_plan(%{plan: %{id: id} = params}, _info) do +def update_plan(%{plan: %{id: id} = params}, _) do with {:ok, plan} <- Domain.update(id, params) do {:ok, %{plan: plan}} end end -def delete_plan(%{id: id}, _info) do +def delete_plan(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end end + +def created(%{id: id}, _, _) do + Zenflows.DB.ID.ts(id) +end + +def refinement_of(plan, _, _) do + plan = Domain.preload(plan, :refinement_of) + {:ok, plan.refinement_of} +end end diff --git a/src/zenflows/vf/plan/type.ex b/src/zenflows/vf/plan/type.ex @@ -31,6 +31,7 @@ uniqueness. @due "The time the plan is expected to be complete." @deletable "The plan is able to be deleted or not." @refinement_of "This plan refines a scenario, making it operational." +@refinement_of_id "(`Scenario`) #{@refinement_of}" @desc """ A logical collection of processes that constitute a body of planned work @@ -58,10 +59,6 @@ object :plan do field :refinement_of, :scenario, resolve: &Resolv.refinement_of/3 end -object :plan_response do - field :plan, non_null(:plan) -end - input_object :plan_create_params do @desc @name field :name, non_null(:string) @@ -72,10 +69,7 @@ input_object :plan_create_params do @desc @due field :due, :datetime - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`Scenario`) " <> @refinement_of + @desc @refinement_of_id field :refinement_of_id, :id, name: "refinement_of" end @@ -91,20 +85,37 @@ input_object :plan_update_params do @desc @due field :due, :datetime - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`Scenario`) " <> @refinement_of + @desc @refinement_of_id field :refinement_of_id, :id, name: "refinement_of" end +object :plan_response do + field :plan, non_null(:plan) +end + +object :plan_edge do + field :cursor, non_null(:id) + field :node, non_null(:plan) +end + +object :plan_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:plan_edge))) +end + object :query_plan do field :plan, :plan do arg :id, non_null(:id) resolve &Resolv.plan/2 end - #plans(start: ID, limit: Int): [Plan!] + field :plans, :plan_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.plans/2 + end end object :mutation_plan do diff --git a/src/zenflows/vf/process/domain.ex b/src/zenflows/vf/process/domain.ex @@ -20,35 +20,48 @@ defmodule Zenflows.VF.Process.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.Process @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()) :: Process.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(Process, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, Process.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(Process, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(Process.t()) +def all(params) do + Paging.page(Process, params) end @spec create(params()) :: {:ok, Process.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:proc, Process.chgset(params)) + |> Multi.insert(:insert, Process.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{proc: p}} -> {:ok, p} + {:ok, %{insert: p}} -> {:ok, p} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, Process.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, Process.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &Process.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &Process.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: p}} -> {:ok, p} @@ -56,11 +69,12 @@ def update(id, params) do end end -@spec delete(id()) :: {:ok, Process.t()} | {:error, chgset()} +@spec delete(id()) :: {:ok, Process.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: p}} -> {:ok, p} @@ -81,17 +95,4 @@ end def preload(proc, :nested_in) do Repo.preload(proc, :nested_in) end - -# Returns a Process 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, Process.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/process/resolv.ex b/src/zenflows/vf/process/resolv.ex @@ -20,41 +20,45 @@ defmodule Zenflows.VF.Process.Resolv do use Absinthe.Schema.Notation -alias Zenflows.VF.{Process, Process.Domain} +alias Zenflows.VF.Process.Domain -def process(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def process(params, _) do + Domain.one(params) end -def create_process(%{process: params}, _info) do +def processes(params, _) do + Domain.all(params) +end + +def create_process(%{process: params}, _) do with {:ok, process} <- Domain.create(params) do {:ok, %{process: process}} end end -def update_process(%{process: %{id: id} = params}, _info) do +def update_process(%{process: %{id: id} = params}, _) do with {:ok, proc} <- Domain.update(id, params) do {:ok, %{process: proc}} end end -def delete_process(%{id: id}, _info) do +def delete_process(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end end -def based_on(%Process{} = proc, _args, _info) do +def based_on(proc, _, _) do proc = Domain.preload(proc, :based_on) {:ok, proc.based_on} end -def planned_within(%Process{} = proc, _args, _info) do +def planned_within(proc, _, _) do proc = Domain.preload(proc, :planned_within) {:ok, proc.planned_within} end -def nested_in(%Process{} = proc, _args, _info) do +def nested_in(proc, _, _) do proc = Domain.preload(proc, :nested_in) {:ok, proc.nested_in} end diff --git a/src/zenflows/vf/process/type.ex b/src/zenflows/vf/process/type.ex @@ -41,12 +41,15 @@ References one or more concepts in a common taxonomy or other classification scheme for purposes of categorization or grouping. """ @based_on "The definition or specification for a process." +@based_on_id "(`ProcesssSpecification`) #{@based_on}" @planned_within """ The process with its inputs and outputs is part of the plan. """ +@planned_within_id "(`Plan`) #{@planned_within}" @nested_in """ The process with its inputs and outputs is part of the scenario. """ +@nested_in_id "(`Scenario`) #{@nested_in}" @desc """ A logical collection of processes that constitute a body of processned work @@ -88,10 +91,6 @@ object :process do field :nested_in, :scenario, resolve: &Resolv.nested_in/3 end -object :process_response do - field :process, non_null(:process) -end - input_object :process_create_params do @desc @name field :name, non_null(:string) @@ -111,22 +110,13 @@ input_object :process_create_params do @desc @classified_as field :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`) " <> @based_on + @desc @based_on_id field :based_on_id, :id, name: "based_on" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`Plan`) " <> @planned_within + @desc @planned_within_id field :planned_within_id, :id, name: "planned_within" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`Scenario`) " <> @nested_in + @desc @nested_in_id field :nested_in_id, :id, name: "nested_in" end @@ -151,32 +141,43 @@ input_object :process_update_params do @desc @classified_as field :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`) " <> @based_on + @desc :based_on_id field :based_on_id, :id, name: "based_on" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`Plan`) " <> @planned_within + @desc @planned_within_id field :planned_within_id, :id, name: "planned_within" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`Scenario`) " <> @nested_in + @desc @nested_in_id field :nested_in_id, :id, name: "nested_in" end +object :process_response do + field :process, non_null(:process) +end + +object :process_edge do + field :cursor, non_null(:id) + field :node, non_null(:process) +end + +object :process_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:process_edge))) +end + object :query_process do field :process, :process do arg :id, non_null(:id) resolve &Resolv.process/2 end - #processes(start: ID, limit: Int): [Process!] + field :processes, :process_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.processes/2 + end end object :mutation_process do diff --git a/src/zenflows/vf/process_specification/domain.ex b/src/zenflows/vf/process_specification/domain.ex @@ -20,63 +20,66 @@ defmodule Zenflows.VF.ProcessSpecification.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.ProcessSpecification @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()) :: ProcessSpecification.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(ProcessSpecification, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, ProcessSpecification.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(ProcessSpecification, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(ProcessSpecification.t()) +def all(params) do + Paging.page(ProcessSpecification, params) end @spec create(params()) :: {:ok, ProcessSpecification.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:proc_spec, ProcessSpecification.chgset(params)) + |> Multi.insert(:insert, ProcessSpecification.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{proc_spec: ps}} -> {:ok, ps} + {:ok, %{insert: p}} -> {:ok, p} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, ProcessSpecification.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, ProcessSpecification.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &ProcessSpecification.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &ProcessSpecification.chgset(&1.one, params)) |> Repo.transaction() |> case do - {:ok, %{update: ps}} -> {:ok, ps} + {:ok, %{update: p}} -> {:ok, p} {:error, _, msg_or_cset, _} -> {:error, msg_or_cset} end end -@spec delete(id()) :: {:ok, ProcessSpecification.t()} | {:error, chgset()} +@spec delete(id()) + :: {:ok, ProcessSpecification.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: ps}} -> {:ok, ps} + {:ok, %{delete: p}} -> {:ok, p} {:error, _, msg_or_cset, _} -> {:error, msg_or_cset} end end - -# Returns a ProcessSpecification 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, ProcessSpecification.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - ps -> {:ok, ps} - end - end -end end diff --git a/src/zenflows/vf/process_specification/resolv.ex b/src/zenflows/vf/process_specification/resolv.ex @@ -20,23 +20,27 @@ defmodule Zenflows.VF.ProcessSpecification.Resolv do alias Zenflows.VF.ProcessSpecification.Domain -def process_specification(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def process_specification(params, _) do + Domain.one(params) end -def create_process_specification(%{process_specification: params}, _info) do +def process_specifications(params, _) do + Domain.all(params) +end + +def create_process_specification(%{process_specification: params}, _) do with {:ok, proc_spec} <- Domain.create(params) do {:ok, %{process_specification: proc_spec}} end end -def update_process_specification(%{process_specification: %{id: id} = params}, _info) do +def update_process_specification(%{process_specification: %{id: id} = params}, _) do with {:ok, proc_spec} <- Domain.update(id, params) do {:ok, %{process_specification: proc_spec}} end end -def delete_process_specification(%{id: id}, _info) do +def delete_process_specification(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end diff --git a/src/zenflows/vf/process_specification/type.ex b/src/zenflows/vf/process_specification/type.ex @@ -39,10 +39,6 @@ object :process_specification do field :note, :string end -object :process_specification_response do - field :process_specification, non_null(:process_specification) -end - input_object :process_specification_create_params do @desc @name field :name, non_null(:string) @@ -61,11 +57,33 @@ input_object :process_specification_update_params do field :note, :string end +object :process_specification_response do + field :process_specification, non_null(:process_specification) +end + +object :process_specification_edge do + field :cursor, non_null(:id) + field :node, non_null(:process_specification) +end + +object :process_specification_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:process_specification_edge))) +end + object :query_process_specification do field :process_specification, :process_specification do arg :id, non_null(:id) resolve &Resolv.process_specification/2 end + + field :process_specifications, non_null(:process_specification_connection) do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.process_specifications/2 + end end object :mutation_process_specification do 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/src/zenflows/vf/proposal/domain.ex b/src/zenflows/vf/proposal/domain.ex @@ -20,6 +20,7 @@ defmodule Zenflows.VF.Proposal.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.Proposal @typep repo() :: Ecto.Repo.t() @@ -27,20 +28,22 @@ alias Zenflows.VF.Proposal @typep id() :: Zenflows.DB.Schema.id() @typep params() :: Zenflows.DB.Schema.params() -@spec one(repo(), id()) :: {:ok, Proposal.t()} | {:error, String.t()} -def one(repo \\ Repo, id) do - one_by(repo, id: id) -end - -@spec one_by(repo(), map() | Keyword.t()) +@spec one(repo(), id() | map() | Keyword.t()) :: {:ok, Proposal.t()} | {:error, String.t()} -def one_by(repo \\ Repo, clauses) do +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(Proposal, clauses) do nil -> {:error, "not found"} found -> {:ok, found} end end +@spec all(Paging.params()) :: Paging.result(Proposal.t()) +def all(params) do + Paging.page(Proposal, params) +end + @spec create(params()) :: {:ok, Proposal.t()} | {:error, chgset()} def create(params) do Multi.new() @@ -57,7 +60,7 @@ end def update(id, params) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) + |> Multi.run(:one, &one/2) |> Multi.update(:update, &Proposal.chgset(&1.one, params)) |> Repo.transaction() |> case do @@ -71,8 +74,8 @@ end def delete(id) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) - |> Multi.delete(:delete, &(&1.one)) + |> Multi.run(:one, &one/2) + |> Multi.delete(:delete, & &1.one) |> Repo.transaction() |> case do {:ok, %{delete: pi}} -> {:ok, pi} diff --git a/src/zenflows/vf/proposal/resolv.ex b/src/zenflows/vf/proposal/resolv.ex @@ -20,38 +20,12 @@ defmodule Zenflows.VF.Proposal.Resolv do alias Zenflows.VF.Proposal.Domain -def eligible_location(prop, _, _) do - prop = Domain.preload(prop, :eligible_location) - {:ok, prop.eligible_location} -end - -def publishes(prop, _, _) do - prop = Domain.preload(prop, :publishes) - {:ok, prop.publishes} -end - -def primary_intents(prop, _, _) do - prop = Domain.preload(prop, :primary_intents) - {:ok, prop.primary_intents} -end - -def reciprocal_intents(prop, _, _) do - prop = Domain.preload(prop, :reciprocal_intents) - {:ok, prop.reciprocal_intents} +def proposal(params, _) do + Domain.one(params) end -def proposal(%{id: id}, _) do - Domain.one(id) -end - -def proposals(_params, _) do - {:ok, %{ - edges: [], - page_info: %{ - has_previous_page: false, - has_next_page: false, - }, - }} +def proposals(params, _) do + Domain.all(params) end def offers(_params, _) do @@ -91,4 +65,24 @@ def delete_proposal(%{id: id}, _) do {:ok, true} end end + +def eligible_location(prop, _, _) do + prop = Domain.preload(prop, :eligible_location) + {:ok, prop.eligible_location} +end + +def publishes(prop, _, _) do + prop = Domain.preload(prop, :publishes) + {:ok, prop.publishes} +end + +def primary_intents(prop, _, _) do + prop = Domain.preload(prop, :primary_intents) + {:ok, prop.primary_intents} +end + +def reciprocal_intents(prop, _, _) do + prop = Domain.preload(prop, :reciprocal_intents) + {:ok, prop.reciprocal_intents} +end end diff --git a/src/zenflows/vf/proposal/type.ex b/src/zenflows/vf/proposal/type.ex @@ -74,20 +74,6 @@ object :proposal do resolve: &Resolv.reciprocal_intents/3 end -object :proposal_response do - field :proposal, non_null(:proposal) -end - -object :proposal_edge do - field :cursor, non_null(:string) - field :node, non_null(:proposal) -end - -object :proposal_connection do - field :page_info, non_null(:page_info) - field :edges, non_null(list_of(non_null(:proposal_edge))) -end - input_object :proposal_create_params do @desc @name field :name, :string @@ -130,6 +116,20 @@ input_object :proposal_update_params do field :eligible_location_id, :id, name: "eligible_location" end +object :proposal_response do + field :proposal, non_null(:proposal) +end + +object :proposal_edge do + field :cursor, non_null(:id) + field :node, non_null(:proposal) +end + +object :proposal_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:proposal_edge))) +end + object :query_proposal do field :proposal, :proposal do arg :id, non_null(:id) @@ -138,29 +138,27 @@ object :query_proposal do field :proposals, non_null(:proposal_connection) do arg :first, :integer - arg :after, :string + arg :after, :id arg :last, :integer - arg :before, :string + arg :before, :id resolve &Resolv.proposals/2 end @desc "List all proposals that are being listed as offers." field :offers, non_null(:proposal_connection) do arg :first, :integer - arg :first, :integer - arg :after, :string + arg :after, :id arg :last, :integer - arg :before, :string + arg :before, :id resolve &Resolv.offers/2 end @desc "List all proposals that are being listed as requests." field :requests, non_null(:proposal_connection) do arg :first, :integer - arg :first, :integer - arg :after, :string + arg :after, :id arg :last, :integer - arg :before, :string + arg :before, :id resolve &Resolv.offers/2 end end diff --git a/src/zenflows/vf/proposed_intent/domain.ex b/src/zenflows/vf/proposed_intent/domain.ex @@ -20,6 +20,7 @@ defmodule Zenflows.VF.ProposedIntent.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.ProposedIntent @typep repo() :: Ecto.Repo.t() @@ -27,20 +28,22 @@ alias Zenflows.VF.ProposedIntent @typep id() :: Zenflows.DB.Schema.id() @typep params() :: Zenflows.DB.Schema.params() -@spec one(repo(), id()) :: {:ok, ProposedIntent.t()} | {:error, String.t()} -def one(repo \\ Repo, id) do - one_by(repo, id: id) -end - -@spec one_by(repo(), map() | Keyword.t()) +@spec one(repo(), id() | map() | Keyword.t()) :: {:ok, ProposedIntent.t()} | {:error, String.t()} -def one_by(repo \\ Repo, clauses) do +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(ProposedIntent, clauses) do nil -> {:error, "not found"} found -> {:ok, found} end end +@spec all(Paging.params()) :: Paging.result(ProposedIntent.t()) +def all(params) do + Paging.page(ProposedIntent, params) +end + @spec create(params()) :: {:ok, ProposedIntent.t()} | {:error, chgset()} def create(params) do Multi.new() @@ -57,8 +60,8 @@ end def delete(id) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) - |> Multi.delete(:delete, &(&1.one)) + |> Multi.run(:one, &one/2) + |> Multi.delete(:delete, & &1.one) |> Repo.transaction() |> case do {:ok, %{delete: pi}} -> {:ok, pi} diff --git a/src/zenflows/vf/proposed_intent/resolv.ex b/src/zenflows/vf/proposed_intent/resolv.ex @@ -20,16 +20,6 @@ defmodule Zenflows.VF.ProposedIntent.Resolv do alias Zenflows.VF.ProposedIntent.Domain -def published_in(prop_int, _, _) do - prop_int = Domain.preload(prop_int, :published_in) - {:ok, prop_int.published_in} -end - -def publishes(prop_int, _, _) do - prop_int = Domain.preload(prop_int, :publishes) - {:ok, prop_int.publishes} -end - def propose_intent(params, _) do with {:ok, prop_int} <- Domain.create(params) do {:ok, %{proposed_intent: prop_int}} @@ -41,4 +31,14 @@ def delete_proposed_intent(%{id: id}, _) do {:ok, true} end end + +def published_in(prop_int, _, _) do + prop_int = Domain.preload(prop_int, :published_in) + {:ok, prop_int.published_in} +end + +def publishes(prop_int, _, _) do + prop_int = Domain.preload(prop_int, :publishes) + {:ok, prop_int.publishes} +end end diff --git a/src/zenflows/vf/recipe_exchange/domain.ex b/src/zenflows/vf/recipe_exchange/domain.ex @@ -20,35 +20,48 @@ defmodule Zenflows.VF.RecipeExchange.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.RecipeExchange @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()) :: RecipeExchange.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(RecipeExchange, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, RecipeExchange.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(RecipeExchange, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(RecipeExchange.t()) +def all(params) do + Paging.page(RecipeExchange, params) end @spec create(params()) :: {:ok, RecipeExchange.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:rec_exch, RecipeExchange.chgset(params)) + |> Multi.insert(:insert, RecipeExchange.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{rec_exch: re}} -> {:ok, re} + {:ok, %{insert: re}} -> {:ok, re} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, RecipeExchange.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, RecipeExchange.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &RecipeExchange.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &RecipeExchange.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: re}} -> {:ok, re} @@ -56,27 +69,17 @@ def update(id, params) do end end -@spec delete(id()) :: {:ok, RecipeExchange.t()} | {:error, chgset()} +@spec delete(id()) + :: {:ok, RecipeExchange.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: re}} -> {:ok, re} {:error, _, msg_or_cset, _} -> {:error, msg_or_cset} end end - -# Returns a RecipeExchange 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, RecipeExchange.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - re -> {:ok, re} - end - end -end end diff --git a/src/zenflows/vf/recipe_exchange/resolv.ex b/src/zenflows/vf/recipe_exchange/resolv.ex @@ -20,23 +20,27 @@ defmodule Zenflows.VF.RecipeExchange.Resolv do alias Zenflows.VF.RecipeExchange.Domain -def recipe_exchange(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def recipe_exchange(params, _) do + Domain.one(params) end -def create_recipe_exchange(%{recipe_exchange: params}, _info) do +def recipe_exchanges(params, _) do + Domain.all(params) +end + +def create_recipe_exchange(%{recipe_exchange: params}, _) do with {:ok, rec_exch} <- Domain.create(params) do {:ok, %{recipe_exchange: rec_exch}} end end -def update_recipe_exchange(%{recipe_exchange: %{id: id} = params}, _info) do +def update_recipe_exchange(%{recipe_exchange: %{id: id} = params}, _) do with {:ok, rec_exch} <- Domain.update(id, params) do {:ok, %{recipe_exchange: rec_exch}} end end -def delete_recipe_exchange(%{id: id}, _info) do +def delete_recipe_exchange(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end diff --git a/src/zenflows/vf/recipe_exchange/type.ex b/src/zenflows/vf/recipe_exchange/type.ex @@ -39,10 +39,6 @@ object :recipe_exchange do field :note, :string end -object :recipe_exchange_response do - field :recipe_exchange, non_null(:recipe_exchange) -end - input_object :recipe_exchange_create_params do @desc @name field :name, non_null(:string) @@ -61,11 +57,33 @@ input_object :recipe_exchange_update_params do field :note, :string end +object :recipe_exchange_response do + field :recipe_exchange, non_null(:recipe_exchange) +end + +object :recipe_exchange_edge do + field :cursor, non_null(:id) + field :node, non_null(:recipe_exchange) +end + +object :recipe_exchange_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:recipe_exchange_edge))) +end + object :query_recipe_exchange do field :recipe_exchange, :recipe_exchange do arg :id, non_null(:id) resolve &Resolv.recipe_exchange/2 end + + field :recipe_exchanges, :recipe_exchange_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.recipe_exchanges/2 + end end object :mutation_recipe_exchange do diff --git a/src/zenflows/vf/recipe_flow/domain.ex b/src/zenflows/vf/recipe_flow/domain.ex @@ -20,6 +20,7 @@ defmodule Zenflows.VF.RecipeFlow.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.{ Action, Measure, @@ -28,31 +29,43 @@ alias Zenflows.VF.{ @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()) :: RecipeFlow.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(RecipeFlow, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, RecipeFlow.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(RecipeFlow, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(RecipeFlow.t()) +def all(params) do + Paging.page(RecipeFlow, params) end @spec create(params()) :: {:ok, RecipeFlow.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:rec_flow, RecipeFlow.chgset(params)) + |> Multi.insert(:insert, RecipeFlow.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{rec_flow: rf}} -> {:ok, rf} + {:ok, %{insert: rf}} -> {:ok, rf} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, RecipeFlow.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, RecipeFlow.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &RecipeFlow.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &RecipeFlow.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: rf}} -> {:ok, rf} @@ -60,11 +73,12 @@ def update(id, params) do end end -@spec delete(id()) :: {:ok, RecipeFlow.t()} | {:error, chgset()} +@spec delete(id()) :: {:ok, RecipeFlow.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: rf}} -> {:ok, rf} @@ -103,16 +117,4 @@ end def preload(rec_flow, :recipe_clause_of) do Repo.preload(rec_flow, :recipe_clause_of) end - -# Returns a RecipeFlow 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, RecipeFlow.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - rf -> {:ok, rf} - end - end -end end diff --git a/src/zenflows/vf/recipe_flow/resolv.ex b/src/zenflows/vf/recipe_flow/resolv.ex @@ -20,64 +20,65 @@ defmodule Zenflows.VF.RecipeFlow.Resolv do use Absinthe.Schema.Notation -alias Zenflows.VF.{ - RecipeFlow, - RecipeFlow.Domain, -} +alias Zenflows.VF.RecipeFlow.Domain -def recipe_flow(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def recipe_flow(params, _) do + Domain.one(params) end -def create_recipe_flow(%{recipe_flow: params}, _info) do +def recipe_flows(params, _) do + Domain.all(params) +end + +def create_recipe_flow(%{recipe_flow: params}, _) do with {:ok, rec_flow} <- Domain.create(params) do {:ok, %{recipe_flow: rec_flow}} end end -def update_recipe_flow(%{recipe_flow: %{id: id} = params}, _info) do +def update_recipe_flow(%{recipe_flow: %{id: id} = params}, _) do with {:ok, rec_flow} <- Domain.update(id, params) do {:ok, %{recipe_flow: rec_flow}} end end -def delete_recipe_flow(%{id: id}, _info) do +def delete_recipe_flow(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end end -def resource_quantity(%RecipeFlow{} = rec_flow, _args, _info) do +def resource_quantity(rec_flow, _, _) do rec_flow = Domain.preload(rec_flow, :resource_quantity) {:ok, rec_flow.resource_quantity} end -def effort_quantity(%RecipeFlow{} = rec_flow, _args, _info) do +def effort_quantity(rec_flow, _, _) do rec_flow = Domain.preload(rec_flow, :effort_quantity) {:ok, rec_flow.effort_quantity} end -def recipe_flow_resource(%RecipeFlow{} = rec_flow, _args, _info) do +def recipe_flow_resource(rec_flow, _, _) do rec_flow = Domain.preload(rec_flow, :recipe_flow_resource) {:ok, rec_flow.recipe_flow_resource} end -def action(%RecipeFlow{} = rec_flow, _args, _info) do +def action(rec_flow, _, _) do rec_flow = Domain.preload(rec_flow, :action) {:ok, rec_flow.action} end -def recipe_input_of(%RecipeFlow{} = rec_flow, _args, _info) do +def recipe_input_of(rec_flow, _, _) do rec_flow = Domain.preload(rec_flow, :recipe_input_of) {:ok, rec_flow.recipe_input_of} end -def recipe_output_of(%RecipeFlow{} = rec_flow, _args, _info) do +def recipe_output_of(rec_flow, _, _) do rec_flow = Domain.preload(rec_flow, :recipe_output_of) {:ok, rec_flow.recipe_output_of} end -def recipe_clause_of(%RecipeFlow{} = rec_flow, _args, _info) do +def recipe_clause_of(rec_flow, _, _) do rec_flow = Domain.preload(rec_flow, :recipe_clause_of) {:ok, rec_flow.recipe_clause_of} end diff --git a/src/zenflows/vf/recipe_flow/type.ex b/src/zenflows/vf/recipe_flow/type.ex @@ -33,13 +33,18 @@ or other measures of effort or usefulness. @recipe_flow_resource """ The resource definition referenced by this flow in the recipe. """ +@recipe_flow_resource_id "(`RecipeResource`) #{@recipe_flow_resource}" @action """ Relates a process input or output to a verb, such as consume, produce, work, modify, etc. """ +@action_id "(`Action`) #{@action}" @recipe_input_of "Relates an input flow to its process in a recipe." +@recipe_input_of_id "(`RecipeProcess`) #{@recipe_input_of}" @recipe_output_of "Relates an output flow to its process in a recipe." +@recipe_output_of_id "(`RecipeProcess`) #{@recipe_output_of}" @recipe_clause_of "Relates a flow to its exchange agreement in a recipe." +@recipe_clause_of_id "(`RecipeExchange`) #{@recipe_clause_of}" @note "A textual description or comment." @desc """ @@ -80,10 +85,6 @@ object :recipe_flow do field :note, :string end -object :recipe_flow_response do - field :recipe_flow, non_null(:recipe_flow) -end - input_object :recipe_flow_create_params do @desc @resource_quantity field :resource_quantity, :imeasure @@ -91,32 +92,20 @@ input_object :recipe_flow_create_params do @desc @effort_quantity field :effort_quantity, :imeasure - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`RecipeResource`) " <> @recipe_flow_resource + @desc @recipe_flow_resource_id field :recipe_flow_resource_id, non_null(:id), name: "recipe_flow_resource" - @desc "(`Action`) " <> @action + @desc @action_id field :action_id, non_null(:string), name: "action" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`RecipeProcess`) " <> @recipe_input_of + @desc @recipe_input_of_id field :recipe_input_of_id, :id, name: "recipe_input_of" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`RecipeProcess`) " <> @recipe_output_of + @desc @recipe_output_of_id field :recipe_output_of_id, :id, name: "recipe_output_of" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`RecipeExchange`) " <> @recipe_clause_of + @desc @recipe_clause_of_id field :recipe_clause_of_id, :id, name: "recipe_clause_of" @desc @note @@ -132,44 +121,52 @@ input_object :recipe_flow_update_params do @desc @effort_quantity field :effort_quantity, :imeasure - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`RecipeResource`) " <> @recipe_flow_resource + @desc @recipe_flow_resource_id field :recipe_flow_resource_id, :id, name: "recipe_flow_resource" - @desc "(`Action`) " <> @action + @desc @action_id field :action_id, :string, name: "action" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`RecipeProcess`) " <> @recipe_input_of + @desc @recipe_input_of_id field :recipe_input_of_id, :id, name: "recipe_input_of" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`RecipeProcess`) " <> @recipe_output_of + @desc @recipe_output_of_id field :recipe_output_of_id, :id, name: "recipe_output_of" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`RecipeExchange`) " <> @recipe_clause_of + @desc @recipe_clause_of_id field :recipe_clause_of_id, :id, name: "recipe_clause_of" @desc @note field :note, :string end +object :recipe_flow_response do + field :recipe_flow, non_null(:recipe_flow) +end + +object :recipe_flow_edge do + field :cursor, non_null(:id) + field :node, non_null(:recipe_flow) +end + +object :recipe_flow_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:recipe_flow_edge))) +end + object :query_recipe_flow do field :recipe_flow, :recipe_flow do arg :id, non_null(:id) resolve &Resolv.recipe_flow/2 end - #recipeFlow(start: ID, limit: Int): [RecipeFlow!] + field :recipe_flows, :recipe_flow_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.recipe_flows/2 + end end object :mutation_recipe_flow do 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/src/zenflows/vf/recipe_resource/domain.ex b/src/zenflows/vf/recipe_resource/domain.ex @@ -20,35 +20,48 @@ defmodule Zenflows.VF.RecipeResource.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.RecipeResource @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()) :: RecipeResource.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(RecipeResource, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, RecipeResource.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(RecipeResource, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(RecipeResource.t()) +def all(params) do + Paging.page(RecipeResource, params) end @spec create(params()) :: {:ok, RecipeResource.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:rec_res, RecipeResource.chgset(params)) + |> Multi.insert(:insert, RecipeResource.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{rec_res: rr}} -> {:ok, rr} + {:ok, %{insert: rr}} -> {:ok, rr} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, RecipeResource.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, RecipeResource.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &RecipeResource.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &RecipeResource.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: rr}} -> {:ok, rr} @@ -56,11 +69,13 @@ def update(id, params) do end end -@spec delete(id()) :: {:ok, RecipeResource.t()} | {:error, chgset()} +@spec delete(id()) + :: {:ok, RecipeResource.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: rr}} -> {:ok, rr} @@ -81,16 +96,4 @@ end def preload(rec_res, :resource_conforms_to) do Repo.preload(rec_res, :resource_conforms_to) end - -# Returns a RecipeResource 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, RecipeResource.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - rr -> {:ok, rr} - end - end -end end diff --git a/src/zenflows/vf/recipe_resource/resolv.ex b/src/zenflows/vf/recipe_resource/resolv.ex @@ -18,44 +18,45 @@ defmodule Zenflows.VF.RecipeResource.Resolv do @moduledoc "Resolvers of RecipeResources." -alias Zenflows.VF.{ - RecipeResource, - RecipeResource.Domain, -} +alias Zenflows.VF.RecipeResource.Domain -def recipe_resource(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def recipe_resource(params, _) do + Domain.one(params) end -def create_recipe_resource(%{recipe_resource: params}, _info) do +def recipe_resources(params, _) do + Domain.all(params) +end + +def create_recipe_resource(%{recipe_resource: params}, _) do with {:ok, proc_spec} <- Domain.create(params) do {:ok, %{recipe_resource: proc_spec}} end end -def update_recipe_resource(%{recipe_resource: %{id: id} = params}, _info) do +def update_recipe_resource(%{recipe_resource: %{id: id} = params}, _) do with {:ok, proc_spec} <- Domain.update(id, params) do {:ok, %{recipe_resource: proc_spec}} end end -def delete_recipe_resource(%{id: id}, _info) do +def delete_recipe_resource(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end end -def unit_of_resource(%RecipeResource{} = rec_res, _args, _info) do +def unit_of_resource(rec_res, _, _) do rec_res = Domain.preload(rec_res, :unit_of_resource) {:ok, rec_res.unit_of_resource} end -def unit_of_effort(%RecipeResource{} = rec_res, _args, _info) do +def unit_of_effort(rec_res, _, _) do rec_res = Domain.preload(rec_res, :unit_of_effort) {:ok, rec_res.unit_of_effort} end -def resource_conforms_to(%RecipeResource{} = rec_res, _args, _info) do +def resource_conforms_to(rec_res, _, _) do rec_res = Domain.preload(rec_res, :resource_conforms_to) {:ok, rec_res.resource_conforms_to} end diff --git a/src/zenflows/vf/recipe_resource/type.ex b/src/zenflows/vf/recipe_resource/type.ex @@ -32,16 +32,19 @@ The base64-encoded image binary relevant to the entity, such as a photo, diagram @unit_of_resource """ The unit of inventory used for this resource in the recipe. """ +@unit_of_resource_id "(`Unit`) #{@unit_of_resource}" @unit_of_effort """ The unit used for use action on this resource or work action in the recipe. """ +@unit_of_effort_id "(`Unit`) #{@unit_of_resource}" @note "A textual description or comment." @resource_conforms_to """ The primary resource specification or definition of an existing or potential economic resource. A resource will have only one, as this specifies exactly what the resource is. """ +@resource_conforms_to_id "(`ResourceSpecification`) #{@resource_conforms_to}" @resource_classified_as """ References a concept in a common taxonomy or other classification scheme for purposes of categorization or grouping. @@ -86,21 +89,14 @@ object :recipe_resource do field :substitutable, non_null(:boolean) end -object :recipe_resource_response do - field :recipe_resource, non_null(:recipe_resource) -end - input_object :recipe_resource_create_params do @desc @name field :name, non_null(:string) - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`Unit`) " <> @unit_of_resource + @desc @unit_of_resource_id field :unit_of_resource_id, :id, name: "unit_of_resource" - @desc "(`Unit`) " <> @unit_of_effort + @desc @unit_of_effort_id field :unit_of_effort_id, :id, name: "unit_of_effort" @desc @image @@ -109,7 +105,7 @@ input_object :recipe_resource_create_params do @desc @note field :note, :string - @desc "(`ResourceSpecification`) " <> @resource_conforms_to + @desc @resource_conforms_to_id field :resource_conforms_to_id, :id, name: "resource_conforms_to" @desc @resource_classified_as @@ -125,10 +121,10 @@ input_object :recipe_resource_update_params do @desc @name field :name, :string - @desc "(`Unit`) " <> @unit_of_resource + @desc @unit_of_resource_id field :unit_of_resource_id, :id, name: "unit_of_resource" - @desc "(`Unit`) " <> @unit_of_effort + @desc @unit_of_effort_id field :unit_of_effort_id, :id, name: "unit_of_effort" @desc @image @@ -137,7 +133,7 @@ input_object :recipe_resource_update_params do @desc @note field :note, :string - @desc "(`ResourceSpecification`) " <> @resource_conforms_to + @desc @resource_conforms_to_id field :resource_conforms_to_id, :id, name: "resource_conforms_to" @desc @resource_classified_as @@ -147,13 +143,33 @@ input_object :recipe_resource_update_params do field :substitutable, :boolean end +object :recipe_resource_response do + field :recipe_resource, non_null(:recipe_resource) +end + +object :recipe_resource_edge do + field :cursor, non_null(:id) + field :node, non_null(:recipe_resource) +end + +object :recipe_resource_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:recipe_resource_edge))) +end + object :query_recipe_resource do field :recipe_resource, :recipe_resource do arg :id, non_null(:id) resolve &Resolv.recipe_resource/2 end - #recipeResources(start: ID, limit: Int): [RecipeResource!] + field :recipe_resources, :recipe_resource_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.recipe_resources/2 + end end object :mutation_recipe_resource do diff --git a/src/zenflows/vf/resource_specification/domain.ex b/src/zenflows/vf/resource_specification/domain.ex @@ -20,6 +20,7 @@ defmodule Zenflows.VF.ResourceSpecification.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.ResourceSpecification @typep repo() :: Ecto.Repo.t() @@ -27,21 +28,24 @@ alias Zenflows.VF.ResourceSpecification @typep id() :: Zenflows.DB.Schema.id() @typep params() :: Zenflows.DB.Schema.params() -@spec one(repo(), id()) :: {:ok, ResourceSpecification.t()} | {:error, String.t()} -def one(repo \\ Repo, id) do - one_by(repo, id: id) -end - -@spec one_by(repo(), map() | Keyword.t()) +@spec one(repo(), id() | map() | Keyword.t()) :: {:ok, ResourceSpecification.t()} | {:error, String.t()} -def one_by(repo \\ Repo, clauses) do +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(ResourceSpecification, clauses) do nil -> {:error, "not found"} found -> {:ok, found} end end -@spec create(repo(), params()) :: {:ok, ResourceSpecification.t()} | {:error, chgset()} +@spec all(Paging.params()) :: Paging.result(ResourceSpecification.t()) +def all(params) do + Paging.page(ResourceSpecification, params) +end + +@spec create(repo(), params()) + :: {:ok, ResourceSpecification.t()} | {:error, chgset()} def create(repo \\ Repo, params) do Multi.new() |> Multi.insert(:insert, ResourceSpecification.chgset(params)) @@ -57,7 +61,7 @@ end def update(id, params) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) + |> Multi.run(:one, &one/2) |> Multi.update(:update, &ResourceSpecification.chgset(&1.one, params)) |> Repo.transaction() |> case do @@ -71,8 +75,8 @@ end def delete(id) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) - |> Multi.delete(:delete, &(&1.one)) + |> Multi.run(:one, &one/2) + |> Multi.delete(:delete, & &1.one) |> Repo.transaction() |> case do {:ok, %{delete: rs}} -> {:ok, rs} diff --git a/src/zenflows/vf/resource_specification/resolv.ex b/src/zenflows/vf/resource_specification/resolv.ex @@ -18,39 +18,40 @@ defmodule Zenflows.VF.ResourceSpecification.Resolv do @moduledoc "Resolvers of ResourceSpecifications." -alias Zenflows.VF.{ - ResourceSpecification, - ResourceSpecification.Domain, -} +alias Zenflows.VF.ResourceSpecification.Domain -def resource_specification(%{id: id}, _info) do - Domain.one(id) +def resource_specification(params, _) do + Domain.one(params) end -def create_resource_specification(%{resource_specification: params}, _info) do +def resource_specifications(params, _) do + Domain.all(params) +end + +def create_resource_specification(%{resource_specification: params}, _) do with {:ok, proc_spec} <- Domain.create(params) do {:ok, %{resource_specification: proc_spec}} end end -def update_resource_specification(%{resource_specification: %{id: id} = params}, _info) do +def update_resource_specification(%{resource_specification: %{id: id} = params}, _) do with {:ok, proc_spec} <- Domain.update(id, params) do {:ok, %{resource_specification: proc_spec}} end end -def delete_resource_specification(%{id: id}, _info) do +def delete_resource_specification(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end end -def default_unit_of_resource(%ResourceSpecification{} = res_spec, _args, _info) do +def default_unit_of_resource(res_spec, _, _) do res_spec = Domain.preload(res_spec, :default_unit_of_resource) {:ok, res_spec.default_unit_of_resource} end -def default_unit_of_effort(%ResourceSpecification{} = res_spec, _args, _info) do +def default_unit_of_effort(res_spec, _, _) do res_spec = Domain.preload(res_spec, :default_unit_of_effort) {:ok, res_spec.default_unit_of_effort} end diff --git a/src/zenflows/vf/resource_specification/type.ex b/src/zenflows/vf/resource_specification/type.ex @@ -35,7 +35,9 @@ References a concept in a common taxonomy or other classification scheme for purposes of categorization or grouping. """ @default_unit_of_resource "The default unit used for the resource itself." +@default_unit_of_resource_id "(`Unit`) #{@default_unit_of_resource}" @default_unit_of_effort "The default unit used for use or work." +@default_unit_of_effort_id "(`Unit`) #{@default_unit_of_effort}" @note "A textual description or comment." @desc """ @@ -67,10 +69,6 @@ object :resource_specification do resolve: &Resolv.default_unit_of_effort/3 end -object :resource_specification_response do - field :resource_specification, non_null(:resource_specification) -end - input_object :resource_specification_create_params do @desc @name field :name, non_null(:string) @@ -84,13 +82,10 @@ input_object :resource_specification_create_params do @desc @note field :note, :string - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc @default_unit_of_resource + @desc @default_unit_of_resource_id field :default_unit_of_resource_id, :id, name: "default_unit_of_resource" - @desc @default_unit_of_effort + @desc @default_unit_of_effort_id field :default_unit_of_effort_id, :id, name: "default_unit_of_effort" end @@ -109,20 +104,40 @@ input_object :resource_specification_update_params do @desc @note field :note, :string - @desc @default_unit_of_resource + @desc @default_unit_of_resource_id field :default_unit_of_resource_id, :id, name: "default_unit_of_resource" - @desc @default_unit_of_effort + @desc @default_unit_of_effort_id field :default_unit_of_effort_id, :id, name: "default_unit_of_effort" end +object :resource_specification_response do + field :resource_specification, non_null(:resource_specification) +end + +object :resource_specification_edge do + field :cursor, non_null(:id) + field :node, non_null(:resource_specification) +end + +object :resource_specification_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:resource_specification_edge))) +end + object :query_resource_specification do field :resource_specification, :resource_specification do arg :id, non_null(:id) resolve &Resolv.resource_specification/2 end - #resourceSpecifications(start: ID, limit: Int): [ResourceSpecification!] + field :resource_specifications, :resource_specification_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.resource_specifications/2 + end end object :mutation_resource_specification do diff --git a/src/zenflows/vf/role_behavior/domain.ex b/src/zenflows/vf/role_behavior/domain.ex @@ -20,35 +20,48 @@ defmodule Zenflows.VF.RoleBehavior.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.RoleBehavior @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()) :: RoleBehavior.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(RoleBehavior, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, RoleBehavior.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(RoleBehavior, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(RoleBehavior.t()) +def all(params) do + Paging.page(RoleBehavior, params) end @spec create(params()) :: {:ok, RoleBehavior.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:role_beh, RoleBehavior.chgset(params)) + |> Multi.insert(:insert, RoleBehavior.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{role_beh: rb}} -> {:ok, rb} + {:ok, %{insert: rb}} -> {:ok, rb} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, RoleBehavior.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, RoleBehavior.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &RoleBehavior.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &RoleBehavior.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: rb}} -> {:ok, rb} @@ -59,24 +72,13 @@ end @spec delete(id()) :: {:ok, RoleBehavior.t()} | {:error, 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: rb}} -> {:ok, rb} {:error, _, msg_or_cset, _} -> {:error, msg_or_cset} end end - -# Returns a RoleBehavior 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, RoleBehavior.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - rb -> {:ok, rb} - end - end -end end diff --git a/src/zenflows/vf/role_behavior/resolv.ex b/src/zenflows/vf/role_behavior/resolv.ex @@ -20,8 +20,12 @@ defmodule Zenflows.VF.RoleBehavior.Resolv do alias Zenflows.VF.RoleBehavior.Domain -def role_behavior(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def role_behavior(params, _info) do + Domain.one(params) +end + +def role_behaviors(params, _info) do + Domain.all(params) end def create_role_behavior(%{role_behavior: params}, _info) do diff --git a/src/zenflows/vf/role_behavior/type.ex b/src/zenflows/vf/role_behavior/type.ex @@ -41,10 +41,6 @@ object :role_behavior do field :note, :string end -object :role_behavior_response do - field :role_behavior, non_null(:role_behavior) -end - input_object :role_behavior_create_params do @desc @name field :name, non_null(:string) @@ -63,11 +59,33 @@ input_object :role_behavior_update_params do field :note, :string end +object :role_behavior_response do + field :role_behavior, non_null(:role_behavior) +end + +object :role_behavior_edge do + field :cursor, non_null(:id) + field :node, non_null(:role_behavior) +end + +object :role_behavior_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:role_behavior_edge))) +end + object :query_role_behavior do field :role_behavior, :role_behavior do arg :id, non_null(:id) resolve &Resolv.role_behavior/2 end + + field :role_behaviors, :role_behavior_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.role_behaviors/2 + end end object :mutation_role_behavior do diff --git a/src/zenflows/vf/scenario/domain.ex b/src/zenflows/vf/scenario/domain.ex @@ -20,17 +20,28 @@ defmodule Zenflows.VF.Scenario.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.Scenario @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()) :: Scenario.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(Scenario, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, Scenario.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(Scenario, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(Scenario.t()) +def all(params) do + Paging.page(Scenario, params) end @spec create(params()) :: {:ok, Scenario.t()} | {:error, chgset()} @@ -44,11 +55,13 @@ def create(params) do end end -@spec update(id(), params()) :: {:ok, Scenario.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, Scenario.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &Scenario.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &Scenario.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: s}} -> {:ok, s} @@ -56,11 +69,12 @@ def update(id, params) do end end -@spec delete(id()) :: {:ok, Scenario.t()} | {:error, chgset()} +@spec delete(id()) :: {:ok, Scenario.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: s}} -> {:ok, s} @@ -76,17 +90,4 @@ end def preload(scen, :refinement_of) do Repo.preload(scen, :refinement_of) end - -# Returns a Scenario 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, Scenario.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - s -> {:ok, s} - end - end -end end diff --git a/src/zenflows/vf/scenario/resolv.ex b/src/zenflows/vf/scenario/resolv.ex @@ -20,36 +20,40 @@ defmodule Zenflows.VF.Scenario.Resolv do use Absinthe.Schema.Notation -alias Zenflows.VF.{Scenario, Scenario.Domain} +alias Zenflows.VF.Scenario.Domain -def scenario(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def scenario(params, _) do + Domain.one(params) end -def create_scenario(%{scenario: params}, _info) do +def scenarios(params, _) do + Domain.all(params) +end + +def create_scenario(%{scenario: params}, _) do with {:ok, scen} <- Domain.create(params) do {:ok, %{scenario: scen}} end end -def update_scenario(%{scenario: %{id: id} = params}, _info) do +def update_scenario(%{scenario: %{id: id} = params}, _) do with {:ok, scen} <- Domain.update(id, params) do {:ok, %{scenario: scen}} end end -def delete_scenario(%{id: id}, _info) do +def delete_scenario(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end end -def defined_as(%Scenario{} = scen, _args, _info) do +def defined_as(scen, _, _) do scenario = Domain.preload(scen, :defined_as) {:ok, scenario.defined_as} end -def refinement_of(%Scenario{} = scen, _args, _info) do +def refinement_of(scen, _, _) do scenario = Domain.preload(scen, :refinement_of) {:ok, scenario.refinement_of} end diff --git a/src/zenflows/vf/scenario/type.ex b/src/zenflows/vf/scenario/type.ex @@ -38,10 +38,12 @@ period. @defined_as """ The scenario definition for this scenario, for example yearly budget. """ +@defined_as_id "(`ScenarioDefinition`) #{@defined_as}" @refinement_of """ This scenario refines another scenario, often as time moves closer or for more detail. """ +@refinement_of_id "(`Scenario`) #{@refinement_of}" @desc """ An estimated or analytical logical collection of higher level processes @@ -70,10 +72,6 @@ object :scenario do field :refinement_of, :scenario, resolve: &Resolv.refinement_of/3 end -object :scenario_response do - field :scenario, non_null(:scenario) -end - input_object :scenario_create_params do @desc @name field :name, non_null(:string) @@ -87,16 +85,10 @@ input_object :scenario_create_params do @desc @has_end field :has_end, :datetime - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`ScenarioDefinition`) " <> @defined_as + @desc @defined_as_id field :defined_as_id, :id, name: "defined_as" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`Scenario`) " <> @refinement_of + @desc @refinement_of_id field :refinement_of_id, :id, name: "refinement_of" end @@ -115,26 +107,40 @@ input_object :scenario_update_params do @desc @has_end field :has_end, :datetime - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`ScenarioDefinition`) " <> @defined_as + @desc @defined_as_id field :defined_as_id, :id, name: "defined_as" - # TODO: When - # https://github.com/absinthe-graphql/absinthe/issues/1126 results, - # apply the correct changes if any. - @desc "(`Scenario`) " <> @refinement_of + @desc @refinement_of_id field :refinement_of_id, :id, name: "refinement_of" end +object :scenario_response do + field :scenario, non_null(:scenario) +end + +object :scenario_edge do + field :cursor, non_null(:id) + field :node, non_null(:scenario) +end + +object :scenario_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:scenario_edge))) +end + object :query_scenario do field :scenario, :scenario do arg :id, non_null(:id) resolve &Resolv.scenario/2 end - #scenarioDefinitions(start: ID, limit: Int): [Scenario!] + field :scenarios, :scenario_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.scenarios/2 + end end object :mutation_scenario do diff --git a/src/zenflows/vf/scenario_definition/domain.ex b/src/zenflows/vf/scenario_definition/domain.ex @@ -20,35 +20,48 @@ defmodule Zenflows.VF.ScenarioDefinition.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.{Duration, ScenarioDefinition} @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()) :: ScenarioDefinition.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(ScenarioDefinition, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, ScenarioDefinition.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(ScenarioDefinition, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(ScenarioDefinition.t()) +def all(params) do + Paging.page(ScenarioDefinition, params) end @spec create(params()) :: {:ok, ScenarioDefinition.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:scen_def, ScenarioDefinition.chgset(params)) + |> Multi.insert(:insert, ScenarioDefinition.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{scen_def: sd}} -> {:ok, sd} + {:ok, %{insert: sd}} -> {:ok, sd} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, ScenarioDefinition.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, ScenarioDefinition.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &ScenarioDefinition.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &ScenarioDefinition.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: sd}} -> {:ok, sd} @@ -56,11 +69,13 @@ def update(id, params) do end end -@spec delete(id()) :: {:ok, ScenarioDefinition.t()} | {:error, chgset()} +@spec delete(id()) + :: {:ok, ScenarioDefinition.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: sd}} -> {:ok, sd} @@ -72,17 +87,4 @@ end def preload(scen_def, :has_duration) do Duration.preload(scen_def, :has_duration) end - -# Returns a ScenarioDefinition 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, ScenarioDefinition.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - sd -> {:ok, sd} - end - end -end end diff --git a/src/zenflows/vf/scenario_definition/resolv.ex b/src/zenflows/vf/scenario_definition/resolv.ex @@ -20,31 +20,35 @@ defmodule Zenflows.VF.ScenarioDefinition.Resolv do use Absinthe.Schema.Notation -alias Zenflows.VF.{ScenarioDefinition, ScenarioDefinition.Domain} +alias Zenflows.VF.ScenarioDefinition.Domain -def scenario_definition(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def scenario_definition(params, _) do + Domain.one(params) end -def create_scenario_definition(%{scenario_definition: params}, _info) do +def scenario_definitions(params, _) do + Domain.all(params) +end + +def create_scenario_definition(%{scenario_definition: params}, _) do with {:ok, scen_def} <- Domain.create(params) do {:ok, %{scenario_definition: scen_def}} end end -def update_scenario_definition(%{scenario_definition: %{id: id} = params}, _info) do +def update_scenario_definition(%{scenario_definition: %{id: id} = params}, _) do with {:ok, scen_def} <- Domain.update(id, params) do {:ok, %{scenario_definition: scen_def}} end end -def delete_scenario_definition(%{id: id}, _info) do +def delete_scenario_definition(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end end -def has_duration(%ScenarioDefinition{} = scen_def, _args, _info) do +def has_duration(scen_def, _, _) do scen_def = Domain.preload(scen_def, :has_duration) {:ok, scen_def.has_duration} end diff --git a/src/zenflows/vf/scenario_definition/type.ex b/src/zenflows/vf/scenario_definition/type.ex @@ -46,10 +46,6 @@ object :scenario_definition do field :note, :string end -object :scenario_definition_response do - field :scenario_definition, non_null(:scenario_definition) -end - input_object :scenario_definition_create_params do @desc @name field :name, non_null(:string) @@ -74,13 +70,33 @@ input_object :scenario_definition_update_params do field :has_duration, :iduration end +object :scenario_definition_response do + field :scenario_definition, non_null(:scenario_definition) +end + +object :scenario_definition_edge do + field :cursor, non_null(:id) + field :node, non_null(:scenario_definition) +end + +object :scenario_definition_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:scenario_definition_edge))) +end + object :query_scenario_definition do field :scenario_definition, :scenario_definition do arg :id, non_null(:id) resolve &Resolv.scenario_definition/2 end - #scenarioDefinitions(start: ID, limit: Int): [ScenarioDefinition!] + field :scenario_definitions, :scenario_definition_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.scenario_definitions/2 + end end object :mutation_scenario_definition do diff --git a/src/zenflows/vf/spatial_thing/domain.ex b/src/zenflows/vf/spatial_thing/domain.ex @@ -21,35 +21,48 @@ defmodule Zenflows.VF.SpatialThing.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.SpatialThing @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()) :: SpatialThing.t() | nil -def by_id(repo \\ Repo, id) do - repo.get(SpatialThing, id) +@spec one(repo(), id() | map() | Keyword.t()) + :: {:ok, SpatialThing.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(SpatialThing, clauses) do + nil -> {:error, "not found"} + found -> {:ok, found} + end +end + +@spec all(Paging.params()) :: Paging.result(SpatialThing.t()) +def all(params) do + Paging.page(SpatialThing, params) end @spec create(params()) :: {:ok, SpatialThing.t()} | {:error, chgset()} def create(params) do Multi.new() - |> Multi.insert(:spt_thg, SpatialThing.chgset(params)) + |> Multi.insert(:insert, SpatialThing.chgset(params)) |> Repo.transaction() |> case do - {:ok, %{spt_thg: st}} -> {:ok, st} + {:ok, %{insert: st}} -> {:ok, st} {:error, _, cset, _} -> {:error, cset} end end -@spec update(id(), params()) :: {:ok, SpatialThing.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, SpatialThing.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() - |> Multi.run(:get, multi_get(id)) - |> Multi.update(:update, &SpatialThing.chgset(&1.get, params)) + |> Multi.put(:id, id) + |> Multi.run(:one, &one/2) + |> Multi.update(:update, &SpatialThing.chgset(&1.one, params)) |> Repo.transaction() |> case do {:ok, %{update: st}} -> {:ok, st} @@ -57,27 +70,16 @@ def update(id, params) do end end -@spec delete(id()) :: {:ok, SpatialThing.t()} | {:error, chgset()} +@spec delete(id()) :: {:ok, SpatialThing.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: st}} -> {:ok, st} {:error, _, msg_or_cset, _} -> {:error, msg_or_cset} end end - -# Returns a SpatialThing 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, SpatialThing.t()} | {:error, String.t()}) -defp multi_get(id) do - fn repo, _ -> - case by_id(repo, id) do - nil -> {:error, "not found"} - st -> {:ok, st} - end - end -end end diff --git a/src/zenflows/vf/spatial_thing/resolv.ex b/src/zenflows/vf/spatial_thing/resolv.ex @@ -21,23 +21,27 @@ defmodule Zenflows.VF.SpatialThing.Resolv do alias Zenflows.VF.SpatialThing.Domain -def spatial_thing(%{id: id}, _info) do - {:ok, Domain.by_id(id)} +def spatial_thing(params, _) do + Domain.one(params) end -def create_spatial_thing(%{spatial_thing: params}, _info) do +def spatial_things(params, _) do + Domain.all(params) +end + +def create_spatial_thing(%{spatial_thing: params}, _) do with {:ok, spt_thg} <- Domain.create(params) do {:ok, %{spatial_thing: spt_thg}} end end -def update_spatial_thing(%{spatial_thing: %{id: id} = params}, _info) do +def update_spatial_thing(%{spatial_thing: %{id: id} = params}, _) do with {:ok, spt_thg} <- Domain.update(id, params) do {:ok, %{spatial_thing: spt_thg}} end end -def delete_spatial_thing(%{id: id}, _info) do +def delete_spatial_thing(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end diff --git a/src/zenflows/vf/spatial_thing/type.ex b/src/zenflows/vf/spatial_thing/type.ex @@ -58,10 +58,6 @@ object :spatial_thing do field :note, :string end -object :spatial_thing_response do - field :spatial_thing, non_null(:spatial_thing) -end - input_object :spatial_thing_create_params do @desc @name field :name, non_null(:string) @@ -104,13 +100,33 @@ input_object :spatial_thing_update_params do field :note, :string end +object :spatial_thing_response do + field :spatial_thing, non_null(:spatial_thing) +end + +object :spatial_thing_edge do + field :cursor, non_null(:id) + field :node, non_null(:spatial_thing) +end + +object :spatial_thing_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:spatial_thing_edge))) +end + object :query_spatial_thing do field :spatial_thing, :spatial_thing do arg :id, non_null(:id) resolve &Resolv.spatial_thing/2 end - #spatialThings(start: ID, limit: Int): [SpatialThing!] + field :spatial_things, :spatial_thing_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.spatial_things/2 + end end object :mutation_spatial_thing do diff --git a/src/zenflows/vf/unit/domain.ex b/src/zenflows/vf/unit/domain.ex @@ -20,6 +20,7 @@ defmodule Zenflows.VF.Unit.Domain do alias Ecto.Multi alias Zenflows.DB.Repo +alias Zenflows.GQL.Paging alias Zenflows.VF.Unit @typep repo() :: Ecto.Repo.t() @@ -27,20 +28,23 @@ alias Zenflows.VF.Unit @typep id() :: Zenflows.DB.Schema.id() @typep params() :: Zenflows.DB.Schema.params() -@spec one(repo(), id()) :: {:ok, Unit.t()} | {:error, String.t()} -def one(repo \\ Repo, id) do - one_by(repo, id: id) -end - -@spec one_by(repo(), map() | Keyword.t()) +@spec one(repo(), id() | map() | Keyword.t()) :: {:ok, Unit.t()} | {:error, String.t()} -def one_by(repo \\ Repo, clauses) do +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(Unit, clauses) do nil -> {:error, "not found"} found -> {:ok, found} end end +@spec all(Paging.params()) :: Paging.result(Unit.t()) +def all(params) do + Paging.page(Unit, params) +end + + # `repo` is needed since we use that in a migration script. @spec create(repo(), params()) :: {:ok, Unit.t()} | {:error, chgset()} def create(repo \\ Repo, params) do @@ -53,11 +57,12 @@ def create(repo \\ Repo, params) do end end -@spec update(id(), params()) :: {:ok, Unit.t()} | {:error, chgset()} +@spec update(id(), params()) + :: {:ok, Unit.t()} | {:error, String.t() | chgset()} def update(id, params) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) + |> Multi.run(:one, &one/2) |> Multi.update(:update, &Unit.chgset(&1.one, params)) |> Repo.transaction() |> case do @@ -66,12 +71,12 @@ def update(id, params) do end end -@spec delete(id()) :: {:ok, Unit.t()} | {:error, chgset()} +@spec delete(id()) :: {:ok, Unit.t()} | {:error, String.t() | chgset()} def delete(id) do Multi.new() |> Multi.put(:id, id) - |> Multi.run(:one, &one_by/2) - |> Multi.delete(:delete, &(&1.one)) + |> Multi.run(:one, &one/2) + |> Multi.delete(:delete, & &1.one) |> Repo.transaction() |> case do {:ok, %{delete: u}} -> {:ok, u} diff --git a/src/zenflows/vf/unit/resolv.ex b/src/zenflows/vf/unit/resolv.ex @@ -20,23 +20,27 @@ defmodule Zenflows.VF.Unit.Resolv do alias Zenflows.VF.Unit.Domain -def unit(%{id: id}, _info) do - Domain.one(id) +def unit(params, _) do + Domain.one(params) end -def create_unit(%{unit: params}, _info) do +def units(params, _) do + Domain.all(params) +end + +def create_unit(%{unit: params}, _) do with {:ok, unit} <- Domain.create(params) do {:ok, %{unit: unit}} end end -def update_unit(%{unit: %{id: id} = params}, _info) do +def update_unit(%{unit: %{id: id} = params}, _) do with {:ok, unit} <- Domain.update(id, params) do {:ok, %{unit: unit}} end end -def delete_unit(%{id: id}, _info) do +def delete_unit(%{id: id}, _) do with {:ok, _} <- Domain.delete(id) do {:ok, true} end diff --git a/src/zenflows/vf/unit/type.ex b/src/zenflows/vf/unit/type.ex @@ -39,10 +39,6 @@ object :unit do field :symbol, non_null(:string) end -object :unit_response do - field :unit, :unit -end - input_object :unit_create_params do @desc @label field :label, non_null(:string) @@ -61,13 +57,33 @@ input_object :unit_update_params do field :symbol, :string end +object :unit_response do + field :unit, non_null(:unit) +end + +object :unit_edge do + field :cursor, non_null(:id) + field :node, non_null(:unit) +end + +object :unit_connection do + field :page_info, non_null(:page_info) + field :edges, non_null(list_of(non_null(:unit_edge))) +end + object :query_unit do field :unit, :unit do arg :id, non_null(:id) resolve &Resolv.unit/2 end - #units(start: ID, limit: Int): [Unit!] + field :units, :unit_connection do + arg :first, :integer + arg :after, :id + arg :last, :integer + arg :before, :id + resolve &Resolv.units/2 + end end object :mutation_unit do diff --git a/src/zenflows/vf/validate.ex b/src/zenflows/vf/validate.ex @@ -77,7 +77,7 @@ def uri(cset, field) do end) end -@mebibyte 1024**2 +@mebibyte 1024 * 1024 @doc """ Check if the given base64-encoded binary data is at least 1B, at most diff --git a/test/gql/paging.test.exs b/test/gql/paging.test.exs @@ -0,0 +1,298 @@ +# Zenflows is designed to implement the Valueflows vocabulary, +# written and maintained by srfsh <info@dyne.org>. +# Copyright (C) 2021-2022 Dyne.org foundation <foundation@dyne.org>. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +defmodule ZenflowsTest.GQL.Paging do +use ZenflowsTest.Help.EctoCase, async: true + +# What we are testing here is a bit interesting. Because, you see, +# what we actually care about is dependant on the number of records we +# ask for (referred to by "num" from now on). This is because of we +# always try to fetch num+1 records. This basically means that we'll +# have a table of possible cases: +# +# num | len(edges) +# ----+----------- +# 0 | 0 +# 0 | 1 +# ----+----------- +# 1 | 0 +# 1 | 1 +# 1 | 2 +# ----+----------- +# 2 | 0 +# 2 | 1 +# 2 | 2 +# 2 | 3 +# ----+----------- +# 3 | 0 +# 3 | 1 +# 3 | 2 +# 3 | 3 +# 3 | 4 +# ----+----------- +# 4 | 0 +# 4 | 1 +# 4 | 2 +# 4 | 3 +# 4 | 4 +# 4 | 5 + +# Here, we cover the cases of: +# num | len(edges) +# ----+----------- +# 0 | 0 +# 1 | 0 +# 2 | 0 +# 3 | 0 +# 4 | 0 +test "num>=0 && len(edges)==0:" do + Enum.each(0..10, fn n -> + assert %{data: %{"people" => data}} = + run!(""" + query ($n: Int!) { + people (first: $n) {...people} + } + """, vars: %{"n" => n}) + + assert [] = Map.fetch!(data, "edges") + + assert %{ + "startCursor" => nil, + "endCursor" => nil, + "hasPreviousPage" => false, + "hasNextPage" => false, + "totalCount" => 0, + "pageLimit" => ^n, + } = Map.fetch!(data, "pageInfo") + end) +end + +# Here, we cover the cases of: +# num | len(edges) +# ----+----------- +# 1 | 1 +# 2 | 2 +# 3 | 3 +# 4 | 4 +test "num>=1 && len(edges)==num:" do + Enum.reduce(1..10, [], fn n, pers -> + last = %{id: last_cur} = Factory.insert!(:person) + pers = pers ++ [last] + [%{id: first_cur} | _] = pers + + assert %{data: %{"people" => data}} = + run!(""" + query ($n: Int!) { + people (first: $n) {...people} + } + """, vars: %{"n" => n}) + + edges = Map.fetch!(data, "edges") + assert length(edges) == n + + assert %{ + "startCursor" => ^first_cur, + "endCursor" => ^last_cur, + "hasPreviousPage" => false, + "hasNextPage" => false, + "totalCount" => ^n, + "pageLimit" => ^n, + } = Map.fetch!(data, "pageInfo") + + pers + end) +end + +# Here, we cover the cases of: +# num | len(edges) +# ----+----------- +# 0 | 1 +# 1 | 2 +# 2 | 3 +# 3 | 4 +# 4 | 5 +test "num>=0 && len(edges)==num+1:" do + Enum.reduce(0..10, [], fn n, pers -> + pers = pers ++ [Factory.insert!(:person)] + {tmp, _} = Enum.split(pers, n) + first = List.first(tmp) + last = List.last(tmp) + first_cur = if first != nil, do: first.id, else: nil + last_cur = if last != nil, do: last.id, else: nil + + assert %{data: %{"people" => data}} = + run!(""" + query ($n: Int!) { + people (first: $n) {...people} + } + """, vars: %{"n" => n}) + + edges = Map.fetch!(data, "edges") + assert length(edges) == n + + assert %{ + "startCursor" => ^first_cur, + "endCursor" => ^last_cur, + "hasPreviousPage" => false, + "hasNextPage" => true, + "totalCount" => ^n, + "pageLimit" => ^n, + } = Map.fetch!(data, "pageInfo") + + pers + end) +end + +# Here, we cover the last case, which prooves we cover all the cases +# (this is so because of the fact that we only deal with len(edges)<num +# cases, where num>=1): +# num | len(edges) +# ----+----------- +# 2 | 1 +# ----+----------- +# 3 | 1 +# 3 | 2 +# ----+----------- +# 4 | 1 +# 4 | 2 +# 4 | 3 +test "num>=2 && len(edges)>=0 && len(edges)<num:" do + Enum.reduce(1..9, [], fn e, pers -> + pers = pers ++ [Factory.insert!(:person)] + + Enum.each(2..10, fn n -> + if e < n do + assert %{data: %{"people" => data}} = + run!(""" + query ($n: Int!) { + people (first: $n) {...people} + } + """, vars: %{"n" => n}) + + edges = Map.fetch!(data, "edges") + assert length(edges) == e + + %{id: first_cur} = List.first(pers) + %{id: last_cur} = List.last(pers) + + assert %{ + "startCursor" => ^first_cur, + "endCursor" => ^last_cur, + "hasPreviousPage" => false, + "hasNextPage" => false, + "totalCount" => ^e, + "pageLimit" => ^n, + } = Map.fetch!(data, "pageInfo") + end + end) + + pers + end) +end + +# We're dealing with cursors here now. Most of the cases are the +# same as the ones without the cursors, so we omit them. + +# Here, we cover the cases of: +# num | len(edges) +# ----+----------- +# 1 | 1 +# 2 | 2 +# 3 | 3 +# 4 | 4 +test "with cursor: num>=1 && len(edges)==num:" do + Enum.each(1..10, fn n -> + p = Factory.insert!(:person) + + assert %{data: %{"people" => data}} = + run!(""" + query ($cur: ID! $n: Int!) { + people (after: $cur first: $n) {...people} + } + """, vars: %{"n" => n, "cur" => p.id}) + + assert [] = Map.fetch!(data, "edges") + + assert %{ + "startCursor" => nil, + "endCursor" => nil, + "hasPreviousPage" => true, # spec says so if we can't determine + "hasNextPage" => false, + "totalCount" => 0, + "pageLimit" => ^n, + } = Map.fetch!(data, "pageInfo") + end) +end + +# Here, we cover the cases of: +# num | len(edges) +# ----+----------- +# 1 | 2 +# 2 | 3 +# 3 | 4 +# 4 | 5 +test "with cursor: num>=1 && len(edges)==num+1:" do + pers = [Factory.insert!(:person)] + Enum.reduce(1..10, pers, fn n, pers -> + %{id: after_cur} = List.last(pers) + last = %{id: last_cur} = Factory.insert!(:person) + pers = pers ++ [last] + + assert %{data: %{"people" => data}} = + run!(""" + query ($cur: ID! $n: Int!) { + people (after: $cur first: $n) {...people} + } + """, vars: %{"n" => n, "cur" => after_cur}) + + assert [_] = Map.fetch!(data, "edges") + + assert %{ + "startCursor" => ^last_cur, + "endCursor" => ^last_cur, + "hasPreviousPage" => true, # spec + "hasNextPage" => false, + "totalCount" => 1, + "pageLimit" => ^n, + } = Map.fetch!(data, "pageInfo") + + pers + end) +end + +@spec run!(String.t(), Keyword.t()) :: Absinthe.run_result() +def run!(doc, opts \\ []) do + """ + #{doc} + fragment people on PersonConnection { + pageInfo { + startCursor + endCursor + hasPreviousPage + hasNextPage + totalCount + pageLimit + } + edges { + cursor + node {id} + } + } + """ + |> ZenflowsTest.Help.AbsinCase.run!(opts) +end +end diff --git a/test/help/factory.ex b/test/help/factory.ex @@ -41,15 +41,6 @@ end Returns the same string with a unique positive integer attached at the end. """ -@spec uniq(String.t()) :: String.t() -def uniq(str) do - str <> "#{System.unique_integer([:positive])}" -end - -@doc """ -Returns the same string with a unique positive integer attached at -the end. -""" @spec str(String.t()) :: String.t() def str(s) do "#{s}#{System.unique_integer([:positive])}" @@ -65,16 +56,6 @@ def str_list(s, min \\ 1, max \\ 10) do end @doc """ -Returns a list of string composed of one or ten items. Each item is -generated by piping `str` to `uniq/1` -""" -@spec uniq_list(String.t()) :: list(String.t()) -def uniq_list(str) do - max = Enum.random(1..10) - Enum.map(1..max, fn _ -> uniq(str) end) -end - -@doc """ Returns a random integer between 0 (inclusive) and `max` (exclusive). """ @spec int() :: integer() @@ -100,7 +81,7 @@ end @doc "Returns a unique URI string." @spec uri() :: String.t() def uri() do - uniq("schema://user@host:port/path") + str("schema://user@host:port/path") end @doc "Returns a unique base64 encoded string (mock-up of image data)" @@ -144,8 +125,8 @@ end def build(:unit) do %VF.Unit{ - label: uniq("some label"), - symbol: uniq("some symbol"), + label: str("some label"), + symbol: str("some symbol"), } end @@ -158,12 +139,12 @@ end def build(:spatial_thing) do %VF.SpatialThing{ - name: uniq("some name"), - mappable_address: uniq("some mappable_address"), + name: str("some name"), + mappable_address: str("some mappable_address"), lat: float(), long: float(), alt: float(), - note: uniq("some note"), + note: str("some note"), } end @@ -173,16 +154,16 @@ end def build(:process_specification) do %VF.ProcessSpecification{ - name: uniq("some name"), - note: uniq("some note"), + name: str("some name"), + note: str("some note"), } end def build(:resource_specification) do %VF.ResourceSpecification{ - name: uniq("some name"), - resource_classified_as: uniq_list("some uri"), - note: uniq("some note"), + name: str("some name"), + resource_classified_as: str_list("some uri"), + note: str("some note"), image: img(), default_unit_of_effort: build(:unit), default_unit_of_resource: build(:unit), @@ -191,13 +172,13 @@ end def build(:recipe_resource) do %VF.RecipeResource{ - name: uniq("some name"), + name: str("some name"), unit_of_resource: build(:unit), unit_of_effort: build(:unit), - resource_classified_as: uniq_list("some uri"), + resource_classified_as: str_list("some uri"), resource_conforms_to: build(:resource_specification), substitutable: bool(), - note: uniq("some note"), + note: str("some note"), image: img(), } end @@ -205,9 +186,9 @@ end def build(:recipe_process) do dur = build(:iduration) %VF.RecipeProcess{ - name: uniq("some name"), - note: uniq("some note"), - process_classified_as: uniq_list("some uri"), + name: str("some name"), + note: str("some note"), + process_classified_as: str_list("some uri"), process_conforms_to: build(:process_specification), has_duration_unit_type: dur.unit_type, has_duration_numeric_duration: dur.numeric_duration, @@ -216,8 +197,8 @@ end def build(:recipe_exchange) do %VF.RecipeExchange{ - name: uniq("some name"), - note: uniq("some note"), + name: str("some name"), + note: str("some note"), } end @@ -234,19 +215,19 @@ def build(:recipe_flow) do effort_quantity_has_unit: effqty.has_unit, effort_quantity_has_numerical_value: effqty.has_numerical_value, recipe_clause_of: build(:recipe_exchange), - note: uniq("some note"), + note: str("some note"), } end def build(:person) do %VF.Person{ type: :per, - name: uniq("some name"), + name: str("some name"), image: img(), - note: uniq("some note"), + note: str("some note"), primary_location: build(:spatial_thing), - user: uniq("some user"), - email: "#{uniq("user")}@example.com", + user: str("some user"), + email: "#{str("user")}@example.com", # Normally, these are encoded by zenroom (with whatever # encodings it chooses to use), but for testing, this'll # work alright. @@ -261,10 +242,10 @@ end def build(:organization) do %VF.Organization{ type: :org, - name: uniq("some name"), + name: str("some name"), image: img(), - classified_as: uniq_list("some uri"), - note: uniq("some note"), + classified_as: str_list("some uri"), + note: str("some note"), primary_location: build(:spatial_thing), } end @@ -276,17 +257,17 @@ end def build(:role_behavior) do %VF.RoleBehavior{ - name: uniq("some name"), - note: uniq("some note"), + name: str("some name"), + note: str("some note"), } end def build(:agent_relationship_role) do %VF.AgentRelationshipRole{ role_behavior: build(:role_behavior), - role_label: uniq("some role label"), - inverse_role_label: uniq("some role label"), - note: uniq("some note"), + role_label: str("some role label"), + inverse_role_label: str("some role label"), + note: str("some note"), } end @@ -296,22 +277,22 @@ def build(:agent_relationship) do object: build(:agent), relationship: build(:agent_relationship_role), # in_scope_of: - note: uniq("some note"), + note: str("some note"), } end def build(:agreement) do %VF.Agreement{ - name: uniq("some name"), - note: uniq("some note"), + name: str("some name"), + note: str("some note"), } end def build(:scenario_definition) do dur = build(:iduration) %VF.ScenarioDefinition{ - name: uniq("some name"), - note: uniq("some note"), + name: str("some name"), + note: str("some note"), has_duration_unit_type: dur.unit_type, has_duration_numeric_duration: dur.numeric_duration, } @@ -321,8 +302,8 @@ def build(:scenario) do recurse? = bool() %VF.Scenario{ - name: uniq("some name"), - note: uniq("some note"), + name: str("some name"), + note: str("some note"), has_beginning: now(), has_end: now(), defined_as: build(:scenario_definition), @@ -332,21 +313,21 @@ end def build(:plan) do %VF.Plan{ - name: uniq("some name"), + name: str("some name"), due: now(), - note: uniq("some note"), + note: str("some note"), refinement_of: build(:scenario), } end def build(:process) do %VF.Process{ - name: uniq("some name"), - note: uniq("some note"), + name: str("some name"), + note: str("some note"), has_beginning: now(), has_end: now(), finished: bool(), - classified_as: uniq_list("some uri"), + classified_as: str_list("some uri"), based_on: build(:process_specification), # in_scope_of: planned_within: build(:plan), @@ -356,7 +337,7 @@ end def build(:product_batch) do %VF.ProductBatch{ - batch_number: uniq("some batch number"), + batch_number: str("some batch number"), expiry_date: now(), production_date: now(), } @@ -367,11 +348,11 @@ def build(:economic_resource) do qty = build(:imeasure) %VF.EconomicResource{ - name: uniq("some name"), - note: uniq("some note"), + name: str("some name"), + note: str("some note"), image: img(), - tracking_identifier: uniq("some tracking identifier"), - classified_as: uniq_list("some uri"), + tracking_identifier: str("some tracking identifier"), + classified_as: str_list("some uri"), conforms_to: build(:resource_specification), accounting_quantity_has_unit: qty.has_unit, accounting_quantity_has_numerical_value: qty.has_numerical_value, @@ -396,7 +377,7 @@ def build(:appreciation) do %VF.Appreciation{ appreciation_of: build(:economic_event), appreciation_with: build(:economic_event), - note: uniq("some note"), + note: str("some note"), } end @@ -407,13 +388,13 @@ def build(:intent) do availqty = build(:imeasure) %VF.Intent{ - name: uniq("some name"), + name: str("some name"), action_id: build(:action_id), provider: if(agent_mutex?, do: build(:agent)), receiver: unless(agent_mutex?, do: build(:agent)), input_of: build(:process), output_of: build(:process), - resource_classified_as: uniq_list("some uri"), + resource_classified_as: str_list("some uri"), resource_conforms_to: build(:resource_specification), resource_inventoried_as: build(:economic_resource), resource_quantity_has_unit: resqty.has_unit, @@ -429,9 +410,9 @@ def build(:intent) do due: now(), finished: bool(), image: img(), - note: uniq("some note"), + note: str("some note"), # in_scope_of: - agreed_in: uniq("some uri"), + agreed_in: str("some uri"), } end @@ -447,7 +428,7 @@ def build(:commitment) do receiver: build(:agent), input_of: build(:process), output_of: build(:process), - resource_classified_as: uniq_list("some uri"), + resource_classified_as: str_list("some uri"), resource_conforms_to: if(resource_mutex?, do: build(:resource_specification)), resource_inventoried_as: unless(resource_mutex?, do: build(:economic_resource)), resource_quantity_has_unit: resqty.has_unit, @@ -459,9 +440,9 @@ def build(:commitment) do has_point_in_time: unless(datetime_mutex?, do: now()), due: now(), finished: bool(), - note: uniq("some note"), + note: str("some note"), # in_scope_of: - agreed_in: uniq("some uri"), + agreed_in: str("some uri"), independent_demand_of: build(:plan), at_location: build(:spatial_thing), clause_of: build(:agreement), @@ -473,7 +454,7 @@ def build(:fulfillment) do effqty = build(:imeasure) %VF.Fulfillment{ - note: uniq("some note"), + note: str("some note"), fulfilled_by: build(:economic_event), fulfills: build(:commitment), resource_quantity_has_unit: resqty.has_unit, @@ -503,7 +484,7 @@ def build(:satisfaction) do resource_quantity_has_numerical_value: resqty.has_numerical_value, effort_quantity_has_unit: effqty.has_unit, effort_quantity_has_numerical_value: effqty.has_numerical_value, - note: uniq("some note"), + note: str("some note"), } end @@ -515,7 +496,7 @@ def build(:claim) do action_id: build(:action_id), provider: build(:agent), receiver: build(:agent), - resource_classified_as: uniq_list("some uri"), + resource_classified_as: str_list("some uri"), resource_conforms_to: build(:resource_specification), resource_quantity_has_unit: resqty.has_unit, resource_quantity_has_numerical_value: resqty.has_numerical_value, @@ -524,8 +505,8 @@ def build(:claim) do triggered_by: if(bool(), do: build(:economic_event), else: nil), due: now(), finished: bool(), - agreed_in: uniq("some uri"), - note: uniq("some note"), + agreed_in: str("some uri"), + note: str("some note"), # in_scope_of: } end @@ -541,17 +522,17 @@ def build(:settlement) do resource_quantity_has_numerical_value: resqty.has_numerical_value, effort_quantity_has_unit: effqty.has_unit, effort_quantity_has_numerical_value: effqty.has_numerical_value, - note: uniq("some note"), + note: str("some note"), } end def build(:proposal) do %VF.Proposal{ - name: uniq("some name"), + name: str("some name"), has_beginning: now(), has_end: now(), unit_based: bool(), - note: uniq("some note"), + note: str("some note"), eligible_location: build(:spatial_thing), } end diff --git a/test/vf/agent/domain.test.exs b/test/vf/agent/domain.test.exs @@ -27,9 +27,9 @@ setup do } end -describe "by_id/1" do - test "returns a Person", %{per: per} do - agent = Domain.by_id(per.id) +describe "one/1" do + test "with per's id: finds the Person", %{per: per} do + assert {:ok, agent} = Domain.one(per.id) # common assert agent.id == per.id @@ -47,8 +47,8 @@ describe "by_id/1" do assert agent.classified_as == nil end - test "returns an Organization", %{org: org} do - agent = Domain.by_id(org.id) + test "with org's id: finds the Organization", %{org: org} do + assert {:ok, agent} = Domain.one(org.id) # common assert agent.id == org.id @@ -69,20 +69,14 @@ end describe "preload/2" do test "preloads :primary_location for a Person", %{per: per} do - agent = - per.id - |> Domain.by_id() - |> Domain.preload(:primary_location) - + {:ok, agent} = Domain.one(per.id) + agent = Domain.preload(agent, :primary_location) assert agent.primary_location.id == agent.primary_location_id end test "preloads :primary_location for an Organization", %{org: org} do - agent = - org.id - |> Domain.by_id() - |> Domain.preload(:primary_location) - + {:ok, agent} = Domain.one(org.id) + agent = Domain.preload(agent, :primary_location) assert agent.primary_location.id == agent.primary_location_id end end diff --git a/test/vf/agent_relationship/domain.test.exs b/test/vf/agent_relationship/domain.test.exs @@ -28,44 +28,47 @@ setup do object_id: Factory.insert!(:agent).id, relationship_id: Factory.insert!(:agent_relationship_role).id, # in_scope_of: - note: Factory.uniq("note"), + note: Factory.str("note"), }, - agent_relationship: Factory.insert!(:agent_relationship), + inserted: Factory.insert!(:agent_relationship), } end -test "by_id/1 returns an AgentRelationship", %{agent_relationship: rel} do - assert %AgentRelationship{} = Domain.by_id(rel.id) +describe "one/1" do + test "with good id: finds the AgentRelationship", %{inserted: %{id: id}} do + assert {:ok, %AgentRelationship{}} = Domain.one(id) + end + + test "with bad id: doesn't find the AgentRelationship"do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - test "creates an AgentRelationship with valid params", %{params: params} do - assert {:ok, %AgentRelationship{} = rel} = Domain.create(params) - - assert rel.subject_id == params.subject_id - assert rel.object_id == params.object_id - assert rel.relationship_id == params.relationship_id - assert rel.note == params.note + test "with good params: creates an AgentRelationship", %{params: params} do + assert {:ok, %AgentRelationship{} = new} = Domain.create(params) + assert new.subject_id == params.subject_id + assert new.object_id == params.object_id + assert new.relationship_id == params.relationship_id + assert new.note == params.note end - test "doesn't create a AgentRelationship with invalid params" do + test "with bad params: doesn't create an AgentRelationship" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates an AgentRelationship with valid params", %{params: params, agent_relationship: old} do + test "with good params: updates the AgentRelationship", %{params: params, inserted: old} do assert {:ok, %AgentRelationship{} = new} = Domain.update(old.id, params) - assert new.subject_id == params.subject_id assert new.object_id == params.object_id assert new.relationship_id == params.relationship_id assert new.note == params.note end - test "doesn't update a AgentRelationship", %{agent_relationship: old} do + test "with bad params: doesn't update the AgentRelationship", %{inserted: old} do assert {:ok, %AgentRelationship{} = new} = Domain.update(old.id, %{}) - assert new.subject_id == old.subject_id assert new.object_id == old.object_id assert new.relationship_id == old.relationship_id @@ -73,8 +76,14 @@ describe "update/2" do end end -test "delete/1 deletes an AgentRelationship", %{agent_relationship: %{id: id}} do - assert {:ok, %AgentRelationship{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the AgentRelationship", %{inserted: %{id: id}} do + assert {:ok, %AgentRelationship{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the AgentRelationship" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end end diff --git a/test/vf/agent_relationship/type.test.exs b/test/vf/agent_relationship/type.test.exs @@ -21,98 +21,88 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - subject_id: Factory.insert!(:agent).id, - object_id: Factory.insert!(:agent).id, - relationship_id: Factory.insert!(:agent_relationship_role).id, - # in_scope_of: - note: Factory.uniq("note"), + "subject" => Factory.insert!(:agent).id, + "object" => Factory.insert!(:agent).id, + "relationship" => Factory.insert!(:agent_relationship_role).id, + # inScopeOf: + "note" => Factory.str("note"), }, - agent_relationship: Factory.insert!(:agent_relationship), + inserted: Factory.insert!(:agent_relationship), } end +@frag """ +fragment agentRelationship on AgentRelationship { + id + subject { id } + object { id } + relationship { id } + note +} +""" + describe "Query" do - test "agentRelationship()", %{agent_relationship: rel} do + test "agentRelationship", %{inserted: new} do assert %{data: %{"agentRelationship" => data}} = - query!(""" - agentRelationship(id: "#{rel.id}") { - id - subject { id } - object { id } - relationship { - id - } - note + run!(""" + #{@frag} + query ($id: ID!) { + agentRelationship(id: $id) {...agentRelationship} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == rel.id - assert data["subject"]["id"] == rel.subject_id - assert data["object"]["id"] == rel.object_id - assert data["relationship"]["id"] == rel.relationship_id - assert data["note"] == rel.note + assert data["id"] == new.id + assert data["subject"]["id"] == new.subject_id + assert data["object"]["id"] == new.object_id + assert data["relationship"]["id"] == new.relationship_id + assert data["note"] == new.note end end describe "Mutation" do - test "createAgentRelationship()", %{params: params} do + test "createAgentRelationship", %{params: params} do assert %{data: %{"createAgentRelationship" => %{"agentRelationship" => data}}} = - mutation!(""" - createAgentRelationship(relationship: { - subject: "#{params.subject_id}" - object: "#{params.object_id}" - relationship: "#{params.relationship_id}" - note: "#{params.note}" - }) { - agentRelationship { - id - subject { id } - object { id } - relationship { id } - note + run!(""" + #{@frag} + mutation ($relationship: AgentRelationshipCreateParams!) { + createAgentRelationship(relationship: $relationship) { + agentRelationship {...agentRelationship} } } - """) + """, vars: %{"relationship" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["subject"]["id"] == params.subject_id - assert data["object"]["id"] == params.object_id - assert data["relationship"]["id"] == params.relationship_id - assert data["note"] == params.note + assert data["subject"]["id"] == params["subject"] + assert data["object"]["id"] == params["object"] + assert data["relationship"]["id"] == params["relationship"] + assert data["note"] == params["note"] end - test "updateAgentRelationship()", %{params: params, agent_relationship: rel} do + test "updateAgentRelationship", %{params: params, inserted: old} do assert %{data: %{"updateAgentRelationship" => %{"agentRelationship" => data}}} = - mutation!(""" - updateAgentRelationship(relationship: { - id: "#{rel.id}" - subject: "#{params.subject_id}" - object: "#{params.object_id}" - relationship: "#{params.relationship_id}" - note: "#{params.note}" - }) { - agentRelationship { - id - subject { id } - object { id } - relationship { id } - note + run!(""" + #{@frag} + mutation ($relationship: AgentRelationshipUpdateParams!) { + updateAgentRelationship(relationship: $relationship) { + agentRelationship {...agentRelationship} } } - """) + """, vars: %{"relationship" => Map.put(params, "id", old.id)}) - assert data["id"] == rel.id - assert data["subject"]["id"] == params.subject_id - assert data["object"]["id"] == params.object_id - assert data["relationship"]["id"] == params.relationship_id - assert data["note"] == params.note + assert data["id"] == old.id + assert data["subject"]["id"] == params["subject"] + assert data["object"]["id"] == params["object"] + assert data["relationship"]["id"] == params["relationship"] + assert data["note"] == params["note"] end - test "deleteAgentRelationship()", %{agent_relationship: %{id: id}} do + test "deleteAgentRelationship", %{inserted: %{id: id}} do assert %{data: %{"deleteAgentRelationship" => true}} = - mutation!(""" - deleteAgentRelationship(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteAgentRelationship(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/agent_relationship_role/domain.test.exs b/test/vf/agent_relationship_role/domain.test.exs @@ -25,46 +25,50 @@ setup do %{ params: %{ role_behavior_id: Factory.insert!(:role_behavior).id, - role_label: Factory.uniq("role label"), - inverse_role_label: Factory.uniq("inverse role label"), - note: Factory.uniq("note"), + role_label: Factory.str("role label"), + inverse_role_label: Factory.str("inverse role label"), + note: Factory.str("note"), }, - agent_relationship_role: Factory.insert!(:agent_relationship_role), + inserted: Factory.insert!(:agent_relationship_role), } end -test "by_id/1 returns an AgentRelationshipRole", %{agent_relationship_role: rel_role} do - assert %AgentRelationshipRole{} = Domain.by_id(rel_role.id) +describe "one/1" do + test "with good id: finds the AgentRelationshipRole", %{inserted: %{id: id}} do + assert {:ok, %AgentRelationshipRole{}} = Domain.one(id) + end + + test "with bad id: doesn't find the AgentRelationshiprole"do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - test "creates an AgentRelationshipRole with valid params", %{params: params} do - assert {:ok, %AgentRelationshipRole{} = rel_role} = Domain.create(params) + test "with good params: creates an AgentRelationshipRole", %{params: params} do + assert {:ok, %AgentRelationshipRole{} = new} = Domain.create(params) - assert rel_role.role_behavior_id == params.role_behavior_id - assert rel_role.role_label == params.role_label - assert rel_role.inverse_role_label == params.inverse_role_label - assert rel_role.note == params.note + assert new.role_behavior_id == params.role_behavior_id + assert new.role_label == params.role_label + assert new.inverse_role_label == params.inverse_role_label + assert new.note == params.note end - test "doesn't create an AgentRelationshipRole with invalid params" do + test "with bad params: doesn't create an AgentRelationshipRole" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates an AgentRelationshipRole with valid params", %{params: params, agent_relationship_role: old} do + test "with good params: updates the AgentRelationshipRole", %{params: params, inserted: old} do assert {:ok, %AgentRelationshipRole{} = new} = Domain.update(old.id, params) - assert new.role_behavior_id == params.role_behavior_id assert new.role_label == params.role_label assert new.inverse_role_label == params.inverse_role_label assert new.note == params.note end - test "doesn't update an AgentRelationshipRole", %{agent_relationship_role: old} do + test "with bad params: doesn't update the AgentRelationshipRole", %{inserted: old} do assert {:ok, %AgentRelationshipRole{} = new} = Domain.update(old.id, %{}) - assert new.role_behavior_id == old.role_behavior_id assert new.role_label == old.role_label assert new.inverse_role_label == old.inverse_role_label @@ -72,8 +76,14 @@ describe "update/2" do end end -test "delete/1 deletes an AgentRelationshipRole", %{agent_relationship_role: %{id: id}} do - assert {:ok, %AgentRelationshipRole{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the AgentRelationshipRole", %{inserted: %{id: id}} do + assert {:ok, %AgentRelationshipRole{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the AgentRelationshipRole" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end end diff --git a/test/vf/agent_relationship_role/type.test.exs b/test/vf/agent_relationship_role/type.test.exs @@ -21,95 +21,86 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - role_behavior_id: Factory.insert!(:role_behavior).id, - role_label: Factory.uniq("role label"), - inverse_role_label: Factory.uniq("inverse role label"), - note: Factory.uniq("note"), + "roleBehavior" => Factory.insert!(:role_behavior).id, + "roleLabel" => Factory.str("role label"), + "inverseRoleLabel" => Factory.str("inverse role label"), + "note" => Factory.str("note"), }, - agent_relationship_role: Factory.insert!(:agent_relationship_role), + inserted: Factory.insert!(:agent_relationship_role), } end +@frag """ +fragment agentRelationshipRole on AgentRelationshipRole { + id + roleBehavior { id } + roleLabel + inverseRoleLabel + note +} +""" + describe "Query" do - test "agentRelationshipRole()", %{agent_relationship_role: rel_role} do + test "agentRelationshipRole", %{inserted: new} do assert %{data: %{"agentRelationshipRole" => data}} = - query!(""" - agentRelationshipRole(id: "#{rel_role.id}") { - id - roleBehavior { id } - roleLabel - inverseRoleLabel - note + run!(""" + #{@frag} + query ($id: ID!) { + agentRelationshipRole(id: $id) {...agentRelationshipRole} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == rel_role.id - assert data["roleBehavior"]["id"] == rel_role.role_behavior_id - assert data["roleLabel"] == rel_role.role_label - assert data["inverseRoleLabel"] == rel_role.inverse_role_label - assert data["note"] == rel_role.note + assert data["id"] == new.id + assert data["roleBehavior"]["id"] == new.role_behavior_id + assert data["roleLabel"] == new.role_label + assert data["inverseRoleLabel"] == new.inverse_role_label + assert data["note"] == new.note end end describe "Mutation" do - test "createAgentRelationshipRole()", %{params: params} do + test "createAgentRelationshipRole", %{params: params} do assert %{data: %{"createAgentRelationshipRole" => %{"agentRelationshipRole" => data}}} = - mutation!(""" - createAgentRelationshipRole(agentRelationshipRole: { - roleBehavior: "#{params.role_behavior_id}" - roleLabel: "#{params.role_label}" - inverseRoleLabel: "#{params.inverse_role_label}" - note: "#{params.note}" - }) { - agentRelationshipRole { - id - roleBehavior { id } - roleLabel - inverseRoleLabel - note + run!(""" + #{@frag} + mutation ($agentRelationshipRole: AgentRelationshipRoleCreateParams!) { + createAgentRelationshipRole(agentRelationshipRole: $agentRelationshipRole) { + agentRelationshipRole {...agentRelationshipRole} } } - """) + """, vars: %{"agentRelationshipRole" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["roleBehavior"]["id"] == params.role_behavior_id - assert data["roleLabel"] == params.role_label - assert data["inverseRoleLabel"] == params.inverse_role_label - assert data["note"] == params.note + assert data["roleBehavior"]["id"] == params["roleBehavior"] + assert data["roleLabel"] == params["roleLabel"] + assert data["inverseRoleLabel"] == params["inverseRoleLabel"] + assert data["note"] == params["note"] end - test "updateAgentRelationshipRole()", %{params: params, agent_relationship_role: rel_role} do + test "updateAgentRelationshipRole", %{params: params, inserted: old} do assert %{data: %{"updateAgentRelationshipRole" => %{"agentRelationshipRole" => data}}} = - mutation!(""" - updateAgentRelationshipRole(agentRelationshipRole: { - id: "#{rel_role.id}" - roleBehavior: "#{params.role_behavior_id}" - roleLabel: "#{params.role_label}" - inverseRoleLabel: "#{params.inverse_role_label}" - note: "#{params.note}" - }) { - agentRelationshipRole { - id - roleBehavior { id } - roleLabel - inverseRoleLabel - note + run!(""" + #{@frag} + mutation ($agentRelationshipRole: AgentRelationshipRoleUpdateParams!) { + updateAgentRelationshipRole(agentRelationshipRole: $agentRelationshipRole) { + agentRelationshipRole {...agentRelationshipRole} } } - """) - - assert data["id"] == rel_role.id - assert data["roleBehavior"]["id"] == params.role_behavior_id - assert data["roleLabel"] == params.role_label - assert data["inverseRoleLabel"] == params.inverse_role_label - assert data["note"] == params.note + """, vars: %{"agentRelationshipRole" => Map.put(params, "id", old.id)}) + assert data["id"] == old.id + assert data["roleBehavior"]["id"] == params["roleBehavior"] + assert data["roleLabel"] == params["roleLabel"] + assert data["inverseRoleLabel"] == params["inverseRoleLabel"] + assert data["note"] == params["note"] end - test "deleteAgentRelationshipRole()", %{agent_relationship_role: %{id: id}} do + test "deleteAgentRelationshipRole()", %{inserted: %{id: id}} do assert %{data: %{"deleteAgentRelationshipRole" => true}} = - mutation!(""" - deleteAgentRelationshipRole(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteAgentRelationshipRole(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/agreement/domain.test.exs b/test/vf/agreement/domain.test.exs @@ -28,7 +28,6 @@ setup do note: Factory.str("note"), }, inserted: Factory.insert!(:agreement), - id: Factory.id(), } end @@ -37,16 +36,16 @@ describe "one/1" do assert {:ok, %Agreement{}} = Domain.one(id) end - test "with bad id: doesn't find the Agreement", %{id: id} do - assert {:error, "not found"} = Domain.one(id) + test "with bad id: doesn't find the Agreement" do + assert {:error, "not found"} = Domain.one(Factory.id()) end end describe "create/1" do test "with good params: creates an Agreement", %{params: params} do - assert {:ok, %Agreement{} = agreem} = Domain.create(params) - assert agreem.name == params.name - assert agreem.note == params.note + assert {:ok, %Agreement{} = new} = Domain.create(params) + assert new.name == params.name + assert new.note == params.note end test "with bad params: doesn't create an Agreement" do @@ -74,8 +73,8 @@ describe "delete/1" do assert {:error, "not found"} = Domain.one(id) end - test "with bad id: doesn't delete the Agreement", %{id: id} do - assert {:error, "not found"} = Domain.delete(id) + test "with bad id: doesn't delete the Agreement" do + assert {:error, "not found"} = Domain.delete(Factory.id()) end end end diff --git a/test/vf/agreement/type.test.exs b/test/vf/agreement/type.test.exs @@ -38,18 +38,18 @@ fragment agreement on Agreement { """ describe "Query" do - test "agreement", %{inserted: agreem} do + test "agreement", %{inserted: new} do assert %{data: %{"agreement" => data}} = run!(""" #{@frag} query ($id: ID!) { agreement(id: $id) {...agreement} } - """, vars: %{"id" => agreem.id}) + """, vars: %{"id" => new.id}) - assert data["id"] == agreem.id - assert data["name"] == agreem.name - assert data["note"] == agreem.note + assert data["id"] == new.id + assert data["name"] == new.name + assert data["note"] == new.note assert {:ok, created, 0} = DateTime.from_iso8601(data["created"]) assert DateTime.compare(DateTime.utc_now(), created) != :lt end diff --git a/test/vf/appreciation.test.exs b/test/vf/appreciation.test.exs @@ -24,7 +24,7 @@ setup do %{params: %{ appreciation_of_id: Factory.insert!(:economic_event).id, appreciation_with_id: Factory.insert!(:economic_event).id, - note: Factory.uniq("note"), + note: Factory.str("note"), }} end diff --git a/test/vf/claim.test.exs b/test/vf/claim.test.exs @@ -25,7 +25,7 @@ setup do action_id: Factory.build(:action_id), provider_id: Factory.insert!(:agent).id, receiver_id: Factory.insert!(:agent).id, - resource_classified_as: Factory.uniq_list("uri"), + resource_classified_as: Factory.str_list("uri"), resource_conforms_to_id: Factory.insert!(:resource_specification).id, resource_quantity: %{ has_unit_id: Factory.insert!(:unit).id, @@ -38,8 +38,8 @@ setup do triggered_by_id: Factory.insert!(:economic_event).id, due: Factory.now(), finished: Factory.bool(), - note: Factory.uniq("note"), - agreed_in: Factory.uniq("uri"), + note: Factory.str("note"), + agreed_in: Factory.str("uri"), # in_scope_of_id: }} end diff --git a/test/vf/commitment.test.exs b/test/vf/commitment.test.exs @@ -28,7 +28,7 @@ setup do receiver_id: Factory.insert!(:agent).id, input_of_id: Factory.insert!(:process).id, output_of_id: Factory.insert!(:process).id, - resource_classified_as: Factory.uniq_list("uri"), + resource_classified_as: Factory.str_list("uri"), resource_quantity: %{ has_unit_id: Factory.insert!(:unit).id, has_numerical_value: Factory.float(), @@ -39,9 +39,9 @@ setup do }, due: DateTime.utc_now(), finished: Factory.bool(), - note: Factory.uniq("note"), + note: Factory.str("note"), # in_scope_of_id: - agreed_in: Factory.uniq("uri"), + agreed_in: Factory.str("uri"), independent_demand_of_id: Factory.insert!(:plan).id, at_location_id: Factory.insert!(:spatial_thing).id, clause_of_id: Factory.insert!(:agreement).id, diff --git a/test/vf/economic_event/domain.test.exs b/test/vf/economic_event/domain.test.exs @@ -77,8 +77,8 @@ setup ctx do end #@tag :skip -#test "by_id/1 returns a EconomicEvent" do -# assert %EconomicEvent{} = Domain.by_id(eco_evt.id) +#test "one/1 returns a EconomicEvent", %{inserted: new} do +# assert {:ok, %EconomicEvent{}} = Domain.one(new.id) #end describe "`create/2` with raise:" do @@ -142,9 +142,9 @@ describe "`create/2` with raise:" do end test "pass with `:resource_inventoried_as`", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert {:ok, %EconomicEvent{}} = Domain.create(params, nil) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value + params.resource_quantity.has_numerical_value @@ -242,9 +242,9 @@ describe "`create/2` with produce:" do end test "pass with `:resource_inventoried_as`", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert {:ok, %EconomicEvent{}} = Domain.create(params, nil) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value + params.resource_quantity.has_numerical_value @@ -295,9 +295,9 @@ describe "`create/2` with lower:" do end test "pass when all good", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert {:ok, %EconomicEvent{}} = Domain.create(params, nil) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value - params.resource_quantity.has_numerical_value assert res_after.onhand_quantity_has_numerical_value == @@ -349,9 +349,9 @@ describe "`create/2` with consume:" do end test "pass when all good", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert {:ok, %EconomicEvent{}} = Domain.create(params, nil) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value - params.resource_quantity.has_numerical_value @@ -515,7 +515,7 @@ describe "`create/2` with dropoff:" do test "pass when all good", %{params: params} do assert {:ok, %EconomicEvent{} = evt} = Domain.create(params, nil) - res = EconomicResource.Domain.by_id(evt.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(evt.resource_inventoried_as_id) assert res.current_location_id == params.to_location_id end @@ -566,9 +566,9 @@ describe "`create/2` with accept:" do end test "pass when all good", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert {:ok, %EconomicEvent{}} = Domain.create(params, nil) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value @@ -662,12 +662,12 @@ describe "`create/2` with modify:" do end test "pass when all good", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert res_before.stage_id == nil assert {:ok, %EconomicEvent{}} = Domain.create(params, nil) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) - proc = Process.Domain.by_id(params.output_of_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + {:ok, proc} = Process.Domain.one(params.output_of_id) assert res_after.stage_id == proc.based_on_id assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value @@ -758,7 +758,7 @@ describe "`create/2` with transferCustody:" do end test "pass without `:to_resource_inventoried_as`", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) contained_ids = Enum.map(0..9, fn _ -> agent = Factory.insert!(:agent) @@ -788,7 +788,7 @@ describe "`create/2` with transferCustody:" do lot_id: Factory.insert!(:product_batch).id, } assert {:ok, %EconomicEvent{} = evt, _, %EconomicResource{} = to_res} = Domain.create(params, res_params) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value @@ -821,12 +821,12 @@ describe "`create/2` with transferCustody:" do @tag :want_to_resource test "pass with `:to_resource_inventoried_as`", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) - to_res_before = EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + {:ok, to_res_before} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) assert {:ok, %EconomicEvent{}} = Domain.create(params, nil) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) - to_res_after = EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + {:ok, to_res_after} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value @@ -864,7 +864,7 @@ describe "`create/2` with transferCustody:" do @tag :want_container test "fail when the resource is a container and onhand-quantity is non-positive", %{params: params} do err = "the transfer-custody events need container resources to have positive onhand-quantity" - res = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) Changeset.change(res, onhand_quantity_has_numerical_value: 0.0) |> Repo.update!() assert {:error, ^err} = Domain.create(params, nil) @@ -903,7 +903,9 @@ describe "`create/2` with transferCustody:" do } assert {:ok, _, tmp_res, _} = Domain.create(raise_params, %{name: Factory.str("name")}) # TODO: use combine-separate when implemented instead - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(contained_in_id: tmp_res.id) |> Repo.update!() @@ -936,7 +938,9 @@ describe "`create/2` with transferCustody:" do @tag :want_to_resource test "fail when event's unit and to-resource's unit differ", %{params: params} do - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(onhand_quantity_has_unit_id: Factory.insert!(:unit).id) |> Repo.update!() @@ -946,7 +950,9 @@ describe "`create/2` with transferCustody:" do @tag :want_to_resource test "fail when resoure and to-resource don't conform to the same spec", %{params: params} do - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(conforms_to_id: Factory.insert!(:resource_specification).id) |> Repo.update!() @@ -1000,7 +1006,7 @@ describe "`create/2` with transferAllRights:" do end test "pass without `:to_resource_inventoried_as`", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) contained_ids = Enum.map(0..9, fn _ -> agent = Factory.insert!(:agent) @@ -1030,7 +1036,7 @@ describe "`create/2` with transferAllRights:" do lot_id: Factory.insert!(:product_batch).id, } assert {:ok, %EconomicEvent{} = evt, _, %EconomicResource{} = to_res} = Domain.create(params, res_params) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value - params.resource_quantity.has_numerical_value @@ -1062,12 +1068,12 @@ describe "`create/2` with transferAllRights:" do @tag :want_to_resource test "pass with `:to_resource_inventoried_as`", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) - to_res_before = EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + {:ok, to_res_before} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) assert {:ok, %EconomicEvent{}} = Domain.create(params, nil) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) - to_res_after = EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + {:ok, to_res_after} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value - params.resource_quantity.has_numerical_value @@ -1105,7 +1111,7 @@ describe "`create/2` with transferAllRights:" do @tag :want_container test "fail when the resource is a container and accounting-quantity is non-positive", %{params: params} do err = "the transfer-all-rights events need container resources to have positive accounting-quantity" - res = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) Changeset.change(res, accounting_quantity_has_numerical_value: 0.0) |> Repo.update!() assert {:error, ^err} = Domain.create(params, nil) @@ -1144,7 +1150,9 @@ describe "`create/2` with transferAllRights:" do } assert {:ok, _, tmp_res, _} = Domain.create(raise_params, %{name: Factory.str("name")}) # TODO: use combine-separate when implemented instead - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(contained_in_id: tmp_res.id) |> Repo.update!() @@ -1177,7 +1185,9 @@ describe "`create/2` with transferAllRights:" do @tag :want_to_resource test "fail when event's unit and to-resource's unit differ", %{params: params} do - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(accounting_quantity_has_unit_id: Factory.insert!(:unit).id) |> Repo.update!() @@ -1187,7 +1197,9 @@ describe "`create/2` with transferAllRights:" do @tag :want_to_resource test "fail when resoure and to-resource don't conform to the same spec", %{params: params} do - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(conforms_to_id: Factory.insert!(:resource_specification).id) |> Repo.update!() @@ -1241,7 +1253,7 @@ describe "`create/2` with transfer:" do end test "pass without `:to_resource_inventoried_as`", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) contained_ids = Enum.map(0..9, fn _ -> agent = Factory.insert!(:agent) @@ -1271,7 +1283,7 @@ describe "`create/2` with transfer:" do lot_id: Factory.insert!(:product_batch).id, } assert {:ok, %EconomicEvent{} = evt, _, %EconomicResource{} = to_res} = Domain.create(params, res_params) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value - params.resource_quantity.has_numerical_value @@ -1304,12 +1316,12 @@ describe "`create/2` with transfer:" do @tag :want_to_resource test "pass with `:to_resource_inventoried_as`", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) - to_res_before = EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + {:ok, to_res_before} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) assert {:ok, %EconomicEvent{}} = Domain.create(params, nil) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) - to_res_after = EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + {:ok, to_res_after} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value - params.resource_quantity.has_numerical_value @@ -1323,7 +1335,9 @@ describe "`create/2` with transfer:" do end test "fail when provider doesn't have accountability over the resource", %{params: params} do - EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + + res |> Changeset.change(primary_accountable_id: Factory.insert!(:agent).id) |> Repo.update!() assert {:error, "you don't have accountability over this resource"} = @@ -1331,7 +1345,9 @@ describe "`create/2` with transfer:" do end test "fail when provider doesn't have custody over the resource", %{params: params} do - EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + + res |> Changeset.change(custodian_id: Factory.insert!(:agent).id) |> Repo.update!() assert {:error, "you don't have custody over this resource"} = @@ -1352,7 +1368,9 @@ describe "`create/2` with transfer:" do @tag :want_to_resource test "fail when event's unit and to-resource's unit differ", %{params: params} do - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(accounting_quantity_has_unit_id: Factory.insert!(:unit).id) |> Repo.update!() @@ -1363,7 +1381,7 @@ describe "`create/2` with transfer:" do @tag :want_container test "fail when the resource is a container and accounting-quantity is non-positive", %{params: params} do err = "the transfer events need container resources to have positive accounting-quantity" - res = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) Changeset.change(res, accounting_quantity_has_numerical_value: 0.0) |> Repo.update!() assert {:error, ^err} = Domain.create(params, nil) @@ -1375,7 +1393,7 @@ describe "`create/2` with transfer:" do @tag :want_container test "fail when the resource is a container and onhand-quantity is non-positive", %{params: params} do err = "the transfer events need container resources to have positive onhand-quantity" - res = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) Changeset.change(res, onhand_quantity_has_numerical_value: 0.0) |> Repo.update!() assert {:error, ^err} = Domain.create(params, nil) @@ -1386,7 +1404,9 @@ describe "`create/2` with transfer:" do @tag :want_container test "fail when event's quantity value and resource's accounting-quantity value differ", %{params: params} do - EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + + res |> Changeset.change(accounting_quantity_has_numerical_value: params.resource_quantity.has_numerical_value + 1) |> Repo.update!() assert {:error, "the transfer events need to fully transfer the resource"} = @@ -1395,7 +1415,9 @@ describe "`create/2` with transfer:" do @tag :want_container test "fail when event's quantity value and resource's onhnad-quantity value differ", %{params: params} do - EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + + res |> Changeset.change(onhand_quantity_has_numerical_value: params.resource_quantity.has_numerical_value + 1) |> Repo.update!() assert {:error, "the transfer events need to fully transfer the resource"} = @@ -1425,7 +1447,9 @@ describe "`create/2` with transfer:" do } assert {:ok, _, tmp_res, _} = Domain.create(raise_params, %{name: Factory.str("name")}) # TODO: use combine-separate when implemented instead - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(contained_in_id: tmp_res.id) |> Repo.update!() @@ -1458,7 +1482,9 @@ describe "`create/2` with transfer:" do @tag :want_to_resource test "fail when resoure and to-resource don't conform to the same spec", %{params: params} do - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(conforms_to_id: Factory.insert!(:resource_specification).id) |> Repo.update!() @@ -1511,7 +1537,7 @@ describe "`create/2` with move:" do end test "pass without `:to_resource_inventoried_as`", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) contained_ids = Enum.map(0..9, fn _ -> agent = Factory.insert!(:agent) @@ -1541,7 +1567,7 @@ describe "`create/2` with move:" do lot_id: Factory.insert!(:product_batch).id, } assert {:ok, %EconomicEvent{} = evt, _, %EconomicResource{} = to_res} = Domain.create(params, res_params) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value - params.resource_quantity.has_numerical_value @@ -1574,12 +1600,12 @@ describe "`create/2` with move:" do @tag :want_to_resource test "pass with `:to_resource_inventoried_as`", %{params: params} do - res_before = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) - to_res_before = EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res_before} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + {:ok, to_res_before} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) assert {:ok, %EconomicEvent{}} = Domain.create(params, nil) - res_after = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) - to_res_after = EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res_after} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + {:ok, to_res_after} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) assert res_after.accounting_quantity_has_numerical_value == res_before.accounting_quantity_has_numerical_value - params.resource_quantity.has_numerical_value @@ -1593,7 +1619,9 @@ describe "`create/2` with move:" do end test "fail when provider doesn't have accountability over the resource", %{params: params} do - EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + + res |> Changeset.change(primary_accountable_id: Factory.insert!(:agent).id) |> Repo.update!() assert {:error, "you don't have accountability over resource-inventoried-as"} = @@ -1601,7 +1629,9 @@ describe "`create/2` with move:" do end test "fail when provider doesn't have custody over the resource", %{params: params} do - EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + + res |> Changeset.change(custodian_id: Factory.insert!(:agent).id) |> Repo.update!() assert {:error, "you don't have custody over resource-inventoried-as"} = @@ -1610,7 +1640,9 @@ describe "`create/2` with move:" do @tag :want_to_resource test "fail when provider doesn't have accountability over the to-resource", %{params: params} do - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(primary_accountable_id: Factory.insert!(:agent).id) |> Repo.update!() assert {:error, "you don't have accountability over to-resource-inventoried-as"} = @@ -1619,7 +1651,9 @@ describe "`create/2` with move:" do @tag :want_to_resource test "fail when provider doesn't have custody over the to-resource", %{params: params} do - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(custodian_id: Factory.insert!(:agent).id) |> Repo.update!() assert {:error, "you don't have custody over to-resource-inventoried-as"} = @@ -1640,7 +1674,9 @@ describe "`create/2` with move:" do @tag :want_to_resource test "fail when event's unit and to-resource's unit differ", %{params: params} do - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(accounting_quantity_has_unit_id: Factory.insert!(:unit).id) |> Repo.update!() @@ -1651,7 +1687,7 @@ describe "`create/2` with move:" do @tag :want_container test "fail when the resource is a container and accounting-quantity is non-positive", %{params: params} do err = "the move events need container resources to have positive accounting-quantity" - res = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) Changeset.change(res, accounting_quantity_has_numerical_value: 0.0) |> Repo.update!() assert {:error, ^err} = Domain.create(params, nil) @@ -1663,7 +1699,7 @@ describe "`create/2` with move:" do @tag :want_container test "fail when the resource is a container and onhand-quantity is non-positive", %{params: params} do err = "the move events need container resources to have positive onhand-quantity" - res = EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) Changeset.change(res, onhand_quantity_has_numerical_value: 0.0) |> Repo.update!() assert {:error, ^err} = Domain.create(params, nil) @@ -1674,7 +1710,9 @@ describe "`create/2` with move:" do @tag :want_container test "fail when event's quantity value and resource's accounting-quantity value differ", %{params: params} do - EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + + res |> Changeset.change(accounting_quantity_has_numerical_value: params.resource_quantity.has_numerical_value + 1) |> Repo.update!() assert {:error, "the move events need to fully move the resource"} = @@ -1683,7 +1721,9 @@ describe "`create/2` with move:" do @tag :want_container test "fail when event's quantity value and resource's onhnad-quantity value differ", %{params: params} do - EconomicResource.Domain.by_id(params.resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.resource_inventoried_as_id) + + res |> Changeset.change(onhand_quantity_has_numerical_value: params.resource_quantity.has_numerical_value + 1) |> Repo.update!() assert {:error, "the move events need to fully move the resource"} = @@ -1713,7 +1753,9 @@ describe "`create/2` with move:" do } assert {:ok, _, tmp_res, _} = Domain.create(raise_params, %{name: Factory.str("name")}) # TODO: use combine-separate when implemented instead - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(contained_in_id: tmp_res.id) |> Repo.update!() @@ -1746,7 +1788,9 @@ describe "`create/2` with move:" do @tag :want_to_resource test "fail when resoure and to-resource don't conform to the same spec", %{params: params} do - EconomicResource.Domain.by_id(params.to_resource_inventoried_as_id) + {:ok, res} = EconomicResource.Domain.one(params.to_resource_inventoried_as_id) + + res |> Changeset.change(conforms_to_id: Factory.insert!(:resource_specification).id) |> Repo.update!() diff --git a/test/vf/economic_resource/domain.test.exs b/test/vf/economic_resource/domain.test.exs @@ -35,11 +35,11 @@ setup ctx do %{id: unit_id} = Factory.insert!(:unit) num_val = Factory.float() params = %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), + name: Factory.str("name"), + note: Factory.str("note"), image: Factory.img(), - tracking_identifier: Factory.uniq("tracking identifier"), - classified_as: Factory.uniq_list("uri"), + tracking_identifier: Factory.str("tracking identifier"), + classified_as: Factory.str_list("uri"), conforms_to_id: Factory.insert!(:resource_specification).id, accounting_quantity: %{ has_unit_id: unit_id, @@ -67,7 +67,7 @@ setup ctx do end test "by_id/1 returns a EconomicResource", %{inserted: eco_res} do - assert %EconomicResource{} = Domain.by_id(eco_res.id) + assert {:ok, %EconomicResource{}} = Domain.one(eco_res.id) end describe "update/2" do @@ -118,10 +118,9 @@ describe "update/2" do end end -@tag skip: "TODO: fix economic resource factory" test "delete/1 deletes a EconomicResource", %{inserted: %{id: id}} do assert {:ok, %EconomicResource{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil + assert {:error, "not found"} = Domain.one(id) end describe "preload/2" do diff --git a/test/vf/economic_resource/type.test.exs b/test/vf/economic_resource/type.test.exs @@ -18,144 +18,123 @@ defmodule ZenflowsTest.VF.EconomicResource.Type do use ZenflowsTest.Help.AbsinCase, async: true -alias Zenflows.VF.EconomicResource.Domain - setup do %{ params: %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), - image: Factory.uri(), + "name" => Factory.str("name"), + "note" => Factory.str("note"), + "image" => Factory.img(), }, - inserted: - Factory.insert!(:economic_resource) - |> Domain.preload(:accounting_quantity) - |> Domain.preload(:onhand_quantity) + inserted: Factory.insert!(:economic_resource), } end +@frag """ +fragment economicResource on EconomicResource { + id + name + note + image + trackingIdentifier + classifiedAs + conformsTo {id} + accountingQuantity { + hasUnit { id } + hasNumericalValue + } + onhandQuantity { + hasUnit { id } + hasNumericalValue + } + primaryAccountable {id} + custodian {id} + stage {id} + state {id} + currentLocation {id} + lot {id} + containedIn {id} + unitOfEffort {id} +} +""" + describe "Query" do - @tag skip: "TODO: fix economic resource factory" - test "resource()", %{inserted: eco_res} do + test "resource", %{inserted: new} do assert %{data: %{"economicResource" => data}} = - query!(""" - economicResource(id: "#{eco_res.id}") { - id - name - note - image - trackingIdentifier - classifiedAs - conformsTo {id} - accountingQuantity { - hasUnit { id } - hasNumericalValue - } - onhandQuantity { - hasUnit { id } - hasNumericalValue - } - primaryAccountable {id} - custodian {id} - stage {id} - state {id} - currentLocation {id} - lot {id} - containedIn {id} - unitOfEffort {id} + run!(""" + #{@frag} + query ($id: ID!) { + economicResource(id: $id) {...economicResource} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == eco_res.id - assert data["name"] == eco_res.name - assert data["note"] == eco_res.note - # virtual field atm - # assert data["image"] == eco_res.image - assert data["trackingIdentifier"] == eco_res.tracking_identifier - assert data["classifiedAs"] == eco_res.classified_as - assert data["conformsTo"]["id"] == eco_res.conforms_to_id - assert data["accountingQuantity"]["hasUnit"]["id"] == eco_res.accounting_quantity_has_unit_id - assert data["accountingQuantity"]["hasNumericalValue"] == eco_res.accounting_quantity_has_numerical_value - assert data["onhandQuantity"]["hasUnit"]["id"] == eco_res.onhand_quantity_has_unit_id - assert data["onhandQuantity"]["hasNumericalValue"] == eco_res.onhand_quantity_has_numerical_value - assert data["primaryAccountable"]["id"] == eco_res.primary_accountable_id - assert data["custodian"]["id"] == eco_res.custodian_id - assert data["stage"]["id"] == eco_res.stage_id - assert data["state"]["id"] == eco_res.state_id - assert data["currentLocation"]["id"] == eco_res.current_location_id - assert data["lot"]["id"] == eco_res.lot_id - assert data["containedIn"]["id"] == eco_res.contained_in_id - assert data["unitOfEffort"]["id"] == eco_res.unit_of_effort_id + assert data["id"] == new.id + assert data["name"] == new.name + assert data["note"] == new.note + assert data["image"] == new.image + assert data["trackingIdentifier"] == new.tracking_identifier + assert data["classifiedAs"] == new.classified_as + assert data["conformsTo"]["id"] == new.conforms_to_id + assert data["accountingQuantity"]["hasUnit"]["id"] == new.accounting_quantity_has_unit_id + assert data["accountingQuantity"]["hasNumericalValue"] == new.accounting_quantity_has_numerical_value + assert data["onhandQuantity"]["hasUnit"]["id"] == new.onhand_quantity_has_unit_id + assert data["onhandQuantity"]["hasNumericalValue"] == new.onhand_quantity_has_numerical_value + assert data["primaryAccountable"]["id"] == new.primary_accountable_id + assert data["custodian"]["id"] == new.custodian_id + assert data["stage"]["id"] == new.stage_id + assert data["state"]["id"] == new.state_id + assert data["currentLocation"]["id"] == new.current_location_id + assert data["lot"]["id"] == new.lot_id + assert data["containedIn"]["id"] == new.contained_in_id + assert data["unitOfEffort"]["id"] == new.unit_of_effort_id end end describe "Mutation" do - @tag skip: "TODO: fix economic resource factory" - test "updateEconomicResource()", %{params: params, inserted: eco_res} do + @tag skip: "TODO: fix factory" + test "updateEconomicResource", %{params: params, inserted: old} do assert %{data: %{"updateEconomicResource" => %{"economicResource" => data}}} = - mutation!(""" - updateEconomicResource(resource: { - id: "#{eco_res.id}" - note: "#{params.note}" - image: "#{params.image}" - }) { - economicResource { - id - name - note - image - trackingIdentifier - classifiedAs - conformsTo {id} - accountingQuantity { - hasUnit { id } - hasNumericalValue - } - onhandQuantity { - hasUnit { id } - hasNumericalValue - } - primaryAccountable {id} - custodian {id} - stage {id} - state {id} - currentLocation {id} - lot {id} - containedIn {id} - unitOfEffort {id} + run!(""" + #{@frag} + mutation ($resource: EconomicResourceUpdateParams!) { + updateEconomicResource(resource: $resource) { + economicResource {...economicResource} } } - """) + """, vars: %{"resource" => %{ + "id" => old.id, + "note" => params["note"], + "image" => params["image"], + }}) - assert data["id"] == eco_res.id - assert data["id"] == eco_res.id - assert data["name"] == eco_res.name - assert data["note"] == params.note - # virtual field atm - # assert data["image"] == eco_res.image - assert data["trackingIdentifier"] == eco_res.tracking_identifier - assert data["classifiedAs"] == eco_res.classified_as - assert data["conformsTo"]["id"] == eco_res.conforms_to_id - assert data["accountingQuantity"]["hasUnit"]["id"] == eco_res.accounting_quantity_has_unit_id - assert data["accountingQuantity"]["hasNumericalValue"] == eco_res.accounting_quantity_has_numerical_value - assert data["onhandQuantity"]["hasUnit"]["id"] == eco_res.onhand_quantity_has_unit_id - assert data["onhandQuantity"]["hasNumericalValue"] == eco_res.onhand_quantity_has_numerical_value - assert data["primaryAccountable"]["id"] == eco_res.primary_accountable_id - assert data["custodian"]["id"] == eco_res.custodian_id - assert data["stage"]["id"] == eco_res.stage_id - assert data["state"]["id"] == eco_res.state_id - assert data["currentLocation"]["id"] == eco_res.current_location_id - assert data["lot"]["id"] == eco_res.lot_id - assert data["containedIn"]["id"] == eco_res.contained_in_id - assert data["unitOfEffort"]["id"] == eco_res.unit_of_effort_id + assert data["id"] == old.id + assert data["id"] == old.id + assert data["name"] == old.name + assert data["note"] == params["note"] + assert data["image"] == params["image"] + assert data["trackingIdentifier"] == old.tracking_identifier + assert data["classifiedAs"] == old.classified_as + assert data["conformsTo"]["id"] == old.conforms_to_id + assert data["accountingQuantity"]["hasUnit"]["id"] == old.accounting_quantity_has_unit_id + assert data["accountingQuantity"]["hasNumericalValue"] == old.accounting_quantity_has_numerical_value + assert data["onhandQuantity"]["hasUnit"]["id"] == old.onhand_quantity_has_unit_id + assert data["onhandQuantity"]["hasNumericalValue"] == old.onhand_quantity_has_numerical_value + assert data["primaryAccountable"]["id"] == old.primary_accountable_id + assert data["custodian"]["id"] == old.custodian_id + assert data["stage"]["id"] == old.stage_id + assert data["state"]["id"] == old.state_id + assert data["currentLocation"]["id"] == old.current_location_id + assert data["lot"]["id"] == old.lot_id + assert data["containedIn"]["id"] == old.contained_in_id + assert data["unitOfEffort"]["id"] == old.unit_of_effort_id end - @tag skip: "TODO: fix economic resource factory" test "deleteEconomicResource()", %{inserted: %{id: id}} do assert %{data: %{"deleteEconomicResource" => true}} = - mutation!(""" - deleteEconomicResource(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteEconomicResource(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/fulfillment.test.exs b/test/vf/fulfillment.test.exs @@ -22,7 +22,7 @@ alias Zenflows.VF.Fulfillment setup do %{params: %{ - note: Factory.uniq("note"), + note: Factory.str("note"), fulfilled_by_id: Factory.insert!(:economic_event).id, fulfills_id: Factory.insert!(:commitment).id, resource_quantity: %{ diff --git a/test/vf/intent/domain.test.exs b/test/vf/intent/domain.test.exs @@ -41,7 +41,7 @@ setup do receiver_id: Factory.insert!(:agent).id, resource_inventoried_as_id: Factory.insert!(:economic_resource).id, resource_conforms_to_id: Factory.insert!(:resource_specification).id, - resource_classified_as: Factory.uniq_list("uri"), + resource_classified_as: Factory.str_list("uri"), resource_quantity: %{ has_unit_id: Factory.insert!(:unit).id, has_numerical_value: Factory.float(), @@ -61,13 +61,12 @@ setup do finished: Factory.bool(), at_location_id: Factory.insert!(:spatial_thing).id, image: Factory.img(), - name: Factory.uniq("name"), - note: Factory.uniq("note"), + name: Factory.str("name"), + note: Factory.str("note"), # in_scope_of_id: - agreed_in: Factory.uniq("uri"), + agreed_in: Factory.str("uri"), }, inserted: Factory.insert!(:intent), - id: Factory.id(), } end @@ -76,8 +75,8 @@ describe "one/1" do assert {:ok, %Intent{}} = Domain.one(id) end - test "with bad id: doesn't find the Intent", %{id: id} do - assert {:error, "not found"} = Domain.one(id) + test "with bad id: doesn't find the Intent" do + assert {:error, "not found"} = Domain.one(Factory.id()) end end @@ -223,8 +222,8 @@ describe "delete/1" do assert {:error, "not found"} = Domain.one(id) end - test "with bad id: doesn't delete the Intent", %{id: id} do - assert {:error, "not found"} = Domain.delete(id) + test "with bad id: doesn't delete the Intent" do + assert {:error, "not found"} = Domain.delete(Factory.id()) end end diff --git a/test/vf/intent/type.test.exs b/test/vf/intent/type.test.exs @@ -30,7 +30,7 @@ setup do "receiver" => Factory.insert!(:agent).id, "resourceInventoriedAs" => Factory.insert!(:economic_resource).id, "resourceConformsTo" => Factory.insert!(:resource_specification).id, - "resourceClassifiedAs" => Factory.uniq_list("uri"), + "resourceClassifiedAs" => Factory.str_list("uri"), "resourceQuantity" => %{ "hasUnit" => Factory.insert!(:unit).id, "hasNumericalValue" => Factory.float(), @@ -50,10 +50,10 @@ setup do "finished" => Factory.bool(), "atLocation" => Factory.insert!(:spatial_thing).id, "image" => Factory.img(), - "name" => Factory.uniq("name"), - "note" => Factory.uniq("note"), + "name" => Factory.str("name"), + "note" => Factory.str("note"), # inScopeOf: - "agreedIn" => Factory.uniq("uri"), + "agreedIn" => Factory.str("uri"), }, inserted: Factory.insert!(:intent), id: Factory.id(), diff --git a/test/vf/organization/domain.test.exs b/test/vf/organization/domain.test.exs @@ -21,68 +21,52 @@ use ZenflowsTest.Help.EctoCase, async: true alias Ecto.Changeset alias Zenflows.VF.{Organization, Organization.Domain} -setup ctx do - if ctx[:no_insert] do - :ok - else - params = %{ - name: Factory.uniq("name"), +setup do + %{ + params: %{ + name: Factory.str("name"), image: Factory.img(), - classified_as: Factory.uniq_list("uri"), - note: Factory.uniq("note"), + classified_as: Factory.str_list("uri"), + note: Factory.str("note"), primary_location_id: Factory.insert!(:spatial_thing).id, - } - - %{params: params, org: Factory.insert!(:organization)} - end + }, + inserted: Factory.insert!(:organization), + } end -describe "by_id/1" do - test "returns an Organization", %{org: org} do - assert %Organization{type: :org} = Domain.by_id(org.id) +describe "one/1" do + test "with good id: finds the Organization", %{inserted: %{id: id}} do + assert {:ok, %Organization{}} = Domain.one(id) end - test "doesn't return a Person" do + test "with per's id: doesn't return a Person" do per = Factory.insert!(:person) - - assert Domain.by_id(per.id) == nil + assert {:error, "not found"} = Domain.one(per.id) end -end - -@tag :no_insert -test "all/0 returns all Organizations" do - want_ids = - Enum.map(1..10, fn _ -> Factory.insert!(:organization).id end) - |> Enum.sort() - have_ids = - Domain.all() - |> Enum.map(& &1.id) - |> Enum.sort() - assert have_ids == want_ids + test "with bad id: doesn't find the Organization" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - test "creates an Organization with valid params", %{params: params} do - assert {:ok, %Organization{} = org} = Domain.create(params) - - assert org.type == :org - assert org.name == params.name - assert org.image == params.image - assert org.classified_as == params.classified_as - assert org.note == params.note - assert org.primary_location_id == params.primary_location_id - end + test "with good params: creates an Organization", %{params: params} do + assert {:ok, %Organization{} = new} = Domain.create(params) + assert new.type == :org + assert new.name == params.name + assert new.image == params.image + assert new.classified_as == params.classified_as + assert new.note == params.note + assert new.primary_location_id == params.primary_location_id end - test "doesn't create an Organization with invalid params" do + test "with bad params: doesn't create an Organization" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates an Organization with valid params", %{params: params, org: old} do + test "with good params: updates the Organization", %{params: params, inserted: old} do assert {:ok, %Organization{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.classified_as == params.classified_as assert new.note == params.note @@ -90,9 +74,8 @@ describe "update/2" do assert new.primary_location_id == params.primary_location_id end - test "doesn't update an Organization with invalid params", %{org: old} do + test "with bad params: doesn't update the Organization", %{inserted: old} do assert {:ok, %Organization{} = new} = Domain.update(old.id, %{}) - assert new.name == old.name assert new.classified_as == old.classified_as assert new.note == old.note @@ -101,8 +84,14 @@ describe "update/2" do end end -test "delete/1 deletes an Organization", %{org: %{id: id}} do - assert {:ok, %Organization{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the Organization", %{inserted: %{id: id}} do + assert {:ok, %Organization{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the Organization" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end end diff --git a/test/vf/organization/type.test.exs b/test/vf/organization/type.test.exs @@ -21,38 +21,43 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - "name" => Factory.uniq("name"), + "name" => Factory.str("name"), "image" => Factory.img(), - "classifiedAs" => Factory.uniq_list("uri"), - "note" => Factory.uniq("note"), + "classifiedAs" => Factory.str_list("uri"), + "note" => Factory.str("note"), "primaryLocation" => Factory.insert!(:spatial_thing).id, }, - org: Factory.insert!(:organization), + inserted: Factory.insert!(:organization), } end +@frag """ +fragment organization on Organization { + id + name + note + image + primaryLocation { id } + classifiedAs +} +""" + describe "Query" do - test "organization()", %{org: org} do + test "organization()", %{inserted: new} do assert %{data: %{"organization" => data}} = run!(""" + #{@frag} query ($id: ID!) { - organization(id: $id) { - id - name - note - image - primaryLocation { id } - classifiedAs - } + organization(id: $id) {...organization} } - """, vars: %{"id" => org.id}) + """, vars: %{"id" => new.id}) - assert data["id"] == org.id - assert data["name"] == org.name - assert data["note"] == org.note - assert data["image"] == org.image - assert data["primaryLocation"]["id"] == org.primary_location_id - assert data["classifiedAs"] == org.classified_as + assert data["id"] == new.id + assert data["name"] == new.name + assert data["note"] == new.note + assert data["image"] == new.image + assert data["primaryLocation"]["id"] == new.primary_location_id + assert data["classifiedAs"] == new.classified_as end end @@ -60,16 +65,10 @@ describe "Mutation" do test "createOrganization", %{params: params} do assert %{data: %{"createOrganization" => %{"agent" => data}}} = run!(""" + #{@frag} mutation ($organization: OrganizationCreateParams!) { createOrganization(organization: $organization) { - agent { - id - name - note - image - primaryLocation { id } - classifiedAs - } + agent {...organization} } } """, vars: %{"organization" => params}) @@ -84,39 +83,34 @@ describe "Mutation" do assert data == params end - test "updateOrganization()", %{params: params, org: org} do + test "updateOrganization()", %{params: params, inserted: old} do assert %{data: %{"updateOrganization" => %{"agent" => data}}} = run!(""" + #{@frag} mutation ($organization: OrganizationUpdateParams!) { updateOrganization(organization: $organization) { - agent { - id - name - note - image - primaryLocation { id } - classifiedAs - } + agent {...organization} } } """, vars: %{"organization" => params |> Map.take(~w[name note image primaryLocation classifiedAs]) - |> Map.put("id", org.id) + |> Map.put("id", old.id) }) + assert data["id"] == old.id keys = ~w[name image note classifiedAs] assert Map.take(data, keys) == Map.take(params, keys) assert data["primaryLocation"]["id"] == params["primaryLocation"] end - test "deleteOrganization", %{org: org} do + test "deleteOrganization", %{inserted: %{id: id}} do assert %{data: %{"deleteOrganization" => true}} = run!(""" mutation ($id: ID!) { deleteOrganization(id: $id) } - """, vars: %{"id" => org.id}) + """, vars: %{"id" => id}) end end end diff --git a/test/vf/person/domain.test.exs b/test/vf/person/domain.test.exs @@ -21,80 +21,65 @@ use ZenflowsTest.Help.EctoCase, async: true alias Ecto.Changeset alias Zenflows.VF.{Person, Person.Domain} -setup ctx do - params = %{ - name: Factory.uniq("name"), - image: Factory.img(), - note: Factory.uniq("note"), - primary_location_id: Factory.insert!(:spatial_thing).id, - user: Factory.uniq("user"), - email: "#{Factory.uniq("user")}@example.com", - ecdh_public_key: Base.encode64("ecdh_public_key"), - eddsa_public_key: Base.encode64("eddsa_public_key"), - ethereum_address: Base.encode64("ethereum_address"), - reflow_public_key: Base.encode64("reflow_public_key"), - schnorr_public_key: Base.encode64("schnorr_public_key"), +setup do + %{ + params: %{ + name: Factory.str("name"), + image: Factory.img(), + note: Factory.str("note"), + primary_location_id: Factory.insert!(:spatial_thing).id, + user: Factory.str("user"), + email: "#{Factory.str("user")}@example.com", + ecdh_public_key: Base.encode64("ecdh_public_key"), + eddsa_public_key: Base.encode64("eddsa_public_key"), + ethereum_address: Base.encode64("ethereum_address"), + reflow_public_key: Base.encode64("reflow_public_key"), + schnorr_public_key: Base.encode64("schnorr_public_key"), + }, + inserted: Factory.insert!(:person), } - - if ctx[:no_insert] do - %{params: params} - else - %{params: params, per: Factory.insert!(:person)} - end end -describe "by_id/1" do - test "returns a Person", %{per: per} do - assert %Person{type: :per} = Domain.by_id(per.id) +describe "one/1" do + test "with good id: finds the Person", %{inserted: %{id: id}} do + assert {:ok, %Person{}} = Domain.one(id) end - test "doesn't return an Organization" do + test "with org's id: doesn't return an Organization" do org = Factory.insert!(:organization) - - assert Domain.by_id(org.id) == nil + assert {:error, "not found"} = Domain.one(org.id) end -end - -@tag :no_insert -test "all/0 returns all Persons" do - want_ids = - Enum.map(1..10, fn _ -> Factory.insert!(:person).id end) - |> Enum.sort() - have_ids = - Domain.all() - |> Enum.map(& &1.id) - |> Enum.sort() - assert have_ids == want_ids + test "with bad id: doesn't find the Person" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - test "creates a Person with valid params", %{params: params} do - assert {:ok, %Person{} = per} = Domain.create(params) - - assert per.type == :per - assert per.name == params.name - assert per.note == params.note - assert per.image == params.image - assert per.primary_location_id == params.primary_location_id - assert per.user == params.user - assert per.email == params.email - assert per.ecdh_public_key == params.ecdh_public_key - assert per.eddsa_public_key == params.eddsa_public_key - assert per.ethereum_address == params.ethereum_address - assert per.reflow_public_key == params.reflow_public_key - assert per.schnorr_public_key == params.schnorr_public_key + test "with good params: creates a Person", %{params: params} do + assert {:ok, %Person{} = new} = Domain.create(params) + assert new.type == :per + assert new.name == params.name + assert new.note == params.note + assert new.image == params.image + assert new.primary_location_id == params.primary_location_id + assert new.user == params.user + assert new.email == params.email + assert new.ecdh_public_key == params.ecdh_public_key + assert new.eddsa_public_key == params.eddsa_public_key + assert new.ethereum_address == params.ethereum_address + assert new.reflow_public_key == params.reflow_public_key + assert new.schnorr_public_key == params.schnorr_public_key end - test "doesn't create a Person with invalid params" do + test "with bad params: doesn't create a Person" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates a Person with valid params", %{params: params, per: old} do + test "with good params: updates the Person", %{params: params, inserted: old} do assert {:ok, %Person{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.note == params.note assert new.image == params.image @@ -108,10 +93,8 @@ describe "update/2" do assert new.schnorr_public_key == old.schnorr_public_key end - test "doesn't update a Person with invalid params", %{per: old} do - assert {:ok, %Person{} = new} = - Domain.update(old.id, %{email: "can't change that yet"}) - + test "with bad params: doesn't update the Person", %{inserted: old} do + assert {:ok, %Person{} = new} = Domain.update(old.id, %{email: "can't change that yet"}) assert new.name == old.name assert new.note == old.note assert new.image == old.image @@ -126,8 +109,14 @@ describe "update/2" do end end -test "delete/1 deletes a Person", %{per: %{id: id}} do - assert {:ok, %Person{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the Person", %{inserted: %{id: id}} do + assert {:ok, %Person{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the Person" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end end diff --git a/test/vf/person/type.test.exs b/test/vf/person/type.test.exs @@ -21,106 +21,91 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - "name" => Factory.uniq("name"), + "name" => Factory.str("name"), "image" => Factory.img(), - "note" => Factory.uniq("note"), + "note" => Factory.str("note"), "primaryLocation" => Factory.insert!(:spatial_thing).id, - "user" => Factory.uniq("user"), - "email" => "#{Factory.uniq("user")}@example.com", + "user" => Factory.str("user"), + "email" => "#{Factory.str("user")}@example.com", "ecdhPublicKey" => Base.encode64("ecdh_public_key"), "eddsaPublicKey" => Base.encode64("eddsa_public_key"), "ethereumAddress" => Base.encode64("ethereum_address"), "reflowPublicKey" => Base.encode64("reflow_public_key"), "schnorrPublicKey" => Base.encode64("schnorr_public_key"), }, - per: Factory.insert!(:person), + inserted: Factory.insert!(:person), } end +@frag """ +fragment person on Person { + id + name + note + image + primaryLocation { id } + user + email + ecdhPublicKey + eddsaPublicKey + ethereumAddress + reflowPublicKey + schnorrPublicKey +} +""" + describe "Query" do - test "person()", %{per: per} do + test "person", %{inserted: new} do assert %{data: %{"person" => data}} = run!(""" + #{@frag} query ($id: ID!) { - person(id: $id) { - id - name - note - image - primaryLocation { id } - user - email - ecdhPublicKey - eddsaPublicKey - ethereumAddress - reflowPublicKey - schnorrPublicKey - } + person(id: $id) {...person} } - """, variables: %{"id" => per.id}) - - assert data["id"] == per.id - assert data["name"] == per.name - assert data["note"] == per.note - assert data["image"] == per.image - assert data["primaryLocation"]["id"] == per.primary_location_id - - assert data["user"] == per.user - assert data["email"] == per.email - assert data["ecdhPublicKey"] == per.ecdh_public_key - assert data["eddsaPublicKey"] == per.eddsa_public_key - assert data["ethereumAddress"] == per.ethereum_address - assert data["reflowPublicKey"] == per.reflow_public_key - assert data["schnorrPublicKey"] == per.schnorr_public_key + """, variables: %{"id" => new.id}) + + assert data["id"] == new.id + assert data["name"] == new.name + assert data["note"] == new.note + assert data["image"] == new.image + assert data["primaryLocation"]["id"] == new.primary_location_id + + assert data["user"] == new.user + assert data["email"] == new.email + assert data["ecdhPublicKey"] == new.ecdh_public_key + assert data["eddsaPublicKey"] == new.eddsa_public_key + assert data["ethereumAddress"] == new.ethereum_address + assert data["reflowPublicKey"] == new.reflow_public_key + assert data["schnorrPublicKey"] == new.schnorr_public_key end end describe "Mutation" do - test "createPerson() doesn't create a person without the admin key", %{params: params} do + test "createPerson: doesn't create a person without the admin key", %{params: params} do assert %{data: nil, errors: [%{message: "you are not an admin", path: ["createPerson"]}]} = run!(""" + #{@frag} mutation ($person: PersonCreateParams!) { createPerson(person: $person) { - agent { - id - name - note - primaryLocation { id } - user - email - ecdhPublicKey - eddsaPublicKey - ethereumAddress - reflowPublicKey - schnorrPublicKey - } + agent {...person} } } """, auth?: true, vars: %{"person" => params}) end - test "createPerson() creates a person with the admin key", %{params: params} do + test "createPerson: creates a person with the admin key", %{params: params} do assert %{data: %{"createPerson" => %{"agent" => data}}} = run!(""" + #{@frag} mutation ($person: PersonCreateParams!) { createPerson(person: $person) { - agent { - id - name - note - primaryLocation { id } - user - email - image - ecdhPublicKey - eddsaPublicKey - ethereumAddress - reflowPublicKey - schnorrPublicKey - } + agent {...person} } } - """, vars: %{"person" => params}) + """, + auth?: true, + ctx: %{gql_admin: admin_key()}, + vars: %{"person" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) data = Map.delete(data, "id") @@ -132,60 +117,44 @@ describe "Mutation" do assert data == params end - test "updatePerson()", %{params: params, per: per} do + test "updatePerson", %{params: params, inserted: old} do assert %{data: %{"updatePerson" => %{"agent" => data}}} = run!(""" + #{@frag} mutation ($person: PersonUpdateParams!) { updatePerson(person: $person) { - agent { - id - name - note - primaryLocation { id } - user - email - image - ecdhPublicKey - eddsaPublicKey - ethereumAddress - reflowPublicKey - schnorrPublicKey - } + agent {...person} } } """, vars: %{"person" => params |> Map.take(~w[user name image note primaryLocation]) - |> Map.put("id", per.id) + |> Map.put("id", old.id) }) keys = ~w[user name image note] assert Map.take(data, keys) == Map.take(params, keys) assert data["primaryLocation"]["id"] == params["primaryLocation"] - assert data["id"] == per.id - assert data["email"] == per.email - assert data["ecdhPublicKey"] == per.ecdh_public_key - assert data["eddsaPublicKey"] == per.eddsa_public_key - assert data["ethereumAddress"] == per.ethereum_address - assert data["reflowPublicKey"] == per.reflow_public_key - assert data["schnorrPublicKey"] == per.schnorr_public_key + assert data["id"] == old.id + assert data["email"] == old.email + assert data["ecdhPublicKey"] == old.ecdh_public_key + assert data["eddsaPublicKey"] == old.eddsa_public_key + assert data["ethereumAddress"] == old.ethereum_address + assert data["reflowPublicKey"] == old.reflow_public_key + assert data["schnorrPublicKey"] == old.schnorr_public_key end - test "deletePerson() doesn't delete the person without the admin key", %{per: per} do + test "deletePerson: doesn't delete the person without the admin key", %{inserted: new} do assert %{data: nil, errors: [%{message: "you are not an admin", path: ["deletePerson"]}]} = run!(""" mutation ($id: ID!) { deletePerson(id: $id) } - """, auth?: true, vars: %{"id" => per.id}) + """, auth?: true, vars: %{"id" => new.id}) end - test "deletePerson() deletes the person with the admin key", %{per: per} do - key = - Application.fetch_env!(:zenflows, Zenflows.Admin)[:admin_key] - |> Base.encode16(case: :lower) - + test "deletePerson: deletes the person with the admin key", %{inserted: new} do assert %{data: %{"deletePerson" => true}} = run!( """ @@ -194,9 +163,13 @@ describe "Mutation" do } """, auth?: true, - vars: %{"id" => per.id}, - ctx: %{gql_admin: key} - ) + ctx: %{gql_admin: admin_key()}, + vars: %{"id" => new.id}) + end + + defp admin_key() do + Application.fetch_env!(:zenflows, Zenflows.Admin)[:admin_key] + |> Base.encode16(case: :lower) end end end diff --git a/test/vf/plan/domain.test.exs b/test/vf/plan/domain.test.exs @@ -30,7 +30,6 @@ setup do refinement_of_id: Factory.insert!(:scenario).id, }, inserted: Factory.insert!(:plan), - id: Factory.id(), } end @@ -39,18 +38,18 @@ describe "one/1" do assert {:ok, %Plan{}} = Domain.one(id) end - test "with bad id: doesn't find the Plan", %{id: id} do - assert {:error, "not found"} = Domain.one(id) + test "with bad id: doesn't find the Plan" do + assert {:error, "not found"} = Domain.one(Factory.id()) end end describe "create/1" 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 + assert {:ok, %Plan{} = new} = Domain.create(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 "with bad params: doesn't create an" do @@ -82,8 +81,8 @@ describe "delete/1" do 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) + test "with bad id: doesn't delete the Plan" do + assert {:error, "not found"} = Domain.delete(Factory.id()) end end diff --git a/test/vf/plan/type.test.exs b/test/vf/plan/type.test.exs @@ -23,8 +23,8 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - "name" => Factory.uniq("name"), - "note" => Factory.uniq("note"), + "name" => Factory.str("name"), + "note" => Factory.str("note"), "due" => Factory.iso_now(), "refinementOf" => Factory.insert!(:scenario).id, }, diff --git a/test/vf/process/domain.test.exs b/test/vf/process/domain.test.exs @@ -27,55 +27,55 @@ alias Zenflows.VF.{ Scenario, } -setup ctx do - params = %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), - has_beginning: DateTime.utc_now(), - has_end: DateTime.utc_now(), - finished: Factory.bool(), - classified_as: Factory.uniq_list("class"), - based_on_id: Factory.insert!(:process_specification).id, - planned_within_id: Factory.insert!(:plan).id, - nested_in_id: Factory.insert!(:scenario).id, - } +setup do + %{ + params: %{ + name: Factory.str("name"), + note: Factory.str("note"), + has_beginning: DateTime.utc_now(), + has_end: DateTime.utc_now(), + finished: Factory.bool(), + classified_as: Factory.str_list("class"), + based_on_id: Factory.insert!(:process_specification).id, + planned_within_id: Factory.insert!(:plan).id, + nested_in_id: Factory.insert!(:scenario).id, + }, + inserted: Factory.insert!(:process), + } +end - if ctx[:no_insert] do - %{params: params} - else - %{params: params, process: Factory.insert!(:process)} +describe "one/1" do + test "with good id: finds the Process", %{inserted: %{id: id}} do + assert {:ok, %Process{}} = Domain.one(id) end -end -test "by_id/1 returns a Process", %{process: proc} do - assert %Process{} = Domain.by_id(proc.id) + test "with bad id: doesn't find the Process" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - @tag :no_insert - test "creates a Process", %{params: params} do - assert {:ok, %Process{} = proc} = Domain.create(params) - - assert proc.name == params.name - assert proc.note == params.note - assert proc.has_beginning == params.has_beginning - assert proc.has_end == params.has_end - assert proc.finished == params.finished - assert proc.classified_as == params.classified_as - assert proc.based_on_id == params.based_on_id - assert proc.planned_within_id == params.planned_within_id - assert proc.nested_in_id == params.nested_in_id + test "with good params: creates a Process", %{params: params} do + assert {:ok, %Process{} = new} = Domain.create(params) + assert new.name == params.name + assert new.note == params.note + assert new.has_beginning == params.has_beginning + assert new.has_end == params.has_end + assert new.finished == params.finished + assert new.classified_as == params.classified_as + assert new.based_on_id == params.based_on_id + assert new.planned_within_id == params.planned_within_id + assert new.nested_in_id == params.nested_in_id end - test "doesn't create a Process with invalid params" do + test "with bad params: doesn't create a Process" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates a Process with valid params", %{params: params, process: old} do + test "with good params: updates the Process", %{params: params, inserted: old} do assert {:ok, %Process{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.note == params.note assert new.has_beginning == params.has_beginning @@ -87,9 +87,8 @@ describe "update/2" do assert new.nested_in_id == params.nested_in_id end - test "doesn't update a Process with invalid params", %{process: old} do + test "with bad params: doesn't update the Process", %{inserted: old} do assert {:ok, %Process{} = new} = Domain.update(old.id, %{}) - assert new.name == old.name assert new.note == old.note assert new.has_beginning == old.has_beginning @@ -102,25 +101,31 @@ describe "update/2" do end end -test "delete/1 deletes a Process", %{process: %{id: id}} do - assert {:ok, %Process{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the Process", %{inserted: %{id: id}} do + assert {:ok, %Process{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the Process" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end describe "preload/2" do - test "preloads :based_on", %{process: proc} do + test "preloads :based_on", %{inserted: proc} do proc = Domain.preload(proc, :based_on) assert based_on = %ProcessSpecification{} = proc.based_on assert based_on.id == proc.based_on_id end - test "preloads :planned_within", %{process: proc} do + test "preloads :planned_within", %{inserted: proc} do proc = Domain.preload(proc, :planned_within) assert planed_within = %Plan{} = proc.planned_within assert planed_within.id == proc.planned_within_id end - test "preloads :nested_in", %{process: proc} do + test "preloads :nested_in", %{inserted: proc} do proc = Domain.preload(proc, :nested_in) assert nested_in = %Scenario{} = proc.nested_in assert nested_in.id == proc.nested_in_id diff --git a/test/vf/process/type.test.exs b/test/vf/process/type.test.exs @@ -21,143 +21,110 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), - has_beginning: DateTime.utc_now(), - has_end: DateTime.utc_now(), - finished: Factory.bool(), - classified_as: Factory.uniq_list("class"), - based_on_id: Factory.insert!(:process_specification).id, - planned_within_id: Factory.insert!(:plan).id, - nested_in_id: Factory.insert!(:scenario).id, + "name" => Factory.str("name"), + "note" => Factory.str("note"), + "hasBeginning" => Factory.iso_now(), + "hasEnd" => Factory.iso_now(), + "finished" => Factory.bool(), + "classifiedAs" => Factory.str_list("class"), + "basedOn" => Factory.insert!(:process_specification).id, + "plannedWithin" => Factory.insert!(:plan).id, + "nestedIn" => Factory.insert!(:scenario).id, }, - process: Factory.insert!(:process), + inserted: Factory.insert!(:process), } end +@frag """ +fragment process on Process { + id + name + note + hasBeginning + hasEnd + finished + deletable + classifiedAs + basedOn {id} + plannedWithin {id} + nestedIn {id} +} +""" + describe "Query" do - test "process()", %{process: proc} do + test "process", %{inserted: new} do assert %{data: %{"process" => data}} = - query!(""" - process(id: "#{proc.id}") { - id - name - note - hasBeginning - hasEnd - finished - deletable - classifiedAs - basedOn {id} - plannedWithin {id} - nestedIn {id} + run!(""" + #{@frag} + query ($id: ID!) { + process(id: $id) {...process} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == proc.id - assert data["name"] == proc.name - assert data["hasBeginning"] == DateTime.to_iso8601(proc.has_beginning) - assert data["hasEnd"] == DateTime.to_iso8601(proc.has_end) - assert data["finished"] == proc.finished + assert data["id"] == new.id + assert data["name"] == new.name + assert data["hasBeginning"] == DateTime.to_iso8601(new.has_beginning) + assert data["hasEnd"] == DateTime.to_iso8601(new.has_end) + assert data["finished"] == new.finished assert data["deletable"] == false - assert data["classifiedAs"] == proc.classified_as - assert data["basedOn"]["id"] == proc.based_on_id - assert data["plannedWithin"]["id"] == proc.planned_within_id - assert data["nestedIn"]["id"] == proc.nested_in_id + assert data["classifiedAs"] == new.classified_as + assert data["basedOn"]["id"] == new.based_on_id + assert data["plannedWithin"]["id"] == new.planned_within_id + assert data["nestedIn"]["id"] == new.nested_in_id end end describe "Mutation" do - test "createProcess()", %{params: params} do + test "createProcess", %{params: params} do assert %{data: %{"createProcess" => %{"process" => data}}} = - mutation!(""" - createProcess(process: { - name: "#{params.name}" - note: "#{params.note}" - hasBeginning: "#{params.has_beginning}" - hasEnd: "#{params.has_end}" - finished: #{params.finished} - classifiedAs: #{inspect(params.classified_as)} - basedOn: "#{params.based_on_id}" - plannedWithin: "#{params.planned_within_id}" - nestedIn: "#{params.nested_in_id}" - }) { - process { - id - name - note - hasBeginning - hasEnd - finished - deletable - classifiedAs - basedOn {id} - plannedWithin {id} - nestedIn {id} + run!(""" + #{@frag} + mutation ($process: ProcessCreateParams!) { + createProcess(process: $process) { + process {...process} } } - """) + """, vars: %{"process" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["name"] == params.name - assert data["hasBeginning"] == DateTime.to_iso8601(params.has_beginning) - assert data["hasEnd"] == DateTime.to_iso8601(params.has_end) - assert data["finished"] == params.finished + + keys = ~w[name hasBeginning hasEnd finished classifiedAs] + assert Map.take(data, keys) == Map.take(params, keys) + assert data["deletable"] == false - assert data["classifiedAs"] == params.classified_as - assert data["basedOn"]["id"] == params.based_on_id - assert data["plannedWithin"]["id"] == params.planned_within_id - assert data["nestedIn"]["id"] == params.nested_in_id + assert data["basedOn"]["id"] == params["basedOn"] + assert data["plannedWithin"]["id"] == params["plannedWithin"] + assert data["nestedIn"]["id"] == params["nestedIn"] end - test "updateProcess()", %{params: params, process: proc} do + test "updateProcess", %{params: params, inserted: old} do assert %{data: %{"updateProcess" => %{"process" => data}}} = - mutation!(""" - updateProcess(process: { - id: "#{proc.id}" - name: "#{params.name}" - note: "#{params.note}" - hasBeginning: "#{params.has_beginning}" - hasEnd: "#{params.has_end}" - finished: #{params.finished} - classifiedAs: #{inspect(params.classified_as)} - basedOn: "#{params.based_on_id}" - plannedWithin: "#{params.planned_within_id}" - nestedIn: "#{params.nested_in_id}" - }) { - process { - id - name - note - hasBeginning - hasEnd - finished - deletable - classifiedAs - basedOn {id} - plannedWithin {id} - nestedIn {id} + run!(""" + #{@frag} + mutation ($process: ProcessUpdateParams!) { + updateProcess(process: $process) { + process {...process} } } - """) + """, vars: %{"process" => Map.put(params, "id", old.id)}) + + assert data["id"] == old.id + keys = ~w[name hasBeginning hasEnd finished classifiedAs] + assert Map.take(data, keys) == Map.take(params, keys) - assert data["id"] == proc.id - assert data["name"] == params.name - assert data["hasBeginning"] == DateTime.to_iso8601(params.has_beginning) - assert data["hasEnd"] == DateTime.to_iso8601(params.has_end) - assert data["finished"] == params.finished assert data["deletable"] == false - assert data["classifiedAs"] == params.classified_as - assert data["basedOn"]["id"] == params.based_on_id - assert data["plannedWithin"]["id"] == params.planned_within_id - assert data["nestedIn"]["id"] == params.nested_in_id + assert data["basedOn"]["id"] == params["basedOn"] + assert data["plannedWithin"]["id"] == params["plannedWithin"] + assert data["nestedIn"]["id"] == params["nestedIn"] end - test "deleteProcess()", %{process: %{id: id}} do + test "deleteProcess", %{inserted: %{id: id}} do assert %{data: %{"deleteProcess" => true}} = - mutation!(""" - deleteProcess(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteProcess(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/process_specification/domain.test.exs b/test/vf/process_specification/domain.test.exs @@ -24,48 +24,57 @@ alias Zenflows.VF.{ProcessSpecification, ProcessSpecification.Domain} setup do %{ params: %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), + name: Factory.str("name"), + note: Factory.str("note"), }, - process_specification: Factory.insert!(:process_specification), + inserted: Factory.insert!(:process_specification), } end -test "by_id/1 returns a ProcessSpecification", %{process_specification: proc_spec} do - assert %ProcessSpecification{} = Domain.by_id(proc_spec.id) +describe "one/1" do + test "with good id: finds the ProcessSpecification", %{inserted: %{id: id}} do + assert {:ok, %ProcessSpecification{}} = Domain.one(id) + end + + test "with bad id: doesn't find the ProcessSpecification" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - test "creates a ProcessSpecification with valid params", %{params: params} do - assert {:ok, %ProcessSpecification{} = proc_spec} = Domain.create(params) - - assert proc_spec.name == params.name - assert proc_spec.note == params.note + test "with good params: creates a ProcessSpecification", %{params: params} do + assert {:ok, %ProcessSpecification{} = new} = Domain.create(params) + assert new.name == params.name + assert new.note == params.note end - test "doesn't create a ProcessSpecification with invalid params" do + test "with bad params: doesn't create a ProcessSpecification" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates a ProcessSpecification with valid params", %{params: params, process_specification: old} do + test "with good params: updates the ProcessSpecification", %{params: params, inserted: old} do assert {:ok, %ProcessSpecification{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.note == params.note end - test "doesn't update a ProcessSpecification", %{process_specification: old} do + test "with bad params: doesn't update the ProcessSpecification", %{inserted: old} do assert {:ok, %ProcessSpecification{} = new} = Domain.update(old.id, %{}) - assert new.name == old.name assert new.note == old.note end end -test "delete/1 deletes a ProcessSpecification", %{process_specification: %{id: id}} do - assert {:ok, %ProcessSpecification{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the ProcessSpecification", %{inserted: %{id: id}} do + assert {:ok, %ProcessSpecification{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the ProcessSpecification" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end end diff --git a/test/vf/process_specification/type.test.exs b/test/vf/process_specification/type.test.exs @@ -21,77 +21,77 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), + "name" => Factory.str("name"), + "note" => Factory.str("note"), }, - process_specification: Factory.insert!(:process_specification), + inserted: Factory.insert!(:process_specification), } end +@frag """ +fragment processSpecification on ProcessSpecification { + id + name + note +} +""" + describe "Query" do - test "processSpecification()", %{process_specification: proc_spec} do + test "processSpecification", %{inserted: new} do assert %{data: %{"processSpecification" => data}} = - query!(""" - processSpecification(id: "#{proc_spec.id}") { - id - name - note + run!(""" + #{@frag} + query ($id: ID!) { + processSpecification(id: $id) {...processSpecification} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == proc_spec.id - assert data["name"] == proc_spec.name - assert data["note"] == proc_spec.note + assert data["id"] == new.id + assert data["name"] == new.name + assert data["note"] == new.note end end describe "Mutation" do - test "createProcessSpecification()", %{params: params} do + test "createProcessSpecification", %{params: params} do assert %{data: %{"createProcessSpecification" => %{"processSpecification" => data}}} = - mutation!(""" - createProcessSpecification(processSpecification: { - name: "#{params.name}" - note: "#{params.note}" - }) { - processSpecification { - id - name - note + run!(""" + #{@frag} + mutation ($processSpecification: ProcessSpecificationCreateParams!) { + createProcessSpecification(processSpecification: $processSpecification) { + processSpecification {...processSpecification} } } - """) + """, vars: %{"processSpecification" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["name"] == params.name - assert data["note"] == params.note + assert data["name"] == params["name"] + assert data["note"] == params["note"] end - test "updateProcessSpecification()", %{params: params, process_specification: proc_spec} do + test "updateProcessSpecification", %{params: params, inserted: old} do assert %{data: %{"updateProcessSpecification" => %{"processSpecification" => data}}} = - mutation!(""" - updateProcessSpecification(processSpecification: { - id: "#{proc_spec.id}" - name: "#{params.name}" - note: "#{params.note}" - }) { - processSpecification { - id - name - note + run!(""" + #{@frag} + mutation ($processSpecification: ProcessSpecificationUpdateParams!) { + updateProcessSpecification(processSpecification: $processSpecification) { + processSpecification {...processSpecification} } } - """) + """, vars: %{"processSpecification" => Map.put(params, "id", old.id)}) - assert data["id"] == proc_spec.id - assert data["name"] == params.name - assert data["note"] == params.note + assert data["id"] == old.id + assert data["name"] == params["name"] + assert data["note"] == params["note"] end - test "deleteProcessSpecification()", %{process_specification: %{id: id}} do + test "deleteProcessSpecification", %{inserted: %{id: id}} do assert %{data: %{"deleteProcessSpecification" => true}} = - mutation!(""" - deleteProcessSpecification(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteProcessSpecification(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/product_batch/domain.test.exs b/test/vf/product_batch/domain.test.exs @@ -24,7 +24,7 @@ alias Zenflows.VF.{ProductBatch, ProductBatch.Domain} setup do %{ params: %{ - batch_number: Factory.uniq("batch number"), + batch_number: Factory.str("batch number"), expiry_date: DateTime.utc_now(), production_date: DateTime.utc_now(), }, @@ -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.str("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 diff --git a/test/vf/proposal.test.exs b/test/vf/proposal.test.exs @@ -22,11 +22,11 @@ alias Zenflows.VF.Proposal setup do %{params: %{ - name: Factory.uniq("name"), + name: Factory.str("name"), has_beginning: DateTime.utc_now(), has_end: DateTime.utc_now(), unit_based: Factory.bool(), - note: Factory.uniq("note"), + note: Factory.str("note"), eligible_location_id: Factory.build(:spatial_thing).id, }} end diff --git a/test/vf/proposal/domain.test.exs b/test/vf/proposal/domain.test.exs @@ -35,7 +35,6 @@ setup do eligible_location_id: Factory.insert!(:spatial_thing).id, }, inserted: Factory.insert!(:proposal), - id: Factory.id(), } end @@ -44,37 +43,36 @@ describe "one/1" do assert {:ok, %Proposal{}} = Domain.one(id) end - test "with bad id: doesn't find the Proposal", %{id: id} do - assert {:error, "not found"} = Domain.one(id) + test "with bad id: doesn't find the Proposal" do + assert {:error, "not found"} = Domain.one(Factory.id()) end end describe "create/1" do test "with good params: creates a Proposal", %{params: params} do - assert {:ok, %Proposal{} = prop} = Domain.create(params) - assert prop.name == params.name - assert prop.note == params.note - assert prop.has_beginning == params.has_beginning - assert prop.has_end == params.has_end - assert prop.unit_based == params.unit_based - assert prop.eligible_location_id == params.eligible_location_id + assert {:ok, %Proposal{} = new} = Domain.create(params) + assert new.name == params.name + assert new.note == params.note + assert new.has_beginning == params.has_beginning + assert new.has_end == params.has_end + assert new.unit_based == params.unit_based + assert new.eligible_location_id == params.eligible_location_id end test "with empty params: creates a Proposal" do - assert {:ok, %Proposal{} = prop} = Domain.create(%{}) - assert prop.name == nil - assert prop.note == nil - assert prop.has_beginning == nil - assert prop.has_end == nil - assert prop.unit_based == false # since it defaults - assert prop.eligible_location_id == nil + assert {:ok, %Proposal{} = new} = Domain.create(%{}) + assert new.name == nil + assert new.note == nil + assert new.has_beginning == nil + assert new.has_end == nil + assert new.unit_based == false # since it defaults + assert new.eligible_location_id == nil end end describe "update/2" do test "with good params: updates the Proposal", %{params: params, inserted: old} do assert {:ok, %Proposal{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.note == params.note assert new.has_beginning == params.has_beginning @@ -85,7 +83,6 @@ describe "update/2" do test "with bad params: doesn't update the Proposal", %{inserted: old} do assert {:ok, %Proposal{} = new} = Domain.update(old.id, %{}) - assert new.name == old.name assert new.note == old.note assert new.has_beginning == old.has_beginning @@ -101,8 +98,8 @@ describe "delete/1" do assert {:error, "not found"} = Domain.one(id) end - test "with bad id: doesn't delete the Proposal", %{id: id} do - assert {:error, "not found"} = Domain.delete(id) + test "with bad id: doesn't delete the Proposal" do + assert {:error, "not found"} = Domain.delete(Factory.id()) end end diff --git a/test/vf/proposal/type.test.exs b/test/vf/proposal/type.test.exs @@ -43,61 +43,28 @@ fragment proposal on Proposal { eligibleLocation {id} } """ + describe "Query" do - test "proposal", %{inserted: prop} do + test "proposal", %{inserted: new} do assert %{data: %{"proposal" => data}} = run!(""" #{@frag} query ($id: ID!) { proposal(id: $id) {...proposal} } - """, vars: %{"id" => prop.id}) + """, vars: %{"id" => new.id}) - assert data["id"] == prop.id - assert data["name"] == prop.name - assert data["note"] == prop.note - assert data["unitBased"] == prop.unit_based - assert data["eligibleLocation"]["id"] == prop.eligible_location_id + assert data["id"] == new.id + assert data["name"] == new.name + assert data["note"] == new.note + assert data["unitBased"] == new.unit_based + assert data["eligibleLocation"]["id"] == new.eligible_location_id assert {:ok, has_beginning, 0} = DateTime.from_iso8601(data["hasBeginning"]) assert DateTime.compare(DateTime.utc_now(), has_beginning) != :lt assert {:ok, has_end, 0} = DateTime.from_iso8601(data["hasEnd"]) assert DateTime.compare(DateTime.utc_now(), has_end) != :lt end - test "proposals" do - assert %{data: %{"proposals" => data}} = - run!(""" - #{@frag} - query { - proposals { - pageInfo { - startCursor - endCursor - hasPreviousPage - hasNextPage - totalCount - pageLimit - } - edges { - cursor - node {...proposal} - } - } - } - """) - assert %{ - "pageInfo" => %{ - "startCursor" => nil, - "endCursor" => nil, - "hasPreviousPage" => false, - "hasNextPage" => false, - "totalCount" => nil, - "pageLimit" => nil, - }, - "edges" => [], - } = data - end - test "offers" do assert %{data: %{"offers" => data}} = run!(""" @@ -185,7 +152,7 @@ describe "Mutation" do assert data["eligibleLocation"]["id"] == params["eligibleLocation"] end - test "updateProposal", %{params: params, inserted: prop} do + test "updateProposal", %{params: params, inserted: old} do assert %{data: %{"updateProposal" => %{"proposal" => data}}} = run!(""" #{@frag} @@ -194,9 +161,9 @@ describe "Mutation" do proposal {...proposal} } } - """, vars: %{"proposal" => params |> Map.put("id", prop.id)}) + """, vars: %{"proposal" => Map.put(params, "id", old.id)}) - assert data["id"] == prop.id + assert data["id"] == old.id keys = ~w[name note unitBased hasBeginning hasEnd] assert Map.take(data, keys) == Map.take(params, keys) assert data["eligibleLocation"]["id"] == params["eligibleLocation"] diff --git a/test/vf/proposed_intent/domain.test.exs b/test/vf/proposed_intent/domain.test.exs @@ -34,7 +34,6 @@ setup do published_in_id: Factory.insert!(:proposal).id, }, inserted: Factory.insert!(:proposed_intent), - id: Factory.id(), } end @@ -43,17 +42,17 @@ describe "one/1" do assert {:ok, %ProposedIntent{}} = Domain.one(id) end - test "with bad id: doesn't find the ProposedIntent", %{id: id} do - assert {:error, "not found"} = Domain.one(id) + test "with bad id: doesn't find the ProposedIntent" do + assert {:error, "not found"} = Domain.one(Factory.id()) end end describe "create/1" do test "with good params: creates a ProposedIntent", %{params: params} do - assert {:ok, %ProposedIntent{} = prop_int} = Domain.create(params) - assert prop_int.reciprocal == params.reciprocal - assert prop_int.publishes_id == params.publishes_id - assert prop_int.published_in_id == params.published_in_id + assert {:ok, %ProposedIntent{} = new} = Domain.create(params) + assert new.reciprocal == params.reciprocal + assert new.publishes_id == params.publishes_id + assert new.published_in_id == params.published_in_id end test "with bad params: doesn't create a ProposedIntent" do @@ -67,8 +66,8 @@ describe "delete/1" do assert {:error, "not found"} = Domain.one(id) end - test "with bad id: doesn't delete the ProposedIntent", %{id: id} do - assert {:error, "not found"} = Domain.delete(id) + test "with bad id: doesn't delete the ProposedIntent" do + assert {:error, "not found"} = Domain.delete(Factory.id()) end end diff --git a/test/vf/recipe_exchange/domain.test.exs b/test/vf/recipe_exchange/domain.test.exs @@ -24,48 +24,57 @@ alias Zenflows.VF.{RecipeExchange, RecipeExchange.Domain} setup do %{ params: %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), + name: Factory.str("name"), + note: Factory.str("note"), }, - recipe_exchange: Factory.insert!(:recipe_exchange), + inserted: Factory.insert!(:recipe_exchange), } end -test "by_id/1 returns a RecipeExchange", %{recipe_exchange: rec_exch} do - assert %RecipeExchange{} = Domain.by_id(rec_exch.id) +describe "one/1" do + test "with good id: finds the RecipeExchange", %{inserted: %{id: id}} do + assert {:ok, %RecipeExchange{}} = Domain.one(id) + end + + test "with bad id: doesn't find the RecipeExchange" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - test "creates a RecipeExchange with valid params", %{params: params} do - assert {:ok, %RecipeExchange{} = rec_exch} = Domain.create(params) - - assert rec_exch.name == params.name - assert rec_exch.note == params.note + test "with good params: creates a RecipeExchange", %{params: params} do + assert {:ok, %RecipeExchange{} = new} = Domain.create(params) + assert new.name == params.name + assert new.note == params.note end - test "doesn't create a RecipeExchange with invalid params" do + test "with bad params: doesn't create a Process" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates a RecipeExchange with valid params", %{params: params, recipe_exchange: old} do + test "with good params: updates the RecipeExchange", %{params: params, inserted: old} do assert {:ok, %RecipeExchange{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.note == params.note end - test "doesn't update a RecipeExchange", %{recipe_exchange: old} do + test "with bad params: doesn't update the RecipeExchange", %{inserted: old} do assert {:ok, %RecipeExchange{} = new} = Domain.update(old.id, %{}) - assert new.name == old.name assert new.note == old.note end end -test "delete/1 deletes a RecipeExchange", %{recipe_exchange: %{id: id}} do - assert {:ok, %RecipeExchange{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the RecipeExchange", %{inserted: %{id: id}} do + assert {:ok, %RecipeExchange{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the RecipeExchange" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end end diff --git a/test/vf/recipe_exchange/type.test.exs b/test/vf/recipe_exchange/type.test.exs @@ -21,77 +21,77 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), + "name" => Factory.str("name"), + "note" => Factory.str("note"), }, - recipe_exchange: Factory.insert!(:recipe_exchange), + inserted: Factory.insert!(:recipe_exchange), } end +@frag """ +fragment recipeExchange on RecipeExchange { + id + name + note +} +""" + describe "Query" do - test "recipeExchange()", %{recipe_exchange: rec_exch} do + test "recipeExchange", %{inserted: new} do assert %{data: %{"recipeExchange" => data}} = - query!(""" - recipeExchange(id: "#{rec_exch.id}") { - id - name - note + run!(""" + #{@frag} + query ($id: ID!) { + recipeExchange(id: $id) {...recipeExchange} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == rec_exch.id - assert data["name"] == rec_exch.name - assert data["note"] == rec_exch.note + assert data["id"] == new.id + assert data["name"] == new.name + assert data["note"] == new.note end end describe "Mutation" do - test "createRecipeExchange()", %{params: params} do + test "createRecipeExchange", %{params: params} do assert %{data: %{"createRecipeExchange" => %{"recipeExchange" => data}}} = - mutation!(""" - createRecipeExchange(recipeExchange: { - name: "#{params.name}" - note: "#{params.note}" - }) { - recipeExchange { - id - name - note + run!(""" + #{@frag} + mutation ($recipeExchange: RecipeExchangeCreateParams!) { + createRecipeExchange(recipeExchange: $recipeExchange) { + recipeExchange {...recipeExchange} } } - """) + """, vars: %{"recipeExchange" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["name"] == params.name - assert data["note"] == params.note + assert data["name"] == params["name"] + assert data["note"] == params["note"] end - test "updateRecipeExchange()", %{params: params, recipe_exchange: rec_exch} do + test "updateRecipeExchange", %{params: params, inserted: old} do assert %{data: %{"updateRecipeExchange" => %{"recipeExchange" => data}}} = - mutation!(""" - updateRecipeExchange(recipeExchange: { - id: "#{rec_exch.id}" - name: "#{params.name}" - note: "#{params.note}" - }) { - recipeExchange { - id - name - note + run!(""" + #{@frag} + mutation ($recipeExchange: RecipeExchangeUpdateParams!) { + updateRecipeExchange(recipeExchange: $recipeExchange) { + recipeExchange {...recipeExchange} } } - """) + """, vars: %{"recipeExchange" => Map.put(params, "id", old.id)}) - assert data["id"] == rec_exch.id - assert data["name"] == params.name - assert data["note"] == params.note + assert data["id"] == old.id + assert data["name"] == params["name"] + assert data["note"] == params["note"] end - test "deleteRecipeExchange()", %{recipe_exchange: %{id: id}} do + test "deleteRecipeExchange", %{inserted: %{id: id}} do assert %{data: %{"deleteRecipeExchange" => true}} = - mutation!(""" - deleteRecipeExchange(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteRecipeExchange(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/recipe_flow/domain.test.exs b/test/vf/recipe_flow/domain.test.exs @@ -29,86 +29,83 @@ alias Zenflows.VF.{ RecipeResource, } -setup ctx do - params = %{ - action_id: Factory.build(:action_id), - recipe_input_of_id: Factory.insert!(:recipe_process).id, - recipe_output_of_id: Factory.insert!(:recipe_process).id, - recipe_flow_resource_id: Factory.insert!(:recipe_resource).id, - resource_quantity: %{ - has_unit_id: Factory.insert!(:unit).id, - has_numerical_value: Factory.float(), - }, - effort_quantity: %{ - has_unit_id: Factory.insert!(:unit).id, - has_numerical_value: Factory.float(), - }, - recipe_clause_of_id: Factory.insert!(:recipe_exchange).id, - note: Factory.uniq("some note"), - } +setup do + %{ + params: %{ + action_id: Factory.build(:action_id), + recipe_input_of_id: Factory.insert!(:recipe_process).id, + recipe_output_of_id: Factory.insert!(:recipe_process).id, + recipe_flow_resource_id: Factory.insert!(:recipe_resource).id, + resource_quantity: %{ + has_unit_id: Factory.insert!(:unit).id, + has_numerical_value: Factory.float(), + }, + effort_quantity: %{ + has_unit_id: Factory.insert!(:unit).id, + has_numerical_value: Factory.float(), + }, + recipe_clause_of_id: Factory.insert!(:recipe_exchange).id, + note: Factory.str("some note"), + }, + inserted: Factory.insert!(:recipe_flow), + } +end - if ctx[:no_insert] do - %{params: params} - else - %{params: params, recipe_flow: Factory.insert!(:recipe_flow)} +describe "one/1" do + test "with good id: finds the RecipeFlow", %{inserted: %{id: id}} do + assert {:ok, %RecipeFlow{}} = Domain.one(id) end -end -test "by_id/1 returns a RecipeFlow", %{recipe_flow: rec_flow} do - assert %RecipeFlow{} = Domain.by_id(rec_flow.id) + test "with bad id: doesn't find the RecipeFlow" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - @tag :no_insert - test "creates a RecipeFlow with valid params without `:effort_quantity`", %{params: params} do + test "with good params (with :resource_quantity): creates a RecipeFlow", %{params: params} do params = Map.delete(params, :effort_quantity) - - assert {:ok, %RecipeFlow{} = rec_flow} = Domain.create(params) - assert rec_flow.note == params.note - assert rec_flow.action_id == params.action_id - assert rec_flow.recipe_input_of_id == params.recipe_input_of_id - assert rec_flow.recipe_output_of_id == params.recipe_output_of_id - assert rec_flow.recipe_flow_resource_id == params.recipe_flow_resource_id - assert rec_flow.recipe_clause_of_id == params.recipe_clause_of_id - assert rec_flow.resource_quantity_has_unit_id == params.resource_quantity.has_unit_id - assert rec_flow.resource_quantity_has_numerical_value == params.resource_quantity.has_numerical_value - assert rec_flow.effort_quantity_has_unit_id == nil - assert rec_flow.effort_quantity_has_numerical_value == nil + assert {:ok, %RecipeFlow{} = new} = Domain.create(params) + assert new.note == params.note + assert new.action_id == params.action_id + assert new.recipe_input_of_id == params.recipe_input_of_id + assert new.recipe_output_of_id == params.recipe_output_of_id + assert new.recipe_flow_resource_id == params.recipe_flow_resource_id + assert new.recipe_clause_of_id == params.recipe_clause_of_id + assert new.resource_quantity_has_unit_id == params.resource_quantity.has_unit_id + assert new.resource_quantity_has_numerical_value == params.resource_quantity.has_numerical_value + assert new.effort_quantity_has_unit_id == nil + assert new.effort_quantity_has_numerical_value == nil end - @tag :no_insert - test "creates a RecipeFlow with valid params without :resource_quantity", %{params: params} do + test "with good params (with :effort_quantity): creates a RecipeFlow", %{params: params} do params = Map.delete(params, :resource_quantity) - - assert {:ok, %RecipeFlow{} = rec_flow} = Domain.create(params) - assert rec_flow.note == params.note - assert rec_flow.action_id == params.action_id - assert rec_flow.recipe_input_of_id == params.recipe_input_of_id - assert rec_flow.recipe_output_of_id == params.recipe_output_of_id - assert rec_flow.recipe_flow_resource_id == params.recipe_flow_resource_id - assert rec_flow.recipe_clause_of_id == params.recipe_clause_of_id - assert rec_flow.resource_quantity_has_unit_id == nil - assert rec_flow.resource_quantity_has_numerical_value == nil - assert rec_flow.effort_quantity_has_unit_id == params.effort_quantity.has_unit_id - assert rec_flow.effort_quantity_has_numerical_value == params.effort_quantity.has_numerical_value + assert {:ok, %RecipeFlow{} = new} = Domain.create(params) + assert new.note == params.note + assert new.action_id == params.action_id + assert new.recipe_input_of_id == params.recipe_input_of_id + assert new.recipe_output_of_id == params.recipe_output_of_id + assert new.recipe_flow_resource_id == params.recipe_flow_resource_id + assert new.recipe_clause_of_id == params.recipe_clause_of_id + assert new.resource_quantity_has_unit_id == nil + assert new.resource_quantity_has_numerical_value == nil + assert new.effort_quantity_has_unit_id == params.effort_quantity.has_unit_id + assert new.effort_quantity_has_numerical_value == params.effort_quantity.has_numerical_value end - @tag :no_insert - test "creates a RecipeFlow with valid params", %{params: params} do - assert {:ok, %RecipeFlow{} = rec_flow} = Domain.create(params) - assert rec_flow.note == params.note - assert rec_flow.action_id == params.action_id - assert rec_flow.recipe_input_of_id == params.recipe_input_of_id - assert rec_flow.recipe_output_of_id == params.recipe_output_of_id - assert rec_flow.recipe_flow_resource_id == params.recipe_flow_resource_id - assert rec_flow.resource_quantity_has_unit_id == params.resource_quantity.has_unit_id - assert rec_flow.resource_quantity_has_numerical_value == params.resource_quantity.has_numerical_value - assert rec_flow.effort_quantity_has_unit_id == params.effort_quantity.has_unit_id - assert rec_flow.effort_quantity_has_numerical_value == params.effort_quantity.has_numerical_value + test "with good params (with :resource_quantity and :effort_quantity): creates a RecipeFlow", %{params: params} do + assert {:ok, %RecipeFlow{} = new} = Domain.create(params) + assert new.note == params.note + assert new.action_id == params.action_id + assert new.recipe_input_of_id == params.recipe_input_of_id + assert new.recipe_output_of_id == params.recipe_output_of_id + assert new.recipe_flow_resource_id == params.recipe_flow_resource_id + assert new.resource_quantity_has_unit_id == params.resource_quantity.has_unit_id + assert new.resource_quantity_has_numerical_value == params.resource_quantity.has_numerical_value + assert new.effort_quantity_has_unit_id == params.effort_quantity.has_unit_id + assert new.effort_quantity_has_numerical_value == params.effort_quantity.has_numerical_value end - @tag :no_insert - test "doesn't create a RecipeFlow with valid params without `:resource_quantity` and `:effort_quantity`", %{params: params} do + test "with bad params (without :resource_qunatity and :effort_quantit): doesn't create a RecipeFlow", %{params: params} do params = params |> Map.delete(:resource_quantity) @@ -119,38 +116,14 @@ describe "create/1" do assert Keyword.has_key?(errs, :effort_quantity) end - test "doesn't create a RecipeFlow with invalid params" do + test "with bad params: doesn't create a RecipeFlow" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "doesn't update a RecipeFlow", %{recipe_flow: old} do - assert {:ok, %RecipeFlow{} = new} = Domain.update(old.id, %{}) - assert new.note == old.note - assert new.action_id == old.action_id - assert new.recipe_input_of_id == old.recipe_input_of_id - assert new.recipe_output_of_id == old.recipe_output_of_id - assert new.recipe_flow_resource_id == old.recipe_flow_resource_id - assert new.recipe_clause_of_id == old.recipe_clause_of_id - assert new.resource_quantity_has_unit_id == old.resource_quantity_has_unit_id - assert new.resource_quantity_has_numerical_value == old.resource_quantity_has_numerical_value - assert new.effort_quantity_has_unit_id == old.effort_quantity_has_unit_id - assert new.effort_quantity_has_numerical_value == old.effort_quantity_has_numerical_value - end - - test "doesn't update a RecipeFlow with valid params with `:resource_quantity` and `:effort_quantity` set to nil", %{params: params, recipe_flow: old} do - params = - params - |> Map.put(:resource_quantity, nil) - |> Map.put(:effort_quantity, nil) - - assert {:error, %Changeset{}} = Domain.update(old.id, params) - end - - test "updates a RecipeFlow with valid params without `:effort_quantity`", %{params: params, recipe_flow: old} do + test "with good params (with :resource_quantity): updates the RecipeFlow", %{params: params, inserted: old} do params = Map.delete(params, :effort_quantity) - assert {:ok, %RecipeFlow{} = new} = Domain.update(old.id, params) assert new.note == params.note assert new.action_id == params.action_id @@ -164,9 +137,8 @@ describe "update/2" do assert new.effort_quantity_has_numerical_value == old.effort_quantity_has_numerical_value end - test "updates a RecipeFlow with valid params without `:resource_quantity`", %{params: params, recipe_flow: old} do + test "with good params (with :effort_quantity): updates the RecipeFlow", %{params: params, inserted: old} do params = Map.delete(params, :resource_quantity) - assert {:ok, %RecipeFlow{} = new} = Domain.update(old.id, params) assert new.note == params.note assert new.action_id == params.action_id @@ -180,11 +152,11 @@ describe "update/2" do assert new.effort_quantity_has_numerical_value == params.effort_quantity.has_numerical_value end - test "updates a RecipeFlow with valid params with a new `:resource_quantity` set to `nil`", %{params: params, recipe_flow: old} do - params = - params - |> Map.delete(:effort_quantity) - |> Map.put(:resource_quantity, nil) + test "with good params (with :resource_quantity set to nil): updates the RecipeFlow", %{params: params, inserted: old} do + params = + params + |> Map.delete(:effort_quantity) + |> Map.put(:resource_quantity, nil) assert {:ok, %RecipeFlow{} = new} = Domain.update(old.id, params) assert new.note == params.note @@ -199,11 +171,11 @@ describe "update/2" do assert new.effort_quantity_has_numerical_value == old.effort_quantity_has_numerical_value end - test "updates a RecipeFlow with valid params with a new `:effort_quantity` set to `nil`", %{params: params, recipe_flow: old} do - params = - params - |> Map.delete(:resource_quantity) - |> Map.put(:effort_quantity, nil) + test "with good params (with :effort_quantity set to nil): updates the RecipeFlow", %{params: params, inserted: old} do + params = + params + |> Map.delete(:resource_quantity) + |> Map.put(:effort_quantity, nil) assert {:ok, %RecipeFlow{} = new} = Domain.update(old.id, params) assert new.note == params.note @@ -217,53 +189,82 @@ describe "update/2" do assert new.effort_quantity_has_unit_id == nil assert new.effort_quantity_has_numerical_value == nil end + + test "with bad params: doesn't update the RecipeFlow", %{inserted: old} do + assert {:ok, %RecipeFlow{} = new} = Domain.update(old.id, %{}) + assert new.note == old.note + assert new.action_id == old.action_id + assert new.recipe_input_of_id == old.recipe_input_of_id + assert new.recipe_output_of_id == old.recipe_output_of_id + assert new.recipe_flow_resource_id == old.recipe_flow_resource_id + assert new.recipe_clause_of_id == old.recipe_clause_of_id + assert new.resource_quantity_has_unit_id == old.resource_quantity_has_unit_id + assert new.resource_quantity_has_numerical_value == old.resource_quantity_has_numerical_value + assert new.effort_quantity_has_unit_id == old.effort_quantity_has_unit_id + assert new.effort_quantity_has_numerical_value == old.effort_quantity_has_numerical_value + end + + test "with bad params (with :resource_quantity and :effort_quantity set to nil): doesn't update the RecipeFlow", %{params: params, inserted: old} do + params = + params + |> Map.put(:resource_quantity, nil) + |> Map.put(:effort_quantity, nil) + + assert {:error, %Changeset{}} = Domain.update(old.id, params) + end end -test "delete/1 deletes a RecipeFlow", %{recipe_flow: %{id: id}} do - assert {:ok, %RecipeFlow{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the RecipeFlow", %{inserted: %{id: id}} do + assert {:ok, %RecipeFlow{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the RecipeFlow" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end describe "preload/2" do - test "preloads :resource_quantity", %{recipe_flow: rec_flow} do + test "preloads :resource_quantity", %{inserted: rec_flow} do rec_flow = Domain.preload(rec_flow, :resource_quantity) assert res_qty = %Measure{} = rec_flow.resource_quantity assert res_qty.has_unit_id == rec_flow.resource_quantity_has_unit_id assert res_qty.has_numerical_value == rec_flow.resource_quantity_has_numerical_value end - test "preloads :effort_quantity", %{recipe_flow: rec_flow} do + test "preloads :effort_quantity", %{inserted: rec_flow} do rec_flow = Domain.preload(rec_flow, :effort_quantity) assert eff_qty = %Measure{} = rec_flow.effort_quantity assert eff_qty.has_unit_id == rec_flow.effort_quantity_has_unit_id assert eff_qty.has_numerical_value == rec_flow.effort_quantity_has_numerical_value end - test "preloads :recipe_flow_resource", %{recipe_flow: rec_flow} do + test "preloads :recipe_flow_resource", %{inserted: rec_flow} do rec_flow = Domain.preload(rec_flow, :recipe_flow_resource) assert rec_flow_res = %RecipeResource{} = rec_flow.recipe_flow_resource assert rec_flow_res.id == rec_flow.recipe_flow_resource_id end - test "preloads :action", %{recipe_flow: rec_flow} do + test "preloads :action", %{inserted: rec_flow} do rec_flow = Domain.preload(rec_flow, :action) assert action = %Action{} = rec_flow.action assert action.id == rec_flow.action_id end - test "preloads :recipe_input_of", %{recipe_flow: rec_flow} do + test "preloads :recipe_input_of", %{inserted: rec_flow} do rec_flow = Domain.preload(rec_flow, :recipe_input_of) assert rec_in_of = %RecipeProcess{} = rec_flow.recipe_input_of assert rec_in_of.id == rec_flow.recipe_input_of_id end - test "preloads :recipe_output_of", %{recipe_flow: rec_flow} do + test "preloads :recipe_output_of", %{inserted: rec_flow} do rec_flow = Domain.preload(rec_flow, :recipe_output_of) assert rec_out_of = %RecipeProcess{} = rec_flow.recipe_output_of assert rec_out_of.id == rec_flow.recipe_output_of_id end - test "preloads :recipe_clause_of", %{recipe_flow: rec_flow} do + test "preloads :recipe_clause_of", %{inserted: rec_flow} do rec_flow = Domain.preload(rec_flow, :recipe_clause_of) assert rec_clause_of = %RecipeExchange{} = rec_flow.recipe_clause_of assert rec_clause_of.id == rec_flow.recipe_clause_of_id diff --git a/test/vf/recipe_flow/type.test.exs b/test/vf/recipe_flow/type.test.exs @@ -18,221 +18,128 @@ defmodule ZenflowsTest.VF.RecipeFlow.Type do use ZenflowsTest.Help.AbsinCase, async: true -alias Zenflows.VF.RecipeFlow.Domain - setup do %{ params: %{ - note: Factory.uniq("some note"), - action_id: Factory.build(:action_id), - recipe_input_of_id: Factory.insert!(:recipe_process).id, - recipe_output_of_id: Factory.insert!(:recipe_process).id, - recipe_flow_resource_id: Factory.insert!(:recipe_resource).id, - resource_quantity: %{ - has_unit_id: Factory.insert!(:unit).id, - has_numerical_value: Factory.float(), + "note" => Factory.str("some note"), + "action" => Factory.build(:action_id), + "recipeInputOf" => Factory.insert!(:recipe_process).id, + "recipeOutputOf" => Factory.insert!(:recipe_process).id, + "recipeFlowResource" => Factory.insert!(:recipe_resource).id, + "resourceQuantity" => %{ + "hasUnit" => Factory.insert!(:unit).id, + "hasNumericalValue" => Factory.float(), }, - effort_quantity: %{ - has_unit_id: Factory.insert!(:unit).id, - has_numerical_value: Factory.float(), + "effortQuantity" => %{ + "hasUnit" => Factory.insert!(:unit).id, + "hasNumericalValue" => Factory.float(), }, - recipe_clause_of_id: Factory.insert!(:recipe_exchange).id, + "recipeClauseOf" => Factory.insert!(:recipe_exchange).id, }, - recipe_flow: - Factory.insert!(:recipe_flow) - |> Domain.preload(:action) - |> Domain.preload(:resource_quantity) - |> Domain.preload(:effort_quantity) - |> Domain.preload(:recipe_flow_resource) - |> Domain.preload(:recipe_input_of) - |> Domain.preload(:recipe_output_of) - |> Domain.preload(:recipe_clause_of) + inserted: Factory.insert!(:recipe_flow), } end -describe "Query" do - test "recipeFlow()", %{recipe_flow: rec_flow} do - %{ - action: action, - resource_quantity: res_qty, - effort_quantity: eff_qty, - recipe_flow_resource: rec_flow_res, - recipe_input_of: rec_in_of, - recipe_output_of: rec_out_of, - recipe_clause_of: rec_clause_of, - } = rec_flow +@frag """ +fragment recipeFlow on RecipeFlow { + id + note + action {id} + resourceQuantity { + hasUnit {id} + hasNumericalValue + } + effortQuantity { + hasUnit {id} + hasNumericalValue + } + recipeFlowResource {id} + recipeInputOf {id} + recipeOutputOf {id} + recipeClauseOf {id} +} +""" +describe "Query" do + test "recipeFlow", %{inserted: new} do assert %{data: %{"recipeFlow" => data}} = - query!(""" - recipeFlow(id: "#{rec_flow.id}") { - id - note - action { id label resourceEffect onhandEffect inputOutput pairsWith } - resourceQuantity { - hasUnit { id } - hasNumericalValue - } - effortQuantity { - hasUnit { id } - hasNumericalValue - } - recipeFlowResource { id } - recipeInputOf { id } - recipeOutputOf { id } - recipeClauseOf { id } + run!(""" + #{@frag} + query ($id: ID!) { + recipeFlow(id: $id) {...recipeFlow} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == rec_flow.id - assert data["note"] == rec_flow.note - assert data["action"]["id"] == action.id - assert data["action"]["label"] == action.label - assert data["action"]["resourceEffect"] == action.resource_effect - assert data["action"]["onhandEffect"] == action.onhand_effect - assert data["action"]["inputOutput"] == action.input_output - assert data["action"]["pairsWith"] == action.pairs_with - assert data["resourceQuantity"]["hasUnit"]["id"] == res_qty.has_unit_id - assert data["resourceQuantity"]["hasNumericalValue"] == res_qty.has_numerical_value - assert data["effortQuantity"]["hasUnit"]["id"] == eff_qty.has_unit_id - assert data["effortQuantity"]["hasNumericalValue"] == eff_qty.has_numerical_value - assert data["recipeFlowResource"]["id"] == rec_flow_res.id - assert data["recipeInputOf"]["id"] == rec_in_of.id - assert data["recipeOutputOf"]["id"] == rec_out_of.id - assert data["recipeClauseOf"]["id"] == rec_clause_of.id + assert data["id"] == new.id + assert data["note"] == new.note + assert data["action"]["id"] == new.action_id + assert data["resourceQuantity"]["hasUnit"]["id"] == new.resource_quantity_has_unit_id + assert data["resourceQuantity"]["hasNumericalValue"] == new.resource_quantity_has_numerical_value + assert data["effortQuantity"]["hasUnit"]["id"] == new.effort_quantity_has_unit_id + assert data["effortQuantity"]["hasNumericalValue"] == new.effort_quantity_has_numerical_value + assert data["recipeFlowResource"]["id"] == new.recipe_flow_resource_id + assert data["recipeInputOf"]["id"] == new.recipe_input_of_id + assert data["recipeOutputOf"]["id"] == new.recipe_output_of_id + assert data["recipeClauseOf"]["id"] == new.recipe_clause_of_id end end describe "Mutation" do - test "createRecipeFlow()", %{params: params} do - %{ - action_id: action_id, - resource_quantity: res_qty, - effort_quantity: eff_qty, - recipe_flow_resource_id: rec_flow_res_id, - recipe_input_of_id: rec_in_of_id, - recipe_output_of_id: rec_out_of_id, - recipe_clause_of_id: rec_clause_of_id, - } = params - + test "createRecipeFlow", %{params: params} do assert %{data: %{"createRecipeFlow" => %{"recipeFlow" => data}}} = - mutation!(""" - createRecipeFlow(recipeFlow: { - note: "#{params.note}" - action: "#{action_id}" - resourceQuantity: { - hasUnit: "#{res_qty.has_unit_id}" - hasNumericalValue: #{res_qty.has_numerical_value} - } - effortQuantity: { - hasUnit: "#{eff_qty.has_unit_id}" - hasNumericalValue: #{eff_qty.has_numerical_value} - } - recipeFlowResource: "#{rec_flow_res_id}" - recipeInputOf: "#{rec_in_of_id}" - recipeOutputOf: "#{rec_out_of_id}" - recipeClauseOf: "#{rec_clause_of_id}" - }) { - recipeFlow { - id - note - action { id label resourceEffect onhandEffect inputOutput pairsWith } - resourceQuantity { - hasUnit { id } - hasNumericalValue - } - effortQuantity { - hasUnit { id } - hasNumericalValue - } - recipeFlowResource { id } - recipeInputOf { id } - recipeOutputOf { id } - recipeClauseOf { id } + run!(""" + #{@frag} + mutation ($recipeFlow: RecipeFlowCreateParams!) { + createRecipeFlow(recipeFlow: $recipeFlow) { + recipeFlow {...recipeFlow} } } - """) + """, vars: %{"recipeFlow" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["note"] == params.note - assert data["action"]["id"] == action_id - assert data["resourceQuantity"]["hasUnit"]["id"] == res_qty.has_unit_id - assert data["resourceQuantity"]["hasNumericalValue"] == res_qty.has_numerical_value - assert data["effortQuantity"]["hasUnit"]["id"] == eff_qty.has_unit_id - assert data["effortQuantity"]["hasNumericalValue"] == eff_qty.has_numerical_value - assert data["recipeFlowResource"]["id"] == rec_flow_res_id - assert data["recipeInputOf"]["id"] == rec_in_of_id - assert data["recipeOutputOf"]["id"] == rec_out_of_id - assert data["recipeClauseOf"]["id"] == rec_clause_of_id + assert data["note"] == params["note"] + assert data["action"]["id"] == params["action"] + assert data["resourceQuantity"]["hasUnit"]["id"] == params["resourceQuantity"]["hasUnit"] + assert data["resourceQuantity"]["hasNumericalValue"] == params["resourceQuantity"]["hasNumericalValue"] + assert data["effortQuantity"]["hasUnit"]["id"] == params["effortQuantity"]["hasUnit"] + assert data["effortQuantity"]["hasNumericalValue"] == params["effortQuantity"]["hasNumericalValue"] + assert data["recipeFlowResource"]["id"] == params["recipeFlowResource"] + assert data["recipeInputOf"]["id"] == params["recipeInputOf"] + assert data["recipeOutputOf"]["id"] == params["recipeOutputOf"] + assert data["recipeClauseOf"]["id"] == params["recipeClauseOf"] end - test "updateRecipeFlow()", %{params: params, recipe_flow: rec_flow} do - %{ - action_id: action_id, - resource_quantity: res_qty, - effort_quantity: eff_qty, - recipe_flow_resource_id: rec_flow_res_id, - recipe_input_of_id: rec_in_of_id, - recipe_output_of_id: rec_out_of_id, - recipe_clause_of_id: rec_clause_of_id, - } = params - + test "updateRecipeFlow", %{params: params, inserted: old} do assert %{data: %{"updateRecipeFlow" => %{"recipeFlow" => data}}} = - mutation!(""" - updateRecipeFlow(recipeFlow: { - id: "#{rec_flow.id}" - note: "#{params.note}" - action: "#{action_id}" - resourceQuantity: { - hasUnit: "#{res_qty.has_unit_id}" - hasNumericalValue: #{res_qty.has_numerical_value} - } - effortQuantity: { - hasUnit: "#{eff_qty.has_unit_id}" - hasNumericalValue: #{eff_qty.has_numerical_value} - } - recipeFlowResource: "#{rec_flow_res_id}" - recipeInputOf: "#{rec_in_of_id}" - recipeOutputOf: "#{rec_out_of_id}" - recipeClauseOf: "#{rec_clause_of_id}" - }) { - recipeFlow { - id - note - action { id label resourceEffect onhandEffect inputOutput pairsWith } - resourceQuantity { - hasUnit { id } - hasNumericalValue - } - effortQuantity { - hasUnit { id } - hasNumericalValue - } - recipeFlowResource { id } - recipeInputOf { id } - recipeOutputOf { id } - recipeClauseOf { id } + run!(""" + #{@frag} + mutation ($recipeFlow: RecipeFlowUpdateParams!) { + updateRecipeFlow(recipeFlow: $recipeFlow) { + recipeFlow {...recipeFlow} } } - """) + """, vars: %{"recipeFlow" => Map.put(params, "id", old.id)}) - assert data["id"] == rec_flow.id - assert data["note"] == params.note - assert data["action"]["id"] == action_id - assert data["resourceQuantity"]["hasUnit"]["id"] == res_qty.has_unit_id - assert data["resourceQuantity"]["hasNumericalValue"] == res_qty.has_numerical_value - assert data["effortQuantity"]["hasUnit"]["id"] == eff_qty.has_unit_id - assert data["effortQuantity"]["hasNumericalValue"] == eff_qty.has_numerical_value - assert data["recipeFlowResource"]["id"] == rec_flow_res_id - assert data["recipeInputOf"]["id"] == rec_in_of_id - assert data["recipeOutputOf"]["id"] == rec_out_of_id - assert data["recipeClauseOf"]["id"] == rec_clause_of_id + assert data["id"] == old.id + assert data["note"] == params["note"] + assert data["action"]["id"] == params["action"] + assert data["resourceQuantity"]["hasUnit"]["id"] == params["resourceQuantity"]["hasUnit"] + assert data["resourceQuantity"]["hasNumericalValue"] == params["resourceQuantity"]["hasNumericalValue"] + assert data["effortQuantity"]["hasUnit"]["id"] == params["effortQuantity"]["hasUnit"] + assert data["effortQuantity"]["hasNumericalValue"] == params["effortQuantity"]["hasNumericalValue"] + assert data["recipeFlowResource"]["id"] == params["recipeFlowResource"] + assert data["recipeInputOf"]["id"] == params["recipeInputOf"] + assert data["recipeOutputOf"]["id"] == params["recipeOutputOf"] + assert data["recipeClauseOf"]["id"] == params["recipeClauseOf"] end - test "deleteRecipeFlow()", %{recipe_flow: %{id: id}} do + test "deleteRecipeFlow", %{inserted: %{id: id}} do assert %{data: %{"deleteRecipeFlow" => true}} = - mutation!(""" - deleteRecipeFlow(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteRecipeFlow(id: $id) + } + """, vars: %{"id" => id}) end end end 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.str("name"), + note: Factory.str("note"), + process_classified_as: Factory.str_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.str("name"), + "hasDuration" => %{ + "unitType" => Factory.build(:time_unit) |> to_string(), + "numericDuration" => Factory.float(), + }, + "processClassifiedAs" => Factory.str_list("uri"), + "processConformsTo" => Factory.insert!(:process_specification).id, + "note" => Factory.str("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 diff --git a/test/vf/recipe_resource/domain.test.exs b/test/vf/recipe_resource/domain.test.exs @@ -28,46 +28,50 @@ alias Zenflows.VF.{ setup do %{ params: %{ - name: Factory.uniq("name"), - resource_classified_as: Factory.uniq_list("uri"), + name: Factory.str("name"), + resource_classified_as: Factory.str_list("uri"), unit_of_effort_id: Factory.insert!(:unit).id, unit_of_resource_id: Factory.insert!(:unit).id, resource_conforms_to_id: Factory.insert!(:resource_specification).id, substitutable: Factory.bool(), - note: Factory.uniq("note"), + note: Factory.str("note"), image: Factory.img(), }, - recipe_resource: Factory.insert!(:recipe_resource), + inserted: Factory.insert!(:recipe_resource), } end -test "by_id/1 returns a RecipeResource", %{recipe_resource: rec_res} do - assert %RecipeResource{} = Domain.by_id(rec_res.id) +describe "one/1" do + test "with good id: finds the RecipeResource", %{inserted: %{id: id}} do + assert {:ok, %RecipeResource{}} = Domain.one(id) + end + + test "with bad id: doesn't find the RecipeResource" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - test "creates a RecipeResource with valid params", %{params: params} do - assert {:ok, %RecipeResource{} = rec_res} = Domain.create(params) - - assert rec_res.name == params.name - assert rec_res.resource_classified_as == params.resource_classified_as - assert rec_res.unit_of_resource_id == params.unit_of_resource_id - assert rec_res.unit_of_effort_id == params.unit_of_effort_id - assert rec_res.resource_conforms_to_id == params.resource_conforms_to_id - assert rec_res.substitutable == params.substitutable - assert rec_res.note == params.note - assert rec_res.image == params.image + test "with good params: creates a RecipeResource", %{params: params} do + assert {:ok, %RecipeResource{} = new} = Domain.create(params) + assert new.name == params.name + assert new.resource_classified_as == params.resource_classified_as + assert new.unit_of_resource_id == params.unit_of_resource_id + assert new.unit_of_effort_id == params.unit_of_effort_id + assert new.resource_conforms_to_id == params.resource_conforms_to_id + assert new.substitutable == params.substitutable + assert new.note == params.note + assert new.image == params.image end - test "doesn't create a RecipeResource with invalid params" do + test "with bad params: doesn't create a Process" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates a RecipeResource with valid params", %{params: params, recipe_resource: old} do + test "with good params: updates the RecipeResource", %{params: params, inserted: old} do assert {:ok, %RecipeResource{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.resource_classified_as == params.resource_classified_as assert new.unit_of_resource_id == params.unit_of_resource_id @@ -78,9 +82,8 @@ describe "update/2" do assert new.image == params.image end - test "doesn't update a RecipeResource", %{recipe_resource: old} do + test "with bad params: doesn't update the RecipeResource", %{inserted: old} do assert {:ok, %RecipeResource{} = new} = Domain.update(old.id, %{}) - assert new.name == old.name assert new.resource_classified_as == old.resource_classified_as assert new.unit_of_resource_id == old.unit_of_resource_id @@ -92,19 +95,25 @@ describe "update/2" do end end -test "delete/1 deletes a RecipeResource", %{recipe_resource: %{id: id}} do - assert {:ok, %RecipeResource{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the RecipeResource", %{inserted: %{id: id}} do + assert {:ok, %RecipeResource{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the RecipeResource" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end describe "preload/2" do - test "preloads :unit_of_resource", %{recipe_resource: rec_res} do + test "preloads :unit_of_resource", %{inserted: rec_res} do rec_res = Domain.preload(rec_res, :unit_of_resource) assert unit_res = %Unit{} = rec_res.unit_of_resource assert unit_res.id == rec_res.unit_of_resource_id end - test "preloads :unit_of_effort", %{recipe_resource: rec_res} do + test "preloads :unit_of_effort", %{inserted: rec_res} do rec_res = Domain.preload(rec_res, :unit_of_effort) assert unit_eff = %Unit{} = rec_res.unit_of_effort assert unit_eff.id == rec_res.unit_of_effort_id diff --git a/test/vf/recipe_resource/type.test.exs b/test/vf/recipe_resource/type.test.exs @@ -21,67 +21,63 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - "name" => Factory.uniq("name"), - "resourceClassifiedAs" => Factory.uniq_list("uri"), + "name" => Factory.str("name"), + "resourceClassifiedAs" => Factory.str_list("uri"), "unitOfEffort" => Factory.insert!(:unit).id, "unitOfResource" => Factory.insert!(:unit).id, "resourceConformsTo" => Factory.insert!(:resource_specification).id, "substitutable" => Factory.bool(), - "note" => Factory.uniq("note"), + "note" => Factory.str("note"), "image" => Factory.img(), }, - recipe_resource: Factory.insert!(:recipe_resource), + inserted: Factory.insert!(:recipe_resource), } end +@frag """ +fragment recipeResource on RecipeResource { + id + name + resourceClassifiedAs + unitOfResource {id} + unitOfEffort {id} + resourceConformsTo {id} + substitutable + image + note +} +""" + describe "Query" do - test "recipeResource()", %{recipe_resource: rec_res} do + test "recipeResource", %{inserted: new} do assert %{data: %{"recipeResource" => data}} = run!(""" + #{@frag} query ($id: ID!) { - recipeResource(id: $id) { - id - name - resourceClassifiedAs - unitOfResource { id } - unitOfEffort { id } - resourceConformsTo { id } - substitutable - image - note - } + recipeResource(id: $id) {...recipeResource} } - """, vars: %{"id" => rec_res.id}) + """, vars: %{"id" => new.id}) - assert data["id"] == rec_res.id - assert data["name"] == rec_res.name - assert data["resourceClassifiedAs"] == rec_res.resource_classified_as - assert data["unitOfResource"]["id"] == rec_res.unit_of_resource_id - assert data["unitOfEffort"]["id"] == rec_res.unit_of_effort_id - assert data["resourceConformsTo"]["id"] == rec_res.resource_conforms_to_id - assert data["note"] == rec_res.note - assert data["substitutable"] == rec_res.substitutable - assert data["image"] == rec_res.image + assert data["id"] == new.id + assert data["name"] == new.name + assert data["resourceClassifiedAs"] == new.resource_classified_as + assert data["unitOfResource"]["id"] == new.unit_of_resource_id + assert data["unitOfEffort"]["id"] == new.unit_of_effort_id + assert data["resourceConformsTo"]["id"] == new.resource_conforms_to_id + assert data["note"] == new.note + assert data["substitutable"] == new.substitutable + assert data["image"] == new.image end end describe "Mutation" do - test "createRecipeResource()", %{params: params} do + test "createRecipeResource", %{params: params} do assert %{data: %{"createRecipeResource" => %{"recipeResource" => data}}} = run!(""" + #{@frag} mutation ($recipeResource: RecipeResourceCreateParams!) { createRecipeResource(recipeResource: $recipeResource) { - recipeResource { - id - name - image - resourceClassifiedAs - unitOfResource { id } - unitOfEffort { id } - resourceConformsTo { id } - substitutable - note - } + recipeResource {...recipeResource} } } """, vars: %{"recipeResource" => params}) @@ -94,27 +90,18 @@ describe "Mutation" do assert data["resourceConformsTo"]["id"] == params["resourceConformsTo"] end - test "updateRecipeResource()", %{params: params, recipe_resource: rec_res} do + test "updateRecipeResource()", %{params: params, inserted: old} do assert %{data: %{"updateRecipeResource" => %{"recipeResource" => data}}} = run!(""" + #{@frag} mutation ($recipeResource: RecipeResourceUpdateParams!) { updateRecipeResource(recipeResource: $recipeResource) { - recipeResource { - id - name - resourceClassifiedAs - unitOfResource { id } - unitOfEffort { id } - resourceConformsTo { id } - substitutable - note - image - } + recipeResource {...recipeResource} } } - """, vars: %{"recipeResource" => Map.put(params, "id", rec_res.id)}) + """, vars: %{"recipeResource" => Map.put(params, "id", old.id)}) - assert data["id"] == rec_res.id + assert data["id"] == old.id keys = ~w[name note image resourceClassifiedAs substitutable] assert Map.take(data, keys) == Map.take(params, keys) assert data["unitOfResource"]["id"] == params["unitOfResource"] @@ -122,7 +109,7 @@ describe "Mutation" do assert data["resourceConformsTo"]["id"] == params["resourceConformsTo"] end - test "deleteRecipeResource()", %{recipe_resource: %{id: id}} do + test "deleteRecipeResource()", %{inserted: %{id: id}} do assert %{data: %{"deleteRecipeResource" => true}} = run!(""" mutation ($id: ID!) { diff --git a/test/vf/resource_specification/domain.test.exs b/test/vf/resource_specification/domain.test.exs @@ -28,15 +28,14 @@ alias Zenflows.VF.{ setup do %{ params: %{ - name: Factory.uniq("name"), - resource_classified_as: Factory.uniq_list("uri"), - note: Factory.uniq("note"), + name: Factory.str("name"), + resource_classified_as: Factory.str_list("uri"), + note: Factory.str("note"), image: Factory.img(), default_unit_of_effort_id: Factory.insert!(:unit).id, default_unit_of_resource_id: Factory.insert!(:unit).id, }, inserted: Factory.insert!(:resource_specification), - id: Factory.id() } end @@ -45,20 +44,20 @@ describe "one/1" do assert {:ok, %ResourceSpecification{}} = Domain.one(id) end - test "with bad id: doesn't find the ResourceSpecification", %{id: id} do - assert {:error, "not found"} = Domain.one(id) + test "with bad id: doesn't find the ResourceSpecification" do + assert {:error, "not found"} = Domain.one(Factory.id()) end end describe "create/1" do test "with good params: creates a ResourceSpecification", %{params: params} do - assert {:ok, %ResourceSpecification{} = res_spec} = Domain.create(params) - assert res_spec.name == params.name - assert res_spec.resource_classified_as == params.resource_classified_as - assert res_spec.note == params.note - assert res_spec.image == params.image - assert res_spec.default_unit_of_resource_id == params.default_unit_of_resource_id - assert res_spec.default_unit_of_effort_id == params.default_unit_of_effort_id + assert {:ok, %ResourceSpecification{} = new} = Domain.create(params) + assert new.name == params.name + assert new.resource_classified_as == params.resource_classified_as + assert new.note == params.note + assert new.image == params.image + assert new.default_unit_of_resource_id == params.default_unit_of_resource_id + assert new.default_unit_of_effort_id == params.default_unit_of_effort_id end test "with bad params: doesn't create a ResourceSpecification" do @@ -94,8 +93,8 @@ describe "delete/1" do assert {:error, "not found"} = Domain.one(id) end - test "with bad id: doesn't delete the ResourceSpecification", %{id: id} do - assert {:error, "not found"} = Domain.delete(id) + test "with bad id: doesn't delete the ResourceSpecification" do + assert {:error, "not found"} = Domain.delete(Factory.id()) end end diff --git a/test/vf/resource_specification/type.test.exs b/test/vf/resource_specification/type.test.exs @@ -21,59 +21,57 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - "name" => Factory.uniq("name"), - "resourceClassifiedAs" => Factory.uniq_list("uri"), - "note" => Factory.uniq("note"), + "name" => Factory.str("name"), + "resourceClassifiedAs" => Factory.str_list("uri"), + "note" => Factory.str("note"), "image" => Factory.img(), "defaultUnitOfEffort" => Factory.insert!(:unit).id, "defaultUnitOfResource" => Factory.insert!(:unit).id, }, - resource_specification: Factory.insert!(:resource_specification), + inserted: Factory.insert!(:resource_specification), } end +@frag """ +fragment resourceSpecification on ResourceSpecification { + id + name + resourceClassifiedAs + defaultUnitOfResource {id} + defaultUnitOfEffort {id} + note + image +} +""" + describe "Query" do - test "resourceSpecification()", %{resource_specification: res_spec} do + test "resourceSpecification", %{inserted: new} do assert %{data: %{"resourceSpecification" => data}} = run!(""" + #{@frag} query ($id: ID!) { - resourceSpecification(id: $id) { - id - name - resourceClassifiedAs - defaultUnitOfResource { id } - defaultUnitOfEffort { id } - note - image - } + resourceSpecification(id: $id) {...resourceSpecification} } - """, vars: %{"id" => res_spec.id}) + """, vars: %{"id" => new.id}) - assert data["id"] == res_spec.id - assert data["name"] == res_spec.name - assert data["resourceClassifiedAs"] == res_spec.resource_classified_as - assert data["defaultUnitOfResource"]["id"] == res_spec.default_unit_of_resource_id - assert data["defaultUnitOfEffort"]["id"] == res_spec.default_unit_of_effort_id - assert data["note"] == res_spec.note - assert data["image"] == res_spec.image + assert data["id"] == new.id + assert data["name"] == new.name + assert data["resourceClassifiedAs"] == new.resource_classified_as + assert data["defaultUnitOfResource"]["id"] == new.default_unit_of_resource_id + assert data["defaultUnitOfEffort"]["id"] == new.default_unit_of_effort_id + assert data["note"] == new.note + assert data["image"] == new.image end end describe "Mutation" do - test "createResourceSpecification()", %{params: params} do + test "createResourceSpecification", %{params: params} do assert %{data: %{"createResourceSpecification" => %{"resourceSpecification" => data}}} = run!(""" + #{@frag} mutation ($resourceSpecification: ResourceSpecificationCreateParams!) { createResourceSpecification(resourceSpecification: $resourceSpecification) { - resourceSpecification { - id - name - resourceClassifiedAs - defaultUnitOfResource { id } - defaultUnitOfEffort { id } - note - image - } + resourceSpecification {...resourceSpecification} } } """, vars: %{"resourceSpecification" => params}) @@ -85,34 +83,25 @@ describe "Mutation" do assert data["defaultUnitOfEffort"]["id"] == params["defaultUnitOfEffort"] end - test "updateResourceSpecification()", %{params: params, resource_specification: res_spec} do + test "updateResourceSpecification()", %{params: params, inserted: old} do assert %{data: %{"updateResourceSpecification" => %{"resourceSpecification" => data}}} = run!(""" + #{@frag} mutation ($resourceSpecification: ResourceSpecificationUpdateParams!) { updateResourceSpecification(resourceSpecification: $resourceSpecification) { - resourceSpecification { - id - name - resourceClassifiedAs - defaultUnitOfResource { id } - defaultUnitOfEffort { id } - note - image - } + resourceSpecification {...resourceSpecification} } } - """, vars: %{"resourceSpecification" => - Map.put(params, "id", res_spec.id), - }) + """, vars: %{"resourceSpecification" => Map.put(params, "id", old.id)}) - assert data["id"] == res_spec.id + assert data["id"] == old.id keys = ~w[name note resourceClassifiedAs note image] assert Map.take(data, keys) == Map.take(params, keys) assert data["defaultUnitOfResource"]["id"] == params["defaultUnitOfResource"] assert data["defaultUnitOfEffort"]["id"] == params["defaultUnitOfEffort"] end - test "deleteResourceSpecification()", %{resource_specification: %{id: id}} do + test "deleteResourceSpecification()", %{inserted: %{id: id}} do assert %{data: %{"deleteResourceSpecification" => true}} = run!(""" mutation ($id: ID!) { diff --git a/test/vf/role_behavior/domain.test.exs b/test/vf/role_behavior/domain.test.exs @@ -24,48 +24,57 @@ alias Zenflows.VF.{RoleBehavior, RoleBehavior.Domain} setup do %{ params: %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), + name: Factory.str("name"), + note: Factory.str("note"), }, - role_behavior: Factory.insert!(:role_behavior), + inserted: Factory.insert!(:role_behavior), } end -test "by_id/1 returns a RoleBehavior", %{role_behavior: role_beh} do - assert %RoleBehavior{} = Domain.by_id(role_beh.id) +describe "one/1" do + test "with good id: finds the RoleBehavior", %{inserted: %{id: id}} do + assert {:ok, %RoleBehavior{}} = Domain.one(id) + end + + test "with bad id: doesn't find the RoleBehavior" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - test "creates a RoleBehavior with valid params", %{params: params} do - assert {:ok, %RoleBehavior{} = role_beh} = Domain.create(params) - - assert role_beh.name == params.name - assert role_beh.note == params.note + test "with good params: creates a RoleBehavior", %{params: params} do + assert {:ok, %RoleBehavior{} = new} = Domain.create(params) + assert new.name == params.name + assert new.note == params.note end - test "doesn't create a RoleBehavior with invalid params" do + test "with bad params: doesn't create a Process" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates a RoleBehavior with valid params", %{params: params, role_behavior: old} do + test "with good params: updates the Process", %{params: params, inserted: old} do assert {:ok, %RoleBehavior{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.note == params.note end - test "doesn't update a RoleBehavior", %{role_behavior: old} do + test "with bad params: doesn't update the Process", %{inserted: old} do assert {:ok, %RoleBehavior{} = new} = Domain.update(old.id, %{}) - assert new.name == old.name assert new.note == old.note end end -test "delete/1 deletes a RoleBehavior", %{role_behavior: %{id: id}} do - assert {:ok, %RoleBehavior{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the RoleBehavior", %{inserted: %{id: id}} do + assert {:ok, %RoleBehavior{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the RoleBehavior" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end end diff --git a/test/vf/role_behavior/type.test.exs b/test/vf/role_behavior/type.test.exs @@ -21,77 +21,77 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), + "name" => Factory.str("name"), + "note" => Factory.str("note"), }, - role_behavior: Factory.insert!(:role_behavior), + inserted: Factory.insert!(:role_behavior), } end +@frag """ +fragment roleBehavior on RoleBehavior { + id + name + note +} +""" + describe "Query" do - test "roleBehavior()", %{role_behavior: role_beh} do + test "roleBehavior", %{inserted: new} do assert %{data: %{"roleBehavior" => data}} = - query!(""" - roleBehavior(id: "#{role_beh.id}") { - id - name - note + run!(""" + #{@frag} + query ($id: ID!) { + roleBehavior(id: $id) {...roleBehavior} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == role_beh.id - assert data["name"] == role_beh.name - assert data["note"] == role_beh.note + assert data["id"] == new.id + assert data["name"] == new.name + assert data["note"] == new.note end end describe "Mutation" do - test "createRoleBehavior()", %{params: params} do + test "createRoleBehavior", %{params: params} do assert %{data: %{"createRoleBehavior" => %{"roleBehavior" => data}}} = - mutation!(""" - createRoleBehavior(roleBehavior: { - name: "#{params.name}" - note: "#{params.note}" - }) { - roleBehavior { - id - name - note + run!(""" + #{@frag} + mutation ($roleBehavior: RoleBehaviorCreateParams!) { + createRoleBehavior(roleBehavior: $roleBehavior) { + roleBehavior {...roleBehavior} } } - """) + """, vars: %{"roleBehavior" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["name"] == params.name - assert data["note"] == params.note + assert data["name"] == params["name"] + assert data["note"] == params["note"] end - test "updateRoleBehavior()", %{params: params, role_behavior: role_beh} do + test "updateRoleBehavior", %{params: params, inserted: old} do assert %{data: %{"updateRoleBehavior" => %{"roleBehavior" => data}}} = - mutation!(""" - updateRoleBehavior(roleBehavior: { - id: "#{role_beh.id}" - name: "#{params.name}" - note: "#{params.note}" - }) { - roleBehavior { - id - name - note + run!(""" + #{@frag} + mutation ($roleBehavior: RoleBehaviorUpdateParams!) { + updateRoleBehavior(roleBehavior: $roleBehavior) { + roleBehavior {...roleBehavior} } } - """) + """, vars: %{"roleBehavior" => Map.put(params, "id", old.id)}) - assert data["id"] == role_beh.id - assert data["name"] == params.name - assert data["note"] == params.note + assert data["id"] == old.id + assert data["name"] == params["name"] + assert data["note"] == params["note"] end - test "deleteRoleBehavior()", %{role_behavior: %{id: id}} do + test "deleteRoleBehavior", %{inserted: %{id: id}} do assert %{data: %{"deleteRoleBehavior" => true}} = - mutation!(""" - deleteRoleBehavior(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteRoleBehavior(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/satisfaction.test.exs b/test/vf/satisfaction.test.exs @@ -22,7 +22,7 @@ alias Zenflows.VF.Satisfaction setup do %{params: %{ - note: Factory.uniq("note"), + note: Factory.str("note"), satisfied_by_id: Factory.insert!(:event_or_commitment).id, satisfies_id: Factory.insert!(:intent).id, resource_quantity: %{ diff --git a/test/vf/scenario/domain.test.exs b/test/vf/scenario/domain.test.exs @@ -25,49 +25,49 @@ alias Zenflows.VF.{ ScenarioDefinition, } -setup ctx do - params = %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), - has_beginning: DateTime.utc_now(), - has_end: DateTime.utc_now(), - defined_as_id: Factory.insert!(:scenario_definition).id, - refinement_of_id: Factory.insert!(:scenario).id, - } +setup do + %{ + params: %{ + name: Factory.str("name"), + note: Factory.str("note"), + has_beginning: DateTime.utc_now(), + has_end: DateTime.utc_now(), + defined_as_id: Factory.insert!(:scenario_definition).id, + refinement_of_id: Factory.insert!(:scenario).id, + }, + inserted: Factory.insert!(:scenario), + } +end - if ctx[:no_insert] do - %{params: params} - else - %{params: params, inserted: Factory.insert!(:scenario)} +describe "one/1" do + test "with good id: finds the Scenario", %{inserted: %{id: id}} do + assert {:ok, %Scenario{}} = Domain.one(id) end -end -test "by_id/1 returns a Scenario", %{inserted: scen} do - assert %Scenario{} = Domain.by_id(scen.id) + test "with bad id: doesn't find the Scenario" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - @tag :no_insert - test "creates a Scenario with valid params", %{params: params} do - assert {:ok, %Scenario{} = scen} = Domain.create(params) - - assert scen.name == params.name - assert scen.note == params.note - assert scen.has_beginning == params.has_beginning - assert scen.has_end == params.has_end - assert scen.defined_as_id == params.defined_as_id - assert scen.refinement_of_id == params.refinement_of_id + test "with good params: creates a Scenario", %{params: params} do + assert {:ok, %Scenario{} = new} = Domain.create(params) + assert new.name == params.name + assert new.note == params.note + assert new.has_beginning == params.has_beginning + assert new.has_end == params.has_end + assert new.defined_as_id == params.defined_as_id + assert new.refinement_of_id == params.refinement_of_id end - test "doesn't create a Scenario with invalid params" do + test "with bad params: doesn't create a Scenario" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates a Scenario with valid params", %{params: params, inserted: old} do + test "with good params: updates the Scenario", %{params: params, inserted: old} do assert {:ok, %Scenario{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.note == params.note assert new.has_beginning == params.has_beginning @@ -76,9 +76,8 @@ describe "update/2" do assert new.refinement_of_id == params.refinement_of_id end - test "doesn't update a Scenario", %{inserted: old} do + test "with bad params: doesn't update the Scenario", %{inserted: old} do assert {:ok, %Scenario{} = new} = Domain.update(old.id, %{}) - assert new.name == old.name assert new.note == old.note assert new.has_beginning == old.has_beginning @@ -88,9 +87,15 @@ describe "update/2" do end end -test "delete/1 deletes a Scenario", %{inserted: %{id: id}} do - assert {:ok, %Scenario{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the Scenario", %{inserted: %{id: id}} do + assert {:ok, %Scenario{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the Scenario" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end describe "preload/2" do diff --git a/test/vf/scenario/type.test.exs b/test/vf/scenario/type.test.exs @@ -21,113 +21,93 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), - has_beginning: DateTime.utc_now(), - has_end: DateTime.utc_now(), - defined_as_id: Factory.insert!(:scenario_definition).id, - refinement_of_id: Factory.insert!(:scenario).id, + "name" => Factory.str("name"), + "note" => Factory.str("note"), + "hasBeginning" => Factory.iso_now(), + "hasEnd" => Factory.iso_now(), + "definedAs" => Factory.insert!(:scenario_definition).id, + "refinementOf" => Factory.insert!(:scenario).id, }, inserted: Factory.insert!(:scenario), } end +@frag """ +fragment scenario on Scenario { + id + name + note + hasBeginning + hasEnd + definedAs {id} + refinementOf {id} +} +""" + describe "Query" do - test "scenario()", %{inserted: scen} do + test "scenario", %{inserted: new} do assert %{data: %{"scenario" => data}} = - query!(""" - scenario(id: "#{scen.id}") { - id - name - note - hasBeginning - hasEnd - definedAs {id} - refinementOf {id} + run!(""" + #{@frag} + query ($id: ID!) { + scenario(id: $id) {...scenario} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == scen.id - assert data["name"] == scen.name - assert data["note"] == scen.note - assert data["hasBeginning"] == DateTime.to_iso8601(scen.has_beginning) - assert data["hasEnd"] == DateTime.to_iso8601(scen.has_end) - assert data["definedAs"]["id"] == scen.defined_as_id - assert data["refinementOf"]["id"] == scen.refinement_of_id + assert data["id"] == new.id + assert data["name"] == new.name + assert data["note"] == new.note + assert data["hasBeginning"] == DateTime.to_iso8601(new.has_beginning) + assert data["hasEnd"] == DateTime.to_iso8601(new.has_end) + assert data["definedAs"]["id"] == new.defined_as_id + assert data["refinementOf"]["id"] == new.refinement_of_id end end describe "Mutation" do - test "createScenario()", %{params: params} do + test "createScenario", %{params: params} do assert %{data: %{"createScenario" => %{"scenario" => data}}} = - mutation!(""" - createScenario(scenario: { - name: "#{params.name}" - note: "#{params.note}" - hasBeginning: "#{params.has_beginning}" - hasEnd: "#{params.has_end}" - definedAs: "#{params.defined_as_id}" - refinementOf: "#{params.refinement_of_id}" - }) { - scenario { - id - name - note - hasBeginning - hasEnd - definedAs {id} - refinementOf {id} + run!(""" + #{@frag} + mutation ($scenario: ScenarioCreateParams!) { + createScenario(scenario: $scenario) { + scenario {...scenario} } } - """) + """, vars: %{"scenario" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["name"] == params.name - assert data["note"] == params.note - assert data["hasBeginning"] == DateTime.to_iso8601(params.has_beginning) - assert data["hasEnd"] == DateTime.to_iso8601(params.has_end) - assert data["definedAs"]["id"] == params.defined_as_id - assert data["refinementOf"]["id"] == params.refinement_of_id + keys = ~w[name note hasBeginning hasEnd] + assert Map.take(data, keys) == Map.take(params, keys) + assert data["definedAs"]["id"] == params["definedAs"] + assert data["refinementOf"]["id"] == params["refinementOf"] end - test "updateScenario()", %{params: params, inserted: scen} do + test "updateScenario", %{params: params, inserted: old} do assert %{data: %{"updateScenario" => %{"scenario" => data}}} = - mutation!(""" - updateScenario(scenario: { - id: "#{scen.id}" - name: "#{params.name}" - note: "#{params.note}" - hasBeginning: "#{params.has_beginning}" - hasEnd: "#{params.has_end}" - definedAs: "#{params.defined_as_id}" - refinementOf: "#{params.refinement_of_id}" - }) { - scenario { - id - name - note - hasBeginning - hasEnd - definedAs {id} - refinementOf {id} + run!(""" + #{@frag} + mutation ($scenario: ScenarioUpdateParams!) { + updateScenario(scenario: $scenario) { + scenario {...scenario} } } - """) + """, vars: %{"scenario" => Map.put(params, "id", old.id)}) - assert data["id"] == scen.id - assert data["name"] == params.name - assert data["note"] == params.note - assert data["hasBeginning"] == DateTime.to_iso8601(params.has_beginning) - assert data["hasEnd"] == DateTime.to_iso8601(params.has_end) - assert data["definedAs"]["id"] == params.defined_as_id - assert data["refinementOf"]["id"] == params.refinement_of_id + assert data["id"] == old.id + keys = ~w[name note hasBeginning hasEnd] + assert Map.take(data, keys) == Map.take(params, keys) + assert data["definedAs"]["id"] == params["definedAs"] + assert data["refinementOf"]["id"] == params["refinementOf"] end - test "deleteScenario()", %{inserted: %{id: id}} do + test "deleteScenario", %{inserted: %{id: id}} do assert %{data: %{"deleteScenario" => true}} = - mutation!(""" - deleteScenario(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteScenario(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/scenario_definition/domain.test.exs b/test/vf/scenario_definition/domain.test.exs @@ -25,53 +25,52 @@ alias Zenflows.VF.{ ScenarioDefinition.Domain, } -setup ctx do - params = %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), - has_duration: Factory.build(:iduration), - } +setup do + %{ + params: %{ + name: Factory.str("name"), + note: Factory.str("note"), + has_duration: Factory.build(:iduration), + }, + inserted: Factory.insert!(:scenario_definition), + } +end - if ctx[:no_insert] do - %{params: params} - else - %{params: params, inserted: Factory.insert!(:scenario_definition)} +describe "one/1" do + test "with good id: finds the ScenarioDefinition", %{inserted: %{id: id}} do + assert {:ok, %ScenarioDefinition{}} = Domain.one(id) end -end -test "by_id/1 returns a ScenarioDefinition", %{inserted: scen_def} do - assert %ScenarioDefinition{} = Domain.by_id(scen_def.id) + test "with bad id: doesn't find the ScenarioDefinition" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - @tag :no_insert - test "creates a ScenarioDefinition with valid params", %{params: params} do - assert {:ok, %ScenarioDefinition{} = scen_def} = Domain.create(params) - - assert scen_def.name == params.name - assert scen_def.note == params.note - assert scen_def.has_duration_unit_type == params.has_duration.unit_type - assert scen_def.has_duration_numeric_duration == params.has_duration.numeric_duration + test "with good params: creates a ScenarioDefinition", %{params: params} do + assert {:ok, %ScenarioDefinition{} = new} = Domain.create(params) + assert new.name == params.name + assert new.note == params.note + assert new.has_duration_unit_type == params.has_duration.unit_type + assert new.has_duration_numeric_duration == params.has_duration.numeric_duration end - test "doesn't create a ScenarioDefinition with invalid params" do + test "with bad params: doesn't create a ScenarioDefinition" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates a ScenarioDefinition with valid params", %{params: params, inserted: old} do + test "with good params: updates the ScenarioDefinition", %{params: params, inserted: old} do assert {:ok, %ScenarioDefinition{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.note == params.note assert new.has_duration_unit_type == params.has_duration.unit_type assert new.has_duration_numeric_duration == params.has_duration.numeric_duration end - test "doesn't update a ScenarioDefinition", %{inserted: old} do + test "with bad params: doesn't update the ScenarioDefinition", %{inserted: old} do assert {:ok, %ScenarioDefinition{} = new} = Domain.update(old.id, %{}) - assert new.name == old.name assert new.note == old.note assert new.has_duration_unit_type == old.has_duration_unit_type @@ -79,9 +78,15 @@ describe "update/2" do end end -test "delete/1 deletes a ScenarioDefinition", %{inserted: %{id: id}} do - assert {:ok, %ScenarioDefinition{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the ScenarioDefinition", %{inserted: %{id: id}} do + assert {:ok, %ScenarioDefinition{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the ScenarioDefinition" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end describe "preload/2" do diff --git a/test/vf/scenario_definition/type.test.exs b/test/vf/scenario_definition/type.test.exs @@ -21,104 +21,89 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - name: Factory.uniq("name"), - note: Factory.uniq("note"), - has_duration: Factory.build(:iduration), + "name" => Factory.str("name"), + "note" => Factory.str("note"), + "hasDuration" => %{ + "unitType" => Factory.build(:time_unit) |> to_string(), + "numericDuration" => Factory.float(), + }, }, inserted: Factory.insert!(:scenario_definition), } end +@frag """ +fragment scenarioDefinition on ScenarioDefinition { + id + name + note + hasDuration { + unitType + numericDuration + } +} +""" + describe "Query" do - test "scenarioDefinition()", %{inserted: scen_def} do + test "scenarioDefinition", %{inserted: new} do assert %{data: %{"scenarioDefinition" => data}} = - query!(""" - scenarioDefinition(id: "#{scen_def.id}") { - id - name - note - hasDuration { - unitType - numericDuration - } + run!(""" + #{@frag} + query ($id: ID!) { + scenarioDefinition(id: $id) {...scenarioDefinition} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == scen_def.id - assert data["name"] == scen_def.name - assert data["note"] == scen_def.note - assert data["hasDuration"]["unitType"] == to_string(scen_def.has_duration_unit_type) - assert data["hasDuration"]["numericDuration"] == scen_def.has_duration_numeric_duration + assert data["id"] == new.id + assert data["name"] == new.name + assert data["note"] == new.note + 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 "createScenarioDefinition()", %{params: params} do + test "createScenarioDefinition", %{params: params} do assert %{data: %{"createScenarioDefinition" => %{"scenarioDefinition" => data}}} = - mutation!(""" - createScenarioDefinition(scenarioDefinition: { - name: "#{params.name}" - note: "#{params.note}" - hasDuration: { - unitType: #{params.has_duration.unit_type} - numericDuration: #{params.has_duration.numeric_duration} - } - }) { - scenarioDefinition { - id - name - note - hasDuration { - unitType - numericDuration - } + run!(""" + #{@frag} + mutation ($scenarioDefinition: ScenarioDefinitionCreateParams!) { + createScenarioDefinition(scenarioDefinition: $scenarioDefinition) { + scenarioDefinition {...scenarioDefinition} } } - """) + """, vars: %{"scenarioDefinition" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["name"] == params.name - assert data["note"] == params.note - 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["hasDuration"] == params["hasDuration"] end - test "updateScenarioDefinition()", %{params: params, inserted: scen_def} do + test "updateScenarioDefinition", %{params: params, inserted: old} do assert %{data: %{"updateScenarioDefinition" => %{"scenarioDefinition" => data}}} = - mutation!(""" - updateScenarioDefinition(scenarioDefinition: { - id: "#{scen_def.id}" - name: "#{params.name}" - note: "#{params.note}" - hasDuration: { - unitType: #{params.has_duration.unit_type} - numericDuration: #{params.has_duration.numeric_duration} - } - }) { - scenarioDefinition { - id - name - note - hasDuration { - unitType - numericDuration - } + run!(""" + #{@frag} + mutation ($scenarioDefinition: ScenarioDefinitionUpdateParams!) { + updateScenarioDefinition(scenarioDefinition: $scenarioDefinition) { + scenarioDefinition {...scenarioDefinition} } } - """) + """, vars: %{"scenarioDefinition" => Map.put(params, "id", old.id)}) - assert data["id"] == scen_def.id - assert data["name"] == params.name - assert data["note"] == params.note - 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["hasDuration"] == params["hasDuration"] end test "deleteScenarioDefinition()", %{inserted: %{id: id}} do assert %{data: %{"deleteScenarioDefinition" => true}} = - mutation!(""" - deleteScenarioDefinition(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteScenarioDefinition(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/settlement.test.exs b/test/vf/settlement.test.exs @@ -22,7 +22,7 @@ alias Zenflows.VF.Settlement setup do %{params: %{ - note: Factory.uniq("note"), + note: Factory.str("note"), settled_by_id: Factory.insert!(:economic_event).id, settles_id: Factory.insert!(:claim).id, resource_quantity: %{ diff --git a/test/vf/spatial_thing/domain.test.exs b/test/vf/spatial_thing/domain.test.exs @@ -24,42 +24,46 @@ alias Zenflows.VF.{SpatialThing, SpatialThing.Domain} setup do %{ params: %{ - name: Factory.uniq("name"), - mappable_address: Factory.uniq("address"), + name: Factory.str("name"), + mappable_address: Factory.str("address"), lat: Factory.float(), long: Factory.float(), alt: Factory.float(), - note: Factory.uniq("note"), + note: Factory.str("note"), }, - spatial_thing: Factory.insert!(:spatial_thing), + inserted: Factory.insert!(:spatial_thing), } end -test "by_id/1 returns a SpatialThing", %{spatial_thing: spt_thg} do - assert %SpatialThing{} = Domain.by_id(spt_thg.id) +describe "one/1" do + test "with good id: finds the SpatialThing", %{inserted: %{id: id}} do + assert {:ok, %SpatialThing{}} = Domain.one(id) + end + + test "with bad id: doesn't find the SpatialThing" do + assert {:error, "not found"} = Domain.one(Factory.id()) + end end describe "create/1" do - test "creates a SpatialThing with valid params", %{params: params} do - assert {:ok, %SpatialThing{} = spt_thg} = Domain.create(params) - - assert spt_thg.name == params.name - assert spt_thg.mappable_address == params.mappable_address - assert spt_thg.lat == params.lat - assert spt_thg.long == params.long - assert spt_thg.alt == params.alt - assert spt_thg.note == params.note + test "with good params: creates a SpatialThing", %{params: params} do + assert {:ok, %SpatialThing{} = new} = Domain.create(params) + assert new.name == params.name + assert new.mappable_address == params.mappable_address + assert new.lat == params.lat + assert new.long == params.long + assert new.alt == params.alt + assert new.note == params.note end - test "doesn't create a SpatialThing with invalid params" do + test "with bad params: doesn't create a SpatialThing" do assert {:error, %Changeset{}} = Domain.create(%{}) end end describe "update/2" do - test "updates a SpatialThing with valid params", %{params: params, spatial_thing: old} do + test "with good params: updates the SpatialThing", %{params: params, inserted: old} do assert {:ok, %SpatialThing{} = new} = Domain.update(old.id, params) - assert new.name == params.name assert new.mappable_address == params.mappable_address assert new.lat == params.lat @@ -68,9 +72,8 @@ describe "update/2" do assert new.note == params.note end - test "doesn't update a SpatialThing", %{spatial_thing: old} do + test "with bad params: doesn't update the SpatialThing", %{inserted: old} do assert {:ok, %SpatialThing{} = new} = Domain.update(old.id, %{}) - assert new.name == old.name assert new.mappable_address == old.mappable_address assert new.lat == old.lat @@ -80,8 +83,14 @@ describe "update/2" do end end -test "delete/1 deletes a SpatialThing", %{spatial_thing: %{id: id}} do - assert {:ok, %SpatialThing{id: ^id}} = Domain.delete(id) - assert Domain.by_id(id) == nil +describe "delete/1" do + test "with good id: deletes the SpatialThing", %{inserted: %{id: id}} do + assert {:ok, %SpatialThing{id: ^id}} = Domain.delete(id) + assert {:error, "not found"} = Domain.one(id) + end + + test "with bad id: doesn't delete the SpatialThing" do + assert {:error, "not found"} = Domain.delete(Factory.id()) + end end end diff --git a/test/vf/spatial_thing/type.test.exs b/test/vf/spatial_thing/type.test.exs @@ -21,113 +21,89 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - name: Factory.uniq("name"), - mappable_address: Factory.uniq("address"), - lat: Factory.float(), - long: Factory.float(), - alt: Factory.float(), - note: Factory.uniq("note"), + "name" => Factory.str("name"), + "mappableAddress" => Factory.str("address"), + "lat" => Factory.float(), + "long" => Factory.float(), + "alt" => Factory.float(), + "note" => Factory.str("note"), }, - spatial_thing: Factory.insert!(:spatial_thing), + inserted: Factory.insert!(:spatial_thing), } end +@frag """ +fragment spatialThing on SpatialThing { + id + name + mappableAddress + lat + long + alt + note +} +""" + describe "Query" do - test "spatialThing()", %{spatial_thing: spt_thg} do + test "spatialThing", %{inserted: new} do assert %{data: %{"spatialThing" => data}} = - query!(""" - spatialThing(id: "#{spt_thg.id}") { - id - name - mappableAddress - lat - long - alt - note + run!(""" + #{@frag} + query ($id: ID!) { + spatialThing(id: $id) {...spatialThing} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == spt_thg.id - assert data["name"] == spt_thg.name - assert data["mappableAddress"] == spt_thg.mappable_address - assert data["lat"] == spt_thg.lat - assert data["long"] == spt_thg.long - assert data["alt"] == spt_thg.alt - assert data["note"] == spt_thg.note + assert data["id"] == new.id + assert data["name"] == new.name + assert data["mappableAddress"] == new.mappable_address + assert data["lat"] == new.lat + assert data["long"] == new.long + assert data["alt"] == new.alt + assert data["note"] == new.note end end describe "Mutation" do - test "createSpatialThing()", %{params: params} do + test "createSpatialThing", %{params: params} do assert %{data: %{"createSpatialThing" => %{"spatialThing" => data}}} = - mutation!(""" - createSpatialThing(spatialThing: { - name: "#{params.name}" - mappableAddress: "#{params.mappable_address}" - lat: #{params.lat} - long: #{params.long} - alt: #{params.alt} - note: "#{params.note}" - }) { - spatialThing { - id - name - mappableAddress - lat - long - alt - note + run!(""" + #{@frag} + mutation ($spatialThing: SpatialThingCreateParams!) { + createSpatialThing(spatialThing: $spatialThing) { + spatialThing {...spatialThing} } } - """) + """, vars: %{"spatialThing" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["name"] == params.name - assert data["mappableAddress"] == params.mappable_address - assert data["lat"] == params.lat - assert data["long"] == params.long - assert data["alt"] == params.alt - assert data["note"] == params.note + data = Map.delete(data, "id") + assert data == params end - test "updateSpatialThing()", %{params: params, spatial_thing: spt_thg} do + test "updateSpatialThing", %{params: params, inserted: old} do assert %{data: %{"updateSpatialThing" => %{"spatialThing" => data}}} = - mutation!(""" - updateSpatialThing(spatialThing: { - id: "#{spt_thg.id}" - name: "#{params.name}" - mappableAddress: "#{params.mappable_address}" - lat: #{params.lat} - long: #{params.long} - alt: #{params.alt} - note: "#{params.note}" - }) { - spatialThing { - id - name - mappableAddress - lat - long - alt - note + run!(""" + #{@frag} + mutation ($spatialThing: SpatialThingUpdateParams!) { + updateSpatialThing(spatialThing: $spatialThing) { + spatialThing {...spatialThing} } } - """) + """, vars: %{"spatialThing" => Map.put(params, "id", old.id)}) - assert data["id"] == spt_thg.id - assert data["name"] == params.name - assert data["mappableAddress"] == params.mappable_address - assert data["lat"] == params.lat - assert data["long"] == params.long - assert data["alt"] == params.alt - assert data["note"] == params.note + assert data["id"] == old.id + data = Map.delete(data, "id") + assert data == params end - test "deleteSpatialThing()", %{spatial_thing: %{id: id}} do + test "deleteSpatialThing", %{inserted: %{id: id}} do assert %{data: %{"deleteSpatialThing" => true}} = - mutation!(""" - deleteSpatialThing(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteSpatialThing(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/unit/domain.test.exs b/test/vf/unit/domain.test.exs @@ -28,7 +28,6 @@ setup do symbol: Factory.str("symbol"), }, inserted: Factory.insert!(:unit), - id: Factory.id(), } end @@ -37,8 +36,8 @@ describe "one/1" do assert {:ok, %Unit{}} = Domain.one(id) end - test "with bad id: doesn't find the Unit", %{id: id} do - assert {:error, "not found"} = Domain.one(id) + test "with bad id: doesn't find the Unit" do + assert {:error, "not found"} = Domain.one(Factory.id()) end end @@ -74,8 +73,8 @@ describe "delete/1" do assert {:error, "not found"} = Domain.one(id) end - test "with bad id: doesn't delete the Unit", %{id: id} do - assert {:error, "not found"} = Domain.delete(id) + test "with bad id: doesn't delete the Unit" do + assert {:error, "not found"} = Domain.delete(Factory.id()) end end end diff --git a/test/vf/unit/type.test.exs b/test/vf/unit/type.test.exs @@ -21,77 +21,77 @@ use ZenflowsTest.Help.AbsinCase, async: true setup do %{ params: %{ - label: Factory.uniq("label"), - symbol: Factory.uniq("symbol"), + "label" => Factory.str("label"), + "symbol" => Factory.str("symbol"), }, - unit: Factory.insert!(:unit), + inserted: Factory.insert!(:unit), } end +@frag """ +fragment unit on Unit { + id + label + symbol +} +""" + describe "Query" do - test "unit()", %{unit: unit} do + test "unit", %{inserted: new} do assert %{data: %{"unit" => data}} = - query!(""" - unit(id: "#{unit.id}") { - id - label - symbol + run!(""" + #{@frag} + query ($id: ID!) { + unit(id: $id) {...unit} } - """) + """, vars: %{"id" => new.id}) - assert data["id"] == unit.id - assert data["label"] == unit.label - assert data["symbol"] == unit.symbol + assert data["id"] == new.id + assert data["label"] == new.label + assert data["symbol"] == new.symbol end end describe "Mutation" do - test "createUnit()", %{params: params} do + test "createUnit", %{params: params} do assert %{data: %{"createUnit" => %{"unit" => data}}} = - mutation!(""" - createUnit(unit: { - label: "#{params.label}" - symbol: "#{params.symbol}" - }) { - unit { - id - label - symbol + run!(""" + #{@frag} + mutation ($unit: UnitCreateParams!) { + createUnit(unit: $unit) { + unit {...unit} } } - """) + """, vars: %{"unit" => params}) assert {:ok, _} = Zenflows.DB.ID.cast(data["id"]) - assert data["label"] == params.label - assert data["symbol"] == params.symbol + assert data["label"] == params["label"] + assert data["symbol"] == params["symbol"] end - test "updateUnit()", %{params: params, unit: unit} do + test "updateUnit", %{params: params, inserted: old} do assert %{data: %{"updateUnit" => %{"unit" => data}}} = - mutation!(""" - updateUnit(unit: { - id: "#{unit.id}" - label: "#{params.label}" - symbol: "#{params.symbol}" - }) { - unit { - id - label - symbol + run!(""" + #{@frag} + mutation ($unit: UnitUpdateParams!) { + updateUnit(unit: $unit) { + unit {...unit} } } - """) + """, vars: %{"unit" => Map.put(params, "id", old.id)}) - assert data["id"] == unit.id - assert data["label"] == params.label - assert data["symbol"] == params.symbol + assert data["id"] == old.id + assert data["label"] == params["label"] + assert data["symbol"] == params["symbol"] end - test "deleteUnit()", %{unit: %{id: id}} do + test "deleteUnit", %{inserted: %{id: id}} do assert %{data: %{"deleteUnit" => true}} = - mutation!(""" - deleteUnit(id: "#{id}") - """) + run!(""" + mutation ($id: ID!) { + deleteUnit(id: $id) + } + """, vars: %{"id" => id}) end end end diff --git a/test/vf/validate.test.exs b/test/vf/validate.test.exs @@ -150,7 +150,7 @@ describe "img/2" do test "with too long param" do assert %Changeset{errors: errs} = - %{img: String.duplicate("a", 25 * 1024**2 + 1)} + %{img: String.duplicate("a", 25 * 1024 * 1024 + 1)} |> img_chgset() |> Validate.img(:img)