domain.test.exs (11991B)
1 # Zenflows is designed to implement the Valueflows vocabulary, 2 # written and maintained by srfsh <info@dyne.org>. 3 # Copyright (C) 2021-2023 Dyne.org foundation <foundation@dyne.org>. 4 # 5 # This program is free software: you can redistribute it and/or modify 6 # it under the terms of the GNU Affero General Public License as published by 7 # the Free Software Foundation, either version 3 of the License, or 8 # (at your option) any later version. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU Affero General Public License for more details. 14 # 15 # You should have received a copy of the GNU Affero General Public License 16 # along with this program. If not, see <https://www.gnu.org/licenses/>. 17 18 defmodule ZenflowsTest.VF.Intent.Domain do 19 use ZenflowsTest.Help.EctoCase, async: true 20 21 alias Ecto.Changeset 22 alias Zenflows.VF.{ 23 Action, 24 Agent, 25 EconomicResource, 26 Intent, 27 Intent.Domain, 28 Measure, 29 Process, 30 ResourceSpecification, 31 SpatialThing, 32 } 33 34 setup do 35 %{ 36 params: %{ 37 action_id: Factory.build(:action_id), 38 input_of_id: Factory.insert!(:process).id, 39 output_of_id: Factory.insert!(:process).id, 40 provider_id: Factory.insert!(:agent).id, 41 receiver_id: Factory.insert!(:agent).id, 42 resource_inventoried_as_id: Factory.insert!(:economic_resource).id, 43 resource_conforms_to_id: Factory.insert!(:resource_specification).id, 44 resource_classified_as: Factory.str_list("uri"), 45 resource_quantity: %{ 46 has_unit_id: Factory.insert!(:unit).id, 47 has_numerical_value: Factory.decimal(), 48 }, 49 effort_quantity: %{ 50 has_unit_id: Factory.insert!(:unit).id, 51 has_numerical_value: Factory.decimal(), 52 }, 53 available_quantity: %{ 54 has_unit_id: Factory.insert!(:unit).id, 55 has_numerical_value: Factory.decimal(), 56 }, 57 has_beginning: Factory.now(), 58 has_end: Factory.now(), 59 has_point_in_time: Factory.now(), 60 due: Factory.now(), 61 finished: Factory.bool(), 62 at_location_id: Factory.insert!(:spatial_thing).id, 63 name: Factory.str("name"), 64 note: Factory.str("note"), 65 # in_scope_of_id: 66 agreed_in: Factory.str("uri"), 67 }, 68 inserted: Factory.insert!(:intent), 69 } 70 end 71 72 describe "one/1" do 73 test "with good id: finds the Intent", %{inserted: %{id: id}} do 74 assert {:ok, %Intent{}} = Domain.one(id) 75 end 76 77 test "with bad id: doesn't find the Intent" do 78 assert {:error, "not found"} = Domain.one(Factory.id()) 79 end 80 end 81 82 describe "create/1" do 83 test "with good params (with only :provider): creates an Intent", %{params: params} do 84 params = Map.put(params, :receiver_id, nil) 85 assert {:ok, %Intent{} = int} = Domain.create(params) 86 87 keys = ~w[ 88 action_id 89 provider_id receiver_id 90 input_of_id output_of_id 91 resource_inventoried_as_id resource_conforms_to_id resource_classified_as 92 has_beginning has_end has_point_in_time due 93 finished name note agreed_in at_location_id 94 ]a # in_scope_of_id 95 assert Map.take(int, keys) == Map.take(params, keys) 96 97 assert int.resource_quantity_has_unit_id == params.resource_quantity.has_unit_id 98 assert Decimal.eq?(int.resource_quantity_has_numerical_value, params.resource_quantity.has_numerical_value) 99 assert int.effort_quantity_has_unit_id == params.effort_quantity.has_unit_id 100 assert Decimal.eq?(int.effort_quantity_has_numerical_value, params.effort_quantity.has_numerical_value) 101 assert int.available_quantity_has_unit_id == params.available_quantity.has_unit_id 102 assert Decimal.eq?(int.available_quantity_has_numerical_value, params.available_quantity.has_numerical_value) 103 end 104 105 test "with good params (with only :receiver): creates an Intent", %{params: params} do 106 params = Map.put(params, :provider_id, nil) 107 assert {:ok, %Intent{} = int} = Domain.create(params) 108 109 keys = ~w[ 110 action_id 111 provider_id receiver_id 112 input_of_id output_of_id 113 resource_inventoried_as_id resource_conforms_to_id resource_classified_as 114 has_beginning has_end has_point_in_time due 115 finished name note agreed_in at_location_id 116 ]a # in_scope_of_id 117 assert Map.take(int, keys) == Map.take(params, keys) 118 119 assert int.resource_quantity_has_unit_id == params.resource_quantity.has_unit_id 120 assert Decimal.eq?(int.resource_quantity_has_numerical_value, params.resource_quantity.has_numerical_value) 121 assert int.effort_quantity_has_unit_id == params.effort_quantity.has_unit_id 122 assert Decimal.eq?(int.effort_quantity_has_numerical_value, params.effort_quantity.has_numerical_value) 123 assert int.available_quantity_has_unit_id == params.available_quantity.has_unit_id 124 assert Decimal.eq?(int.available_quantity_has_numerical_value, params.available_quantity.has_numerical_value) 125 end 126 127 test "with bad params (with both :provider and :receiver): doesn't create an Intent", %{params: params} do 128 assert {:error, %Changeset{errors: errs}} = Domain.create(params) 129 assert {:ok, _} = Keyword.fetch(errs, :provider_id) 130 assert {:ok, _} = Keyword.fetch(errs, :receiver_id) 131 end 132 133 test "with bad params: doesn't create an Intent" do 134 assert {:error, %Changeset{}} = Domain.create(%{}) 135 end 136 end 137 138 describe "update/2" do 139 test "with good params (with only :provider): updates the Intent", %{params: params} do 140 params = Map.put(params, :receiver_id, nil) 141 old = Factory.insert!(:intent, %{receiver: nil, provider: Factory.build(:agent)}) 142 assert {:ok, %Intent{} = new} = Domain.update(old.id, params) 143 144 keys = ~w[ 145 action_id 146 provider_id receiver_id 147 input_of_id output_of_id 148 resource_inventoried_as_id resource_conforms_to_id resource_classified_as 149 has_beginning has_end has_point_in_time due 150 finished name note agreed_in at_location_id 151 ]a # in_scope_of_id 152 assert Map.take(new, keys) == Map.take(params, keys) 153 154 assert new.resource_quantity_has_unit_id == params.resource_quantity.has_unit_id 155 assert Decimal.eq?(new.resource_quantity_has_numerical_value, params.resource_quantity.has_numerical_value) 156 assert new.effort_quantity_has_unit_id == params.effort_quantity.has_unit_id 157 assert Decimal.eq?(new.effort_quantity_has_numerical_value, params.effort_quantity.has_numerical_value) 158 assert new.available_quantity_has_unit_id == params.available_quantity.has_unit_id 159 assert Decimal.eq?(new.available_quantity_has_numerical_value, params.available_quantity.has_numerical_value) 160 end 161 162 test "with good params (with only :receiver): updates the Intent", %{params: params} do 163 params = Map.put(params, :provider_id, nil) 164 old = Factory.insert!(:intent, %{provider: nil, receiver: Factory.build(:agent)}) 165 assert {:ok, %Intent{} = new} = Domain.update(old.id, params) 166 167 keys = ~w[ 168 action_id 169 provider_id receiver_id 170 input_of_id output_of_id 171 resource_inventoried_as_id resource_conforms_to_id resource_classified_as 172 has_beginning has_end has_point_in_time due 173 finished name note agreed_in at_location_id 174 ]a # in_scope_of_id 175 assert Map.take(new, keys) == Map.take(params, keys) 176 177 assert new.resource_quantity_has_unit_id == params.resource_quantity.has_unit_id 178 assert Decimal.eq?(new.resource_quantity_has_numerical_value, params.resource_quantity.has_numerical_value) 179 assert new.effort_quantity_has_unit_id == params.effort_quantity.has_unit_id 180 assert Decimal.eq?(new.effort_quantity_has_numerical_value, params.effort_quantity.has_numerical_value) 181 assert new.available_quantity_has_unit_id == params.available_quantity.has_unit_id 182 assert Decimal.eq?(new.available_quantity_has_numerical_value, params.available_quantity.has_numerical_value) 183 end 184 185 test "with bad params (with both :provider and :receiver): updates the Intent", %{params: params} do 186 int = Factory.insert!(:intent, %{provider: Factory.build(:agent), receiver: nil}) 187 assert {:error, %Changeset{errors: errs}} = Domain.update(int.id, params) 188 189 assert {:ok, _} = Keyword.fetch(errs, :provider_id) 190 assert {:ok, _} = Keyword.fetch(errs, :receiver_id) 191 end 192 193 test "with bad params (with both :receiver and :provider): updates the Intent", %{params: params} do 194 int = Factory.insert!(:intent, %{provider: nil, receiver: Factory.build(:agent)}) 195 assert {:error, %Changeset{errors: errs}} = Domain.update(int.id, params) 196 197 assert {:ok, _} = Keyword.fetch(errs, :provider_id) 198 assert {:ok, _} = Keyword.fetch(errs, :receiver_id) 199 end 200 201 test "with bad params: doesn't update the Intent", %{inserted: old} do 202 assert {:ok, %Intent{} = new} = Domain.update(old.id, %{}) 203 keys = ~w[ 204 action_id 205 provider_id receiver_id 206 input_of_id output_of_id 207 resource_inventoried_as_id resource_conforms_to_id resource_classified_as 208 resource_quantity_has_unit_id resource_quantity_has_numerical_value 209 effort_quantity_has_unit_id effort_quantity_has_numerical_value 210 available_quantity_has_unit_id available_quantity_has_numerical_value 211 has_beginning has_end has_point_in_time due 212 finished name note agreed_in at_location_id 213 ]a # in_scope_of_id 214 assert Map.take(new, keys) == Map.take(old, keys) 215 end 216 end 217 218 describe "delete/1" do 219 test "with good id: deletes the Intent", %{inserted: %{id: id}} do 220 assert {:ok, %Intent{id: ^id}} = Domain.delete(id) 221 assert {:error, "not found"} = Domain.one(id) 222 end 223 224 test "with bad id: doesn't delete the Intent" do 225 assert {:error, "not found"} = Domain.delete(Factory.id()) 226 end 227 end 228 229 describe "preload/2" do 230 test "preloads `:action`", %{inserted: %{id: id}} do 231 assert {:ok, int} = Domain.one(id) 232 int = Domain.preload(int, :action) 233 assert %Action{} = int.action 234 end 235 236 test "preloads `:input_of`", %{inserted: %{id: id}} do 237 assert {:ok, int} = Domain.one(id) 238 int = Domain.preload(int, :input_of) 239 assert %Process{} = int.input_of 240 end 241 242 test "preloads `:output_of`", %{inserted: %{id: id}} do 243 assert {:ok, int} = Domain.one(id) 244 int = Domain.preload(int, :output_of) 245 assert %Process{} = int.output_of 246 end 247 248 test "preloads `:provider`" do 249 %{id: id} = 250 Factory.insert!(:intent, %{provider: Factory.build(:agent), receiver: nil}) 251 252 assert {:ok, int} = Domain.one(id) 253 int = Domain.preload(int, :provider) 254 assert %Agent{} = int.provider 255 end 256 257 test "preloads `:receiver`" do 258 %{id: id} = 259 Factory.insert!(:intent, %{provider: nil, receiver: Factory.build(:agent)}) 260 261 assert {:ok, int} = Domain.one(id) 262 int = Domain.preload(int, :receiver) 263 assert %Agent{} = int.receiver 264 end 265 266 test "preloads `:resource_inventoried_as`", %{inserted: %{id: id}} do 267 assert {:ok, int} = Domain.one(id) 268 int = Domain.preload(int, :resource_inventoried_as) 269 assert %EconomicResource{} = int.resource_inventoried_as 270 end 271 272 test "preloads `:resource_conforms_to`", %{inserted: %{id: id}} do 273 assert {:ok, int} = Domain.one(id) 274 int = Domain.preload(int, :resource_conforms_to) 275 assert %ResourceSpecification{} = int.resource_conforms_to 276 end 277 278 test "preloads `:resource_quantity`", %{inserted: %{id: id}} do 279 assert {:ok, int} = Domain.one(id) 280 int = Domain.preload(int, :resource_quantity) 281 assert %Measure{} = int.resource_quantity 282 end 283 284 test "preloads `:effort_quantity`", %{inserted: %{id: id}} do 285 assert {:ok, int} = Domain.one(id) 286 int = Domain.preload(int, :effort_quantity) 287 assert %Measure{} = int.effort_quantity 288 end 289 290 test "preloads `:available_quantity`", %{inserted: %{id: id}} do 291 assert {:ok, int} = Domain.one(id) 292 int = Domain.preload(int, :available_quantity) 293 assert %Measure{} = int.available_quantity 294 end 295 296 test "preloads `:at_location`", %{inserted: %{id: id}} do 297 assert {:ok, int} = Domain.one(id) 298 int = Domain.preload(int, :at_location) 299 assert %SpatialThing{} = int.at_location 300 end 301 302 test "preloads `:published_in`", %{inserted: %{id: id}} do 303 assert {:ok, int} = Domain.one(id) 304 305 assert [] = Domain.preload(int, :published_in).published_in 306 307 left = 308 Enum.map(0..9, fn _ -> 309 Factory.insert!(:proposed_intent, %{publishes: int}).id 310 end) 311 right = 312 Domain.preload(int, :published_in) 313 |> Map.fetch!(:published_in) 314 |> Enum.map(& &1.id) 315 assert left -- right == [] 316 end 317 end 318 end