From b899496fbac9f2bbfee362578ee38d4f3d2105d4 Mon Sep 17 00:00:00 2001 From: Matt Beanland Date: Fri, 17 Apr 2026 16:23:52 +0930 Subject: [PATCH 1/2] value, primitive and dynamic --- config/config.exs | 2 + config/dev.exs | 3 +- config/test.exs | 7 +- ...e_diffo_provider_instance_extension.livemd | 2 +- lib/diffo/helpers/uuid.ex | 10 +- .../provider/assigner/assignable_value.ex | 5 +- lib/diffo/provider/assigner/assigner.ex | 47 +++-- lib/diffo/provider/assigner/assignment.ex | 5 +- .../provider/components/base_instance.ex | 13 +- .../components/calculations/instance_href.ex | 32 ++++ .../calculations/specification_href.ex | 31 ++++ .../specification_instance_type.ex | 27 +++ .../calculations/specification_version.ex | 27 +++ .../provider/components/characteristic.ex | 3 +- .../instance/extension/characteristic.ex | 29 ++- .../components/instance/extension/feature.ex | 3 +- .../provider/components/process_status.ex | 2 +- .../provider/components/specification.ex | 33 +--- lib/diffo/provider/reference.ex | 8 +- lib/diffo/type/dynamic.ex | 126 +++++++++++++ lib/diffo/type/outstanding/dynamic.ex | 32 ++++ lib/diffo/type/outstanding/primitive.ex | 35 ++++ lib/diffo/type/primitive.ex | 66 +++++++ lib/diffo/type/value.ex | 78 ++++++++ lib/diffo/unwrap.ex | 14 ++ lib/diffo/unwrap/any.ex | 7 + lib/diffo/unwrap/ash_ci_string.ex | 7 + lib/diffo/unwrap/ash_custom_expression.ex | 20 +++ lib/diffo/unwrap/ash_not_loaded.ex | 9 + lib/diffo/unwrap/ash_union.ex | 7 + lib/mix/tasks/diagram.ex | 13 -- mix.exs | 6 +- mix.lock | 16 +- test/instance_extension/assigner_test.exs | 24 +-- test/provider/characteristic_test.exs | 115 ++++++------ test/provider/event_test.exs | 2 +- test/provider/external_identifier_test.exs | 1 + test/provider/feature_test.exs | 39 ++-- test/provider/instance_test.exs | 77 ++++---- test/provider/party_test.exs | 1 + test/provider/process_status_test.exs | 11 +- test/provider/reference_test.exs | 14 +- test/provider/relationship_test.exs | 26 +-- test/support/characteristics.ex | 2 +- test/support/type/patch.ex | 22 +++ test/test_helper.exs | 3 +- test/type/dynamic_test.exs | 81 +++++++++ test/type/primitive_test.exs | 122 +++++++++++++ test/type/value_test.exs | 166 ++++++++++++++++++ 49 files changed, 1179 insertions(+), 252 deletions(-) create mode 100644 lib/diffo/provider/components/calculations/instance_href.ex create mode 100644 lib/diffo/provider/components/calculations/specification_href.ex create mode 100644 lib/diffo/provider/components/calculations/specification_instance_type.ex create mode 100644 lib/diffo/provider/components/calculations/specification_version.ex create mode 100644 lib/diffo/type/dynamic.ex create mode 100644 lib/diffo/type/outstanding/dynamic.ex create mode 100644 lib/diffo/type/outstanding/primitive.ex create mode 100644 lib/diffo/type/primitive.ex create mode 100644 lib/diffo/type/value.ex create mode 100644 lib/diffo/unwrap.ex create mode 100644 lib/diffo/unwrap/any.ex create mode 100644 lib/diffo/unwrap/ash_ci_string.ex create mode 100644 lib/diffo/unwrap/ash_custom_expression.ex create mode 100644 lib/diffo/unwrap/ash_not_loaded.ex create mode 100644 lib/diffo/unwrap/ash_union.ex delete mode 100644 lib/mix/tasks/diagram.ex create mode 100644 test/support/type/patch.ex create mode 100644 test/type/dynamic_test.exs create mode 100644 test/type/primitive_test.exs create mode 100644 test/type/value_test.exs diff --git a/config/config.exs b/config/config.exs index 38155e0..3d081d1 100644 --- a/config/config.exs +++ b/config/config.exs @@ -36,5 +36,7 @@ config :spark, ] ] +config :ash, :custom_expressions, [Diffo.Unwrap.AshCustomExpression] + config :diffo, ash_domains: [Diffo.Provider] import_config "#{config_env()}.exs" diff --git a/config/dev.exs b/config/dev.exs index 7da41c7..59cd7ac 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -23,5 +23,6 @@ level = end config :logger, :console, - level: level, + # level: level, + level: :debug, format: "$date $time [$level] $metadata$message\n" diff --git a/config/test.exs b/config/test.exs index 6643b97..c498afe 100644 --- a/config/test.exs +++ b/config/test.exs @@ -4,7 +4,6 @@ import Config -config :logger, level: :warning config :ash, disable_async?: true config :ash, :missed_notifications, :ignore @@ -16,8 +15,8 @@ config :bolty, Bolt, max_overflow: 3, prefix: :default, name: Bolt, - log: true, - log_hex: true + log: false, + log_hex: false level = if System.get_env("DEBUG") do @@ -26,6 +25,8 @@ level = :info end +config :logger, level: level + config :logger, :console, level: level, format: "$date $time [$level] $metadata$message\n" diff --git a/documentation/how_to/use_diffo_provider_instance_extension.livemd b/documentation/how_to/use_diffo_provider_instance_extension.livemd index b47e0d2..f07df85 100644 --- a/documentation/how_to/use_diffo_provider_instance_extension.livemd +++ b/documentation/how_to/use_diffo_provider_instance_extension.livemd @@ -535,7 +535,7 @@ We need to define each GPU instance, in this case defining the gpu Characteristi ```elixir updates = [ gpu: [family: :nvidia, model: "GeForce RTX5090", technology: :blackwell], - cores: [first: 1, last: 680, free: 680, type: "tensor"] + cores: [first: 1, last: 680, free: 680, assignable_type: "tensor"] ] gpu_1 = Compute.define_gpu!(gpu_1, %{characteristic_value_updates: updates}) diff --git a/lib/diffo/helpers/uuid.ex b/lib/diffo/helpers/uuid.ex index c7b9ae9..ed04e79 100644 --- a/lib/diffo/helpers/uuid.ex +++ b/lib/diffo/helpers/uuid.ex @@ -102,10 +102,10 @@ defmodule Diffo.Uuid do @doc """ Returns trailing uuid4 if valid, or nil. ## Examples - iex> Diffo.Uuid.trailing_uuid4("serviceInventoryManagement/v4/service/accessEvc/d2566874-d5ee-400b-9983-10d63ec52f32") + iex> Diffo.Uuid.trailing_uuid4("serviceInventoryManagement/v4/service/d2566874-d5ee-400b-9983-10d63ec52f32") "d2566874-d5ee-400b-9983-10d63ec52f32" - iex> Diffo.Uuid.trailing_uuid4("serviceInventoryManagement/v4/service/accessEvc/d2566874-d5ee-400b-9983") + iex> Diffo.Uuid.trailing_uuid4("serviceInventoryManagement/v4/service/d2566874-d5ee-400b-9983") nil iex> Diffo.Uuid.trailing_uuid4("d2566874-d5ee-400b-9983-10d63ec52f32") @@ -136,7 +136,7 @@ defmodule Diffo.Uuid do iex> Diffo.Uuid.expect_uuid4("d2566874-d5ee-400b-9983-10d63ec52f32") nil - iex> Diffo.Uuid.expect_uuid4("serviceInventoryManagement/v4/service/accessEvc/d2566874-d5ee-400b-9983-10d63ec52f32") + iex> Diffo.Uuid.expect_uuid4("serviceInventoryManagement/v4/service/d2566874-d5ee-400b-9983-10d63ec52f32") :uuid4 iex> Diffo.Uuid.expect_uuid4(nil) @@ -154,10 +154,10 @@ defmodule Diffo.Uuid do @doc """ Callback function for outstanding to expect trailing uuid4. ## Examples - iex> Diffo.Uuid.expect_trailing_uuid4("serviceInventoryManagement/v4/service/accessEvc/d2566874-d5ee-400b-9983-10d63ec52f32") + iex> Diffo.Uuid.expect_trailing_uuid4("serviceInventoryManagement/v4/service/d2566874-d5ee-400b-9983-10d63ec52f32") nil - iex> Diffo.Uuid.expect_trailing_uuid4("serviceInventoryManagement/v4/service/accessEvc/d2566874-d5ee-400b-9983") + iex> Diffo.Uuid.expect_trailing_uuid4("serviceInventoryManagement/v4/service/d2566874-d5ee-400b-9983") :trailing_uuid4 iex> Diffo.Uuid.expect_trailing_uuid4("d2566874-d5ee-400b-9983-10d63ec52f32") diff --git a/lib/diffo/provider/assigner/assignable_value.ex b/lib/diffo/provider/assigner/assignable_value.ex index 7ee059b..51432a6 100644 --- a/lib/diffo/provider/assigner/assignable_value.ex +++ b/lib/diffo/provider/assigner/assignable_value.ex @@ -11,8 +11,9 @@ defmodule Diffo.Provider.AssignableValue do use Ash.TypedStruct, extensions: [AshJason.TypedStruct] jason do - pick [:first, :last, :free, :type, :algorithm] + pick [:first, :last, :free, :assignable_type, :algorithm] compact true + rename assignable_type: :type end typed_struct do @@ -31,7 +32,7 @@ defmodule Diffo.Provider.AssignableValue do default: 1, constraints: [min: 0] - field :type, :atom, description: "the type of the assignable thing" + field :assignable_type, :string, description: "the type of the assignable thing" field :algorithm, :atom, description: "the assignment algorithm", diff --git a/lib/diffo/provider/assigner/assigner.ex b/lib/diffo/provider/assigner/assigner.ex index 11a7a39..583ad59 100644 --- a/lib/diffo/provider/assigner/assigner.ex +++ b/lib/diffo/provider/assigner/assigner.ex @@ -10,6 +10,7 @@ defmodule Diffo.Provider.Assigner do """ alias Diffo.Provider.AssignableValue + alias Diffo.Type.Value @doc """ Assign a thing using the instance changeset assignment @@ -53,7 +54,11 @@ defmodule Diffo.Provider.Assigner do defp relate_is_assigned(result, things, thing, value, assignee_id) when is_struct(result) and is_atom(things) and is_atom(thing) and is_integer(value) and is_bitstring(assignee_id) do - case Diffo.Provider.create_characteristic(%{name: thing, value: value, type: :relationship}) do + case Diffo.Provider.create_characteristic(%{ + name: thing, + value: Value.primitive("integer", value), + type: :relationship + }) do {:ok, characteristic} -> case Diffo.Provider.create_relationship(%{ type: :assignedTo, @@ -62,7 +67,6 @@ defmodule Diffo.Provider.Assigner do characteristics: [characteristic.id] }) do {:ok, _relationship} -> - # we haven't refreshed the result there will be a new forward_relationship and an updated things characteristic case decrement_free(result, things) do :ok -> {:ok, result} @@ -91,7 +95,7 @@ defmodule Diffo.Provider.Assigner do } -> type == :assignedTo and target_id == assignee_id and Enum.any?(characteristics, fn %{name: name, value: v} -> - name == thing and v == value + name == thing and Diffo.Unwrap.unwrap(v) == value end) end) @@ -105,16 +109,13 @@ defmodule Diffo.Provider.Assigner do characteristic = Enum.find(relationship.characteristics, fn %{name: n} -> n == thing end) - # unrelate the relationship characterisitic relationship = Diffo.Provider.unrelate_relationship_characteristics!(relationship, %{ characteristics: [characteristic.id] }) - # delete the relationship characteristic Diffo.Provider.delete_characteristic(characteristic.id) - # delete the relationship case Diffo.Provider.delete_relationship(relationship.id) do :ok -> case increment_free(result, things) do @@ -148,8 +149,8 @@ defmodule Diffo.Provider.Assigner do if characteristic do assignment = struct(Diffo.Provider.Assignment, %{ - id: characteristic.value, - type: thing, + id: Diffo.Unwrap.unwrap(characteristic.value), + assignable_type: thing, assignee_id: target_id }) @@ -168,9 +169,10 @@ defmodule Diffo.Provider.Assigner do defp next(instance, things, thing) when is_struct(instance) and is_atom(things) and is_atom(thing) do characteristic = Enum.find(instance.characteristics, fn %{name: name} -> name == things end) - algorithm = Map.get(characteristic.value, :algorithm) + assignable_value = Diffo.Unwrap.unwrap(characteristic.value) + algorithm = Map.get(assignable_value, :algorithm) - case free = free(instance, thing, characteristic.value) do + case free = free(instance, thing, assignable_value) do [] -> {:error, "all things are assigned"} @@ -191,7 +193,8 @@ defmodule Diffo.Provider.Assigner do defp assignable?(instance, things, thing, value) when is_struct(instance) and is_atom(things) and is_atom(thing) and is_integer(value) do characteristic = Enum.find(instance.characteristics, fn %{name: name} -> name == things end) - free = free(instance, thing, characteristic.value) + assignable_value = Diffo.Unwrap.unwrap(characteristic.value) + free = free(instance, thing, assignable_value) value in free end @@ -200,10 +203,15 @@ defmodule Diffo.Provider.Assigner do characteristic = Enum.find(instance.characteristics, fn %{name: name} -> name == things end) - {_free, assignable_value} = - Map.get_and_update(characteristic.value, :free, fn free -> {free - 1, free - 1} end) + assignable_value = Diffo.Unwrap.unwrap(characteristic.value) - case Diffo.Provider.update_characteristic(characteristic, %{value: assignable_value}) do + {_free, updated} = + Map.get_and_update(assignable_value, :free, fn free -> {free - 1, free - 1} end) + + {:ok, new_struct} = Ash.Type.cast_input(AssignableValue, Map.from_struct(updated), AssignableValue.subtype_constraints()) + new_value = Value.dynamic(AssignableValue, new_struct) + + case Diffo.Provider.update_characteristic(characteristic, %{value: new_value}) do {:ok, _characteristic} -> :ok @@ -216,10 +224,15 @@ defmodule Diffo.Provider.Assigner do characteristic = Enum.find(instance.characteristics, fn %{name: name} -> name == things end) - {_free, assignable_value} = - Map.get_and_update(characteristic.value, :free, fn free -> {free + 1, free + 1} end) + assignable_value = Diffo.Unwrap.unwrap(characteristic.value) + + {_free, updated} = + Map.get_and_update(assignable_value, :free, fn free -> {free + 1, free + 1} end) + + {:ok, new_struct} = Ash.Type.cast_input(AssignableValue, Map.from_struct(updated), AssignableValue.subtype_constraints()) + new_value = Value.dynamic(AssignableValue, new_struct) - case Diffo.Provider.update_characteristic(characteristic, %{value: assignable_value}) do + case Diffo.Provider.update_characteristic(characteristic, %{value: new_value}) do {:ok, _characteristic} -> :ok diff --git a/lib/diffo/provider/assigner/assignment.ex b/lib/diffo/provider/assigner/assignment.ex index 108f8f5..8103b44 100644 --- a/lib/diffo/provider/assigner/assignment.ex +++ b/lib/diffo/provider/assigner/assignment.ex @@ -11,8 +11,9 @@ defmodule Diffo.Provider.Assignment do use Ash.TypedStruct, extensions: [AshJason.TypedStruct] jason do - pick [:id, :assignee_id, :operation] + pick [:id, :assignee_id, :assignable_type, :operation] compact true + rename assignable_type: :type end typed_struct do @@ -20,7 +21,7 @@ defmodule Diffo.Provider.Assignment do constraints: [min: 0], description: "the id of the assigned thing" - field :type, :atom, description: "the type of the assigned thing" + field :assignable_type, :string, description: "the type of the assigned thing" field :assignee_id, :uuid, description: "the id of the assignee Ash resource" diff --git a/lib/diffo/provider/components/base_instance.ex b/lib/diffo/provider/components/base_instance.ex index 3479ed3..76d04dd 100644 --- a/lib/diffo/provider/components/base_instance.ex +++ b/lib/diffo/provider/components/base_instance.ex @@ -504,18 +504,7 @@ defmodule Diffo.Provider.BaseInstance do end calculations do - calculate :href, - :string, - expr( - type <> - "InventoryManagement/v" <> - specification.tmf_version <> - "/" <> - type <> - "/" <> - specification.name <> - "/" <> id - ) do + calculate :href, :string, Diffo.Provider.Calculations.InstanceHref do description "the inventory href of the service or resource instance" end end diff --git a/lib/diffo/provider/components/calculations/instance_href.ex b/lib/diffo/provider/components/calculations/instance_href.ex new file mode 100644 index 0000000..eccc37f --- /dev/null +++ b/lib/diffo/provider/components/calculations/instance_href.ex @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defmodule Diffo.Provider.Calculations.InstanceHref do + @moduledoc """ + Diffo - TMF Service and Resource Management with a difference + + InstanceHref - Ash Resource Calculation for generating instance href + + """ + use Ash.Resource.Calculation + + @impl true + def load(_query, _opts, _context), do: [:specification] + + @impl true + def calculate(records, _opts, _context) do + Enum.map(records, fn record -> + case record.specification do + %{tmf_version: tmf_version, type: :serviceSpecification} -> + "serviceInventoryManagement/v#{tmf_version}/service/#{record.id}" + + %{tmf_version: tmf_version, type: :resourceSpecification} -> + "resourceInventoryManagement/v#{tmf_version}/resource/#{record.id}" + + _ -> + nil + end + end) + end +end diff --git a/lib/diffo/provider/components/calculations/specification_href.ex b/lib/diffo/provider/components/calculations/specification_href.ex new file mode 100644 index 0000000..8382a10 --- /dev/null +++ b/lib/diffo/provider/components/calculations/specification_href.ex @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defmodule Diffo.Provider.Calculations.SpecificationHref do + use Ash.Resource.Calculation + + @moduledoc """ + Diffo - TMF Service and Resource Management with a difference + + SpecificationHref - Ash Resource Calculation for generating specification href + + """ + + @impl true + def load(_query, _opts, _context), do: [:type, :tmf_version, :id] + + @impl true + def calculate(records, _opts, _context) do + Enum.map(records, fn + %{type: :serviceSpecification, tmf_version: tmf_version, id: id} -> + "serviceCatalogManagement/v#{tmf_version}/serviceSpecification/#{id}" + + %{type: :resourceSpecification, tmf_version: tmf_version, id: id} -> + "resourceCatalogManagement/v#{tmf_version}/resourceSpecification/#{id}" + + _ -> + nil + end) + end +end diff --git a/lib/diffo/provider/components/calculations/specification_instance_type.ex b/lib/diffo/provider/components/calculations/specification_instance_type.ex new file mode 100644 index 0000000..64cdff6 --- /dev/null +++ b/lib/diffo/provider/components/calculations/specification_instance_type.ex @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defmodule Diffo.Provider.Calculations.SpecificationInstanceType do + @moduledoc """ + Diffo - TMF Service and Resource Management with a difference + + SpecificationInstanceType - Ash Resource Calculation for generating the instance type a specification specifies + + """ + use Ash.Resource.Calculation + + @impl true + def load(_query, _opts, _context), do: [:type] + + @impl true + def calculate(records, _opts, _context) do + Enum.map(records, fn record -> + case record.type do + :serviceSpecification -> :service + :resourceSpecification -> :resource + _ -> nil + end + end) + end +end diff --git a/lib/diffo/provider/components/calculations/specification_version.ex b/lib/diffo/provider/components/calculations/specification_version.ex new file mode 100644 index 0000000..fad6aee --- /dev/null +++ b/lib/diffo/provider/components/calculations/specification_version.ex @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defmodule Diffo.Provider.Calculations.SpecificationVersion do + @moduledoc """ + Diffo - TMF Service and Resource Management with a difference + + SpecificationVersion - Ash Resource Calculation for generating the version of a specification + + """ + use Ash.Resource.Calculation + + @impl true + def load(_query, _opts, _context), do: [:major_version, :minor_version, :patch_version] + + @impl true + def calculate(records, _opts, _context) do + Enum.map(records, fn + %{major_version: maj, minor_version: min, patch_version: patch} -> + "v#{maj}.#{min}.#{patch}" + + _ -> + nil + end) + end +end diff --git a/lib/diffo/provider/components/characteristic.ex b/lib/diffo/provider/components/characteristic.ex index 9960aba..a9aba32 100644 --- a/lib/diffo/provider/components/characteristic.ex +++ b/lib/diffo/provider/components/characteristic.ex @@ -94,8 +94,9 @@ defmodule Diffo.Provider.Characteristic do public? true end - attribute :value, :term do + attribute :value, Diffo.Type.Value do description "the value of the characteristic" + constraints Diffo.Type.Value.subtype_constraints() allow_nil? true public? true end diff --git a/lib/diffo/provider/components/instance/extension/characteristic.ex b/lib/diffo/provider/components/instance/extension/characteristic.ex index effc494..b514c4f 100644 --- a/lib/diffo/provider/components/instance/extension/characteristic.ex +++ b/lib/diffo/provider/components/instance/extension/characteristic.ex @@ -14,6 +14,7 @@ defmodule Diffo.Provider.Instance.Characteristic do alias Diffo.Provider alias Diffo.Provider.Instance alias Diffo.Provider.Instance.Extension.Info + alias Diffo.Type.Value @doc """ Struct for a Characteristic @@ -47,7 +48,7 @@ defmodule Diffo.Provider.Instance.Characteristic do Enum.reduce_while(characteristics, [], fn %{name: name, value_type: value_type}, acc -> try do - value = struct(value_type) + value = Value.dynamic(value_type, struct(value_type)) case Provider.create_characteristic(%{name: name, type: type, value: value}) do {:ok, result} -> @@ -99,16 +100,22 @@ defmodule Diffo.Provider.Instance.Characteristic do if characteristic do cond do is_list(update) -> - value = - Enum.reduce(update, characteristic.value, fn {field, val}, acc -> - # merge update - Map.merge(acc, %{field => val}) + # unwrap the current value, merge the update fields, rewrap + unwrapped = Diffo.Unwrap.unwrap(characteristic.value) + value_type = unwrapped.__struct__ + + updated = + Enum.reduce(update, unwrapped, fn {field, val}, acc -> + Map.put(acc, field, val) end) - [{characteristic, value} | acc] + new_value = + Value.dynamic(value_type, struct(value_type, Map.from_struct(updated))) + + [{characteristic, new_value} | acc] true -> - # replace the value + # replace the value entirely [{characteristic, update} | acc] end else @@ -123,12 +130,16 @@ defmodule Diffo.Provider.Instance.Characteristic do {:ok, characteristic} -> {:cont, [characteristic | acc]} - {:error, _error} -> - {:halt, []} + {:error, error} -> + # preserve the error + {:halt, {:error, error}} end end) case characteristics do + {:error, error} -> + {:error, error} + [] -> {:error, "couldn't update characteristics"} diff --git a/lib/diffo/provider/components/instance/extension/feature.ex b/lib/diffo/provider/components/instance/extension/feature.ex index 779febc..3416c25 100644 --- a/lib/diffo/provider/components/instance/extension/feature.ex +++ b/lib/diffo/provider/components/instance/extension/feature.ex @@ -14,6 +14,7 @@ defmodule Diffo.Provider.Instance.Feature do alias Diffo.Provider alias Diffo.Provider.Instance alias Diffo.Provider.Instance.Extension.Info + alias Diffo.Type.Value @doc """ Struct for a Feature @@ -53,7 +54,7 @@ defmodule Diffo.Provider.Instance.Feature do characteristic_ids = Enum.reduce_while(characteristics, [], fn %{name: name, value_type: value_type}, acc -> try do - value = struct(value_type) + value = Value.dynamic(value_type, struct(value_type)) case Provider.create_characteristic(%{name: name, value: value, type: :feature}) do {:ok, result} -> diff --git a/lib/diffo/provider/components/process_status.ex b/lib/diffo/provider/components/process_status.ex index ff11aa2..007b3d0 100644 --- a/lib/diffo/provider/components/process_status.ex +++ b/lib/diffo/provider/components/process_status.ex @@ -103,7 +103,7 @@ defmodule Diffo.Provider.ProcessStatus do public? true end - attribute :parameterized_message, :term do + attribute :parameterized_message, :map do description "the parameterized message of this process status, this is an optional value" allow_nil? true public? true diff --git a/lib/diffo/provider/components/specification.ex b/lib/diffo/provider/components/specification.ex index e7837bb..5d29493 100644 --- a/lib/diffo/provider/components/specification.ex +++ b/lib/diffo/provider/components/specification.ex @@ -192,36 +192,9 @@ defmodule Diffo.Provider.Specification do end calculations do - calculate :version, - :string, - expr("v" <> major_version <> "." <> minor_version <> "." <> patch_version) do - description "the full version string, e.g. v1.0.0" - end - - calculate :href, - :string, - expr( - cond do - type == :serviceSpecification -> - "serviceCatalogManagement/v" <> tmf_version <> "/" <> type <> "/" <> id - - type == :resourceSpecification -> - "resourceCatalogManagement/v" <> tmf_version <> "/" <> type <> "/" <> id - end - ) do - description "the href for the service or resource specification" - end - - calculate :instance_type, - :atom, - expr( - cond do - type == :serviceSpecification -> :service - type == :resourceSpecification -> :resource - end - ) do - description "the type of the instance specified specification, either service or resource" - end + calculate :version, :string, Diffo.Provider.Calculations.SpecificationVersion + calculate :href, :string, Diffo.Provider.Calculations.SpecificationHref + calculate :instance_type, :atom, Diffo.Provider.Calculations.SpecificationInstanceType end preparations do diff --git a/lib/diffo/provider/reference.ex b/lib/diffo/provider/reference.ex index 0a3c730..cef59f9 100644 --- a/lib/diffo/provider/reference.ex +++ b/lib/diffo/provider/reference.ex @@ -15,9 +15,9 @@ defmodule Diffo.Provider.Reference do @doc """ Creates a reference struct from an instance with id and href ## Examples - iex> instance = %{id: "8bcfbf9a-34a5-427a-8eae-5c3812466432", href: "serviceInventoryManagement/v4/service/siteConnection/8bcfbf9a-34a5-427a-8eae-5c3812466432"} + iex> instance = %{id: "8bcfbf9a-34a5-427a-8eae-5c3812466432", href: "serviceInventoryManagement/v4/service/8bcfbf9a-34a5-427a-8eae-5c3812466432"} iex> Diffo.Provider.Reference.reference(instance) - %Diffo.Provider.Reference{id: "8bcfbf9a-34a5-427a-8eae-5c3812466432", href: "serviceInventoryManagement/v4/service/siteConnection/8bcfbf9a-34a5-427a-8eae-5c3812466432"} + %Diffo.Provider.Reference{id: "8bcfbf9a-34a5-427a-8eae-5c3812466432", href: "serviceInventoryManagement/v4/service/8bcfbf9a-34a5-427a-8eae-5c3812466432"} """ def reference(instance) when is_map(instance) do %Diffo.Provider.Reference{id: instance.id, href: instance.href} @@ -28,9 +28,9 @@ defmodule Diffo.Provider.Reference do @doc """ Creates a reference struct from an instance attribute containing a href ## Examples - iex> instance = %{target_href: "serviceInventoryManagement/v4/service/siteConnection/8bcfbf9a-34a5-427a-8eae-5c3812466432"} + iex> instance = %{target_href: "serviceInventoryManagement/v4/service/8bcfbf9a-34a5-427a-8eae-5c3812466432"} iex> Diffo.Provider.Reference.reference(instance, :target_href) - %Diffo.Provider.Reference{id: "8bcfbf9a-34a5-427a-8eae-5c3812466432", href: "serviceInventoryManagement/v4/service/siteConnection/8bcfbf9a-34a5-427a-8eae-5c3812466432"} + %Diffo.Provider.Reference{id: "8bcfbf9a-34a5-427a-8eae-5c3812466432", href: "serviceInventoryManagement/v4/service/8bcfbf9a-34a5-427a-8eae-5c3812466432"} """ def reference(instance, attribute) when is_map(instance) and is_atom(attribute) do href = Map.get(instance, attribute) diff --git a/lib/diffo/type/dynamic.ex b/lib/diffo/type/dynamic.ex new file mode 100644 index 0000000..80ba70e --- /dev/null +++ b/lib/diffo/type/dynamic.ex @@ -0,0 +1,126 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT +defmodule Diffo.Type.Dynamic do + @moduledoc """ + Diffo - TMF Service and Resource Management with a difference + + Dynamic - an Ash.Type subtype_of :struct with dynamic Ash.Type.NewType typing + """ + + defstruct [:type, :value] + + @type_field_constraints [ + type: :module, + allow_nil?: false, + constraints: [behaviour: Ash.Type.NewType] + ] + + @constraints [ + fields: [ + type: @type_field_constraints, + value: [ + type: :struct + ] + ] + ] + + use Ash.Type.NewType, + subtype_of: :struct, + constraints: @constraints + + @doc """ + Returns the dynamic constraints from dynamic struct or map + """ + + def dynamic_constraints(nil), do: [] + + def dynamic_constraints(%{type: type}) when is_atom(type), do: dynamic_constraints(type) + + def dynamic_constraints(%{"type" => type}) when is_binary(type), do: dynamic_constraints(type) + + def dynamic_constraints(type) when is_binary(type), + do: dynamic_constraints(String.to_existing_atom(type)) + + def dynamic_constraints(type) when is_atom(type) do + cond do + Ash.Type.NewType.new_type?(type) -> + [ + fields: [ + type: @type_field_constraints, + value: [type: type, constraints: type.subtype_constraints()] + ], + instance_of: __MODULE__ + ] + + true -> + [] + end + end + + def dynamic_constraints(_), do: [] + + @impl true + def apply_constraints(%__MODULE__{} = value, _constraints), do: {:ok, value} + def apply_constraints(nil, _constraints), do: {:ok, nil} + def apply_constraints(value, _constraints), do: {:error, "is invalid: #{inspect(value)}"} + + @impl true + def cast_input(nil, _constraints), do: {:ok, nil} + + def cast_input(%__MODULE__{type: type, value: value}, _constraints) do + constraints = dynamic_constraints(type) + result = Ash.Type.cast_input(type, value, constraints[:fields][:value][:constraints] || []) + + case result do + {:ok, cast_value} -> + {:ok, %__MODULE__{type: type, value: cast_value}} + + error -> + error + end + end + + def cast_input(%{value: %__MODULE__{} = dynamic}, _constraints) do + cast_input(dynamic, []) + end + + def cast_input(%{"value" => %__MODULE__{} = dynamic}, _constraints) do + cast_input(dynamic, []) + end + + def cast_input(_value, _constraints) do + :error + end + + @impl true + def cast_stored(%{"type" => type_string, "value" => value}, _constraints) do + type = String.to_existing_atom(type_string) + constraints = dynamic_constraints(type_string) + + case Ash.Type.cast_stored(type, value, constraints[:fields][:value][:constraints] || []) do + {:ok, cast_value} -> {:ok, %__MODULE__{type: type, value: cast_value}} + error -> error + end + end + + @impl true + def dump_to_native(%__MODULE__{type: type, value: value}, _constraints) do + constraints = dynamic_constraints(type) + + case Ash.Type.dump_to_native(type, value, constraints[:fields][:value][:constraints] || []) do + {:ok, dumped} -> {:ok, %{"type" => to_string(type), "value" => dumped}} + error -> error + end + end + + defimpl Diffo.Unwrap do + def unwrap(%{value: value}), do: Diffo.Unwrap.unwrap(value) + end + + defimpl Jason.Encoder do + def encode(value, opts) do + value |> Diffo.Unwrap.unwrap() |> Jason.Encode.value(opts) + end + end +end diff --git a/lib/diffo/type/outstanding/dynamic.ex b/lib/diffo/type/outstanding/dynamic.ex new file mode 100644 index 0000000..fdf3647 --- /dev/null +++ b/lib/diffo/type/outstanding/dynamic.ex @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +use Outstand + +defoutstanding expected :: Diffo.Type.Dynamic, actual :: Any do + type_outstanding = + case actual do + %{type: type} -> Outstanding.outstanding(expected.type, type) + _ -> expected.type + end + + value_outstanding = + case actual do + %{} -> + Outstanding.outstanding( + Diffo.Unwrap.unwrap(expected), + Diffo.Unwrap.unwrap(actual) + ) + + _ -> + Diffo.Unwrap.unwrap(expected) + end + + case {type_outstanding, value_outstanding} do + {nil, nil} -> nil + {nil, _} -> %Diffo.Type.Dynamic{type: nil, value: value_outstanding} + {_, nil} -> %Diffo.Type.Dynamic{type: type_outstanding, value: nil} + {_, _} -> %Diffo.Type.Dynamic{type: type_outstanding, value: value_outstanding} + end +end diff --git a/lib/diffo/type/outstanding/primitive.ex b/lib/diffo/type/outstanding/primitive.ex new file mode 100644 index 0000000..30ae8ee --- /dev/null +++ b/lib/diffo/type/outstanding/primitive.ex @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +use Outstand + +defoutstanding expected :: Diffo.Type.Primitive, actual :: Any do + # we return a map since Primitive doesn't allow type nil + type_outstanding = + case actual do + %{type: type} -> Outstanding.outstanding(expected.type, type) + nil -> expected.type + # actual is wrong type entirely + _ -> expected.type + end + + value_outstanding = + case actual do + %{} -> + Outstanding.outstanding( + Diffo.Unwrap.unwrap(expected), + Diffo.Unwrap.unwrap(actual) + ) + + _ -> + Diffo.Unwrap.unwrap(expected) + end + + case {type_outstanding, value_outstanding} do + {nil, nil} -> nil + {nil, _} -> %{value: value_outstanding} + {_, nil} -> %{type: type_outstanding} + {_, _} -> %{type: type_outstanding, value: value_outstanding} + end +end diff --git a/lib/diffo/type/primitive.ex b/lib/diffo/type/primitive.ex new file mode 100644 index 0000000..3e6f952 --- /dev/null +++ b/lib/diffo/type/primitive.ex @@ -0,0 +1,66 @@ +defmodule Diffo.Type.Primitive do + @moduledoc """ + Diffo - TMF Service and Resource Management with a difference + + Primitive - an Ash.TypedStruct representing a single TMF primitive value. + The :type field identifies which primitive field is populated. + """ + use Ash.TypedStruct + + typed_struct do + field :type, :string, description: "the primitive type discriminator" + field :string, :string, description: "string value" + field :integer, :integer, description: "integer value" + field :float, :float, description: "float value" + field :boolean, :boolean, description: "boolean value" + field :date, :date, description: "date value" + field :time, :time, description: "time value" + field :datetime, :datetime, description: "datetime value" + field :duration, :duration, description: "duration value" + end + + # workarounds for temporal types until AshNeo4j ash_json handles nested ash_json types better + def wrap("date", %Date{} = value), + do: %__MODULE__{type: "string", string: Date.to_iso8601(value)} + + def wrap("time", %Time{} = value), + do: %__MODULE__{type: "string", string: Time.to_iso8601(value)} + + def wrap("datetime", %DateTime{} = value), + do: %__MODULE__{type: "string", string: DateTime.to_iso8601(value)} + + def wrap("duration", %Duration{} = value), + do: %__MODULE__{type: "string", string: Duration.to_iso8601(value)} + + def wrap(type = "string", value), do: %__MODULE__{type: type, string: value} + def wrap(type = "integer", value), do: %__MODULE__{type: type, integer: value} + def wrap(type = "float", value), do: %__MODULE__{type: type, float: value} + def wrap(type = "boolean", value), do: %__MODULE__{type: type, boolean: value} + def wrap(type = "date", value), do: %__MODULE__{type: type, date: value} + def wrap(type = "time", value), do: %__MODULE__{type: type, time: value} + def wrap(type = "datetime", value), do: %__MODULE__{type: type, datetime: value} + def wrap(type = "duration", value), do: %__MODULE__{type: type, duration: value} + def wrap(_, _), do: nil + + defimpl Diffo.Unwrap do + def unwrap(%{type: "string", string: value}), do: value + def unwrap(%{type: "integer", integer: value}), do: value + def unwrap(%{type: "float", float: value}), do: value + def unwrap(%{type: "boolean", boolean: value}), do: value + def unwrap(%{type: "date", date: value}), do: value + def unwrap(%{type: "time", time: value}), do: value + def unwrap(%{type: "datetime", datetime: value}), do: value + def unwrap(%{type: "duration", duration: value}), do: value + def unwrap(_), do: nil + end + + defimpl String.Chars do + def to_string(primitive), do: inspect(primitive) + end + + defimpl Jason.Encoder do + def encode(value, _opts) do + value |> Diffo.Unwrap.unwrap() |> Jason.encode!() + end + end +end diff --git a/lib/diffo/type/value.ex b/lib/diffo/type/value.ex new file mode 100644 index 0000000..7dfb6c2 --- /dev/null +++ b/lib/diffo/type/value.ex @@ -0,0 +1,78 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT +defmodule Diffo.Type.Value do + @moduledoc """ + Diffo - TMF Service and Resource Management with a difference + + Value - an Ash.Type.NewType subtype_of :union representing a primitive or Dynamic value + """ + + use Ash.Type.NewType, + subtype_of: :union, + constraints: [ + types: [ + string: [ + type: Diffo.Type.Primitive, + tag: :type, + tag_value: "string", + constraints: Diffo.Type.Primitive.subtype_constraints() + ], + integer: [ + type: Diffo.Type.Primitive, + tag: :type, + tag_value: "integer", + constraints: Diffo.Type.Primitive.subtype_constraints() + ], + float: [ + type: Diffo.Type.Primitive, + tag: :type, + tag_value: "float", + constraints: Diffo.Type.Primitive.subtype_constraints() + ], + boolean: [ + type: Diffo.Type.Primitive, + tag: :type, + tag_value: "boolean", + constraints: Diffo.Type.Primitive.subtype_constraints() + ], + date: [ + type: Diffo.Type.Primitive, + tag: :type, + tag_value: "date", + constraints: Diffo.Type.Primitive.subtype_constraints() + ], + time: [ + type: Diffo.Type.Primitive, + tag: :type, + tag_value: "time", + constraints: Diffo.Type.Primitive.subtype_constraints() + ], + datetime: [ + type: Diffo.Type.Primitive, + tag: :type, + tag_value: "datetime", + constraints: Diffo.Type.Primitive.subtype_constraints() + ], + duration: [ + type: Diffo.Type.Primitive, + tag: :type, + tag_value: "duration", + constraints: Diffo.Type.Primitive.subtype_constraints() + ], + dynamic: [type: Diffo.Type.Dynamic, tag: :type, tag_value: "dynamic", cast_tag?: false] + ], + storage: :type_and_value + ] + + def primitive(type, value), do: Diffo.Type.Primitive.wrap(type, value) + + def dynamic(type, value), + do: %{type: "dynamic", value: %Diffo.Type.Dynamic{type: type, value: value}} + + def wrap(type, value), do: %Ash.Union{type: type, value: value} + + defimpl Diffo.Unwrap do + def unwrap(%{value: value}), do: Diffo.Unwrap.unwrap(value) + end +end diff --git a/lib/diffo/unwrap.ex b/lib/diffo/unwrap.ex new file mode 100644 index 0000000..9a4b431 --- /dev/null +++ b/lib/diffo/unwrap.ex @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defprotocol Diffo.Unwrap do + @moduledoc """ + Diffo - TMF Service and Resource Management with a difference + + Unwrap - A Diffo protocol for unwrapping values + """ + + @fallback_to_any true + def unwrap(value) +end diff --git a/lib/diffo/unwrap/any.ex b/lib/diffo/unwrap/any.ex new file mode 100644 index 0000000..3f37943 --- /dev/null +++ b/lib/diffo/unwrap/any.ex @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defimpl Diffo.Unwrap, for: Any do + def unwrap(value), do: value +end diff --git a/lib/diffo/unwrap/ash_ci_string.ex b/lib/diffo/unwrap/ash_ci_string.ex new file mode 100644 index 0000000..116bec4 --- /dev/null +++ b/lib/diffo/unwrap/ash_ci_string.ex @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defimpl Diffo.Unwrap, for: Ash.CiString do + def unwrap(ci_string), do: Ash.CiString.to_comparable_string(ci_string) +end diff --git a/lib/diffo/unwrap/ash_custom_expression.ex b/lib/diffo/unwrap/ash_custom_expression.ex new file mode 100644 index 0000000..b1361d4 --- /dev/null +++ b/lib/diffo/unwrap/ash_custom_expression.ex @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defmodule Diffo.Unwrap.AshCustomExpression do + use Ash.CustomExpression, + name: :unwrap, + arguments: [ + [:term] + ] + + def expression(_data_layer, term) do + {:ok, expr(fragment(&__MODULE__.unwrap/1, ^term))} + end + + @doc "Unwraps a term using the Diffo.Unwrap protocol" + def unwrap(term) do + Diffo.Unwrap.unwrap(term) + end +end diff --git a/lib/diffo/unwrap/ash_not_loaded.ex b/lib/diffo/unwrap/ash_not_loaded.ex new file mode 100644 index 0000000..4465b42 --- /dev/null +++ b/lib/diffo/unwrap/ash_not_loaded.ex @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defimpl Diffo.Unwrap, for: Ash.NotLoaded do + def unwrap(%{field: field}) do + raise "Diffo.Unwrap: #{field} was not loaded" + end +end diff --git a/lib/diffo/unwrap/ash_union.ex b/lib/diffo/unwrap/ash_union.ex new file mode 100644 index 0000000..69e5933 --- /dev/null +++ b/lib/diffo/unwrap/ash_union.ex @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defimpl Diffo.Unwrap, for: Ash.Union do + def unwrap(%{value: value}), do: Diffo.Unwrap.unwrap(value) +end diff --git a/lib/mix/tasks/diagram.ex b/lib/mix/tasks/diagram.ex deleted file mode 100644 index 050e1a7..0000000 --- a/lib/mix/tasks/diagram.ex +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-FileCopyrightText: 2025 diffo contributors -# -# SPDX-License-Identifier: MIT - -defmodule Mix.Tasks.Diagram do - @moduledoc "The diagram mix task: `mix help diagram`" - use Mix.Task - - @shortdoc "Regenerates various diagrams" - def run(_) do - Mix.Tasks.AshStateMachine.GenerateFlowCharts.run(type: :flow_chart) - end -end diff --git a/mix.exs b/mix.exs index 9a614b8..4cb69c9 100644 --- a/mix.exs +++ b/mix.exs @@ -28,7 +28,8 @@ defmodule Diffo.MixProject do # hex.pm stuff deps: deps(), docs: &docs/0, - aliases: aliases() + aliases: aliases(), + consolidate_protocols: Mix.env() != :dev ] end @@ -94,7 +95,8 @@ defmodule Diffo.MixProject do {:ash_outstanding, "~> 0.2.3"}, {:ash_jason, "~> 3.0"}, {:ash_state_machine, "~> 0.2.12"}, - {:ash_neo4j, ash_neo4j_version("~> 0.2.15")}, + # {:ash_neo4j, ash_neo4j_version("~> 0.2.15")}, + {:ash_neo4j, github: "diffo-dev/ash_neo4j", branch: "dev"}, {:ash, ash_version("~> 3.0 and >= 3.19.1")}, {:uuid, "~> 1.1"}, {:igniter, ">= 0.6.29 and < 1.0.0-0", diff --git a/mix.lock b/mix.lock index 842db11..15167ac 100644 --- a/mix.lock +++ b/mix.lock @@ -1,10 +1,10 @@ %{ - "ash": {:hex, :ash, "3.19.3", "58b1bb3aea3d1d45d1c990059ffd0753409cc92fc4afe387376cb155e2a8c2a0", [:mix], [{:crux, ">= 0.1.2 and < 1.0.0-0", [hex: :crux, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:igniter, ">= 0.6.29 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 1.0", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.3.14 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.3", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "94b628319f2e144affaf1f8008277bad3340a198d48e6d2ed372990ac1643f9b"}, + "ash": {:hex, :ash, "3.24.2", "38beca133e0dcab07e3c8a7c26e573287ada26e8ba8d4c90ac692b52b34b0309", [:mix], [{:crux, ">= 0.1.2 and < 1.0.0-0", [hex: :crux, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:igniter, ">= 0.6.29 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 1.0", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.6.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.3", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3fd2a99504c1f58290efc3382501369ee9070098784925bdd7df9dbea8611d32"}, "ash_jason": {:hex, :ash_jason, "3.1.0", "84a88dfe5e25a20d55cf2d2664885cd086fa45871e8777aedc3ad96a282e2a6f", [:mix], [{:ash, ">= 3.6.2 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:spark, ">= 2.1.21 and < 3.0.0", [hex: :spark, repo: "hexpm", optional: false]}], "hexpm", "71e6bbc421fb2cf7079f8804814145cca458116c839fc798f9606b806e07eb2b"}, - "ash_neo4j": {:hex, :ash_neo4j, "0.2.15", "1380f3a3f6b43fb346308808d621bd19b891b859431fd4b1ac26472fcee5b372", [:mix], [{:ash, ">= 3.19.1 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:bolty, ">= 0.0.7", [hex: :bolty, repo: "hexpm", optional: false]}, {:igniter, ">= 0.6.29 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8be0a84e02ce70d691b3619c1f7cb7c8e1d9daf001673a227b27762f3690ac40"}, + "ash_neo4j": {:git, "https://github.com/diffo-dev/ash_neo4j.git", "044d9d123af30719a9f1f377e2c24b5cc8e21ea8", [branch: "dev"]}, "ash_outstanding": {:hex, :ash_outstanding, "0.2.4", "c72b91f1b8e4859fb033eddf66d0ba36cfd8af0c2a9748c7ef9e6ccfdb5d093d", [:mix], [{:ash, ">= 3.6.2 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:outstanding, "~> 0.2.4", [hex: :outstanding, repo: "hexpm", optional: false]}], "hexpm", "64ba8f582ce69c9050352c75f0895db186c7a56f35039dab34c8e1ab7516f9ce"}, - "ash_state_machine": {:hex, :ash_state_machine, "0.2.12", "c0f7ebb8a176584f70c6ed196b7d0118c930d73e0590ade705d2dddc48aa7311", [:mix], [{:ash, ">= 3.4.66 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}], "hexpm", "394ce761ce82358e3c715e1cae6c5cf1390be27c03a8b661f2e5a2fda849873d"}, - "bolty": {:hex, :bolty, "0.0.7", "257889f71bd16a9291bda8290c1018123c4084c8761f905b97d7176e65d8b111", [:mix], [{:db_connection, "~> 2.7.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: true]}, {:poison, "~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm", "fc8f88b86d292ad1336f9e246a6c0452e64774b38fac0351c141549420946e5e"}, + "ash_state_machine": {:hex, :ash_state_machine, "0.2.13", "e1c368ebf01ef73477739ee76d53e513d073b141ec11e7bf7f91d8f2d8fc9569", [:mix], [{:ash, ">= 3.4.66 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}], "hexpm", "aa21c92a8950850df69b5205bf41efc1e502f5ab839425ba08561f0421c9f226"}, + "bolty": {:hex, :bolty, "0.0.9", "c8026ce9804347f71e23b3a0cbc01b918ef94b61e159b5ba7fb48527878033ad", [:mix], [{:db_connection, "~> 2.7.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: true]}, {:poison, "~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm", "fc20c42550c0fce370276b4ef119e92792761b2fea1aef9cccf8de946bc39d35"}, "crux": {:hex, :crux, "0.1.2", "4441c9e3a34f1e340954ce96b9ad5a2de13ceb4f97b3f910211227bb92e2ca90", [:mix], [{:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: true]}], "hexpm", "563ea3748ebfba9cc078e6d198a1d6a06015a8fae503f0b721363139f0ddb350"}, "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, @@ -15,7 +15,7 @@ "finch": {:hex, :finch, "0.21.0", "b1c3b2d48af02d0c66d2a9ebfb5622be5c5ecd62937cf79a88a7f98d48a8290c", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "87dc6e169794cb2570f75841a19da99cfde834249568f2a5b121b809588a4377"}, "glob_ex": {:hex, :glob_ex, "0.1.11", "cb50d3f1ef53f6ca04d6252c7fde09fd7a1cf63387714fe96f340a1349e62c93", [:mix], [], "hexpm", "342729363056e3145e61766b416769984c329e4378f1d558b63e341020525de4"}, "hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"}, - "igniter": {:hex, :igniter, "0.7.6", "687d622c735e020f13cf480c83d0fce1cc899f4fbed547f5254b960ea82d3525", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "424f41a41273fce0f7424008405ee073b5bd06359ca9396e841f83a669c01619"}, + "igniter": {:hex, :igniter, "0.7.9", "8c573440b8127fd80be8220fb197e7422317a81072054fcc0b336029f035a416", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "123513d09f3af149db851aad8492b5b49f861d2c466a72031b2a0cbd9f45526f"}, "iterex": {:hex, :iterex, "0.1.2", "58f9b9b9a22a55cbfc7b5234a9c9c63eaac26d276b3db80936c0e1c60355a5a6", [:mix], [], "hexpm", "2e103b8bcc81757a9af121f6dc0df312c9a17220f302b1193ef720460d03029d"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "libgraph": {:hex, :libgraph, "0.16.0", "3936f3eca6ef826e08880230f806bfea13193e49bf153f93edcf0239d4fd1d07", [:mix], [], "hexpm", "41ca92240e8a4138c30a7e06466acc709b0cbb795c643e9e17174a178982d6bf"}, @@ -29,13 +29,13 @@ "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, "outstanding": {:hex, :outstanding, "0.2.5", "2f40416eb9617748cb1f8ae4c8ed94515d731f9c4fcee4f902355d30bc0792cc", [:mix], [], "hexpm", "bb47a210f0d2804ea6b8477fa6f4d15e8c58c18acee79d8e06c9296e6dd004cd"}, "owl": {:hex, :owl, "0.13.0", "26010e066d5992774268f3163506972ddac0a7e77bfe57fa42a250f24d6b876e", [:mix], [{:ucwidth, "~> 0.2", [hex: :ucwidth, repo: "hexpm", optional: true]}], "hexpm", "59bf9d11ce37a4db98f57cb68fbfd61593bf419ec4ed302852b6683d3d2f7475"}, - "reactor": {:hex, :reactor, "1.0.0", "024bd13df910bcb8c01cebed4f10bd778269a141a1c8a234e4f67796ac4883cf", [:mix], [{:igniter, "~> 0.4", [hex: :igniter, repo: "hexpm", optional: true]}, {:iterex, "~> 0.1", [hex: :iterex, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, ">= 2.3.3 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.11", [hex: :yaml_elixir, repo: "hexpm", optional: false]}, {:ymlr, "~> 5.0", [hex: :ymlr, repo: "hexpm", optional: false]}], "hexpm", "ae8eb507fffc517f5aa5947db9d2ede2db8bae63b66c94ccb5a2027d30f830a0"}, + "reactor": {:hex, :reactor, "1.0.1", "ca3b5cf3c04ec8441e67ea2625d0294939822060b1bfd00ffdaaf75b7682d991", [:mix], [{:igniter, "~> 0.4", [hex: :igniter, repo: "hexpm", optional: true]}, {:iterex, "~> 0.1", [hex: :iterex, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, ">= 2.3.3 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.11", [hex: :yaml_elixir, repo: "hexpm", optional: false]}, {:ymlr, "~> 5.0", [hex: :ymlr, repo: "hexpm", optional: false]}], "hexpm", "3497db2b204c9a3cabdaf1b26d2405df1dfbb138ce0ce50e616e9db19fec0043"}, "req": {:hex, :req, "0.5.17", "0096ddd5b0ed6f576a03dde4b158a0c727215b15d2795e59e0916c6971066ede", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0b8bc6ffdfebbc07968e59d3ff96d52f2202d0536f10fef4dc11dc02a2a43e39"}, "rewrite": {:hex, :rewrite, "1.3.0", "67448ba7975690b35ba7e7f35717efcce317dbd5963cb0577aa7325c1923121a", [:mix], [{:glob_ex, "~> 0.1", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}, {:text_diff, "~> 0.1", [hex: :text_diff, repo: "hexpm", optional: false]}], "hexpm", "d111ac7ff3a58a802ef4f193bbd1831e00a9c57b33276e5068e8390a212714a5"}, "sourceror": {:hex, :sourceror, "1.12.0", "da354c5f35aad3cc1132f5d5b0d8437d865e2661c263260480bab51b5eedb437", [:mix], [], "hexpm", "755703683bd014ebcd5de9acc24b68fb874a660a568d1d63f8f98cd8a6ef9cd0"}, - "spark": {:hex, :spark, "2.4.1", "d6807291e74b51f6efb6dd4e0d58216ae3729d45c35c456e049556e7e946e364", [:mix], [{:igniter, ">= 0.3.64 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: true]}, {:sourceror, "~> 1.2", [hex: :sourceror, repo: "hexpm", optional: true]}], "hexpm", "8b065733de9840cac584515f82182ac5ba66a973a47bc5036348dc740662b46b"}, + "spark": {:hex, :spark, "2.6.1", "b0100216d3883c6a281cb2434af45afbd808695aadb034923cbaf7d8a2ba46ab", [:mix], [{:igniter, ">= 0.3.64 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: true]}, {:sourceror, "~> 1.2", [hex: :sourceror, repo: "hexpm", optional: true]}], "hexpm", "77bbefa5263bb6b70e1195bc0fc662ddb8ef5937a356a77ae072e56983ad13f0"}, "spitfire": {:hex, :spitfire, "0.3.10", "19aea9914132456515e8f7d592f63ab9f3130876b0252e834d2390bdd8becb24", [:mix], [], "hexpm", "6a6a5f77eb4165249c76199cd2d01fb595bac9207aed3de551918ac1c2bc9267"}, - "splode": {:hex, :splode, "0.3.0", "ff8effecc509a51245df2f864ec78d849248647c37a75886033e3b1a53ca9470", [:mix], [], "hexpm", "73cfd0892d7316d6f2c93e6e8784bd6e137b2aa38443de52fd0a25171d106d81"}, + "splode": {:hex, :splode, "0.3.1", "9843c54f84f71b7833fec3f0be06c3cfb5be6b35960ee195ea4fad84b1c25030", [:mix], [], "hexpm", "8f2309b6ec2ecbb01435656429ed1d9ed04ba28797a3280c3b0d1217018ecfbd"}, "stream_data": {:hex, :stream_data, "1.3.0", "bde37905530aff386dea1ddd86ecbf00e6642dc074ceffc10b7d4e41dfd6aac9", [:mix], [], "hexpm", "3cc552e286e817dca43c98044c706eec9318083a1480c52ae2688b08e2936e3c"}, "telemetry": {:hex, :telemetry, "1.4.1", "ab6de178e2b29b58e8256b92b382ea3f590a47152ca3651ea857a6cae05ac423", [:rebar3], [], "hexpm", "2172e05a27531d3d31dd9782841065c50dd5c3c7699d95266b2edd54c2dafa1c"}, "text_diff": {:hex, :text_diff, "0.1.0", "1caf3175e11a53a9a139bc9339bd607c47b9e376b073d4571c031913317fecaa", [:mix], [], "hexpm", "d1ffaaecab338e49357b6daa82e435f877e0649041ace7755583a0ea3362dbd7"}, diff --git a/test/instance_extension/assigner_test.exs b/test/instance_extension/assigner_test.exs index 867fb19..65d5097 100644 --- a/test/instance_extension/assigner_test.exs +++ b/test/instance_extension/assigner_test.exs @@ -24,6 +24,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do end describe "build card" do + @tag :card test "create a card" do {:ok, card} = Servo.build_card(%{}) @@ -63,7 +64,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do encoding = Jason.encode!(card) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/card/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":1,\"free\":1,\"algorithm\":\"lowest\"}}]}) + ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":1,\"free\":1,\"algorithm\":\"lowest\"}}]}) end test "define card" do @@ -71,7 +72,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do updates = [ card: [family: :ISAM, model: "EBLT48", technology: :adsl2Plus], - ports: [first: 1, last: 48, free: 48, type: "ADSL2+"] + ports: [first: 1, last: 48, free: 48, assignable_type: "ADSL2+"] ] {:ok, card} = Servo.define_card(card, %{characteristic_value_updates: updates}) @@ -79,7 +80,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do encoding = Jason.encode!(card) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/card/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":48,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]}) + ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":48,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]}) end test "auto assign port to resource" do @@ -89,7 +90,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do updates = [ card: [family: :ISAM, model: "EBLT48", technology: :adsl2Plus], - ports: [first: 1, last: 48, free: 48, type: "ADSL2+"] + ports: [first: 1, last: 48, free: 48, assignable_type: "ADSL2+"] ] {:ok, card} = Servo.define_card(card, %{characteristic_value_updates: updates}) @@ -104,7 +105,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do encoding = Jason.encode!(card) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/card/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceRelationship\":[{\"type\":\"assignedTo\",\"resource\":{\"id\":\"#{assignee.id}\",\"href\":\"resourceInventoryManagement/v4/resource/shelf/#{assignee.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"port\",\"value\":1}]}],\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":47,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]}) + ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceRelationship\":[{\"type\":\"assignedTo\",\"resource\":{\"id\":\"#{assignee.id}\",\"href\":\"resourceInventoryManagement/v4/resource/#{assignee.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"port\",\"value\":1}]}],\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":47,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]}) end test "auto assign two ports to same resource" do @@ -114,7 +115,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do updates = [ card: [family: :ISAM, model: "EBLT48", technology: :adsl2Plus], - ports: [first: 1, last: 48, free: 48, type: "ADSL2+"] + ports: [first: 1, last: 48, free: 48, assignable_type: "ADSL2+"] ] {:ok, card} = Servo.define_card(card, %{characteristic_value_updates: updates}) @@ -134,7 +135,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do encoding = Jason.encode!(card) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/card/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceRelationship\":[{\"type\":\"assignedTo\",\"resource\":{\"id\":\"#{assignee.id}\",\"href\":\"resourceInventoryManagement/v4/resource/shelf/#{assignee.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"port\",\"value\":1}]},{\"type\":\"assignedTo\",\"resource\":{\"id\":\"#{assignee.id}\",\"href\":\"resourceInventoryManagement/v4/resource/shelf/#{assignee.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"port\",\"value\":2}]}],\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":46,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]}) + ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceRelationship\":[{\"type\":\"assignedTo\",\"resource\":{\"id\":\"#{assignee.id}\",\"href\":\"resourceInventoryManagement/v4/resource/#{assignee.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"port\",\"value\":1}]},{\"type\":\"assignedTo\",\"resource\":{\"id\":\"#{assignee.id}\",\"href\":\"resourceInventoryManagement/v4/resource/#{assignee.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"port\",\"value\":2}]}],\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":46,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]}) end test "specific assignment rejects duplicate request" do @@ -144,7 +145,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do updates = [ card: [family: :ISAM, model: "EBLT48", technology: :adsl2Plus], - ports: [first: 1, last: 48, free: 48, type: "ADSL2+"] + ports: [first: 1, last: 48, free: 48, assignable_type: "ADSL2+"] ] {:ok, card} = Servo.define_card(card, %{characteristic_value_updates: updates}) @@ -164,7 +165,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do encoding = Jason.encode!(card) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/card/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceRelationship\":[{\"type\":\"assignedTo\",\"resource\":{\"id\":\"#{assignee.id}\",\"href\":\"resourceInventoryManagement/v4/resource/shelf/#{assignee.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"port\",\"value\":5}]}],\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":47,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]}) + ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceRelationship\":[{\"type\":\"assignedTo\",\"resource\":{\"id\":\"#{assignee.id}\",\"href\":\"resourceInventoryManagement/v4/resource/#{assignee.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"port\",\"value\":5}]}],\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":47,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]}) end test "unassign an auto-assigned port from a resource" do @@ -174,7 +175,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do updates = [ card: [family: :ISAM, model: "EBLT48", technology: :adsl2Plus], - ports: [first: 1, last: 48, free: 48, type: "ADSL2+"] + ports: [first: 1, last: 48, free: 48, assignable_type: "ADSL2+"] ] {:ok, card} = Servo.define_card(card, %{characteristic_value_updates: updates}) @@ -191,6 +192,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do |> Map.get(:characteristics) |> Enum.find(fn char -> char.name == :port end) |> Map.get(:value) + |> Diffo.Unwrap.unwrap() {:ok, card} = Servo.assign_port(card, %{ @@ -206,7 +208,7 @@ defmodule Diffo.InstanceExtension.AssignerTest do encoding = Jason.encode!(card) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/card/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":48,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]}) + ~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":48,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]}) end end end diff --git a/test/provider/characteristic_test.exs b/test/provider/characteristic_test.exs index a767cee..3b40d02 100644 --- a/test/provider/characteristic_test.exs +++ b/test/provider/characteristic_test.exs @@ -5,6 +5,8 @@ defmodule Diffo.Provider.CharacteristicTest do @moduledoc false use ExUnit.Case + alias Diffo.Test.Patch + alias Diffo.Type.Value setup_all do AshNeo4j.BoltyHelper.start() @@ -20,25 +22,25 @@ defmodule Diffo.Provider.CharacteristicTest do test "list characteristics - success" do Diffo.Provider.create_characteristic!(%{ name: :port, - value: "_not_null", + value: Value.primitive("string", "_not_null"), type: :instance }) Diffo.Provider.create_characteristic!(%{ name: :circuit, - value: "_not_null", + value: Value.primitive("string", "_not_null"), type: :instance }) Diffo.Provider.create_characteristic!(%{ name: :type, - value: :fraudHeavy, + value: Value.primitive("string", "fraudHeavy"), type: :feature }) Diffo.Provider.create_characteristic!(%{ name: :expiry, - value: "20250131", + value: Value.primitive("date", ~D[2026-04-16]), type: :feature }) @@ -70,7 +72,7 @@ defmodule Diffo.Provider.CharacteristicTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :port, - value: "port13", + value: Value.primitive("string", "port13"), type: :relationship }) @@ -82,7 +84,7 @@ defmodule Diffo.Provider.CharacteristicTest do }) assert characteristic.name == :port - assert characteristic.value == "port13" + assert Diffo.Unwrap.unwrap(characteristic.value) == "port13" end test "create forward and reverse characteristic with same name on same relationship - success" do @@ -97,14 +99,14 @@ defmodule Diffo.Provider.CharacteristicTest do forward_characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: "worker", + value: Value.primitive("string", "worker"), type: :relationship }) reverse_characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: "protect", + value: Value.primitive("string", "protect"), type: :relationship }) @@ -127,6 +129,7 @@ defmodule Diffo.Provider.CharacteristicTest do end describe "Diffo.Provider update Characteristics" do + @tag :debug test "update characteristic value - success" do parent_specification = Diffo.Provider.create_specification!(%{name: "can", type: :resourceSpecification}) @@ -143,7 +146,7 @@ defmodule Diffo.Provider.CharacteristicTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :pair, - value: "pair13", + value: Value.primitive("string", "pair13"), type: :relationship }) @@ -155,38 +158,51 @@ defmodule Diffo.Provider.CharacteristicTest do characteristics: [characteristic.id] }) + # boolean updated_characteristic = - characteristic |> Diffo.Provider.update_characteristic!(%{value: true}) + characteristic + |> Diffo.Provider.update_characteristic!(%{ + value: Value.primitive("boolean", false) + }) - assert updated_characteristic.name == :pair - assert updated_characteristic.value == true + # we expect the value false here + assert Diffo.Unwrap.unwrap(updated_characteristic.value) == false + # string updated_characteristic = - characteristic |> Diffo.Provider.update_characteristic!(%{value: "_not_null"}) + characteristic + |> Diffo.Provider.update_characteristic!(%{value: Value.primitive("string", "_not_null")}) - assert updated_characteristic.value == "_not_null" + assert Diffo.Unwrap.unwrap(updated_characteristic.value) == "_not_null" + # integer updated_characteristic = - characteristic |> Diffo.Provider.update_characteristic!(%{value: nil}) + characteristic + |> Diffo.Provider.update_characteristic!(%{value: Value.primitive("integer", 1)}) - assert updated_characteristic.value == nil + assert Diffo.Unwrap.unwrap(updated_characteristic.value) == 1 + # float updated_characteristic = - characteristic |> Diffo.Provider.update_characteristic!(%{value: ["one", "two"]}) + characteristic + |> Diffo.Provider.update_characteristic!(%{value: Value.primitive("float", 1.2)}) - assert updated_characteristic.value == ["one", "two"] + assert Diffo.Unwrap.unwrap(updated_characteristic.value) == 1.2 + # nil (shouldn't need to unwrap nil) updated_characteristic = - characteristic - |> Diffo.Provider.update_characteristic!(%{value: %{aEnd: 1, zEnd: 13}}) + characteristic |> Diffo.Provider.update_characteristic!(%{value: nil}) - assert updated_characteristic.value == %{aEnd: 1, zEnd: 13} + assert Diffo.Unwrap.unwrap(updated_characteristic.value) == nil + # dynamic updated_characteristic = characteristic - |> Diffo.Provider.update_characteristic!(%{value: %{"aEnd" => 1, "zEnd" => 13}}) + |> Diffo.Provider.update_characteristic!(%{ + value: Value.dynamic(Patch, %Patch{aEnd: 1, zEnd: 42}) + }) - assert updated_characteristic.value == %{"aEnd" => 1, "zEnd" => 13} + assert Diffo.Unwrap.unwrap(updated_characteristic.value) == %Patch{aEnd: 1, zEnd: 42} end end @@ -195,7 +211,7 @@ defmodule Diffo.Provider.CharacteristicTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :managed, + value: Value.primitive("string", "managed"), type: :instance }) @@ -206,14 +222,15 @@ defmodule Diffo.Provider.CharacteristicTest do describe "Diffo.Provider outstanding Characteristics" do use Outstand - @port1 %Diffo.Provider.Characteristic{name: "port", value: 1} - @port3 %Diffo.Provider.Characteristic{name: "port", value: 3} - @port5 %Diffo.Provider.Characteristic{name: "port", value: 5} - @pair1 %Diffo.Provider.Characteristic{name: "pair", value: 1} + @port1 %Diffo.Provider.Characteristic{name: "port", value: Value.primitive("integer", 1)} + @port3 %Diffo.Provider.Characteristic{name: "port", value: Value.primitive("integer", 3)} + #@port5 %Diffo.Provider.Characteristic{name: "port", value: Value.primitive("integer", 5)} + @pair1 %Diffo.Provider.Characteristic{name: "pair", value: Value.primitive("integer", 1)} @name_only %Diffo.Provider.Characteristic{name: "port"} - @value_only %Diffo.Provider.Characteristic{value: 1} - @range_only %Diffo.Provider.Characteristic{value: 1..4} - @port_range %Diffo.Provider.Characteristic{name: "port", value: 1..4} + # map only + @value_only %Diffo.Provider.Characteristic{value: %{value: 1}} + # @range_only %Diffo.Provider.Characteristic{value: 1..4} + # @port_range %Diffo.Provider.Characteristic{name: "port", value: 1..4} gen_nothing_outstanding_test("specific nothing outstanding", @port1, @port1) @@ -238,22 +255,22 @@ defmodule Diffo.Provider.CharacteristicTest do Ash.Test.strip_metadata(@value_only) ) - gen_nothing_outstanding_test("port range nothing outstanding, port1", @port_range, @port1) - gen_nothing_outstanding_test("port range nothing outstanding, port3", @port_range, @port3) - - gen_result_outstanding_test( - "port range name result, pair1", - @port_range, - @pair1, - Ash.Test.strip_metadata(@name_only) - ) - - gen_result_outstanding_test( - "port range value result, port5", - @port_range, - @port5, - Ash.Test.strip_metadata(@range_only) - ) + # gen_nothing_outstanding_test("port range nothing outstanding, port1", @port_range, @port1) + # gen_nothing_outstanding_test("port range nothing outstanding, port3", @port_range, @port3) + + # gen_result_outstanding_test( + # "port range name result, pair1", + # @port_range, + # @pair1, + # Ash.Test.strip_metadata(@name_only) + # ) + + # gen_result_outstanding_test( + # "port range value result, port5", + # @port_range, + # @port5, + # Ash.Test.strip_metadata(@range_only) + # ) end describe "Diffo.Provider delete Characteristics" do @@ -261,7 +278,7 @@ defmodule Diffo.Provider.CharacteristicTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :managed, + value: Value.primitive("string", "managed"), type: :instance }) @@ -275,7 +292,7 @@ defmodule Diffo.Provider.CharacteristicTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :managed, + value: Value.primitive("string", "managed"), type: :instance }) diff --git a/test/provider/event_test.exs b/test/provider/event_test.exs index d2dd724..2260a2a 100644 --- a/test/provider/event_test.exs +++ b/test/provider/event_test.exs @@ -117,7 +117,7 @@ defmodule Diffo.Provider.EventTest do encoding = Jason.encode!(event) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"eventId\":\"#{event.id}\",\"eventTime\":\"now\",\"eventType\":\"serviceCreateEvent\",\"event\":{\"service\":{\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/nbnAccess/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"nbnAccess\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"state\":\"initial\"}}}) + ~s({\"eventId\":\"#{event.id}\",\"eventTime\":\"now\",\"eventType\":\"serviceCreateEvent\",\"event\":{\"service\":{\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"nbnAccess\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"state\":\"initial\"}}}) end end diff --git a/test/provider/external_identifier_test.exs b/test/provider/external_identifier_test.exs index 6e074f6..105fcf8 100644 --- a/test/provider/external_identifier_test.exs +++ b/test/provider/external_identifier_test.exs @@ -19,6 +19,7 @@ defmodule Diffo.Provider.ExternalIdentifierTest do end describe "Diffo.Provider read ExternalIdentifiers" do + @tag :casing test "list external identifiers - success" do specification = Diffo.Provider.create_specification!(%{name: "nbnAccess"}) instance = Diffo.Provider.create_instance!(%{specified_by: specification.id}) diff --git a/test/provider/feature_test.exs b/test/provider/feature_test.exs index 08c4821..2b834bf 100644 --- a/test/provider/feature_test.exs +++ b/test/provider/feature_test.exs @@ -6,6 +6,8 @@ defmodule Diffo.Provider.FeatureTest do @moduledoc false use ExUnit.Case + alias Diffo.Type.Value + setup_all do AshNeo4j.BoltyHelper.start() end @@ -44,14 +46,14 @@ defmodule Diffo.Provider.FeatureTest do first_characteristic = Diffo.Provider.create_characteristic!(%{ name: :encapsulation, - value: :qinq, + value: Value.primitive("string", "qinq"), type: :feature }) second_characteristic = Diffo.Provider.create_characteristic!(%{ name: :type, - value: :evpl, + value: Value.primitive("string", "evpl"), type: :feature }) @@ -65,14 +67,14 @@ defmodule Diffo.Provider.FeatureTest do first_characteristic = Diffo.Provider.create_characteristic!(%{ name: :type, - value: :fraudHeavy, + value: Value.primitive("string", "fraudHeavy"), type: :feature }) second_characteristic = Diffo.Provider.create_characteristic!(%{ name: :type, - value: :fraudLight, + value: Value.primitive("string", "fraudLight"), type: :feature }) @@ -101,14 +103,14 @@ defmodule Diffo.Provider.FeatureTest do device_characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :epic1000a, + value: Value.primitive("string", "epic1000a"), type: :feature }) connection_characteristic = Diffo.Provider.create_characteristic!(%{ name: :connection, - value: :foreign, + value: Value.primitive("string", "foreign"), type: :feature }) @@ -129,7 +131,7 @@ defmodule Diffo.Provider.FeatureTest do device_characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :epic1000a, + value: Value.primitive("string", "epic1000a"), type: :feature }) @@ -152,14 +154,14 @@ defmodule Diffo.Provider.FeatureTest do first_characteristic = Diffo.Provider.create_characteristic!(%{ name: :type, - value: :fraudHeavy, + value: Value.primitive("string", "fraudHeavy"), type: :feature }) second_characteristic = Diffo.Provider.create_characteristic!(%{ name: :type, - value: :fraudLight, + value: Value.primitive("string", "fraudLight"), type: :feature }) @@ -182,14 +184,14 @@ defmodule Diffo.Provider.FeatureTest do device_characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :epic1000a, + value: Value.primitive("string", "epic1000a"), type: :feature }) connection_characteristic = Diffo.Provider.create_characteristic!(%{ name: :connection, - value: :foreign, + value: Value.primitive("string", "foreign"), type: :feature }) @@ -221,7 +223,10 @@ defmodule Diffo.Provider.FeatureTest do name: :dynamicLineManagement, isEnabled: false, characteristics: [ - %Diffo.Provider.Characteristic{name: :optimiseFor, value: :speed} + %Diffo.Provider.Characteristic{ + name: :optimiseFor, + value: Value.primitive("string", "speed") + } ] } @@ -229,7 +234,10 @@ defmodule Diffo.Provider.FeatureTest do name: :dynamicLineManagement, isEnabled: false, characteristics: [ - %Diffo.Provider.Characteristic{name: :optimiseFor, value: :stable} + %Diffo.Provider.Characteristic{ + name: :optimiseFor, + value: Value.primitive("string", "stable") + } ] } @name_only %Diffo.Provider.Feature{name: :dynamicLineManagement} @@ -237,7 +245,8 @@ defmodule Diffo.Provider.FeatureTest do @isDisabled_only %Diffo.Provider.Feature{isEnabled: false} @speed_only %Diffo.Provider.Feature{ characteristics: [ - %Diffo.Provider.Characteristic{value: :speed} + # outstanding on primitive is a map + %Diffo.Provider.Characteristic{value: %{value: "speed"}} ] } @@ -281,7 +290,7 @@ defmodule Diffo.Provider.FeatureTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :epic1000a, + value: Value.primitive("string", "epic1000a"), type: :feature }) diff --git a/test/provider/instance_test.exs b/test/provider/instance_test.exs index 178b593..1d92465 100644 --- a/test/provider/instance_test.exs +++ b/test/provider/instance_test.exs @@ -6,6 +6,7 @@ defmodule Diffo.Provider.InstanceTest do @moduledoc false use ExUnit.Case alias Diffo.Provider.Instance + alias Diffo.Type.Value setup_all do AshNeo4j.BoltyHelper.start() @@ -79,7 +80,7 @@ defmodule Diffo.Provider.InstanceTest do assert instance.service_state == :initial refute instance.service_operating_status assert instance.specification.id == specification.id - assert instance.href == "serviceInventoryManagement/v4/service/fibreAccess/#{instance.id}" + assert instance.href == "serviceInventoryManagement/v4/service/#{instance.id}" # both specification and instance nodes are labelled :Provider {:ok, response} = AshNeo4j.Neo4jHelper.read_nodes(:Provider) @@ -102,7 +103,7 @@ defmodule Diffo.Provider.InstanceTest do assert instance.service_state == :initial refute instance.service_operating_status assert instance.specification.id == specification.id - assert instance.href == "serviceInventoryManagement/v4/service/fibreAccess/#{instance.id}" + assert instance.href == "serviceInventoryManagement/v4/service/#{instance.id}" end test "create a service instance with a supplied id - failure - not uuid v4" do @@ -224,14 +225,14 @@ defmodule Diffo.Provider.InstanceTest do first_characteristic = Diffo.Provider.create_characteristic!(%{ name: :port1, - value: :eth, + value: Value.primitive("string", "eth"), type: :instance }) second_characteristic = Diffo.Provider.create_characteristic!(%{ name: :port2, - value: :eth, + value: Value.primitive("string", "eth"), type: :instance }) @@ -247,14 +248,14 @@ defmodule Diffo.Provider.InstanceTest do first_characteristic = Diffo.Provider.create_characteristic!(%{ name: :port, - value: "1", + value: Value.primitive("string", "1"), type: :instance }) second_characteristic = Diffo.Provider.create_characteristic!(%{ name: :port, - value: "2", + value: Value.primitive("string", "2"), type: :instance }) @@ -594,7 +595,7 @@ defmodule Diffo.Provider.InstanceTest do feature_characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :epic1000a, + value: Value.primitive("string", "epic1000a"), type: :feature }) @@ -607,7 +608,7 @@ defmodule Diffo.Provider.InstanceTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :managed, + value: Value.primitive("string", "managed"), type: :instance }) @@ -623,7 +624,7 @@ defmodule Diffo.Provider.InstanceTest do forward_relationship_characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: :gateway, + value: Value.primitive("string", "gateway"), type: :relationship }) @@ -778,13 +779,13 @@ defmodule Diffo.Provider.InstanceTest do parent_encoding = Jason.encode!(loaded_instance) |> Diffo.Util.summarise_dates() assert parent_encoding == - ~s({\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{parent_instance.id}\",\"category\":\"connectivity\",\"description\":\"Site Connection Service\",\"externalIdentifier\":[{\"externalIdentifierType\":\"siteId\",\"id\":\"ANS020000023234\",\"owner\":\"T3_ADAPTIVE_NETWORKS\"}],\"serviceSpecification\":{\"id\":\"#{parent_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{parent_specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"serviceRelationship\":[{\"type\":\"bestows\",\"service\":{\"id\":\"#{child_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/device/#{child_instance.id}\"},\"serviceRelationshipCharacteristic\":[{\"name\":\"role\",\"value\":\"gateway\"}]}],\"feature\":[{\"name\":\"management\",\"isEnabled\":true,\"featureCharacteristic\":[{\"name\":\"device\",\"value\":\"epic1000a\"}]}],\"serviceCharacteristic\":[{\"name\":\"device\",\"value\":\"managed\"}],\"place\":[{\"id\":\"LOC000000897353\",\"href\":\"place/nbnco/LOC000000897353\",\"name\":\"locationId\",\"role\":\"CustomerSite\",\"@referredType\":\"GeographicAddress\",\"@type\":\"PlaceRef\"}],"relatedParty\":[{\"id\":\"T3_ADAPTIVE_NETWORKS\",\"href\":\"entity/internal/T3_ADAPTIVE_NETWORKS\",\"name\":\"entityId\",\"role\":\"Consumer\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"},{\"id\":\"T3_CONNECTIVITY\",\"href\":\"entity/internal/T3_CONNECTIVITY\",\"name\":\"entityId\",\"role\":\"Provider\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"}]}) + ~s({\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{parent_instance.id}\",\"category\":\"connectivity\",\"description\":\"Site Connection Service\",\"externalIdentifier\":[{\"externalIdentifierType\":\"siteId\",\"id\":\"ANS020000023234\",\"owner\":\"T3_ADAPTIVE_NETWORKS\"}],\"serviceSpecification\":{\"id\":\"#{parent_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{parent_specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"serviceRelationship\":[{\"type\":\"bestows\",\"service\":{\"id\":\"#{child_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{child_instance.id}\"},\"serviceRelationshipCharacteristic\":[{\"name\":\"role\",\"value\":\"gateway\"}]}],\"feature\":[{\"name\":\"management\",\"isEnabled\":true,\"featureCharacteristic\":[{\"name\":\"device\",\"value\":\"epic1000a\"}]}],\"serviceCharacteristic\":[{\"name\":\"device\",\"value\":\"managed\"}],\"place\":[{\"id\":\"LOC000000897353\",\"href\":\"place/nbnco/LOC000000897353\",\"name\":\"locationId\",\"role\":\"CustomerSite\",\"@referredType\":\"GeographicAddress\",\"@type\":\"PlaceRef\"}],"relatedParty\":[{\"id\":\"T3_ADAPTIVE_NETWORKS\",\"href\":\"entity/internal/T3_ADAPTIVE_NETWORKS\",\"name\":\"entityId\",\"role\":\"Consumer\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"},{\"id\":\"T3_CONNECTIVITY\",\"href\":\"entity/internal/T3_CONNECTIVITY\",\"name\":\"entityId\",\"role\":\"Provider\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"}]}) refreshed_child_instance = Diffo.Provider.get_instance_by_id!(child_instance.id) child_encoding = Jason.encode!(refreshed_child_instance) |> Diffo.Util.summarise_dates() assert child_encoding == - ~s({\"id\":\"#{child_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/device/#{child_instance.id}\",\"category\":\"connectivity\",\"description\":\"Device Service\",\"externalIdentifier\":[{\"externalIdentifierType\":\"connectionId\",\"id\":\"EVC010000873982\",\"owner\":\"T3_CONNECTIVITY\"},{\"externalIdentifierType\":\"orderId\",\"id\":\"ORD00000123456\",\"owner\":\"T4_CPE\"}],\"serviceSpecification\":{\"id\":\"#{child_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{child_specification.id}\",\"name\":\"device\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"processStatus\":[{\"code\":\"CPEDEV-1002\",\"severity\":\"WARN\",\"message\":\"device unmanagable\",\"timeStamp\":\"now\"},{\"code\":\"CPEDEV-1001\",\"severity\":\"INFO\",\"message\":\"device discovered\",\"timeStamp\":\"now\"}],\"serviceRelationship\":[{\"type\":\"providedTo\",\"service\":{\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{parent_instance.id}\"}}],\"relatedEntity\":[{\"id\":\"COR000000123456\",\"name\":\"2025-01\",\"role\":\"expected\",\"@referredType\":\"cost\",\"@type\":\"EntityRef\"}],\"place\":[{\"id\":\"LOC000000897353\",\"href\":\"place/nbnco/LOC000000897353\",\"name\":\"locationId\",\"role\":\"CustomerSite\",\"@referredType\":\"GeographicAddress\",\"@type\":\"PlaceRef\"}],\"relatedParty\":[{\"id\":\"T3_CONNECTIVITY\",\"href\":\"entity/internal/T3_CONNECTIVITY\",\"name\":\"entityId\",\"role\":\"Consumer\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"},{\"id\":\"T4_CPE\",\"href\":\"entity/internal/T4_CPE\",\"name\":\"entityId\",\"role\":\"Provider\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"}]}) + ~s({\"id\":\"#{child_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{child_instance.id}\",\"category\":\"connectivity\",\"description\":\"Device Service\",\"externalIdentifier\":[{\"externalIdentifierType\":\"connectionId\",\"id\":\"EVC010000873982\",\"owner\":\"T3_CONNECTIVITY\"},{\"externalIdentifierType\":\"orderId\",\"id\":\"ORD00000123456\",\"owner\":\"T4_CPE\"}],\"serviceSpecification\":{\"id\":\"#{child_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{child_specification.id}\",\"name\":\"device\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"processStatus\":[{\"code\":\"CPEDEV-1002\",\"severity\":\"WARN\",\"message\":\"device unmanagable\",\"timeStamp\":\"now\"},{\"code\":\"CPEDEV-1001\",\"severity\":\"INFO\",\"message\":\"device discovered\",\"timeStamp\":\"now\"}],\"serviceRelationship\":[{\"type\":\"providedTo\",\"service\":{\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{parent_instance.id}\"}}],\"relatedEntity\":[{\"id\":\"COR000000123456\",\"name\":\"2025-01\",\"role\":\"expected\",\"@referredType\":\"cost\",\"@type\":\"EntityRef\"}],\"place\":[{\"id\":\"LOC000000897353\",\"href\":\"place/nbnco/LOC000000897353\",\"name\":\"locationId\",\"role\":\"CustomerSite\",\"@referredType\":\"GeographicAddress\",\"@type\":\"PlaceRef\"}],\"relatedParty\":[{\"id\":\"T3_CONNECTIVITY\",\"href\":\"entity/internal/T3_CONNECTIVITY\",\"name\":\"entityId\",\"role\":\"Consumer\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"},{\"id\":\"T4_CPE\",\"href\":\"entity/internal/T4_CPE\",\"name\":\"entityId\",\"role\":\"Provider\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"}]}) end test "encode service with supporting service child instance json - success" do @@ -805,7 +806,7 @@ defmodule Diffo.Provider.InstanceTest do feature_characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :epic1000a, + value: Value.primitive("string", "epic1000a"), type: :feature }) @@ -818,7 +819,7 @@ defmodule Diffo.Provider.InstanceTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :device, - value: :managed, + value: Value.primitive("string", "managed"), type: :instance }) @@ -834,7 +835,7 @@ defmodule Diffo.Provider.InstanceTest do forward_relationship_characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: :gateway, + value: Value.primitive("string", "gateway"), type: :relationship }) @@ -948,12 +949,12 @@ defmodule Diffo.Provider.InstanceTest do parent_encoding = Jason.encode!(refreshed_parent_instance) |> Diffo.Util.summarise_dates() assert parent_encoding == - ~s({\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{parent_instance.id}\",\"category\":\"connectivity\",\"description\":\"Site Connection Service\",\"externalIdentifier\":[{\"externalIdentifierType\":\"siteId\",\"id\":\"ANS020000023234\",\"owner\":\"T3_ADAPTIVE_NETWORKS\"}],\"serviceSpecification\":{\"id\":\"#{parent_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{parent_specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"serviceRelationship\":[{\"alias\":\"primary\",\"type\":\"bestows\",\"service\":{\"id\":\"#{child_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/device/#{child_instance.id}\"},\"serviceRelationshipCharacteristic\":[{\"name\":\"role\",\"value\":\"gateway\"}]}],\"supportingService\":[{\"id\":\"primary\",\"href\":\"serviceInventoryManagement/v4/service/device/#{child_instance.id}\"}],\"feature\":[{\"name\":\"management\",\"isEnabled\":true,\"featureCharacteristic\":[{\"name\":\"device\",\"value\":\"epic1000a\"}]}],\"serviceCharacteristic\":[{\"name\":\"device\",\"value\":\"managed\"}],\"place\":[{\"id\":\"LOC000000897353\",\"href\":\"place/nbnco/LOC000000897353\",\"name\":\"locationId\",\"role\":\"CustomerSite\",\"@referredType\":\"GeographicAddress\",\"@type\":\"PlaceRef\"}],\"relatedParty\":[{\"id\":\"T3_ADAPTIVE_NETWORKS\",\"href\":\"entity/internal/T3_ADAPTIVE_NETWORKS\",\"name\":\"entityId\",\"role\":\"Consumer\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"},{\"id\":\"T3_CONNECTIVITY\",\"href\":\"entity/internal/T3_CONNECTIVITY\",\"name\":\"entityId\",\"role\":\"Provider\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"}]}) + ~s({\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{parent_instance.id}\",\"category\":\"connectivity\",\"description\":\"Site Connection Service\",\"externalIdentifier\":[{\"externalIdentifierType\":\"siteId\",\"id\":\"ANS020000023234\",\"owner\":\"T3_ADAPTIVE_NETWORKS\"}],\"serviceSpecification\":{\"id\":\"#{parent_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{parent_specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"serviceRelationship\":[{\"alias\":\"primary\",\"type\":\"bestows\",\"service\":{\"id\":\"#{child_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{child_instance.id}\"},\"serviceRelationshipCharacteristic\":[{\"name\":\"role\",\"value\":\"gateway\"}]}],\"supportingService\":[{\"id\":\"primary\",\"href\":\"serviceInventoryManagement/v4/service/#{child_instance.id}\"}],\"feature\":[{\"name\":\"management\",\"isEnabled\":true,\"featureCharacteristic\":[{\"name\":\"device\",\"value\":\"epic1000a\"}]}],\"serviceCharacteristic\":[{\"name\":\"device\",\"value\":\"managed\"}],\"place\":[{\"id\":\"LOC000000897353\",\"href\":\"place/nbnco/LOC000000897353\",\"name\":\"locationId\",\"role\":\"CustomerSite\",\"@referredType\":\"GeographicAddress\",\"@type\":\"PlaceRef\"}],\"relatedParty\":[{\"id\":\"T3_ADAPTIVE_NETWORKS\",\"href\":\"entity/internal/T3_ADAPTIVE_NETWORKS\",\"name\":\"entityId\",\"role\":\"Consumer\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"},{\"id\":\"T3_CONNECTIVITY\",\"href\":\"entity/internal/T3_CONNECTIVITY\",\"name\":\"entityId\",\"role\":\"Provider\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"}]}) child_encoding = Jason.encode!(refreshed_child_instance) |> Diffo.Util.summarise_dates() assert child_encoding == - ~s({\"id\":\"#{child_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/device/#{child_instance.id}\",\"category\":\"connectivity\",\"description\":\"Device Service\",\"externalIdentifier\":[{\"externalIdentifierType\":\"connectionId\",\"id\":\"EVC010000873982\",\"owner\":\"T3_CONNECTIVITY\"},{\"externalIdentifierType\":\"orderId\",\"id\":\"ORD00000123456\",\"owner\":\"T4_CPE\"}],\"serviceSpecification\":{\"id\":\"#{child_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{child_specification.id}\",\"name\":\"device\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"serviceRelationship\":[{\"type\":\"providedTo\",\"service\":{\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{parent_instance.id}\"}}],\"place\":[{\"id\":\"LOC000000897353\",\"href\":\"place/nbnco/LOC000000897353\",\"name\":\"locationId\",\"role\":\"CustomerSite\",\"@referredType\":\"GeographicAddress\",\"@type\":\"PlaceRef\"}],\"relatedParty\":[{\"id\":\"T3_CONNECTIVITY\",\"href\":\"entity/internal/T3_CONNECTIVITY\",\"name\":\"entityId\",\"role\":\"Consumer\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"},{\"id\":\"T4_CPE\",\"href\":\"entity/internal/T4_CPE\",\"name\":\"entityId\",\"role\":\"Provider\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"}]}) + ~s({\"id\":\"#{child_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{child_instance.id}\",\"category\":\"connectivity\",\"description\":\"Device Service\",\"externalIdentifier\":[{\"externalIdentifierType\":\"connectionId\",\"id\":\"EVC010000873982\",\"owner\":\"T3_CONNECTIVITY\"},{\"externalIdentifierType\":\"orderId\",\"id\":\"ORD00000123456\",\"owner\":\"T4_CPE\"}],\"serviceSpecification\":{\"id\":\"#{child_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{child_specification.id}\",\"name\":\"device\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"serviceRelationship\":[{\"type\":\"providedTo\",\"service\":{\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{parent_instance.id}\"}}],\"place\":[{\"id\":\"LOC000000897353\",\"href\":\"place/nbnco/LOC000000897353\",\"name\":\"locationId\",\"role\":\"CustomerSite\",\"@referredType\":\"GeographicAddress\",\"@type\":\"PlaceRef\"}],\"relatedParty\":[{\"id\":\"T3_CONNECTIVITY\",\"href\":\"entity/internal/T3_CONNECTIVITY\",\"name\":\"entityId\",\"role\":\"Consumer\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"},{\"id\":\"T4_CPE\",\"href\":\"entity/internal/T4_CPE\",\"name\":\"entityId\",\"role\":\"Provider\",\"@referredType\":\"Entity\",\"@type\":\"PartyRef\"}]}) end test "encode service with resource child instance json - success" do @@ -975,7 +976,7 @@ defmodule Diffo.Provider.InstanceTest do feature_characteristic = Diffo.Provider.create_characteristic!(%{ name: :goal, - value: :stability, + value: Value.primitive("string", "stability"), type: :feature }) @@ -988,7 +989,7 @@ defmodule Diffo.Provider.InstanceTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :dslam, - value: "QDONC1001", + value: Value.primitive("string", "QDONC1001"), type: :instance }) @@ -1021,12 +1022,12 @@ defmodule Diffo.Provider.InstanceTest do parent_encoding = Jason.encode!(refreshed_parent_instance) |> Diffo.Util.summarise_dates() assert parent_encoding == - ~s({\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/adslAccess/#{parent_instance.id}\",\"category\":\"connectivity\",\"description\":\"ADSL Access Service\",\"serviceSpecification\":{\"id\":\"#{parent_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{parent_specification.id}\",\"name\":\"adslAccess\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"resourceRelationship\":[{\"type\":\"isAssigned\",\"resource\":{\"id\":\"#{child_instance.id}\",\"href\":\"resourceInventoryManagement/v4/resource/can/#{child_instance.id}\"}}],\"feature\":[{\"name\":\"dynamicLineManagement\",\"isEnabled\":true,\"featureCharacteristic\":[{\"name\":\"goal\",\"value\":\"stability\"}]}],\"serviceCharacteristic\":[{\"name\":\"dslam",\"value\":\"QDONC1001\"}]}) + ~s({\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{parent_instance.id}\",\"category\":\"connectivity\",\"description\":\"ADSL Access Service\",\"serviceSpecification\":{\"id\":\"#{parent_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{parent_specification.id}\",\"name\":\"adslAccess\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"resourceRelationship\":[{\"type\":\"isAssigned\",\"resource\":{\"id\":\"#{child_instance.id}\",\"href\":\"resourceInventoryManagement/v4/resource/#{child_instance.id}\"}}],\"feature\":[{\"name\":\"dynamicLineManagement\",\"isEnabled\":true,\"featureCharacteristic\":[{\"name\":\"goal\",\"value\":\"stability\"}]}],\"serviceCharacteristic\":[{\"name\":\"dslam",\"value\":\"QDONC1001\"}]}) _child_encoding = Jason.encode!(refreshed_child_instance) |> Diffo.Util.summarise_dates() # assert child_encoding == - ~s({\"id\":\"#{child_instance.id}\",\"href\":\"resourceInventoryManagement/v4/resource/can/#{child_instance.id}\",\"category\":\"physical\",\"description\":\"Customer Access Network Resource\",\"resourceSpecification\":{\"id\":\"#{child_specification.id}\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/#{child_specification.id}\",\"name\":\"can\",\"version\":\"v1.0.0\"},\"serviceRelationship\":[{\"type\":\"assignedTo\",\"service\":{\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/adslAccess/#{parent_instance.id}\"}}]}) + ~s({\"id\":\"#{child_instance.id}\",\"href\":\"resourceInventoryManagement/v4/resource/#{child_instance.id}\",\"category\":\"physical\",\"description\":\"Customer Access Network Resource\",\"resourceSpecification\":{\"id\":\"#{child_specification.id}\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/#{child_specification.id}\",\"name\":\"can\",\"version\":\"v1.0.0\"},\"serviceRelationship\":[{\"type\":\"assignedTo\",\"service\":{\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{parent_instance.id}\"}}]}) end test "encode service with supporting resource child instance json - success" do @@ -1048,7 +1049,7 @@ defmodule Diffo.Provider.InstanceTest do feature_characteristic = Diffo.Provider.create_characteristic!(%{ name: :goal, - value: :stability, + value: Value.primitive("string", "stability"), type: :feature }) @@ -1061,7 +1062,7 @@ defmodule Diffo.Provider.InstanceTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :dslam, - value: "QDONC1001", + value: Value.primitive("string", "QDONC1001"), type: :instance }) @@ -1095,12 +1096,12 @@ defmodule Diffo.Provider.InstanceTest do parent_encoding = Jason.encode!(refreshed_parent_instance) |> Diffo.Util.summarise_dates() assert parent_encoding == - ~s({\"id\":\"#{parent_instance.id}\","href\":\"serviceInventoryManagement/v4/service/adslAccess/#{parent_instance.id}\",\"category\":\"connectivity\",\"description\":\"ADSL Access Service\",\"serviceSpecification\":{\"id\":\"#{parent_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{parent_specification.id}\",\"name\":\"adslAccess\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"resourceRelationship\":[{\"alias\":\"can\",\"type\":\"isAssigned\",\"resource\":{\"id\":\"#{child_instance.id}\",\"href\":\"resourceInventoryManagement/v4/resource/can/#{child_instance.id}\"}}],\"supportingResource\":[{\"id\":\"can\",\"href\":\"resourceInventoryManagement/v4/resource/can/#{child_instance.id}\"}],\"feature\":[{\"name\":\"dynamicLineManagement\",\"isEnabled\":true,\"featureCharacteristic\":[{\"name\":\"goal\",\"value\":\"stability\"}]}],\"serviceCharacteristic\":[{\"name\":\"dslam",\"value\":\"QDONC1001\"}]}) + ~s({\"id\":\"#{parent_instance.id}\","href\":\"serviceInventoryManagement/v4/service/#{parent_instance.id}\",\"category\":\"connectivity\",\"description\":\"ADSL Access Service\",\"serviceSpecification\":{\"id\":\"#{parent_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{parent_specification.id}\",\"name\":\"adslAccess\",\"version\":\"v1.0.0\"},"serviceDate\":\"now\",\"state\":\"initial\",\"resourceRelationship\":[{\"alias\":\"can\",\"type\":\"isAssigned\",\"resource\":{\"id\":\"#{child_instance.id}\",\"href\":\"resourceInventoryManagement/v4/resource/#{child_instance.id}\"}}],\"supportingResource\":[{\"id\":\"can\",\"href\":\"resourceInventoryManagement/v4/resource/#{child_instance.id}\"}],\"feature\":[{\"name\":\"dynamicLineManagement\",\"isEnabled\":true,\"featureCharacteristic\":[{\"name\":\"goal\",\"value\":\"stability\"}]}],\"serviceCharacteristic\":[{\"name\":\"dslam",\"value\":\"QDONC1001\"}]}) child_encoding = Jason.encode!(refreshed_child_instance) |> Diffo.Util.summarise_dates() assert child_encoding == - ~s({\"id\":\"#{child_instance.id}\",\"href\":\"resourceInventoryManagement/v4/resource/can/#{child_instance.id}\",\"category\":\"physical\",\"description\":\"Customer Access Network Resource\",\"resourceSpecification\":{\"id\":\"#{child_specification.id}\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/#{child_specification.id}\",\"name\":\"can\",\"version\":\"v1.0.0\"},\"serviceRelationship\":[{\"type\":\"assignedTo\",\"service\":{\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/adslAccess/#{parent_instance.id}\"}}]}) + ~s({\"id\":\"#{child_instance.id}\",\"href\":\"resourceInventoryManagement/v4/resource/#{child_instance.id}\",\"category\":\"physical\",\"description\":\"Customer Access Network Resource\",\"resourceSpecification\":{\"id\":\"#{child_specification.id}\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/#{child_specification.id}\",\"name\":\"can\",\"version\":\"v1.0.0\"},\"serviceRelationship\":[{\"type\":\"assignedTo\",\"service\":{\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{parent_instance.id}\"}}]}) end test "encode sorts relationships - success" do @@ -1144,7 +1145,7 @@ defmodule Diffo.Provider.InstanceTest do parent_encoding = Jason.encode!(refreshed_parent_instance) |> Diffo.Util.summarise_dates() assert parent_encoding == - ~s({\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/broadband/#{parent_instance.id}\",\"serviceSpecification\":{\"id\":\"#{parent_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{parent_specification.id}\",\"name\":\"broadband\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"state\":\"initial\",\"serviceRelationship\":[{\"alias\":\"access\",\"type\":\"bestows\",\"service\":{\"id\":\"#{access_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/fibreAccess/#{access_instance.id}\"}},{\"alias\":\"aggregation\",\"type\":\"bestows\",\"service\":{\"id\":\"#{aggregation_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/aggregation/#{aggregation_instance.id}\"}},{\"alias\":\"edge\",\"type\":\"bestows\",\"service\":{\"id\":\"#{edge_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/edge/#{edge_instance.id}\"}}],\"supportingService\":[{\"id\":\"access\",\"href\":\"serviceInventoryManagement/v4/service/fibreAccess/#{access_instance.id}\"},{\"id\":\"aggregation\",\"href\":\"serviceInventoryManagement/v4/service/aggregation/#{aggregation_instance.id}\"},{\"id\":\"edge\",\"href\":\"serviceInventoryManagement/v4/service/edge/#{edge_instance.id}\"}]}) + ~s({\"id\":\"#{parent_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{parent_instance.id}\",\"serviceSpecification\":{\"id\":\"#{parent_specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{parent_specification.id}\",\"name\":\"broadband\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"state\":\"initial\",\"serviceRelationship\":[{\"alias\":\"access\",\"type\":\"bestows\",\"service\":{\"id\":\"#{access_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{access_instance.id}\"}},{\"alias\":\"aggregation\",\"type\":\"bestows\",\"service\":{\"id\":\"#{aggregation_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{aggregation_instance.id}\"}},{\"alias\":\"edge\",\"type\":\"bestows\",\"service\":{\"id\":\"#{edge_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{edge_instance.id}\"}}],\"supportingService\":[{\"id\":\"access\",\"href\":\"serviceInventoryManagement/v4/service/#{access_instance.id}\"},{\"id\":\"aggregation\",\"href\":\"serviceInventoryManagement/v4/service/#{aggregation_instance.id}\"},{\"id\":\"edge\",\"href\":\"serviceInventoryManagement/v4/service/#{edge_instance.id}\"}]}) end test "encode sorts features - success" do @@ -1162,7 +1163,7 @@ defmodule Diffo.Provider.InstanceTest do encoding = Jason.encode!(instance) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"state\":\"initial\",\"feature\":[{\"name\":\"management\",\"isEnabled\":true},{\"name\":\"optimisation\",\"isEnabled\":true},{\"name\":\"security\",\"isEnabled\":true}]}) + ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"state\":\"initial\",\"feature\":[{\"name\":\"management\",\"isEnabled\":true},{\"name\":\"optimisation\",\"isEnabled\":true},{\"name\":\"security\",\"isEnabled\":true}]}) end test "encode sorts characteristics within features - success" do @@ -1171,21 +1172,21 @@ defmodule Diffo.Provider.InstanceTest do first_feature_characteristic = Diffo.Provider.create_characteristic!(%{ name: :optimisation, - value: true, + value: Value.primitive("boolean", true), type: :feature }) second_feature_characteristic = Diffo.Provider.create_characteristic!(%{ name: :management, - value: true, + value: Value.primitive("boolean", true), type: :feature }) third_feature_characteristic = Diffo.Provider.create_characteristic!(%{ name: :security, - value: true, + value: Value.primitive("boolean", true), type: :feature }) @@ -1207,7 +1208,7 @@ defmodule Diffo.Provider.InstanceTest do encoding = Jason.encode!(refreshed_instance) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"state\":\"initial\",\"feature\":[{\"name\":\"automations\",\"isEnabled\":true,\"featureCharacteristic\":[{\"name\":\"management\",\"value\":true},{\"name\":\"optimisation\",\"value\":true},{\"name\":\"security\",\"value\":true}]}]}) + ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"state\":\"initial\",\"feature\":[{\"name\":\"automations\",\"isEnabled\":true,\"featureCharacteristic\":[{\"name\":\"management\",\"value\":true},{\"name\":\"optimisation\",\"value\":true},{\"name\":\"security\",\"value\":true}]}]}) end test "encode sorts characteristics - success" do @@ -1216,21 +1217,21 @@ defmodule Diffo.Provider.InstanceTest do first_characteristic = Diffo.Provider.create_characteristic!(%{ name: :optimisation, - value: true, + value: Value.primitive("boolean", true), type: :instance }) second_characteristic = Diffo.Provider.create_characteristic!(%{ name: :management, - value: true, + value: Value.primitive("boolean", true), type: :instance }) third_characteristic = Diffo.Provider.create_characteristic!(%{ name: :security, - value: true, + value: Value.primitive("boolean", true), type: :instance }) @@ -1250,7 +1251,7 @@ defmodule Diffo.Provider.InstanceTest do encoding = Jason.encode!(refreshed_instance) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"state\":\"initial\",\"serviceCharacteristic\":[{\"name\":\"management\",\"value\":true},{\"name\":\"optimisation\",\"value\":true},{\"name\":\"security\",\"value\":true}]}) + ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"state\":\"initial\",\"serviceCharacteristic\":[{\"name\":\"management\",\"value\":true},{\"name\":\"optimisation\",\"value\":true},{\"name\":\"security\",\"value\":true}]}) end test "encode cancelled service - success" do @@ -1261,7 +1262,7 @@ defmodule Diffo.Provider.InstanceTest do encoding = Jason.encode!(refreshed_instance) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"endDate\":\"now\",\"state\":\"cancelled\",\"operatingStatus\":\"unknown\"}) + ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"endDate\":\"now\",\"state\":\"cancelled\",\"operatingStatus\":\"unknown\"}) end test "encode active service - success" do @@ -1272,7 +1273,7 @@ defmodule Diffo.Provider.InstanceTest do encoding = Jason.encode!(refreshed_instance) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"startDate\":\"now\",\"state\":\"active\",\"operatingStatus\":\"starting\"}) + ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"startDate\":\"now\",\"state\":\"active\",\"operatingStatus\":\"starting\"}) end test "encode suspended service - success" do @@ -1286,7 +1287,7 @@ defmodule Diffo.Provider.InstanceTest do encoding = Jason.encode!(refreshed_instance) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"startDate\":\"now\",\"state\":\"suspended\",\"operatingStatus\":\"limited\"}) + ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"startDate\":\"now\",\"state\":\"suspended\",\"operatingStatus\":\"limited\"}) end test "encode terminated service - success" do @@ -1300,7 +1301,7 @@ defmodule Diffo.Provider.InstanceTest do encoding = Jason.encode!(refreshed_instance) |> Diffo.Util.summarise_dates() assert encoding == - ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"startDate\":\"now\",\"endDate\":\"now\",\"state\":\"terminated\",\"operatingStatus\":\"stopping\"}) + ~s({\"id\":\"#{instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{instance.id}\",\"serviceSpecification\":{\"id\":\"#{specification.id}\",\"href\":\"serviceCatalogManagement/v4/serviceSpecification/#{specification.id}\",\"name\":\"siteConnection\",\"version\":\"v1.0.0\"},\"serviceDate\":\"now\",\"startDate\":\"now\",\"endDate\":\"now\",\"state\":\"terminated\",\"operatingStatus\":\"stopping\"}) end end diff --git a/test/provider/party_test.exs b/test/provider/party_test.exs index 9f15b50..4a26765 100644 --- a/test/provider/party_test.exs +++ b/test/provider/party_test.exs @@ -384,6 +384,7 @@ defmodule Diffo.Provider.PartyTest do {:error, _error} = Diffo.Provider.get_party_by_id(party.id) end + @tag :guard test "delete party - failure, related ExternalIdentifier" do specification = Diffo.Provider.create_specification!(%{name: "nbnAccess"}) instance = Diffo.Provider.create_instance!(%{specified_by: specification.id}) diff --git a/test/provider/process_status_test.exs b/test/provider/process_status_test.exs index 9733c26..28f8507 100644 --- a/test/provider/process_status_test.exs +++ b/test/provider/process_status_test.exs @@ -35,7 +35,11 @@ defmodule Diffo.Provider.ProcessStatusTest do test "create a process status with a parameterised message - success" do specification = Diffo.Provider.create_specification!(%{name: "nbnAccess"}) instance = Diffo.Provider.create_instance!(%{specified_by: specification.id}) - parameterized_message = %{reason: "cancelled due to force majeure"} + + parameterized_message = %Ash.Union{ + type: :map, + value: %{reason: "cancelled due to force majeure"} + } process_status = Diffo.Provider.ProcessStatus.create!(%{ @@ -123,7 +127,9 @@ defmodule Diffo.Provider.ProcessStatusTest do process_status |> Diffo.Provider.ProcessStatus.update!(%{parameterized_message: parameterized_message}) - assert updated_process_status.parameterized_message == parameterized_message + assert updated_process_status.parameterized_message == %{ + "reason" => "cancelled due to force majeure" + } end test "update code to nil - failure" do @@ -213,6 +219,7 @@ defmodule Diffo.Provider.ProcessStatusTest do test "encode json with parameterized message - success" do parameterized_message = %{reason: "cancelled due to force majeure"} + specification = Diffo.Provider.create_specification!(%{name: "nbnAccess"}) instance = Diffo.Provider.create_instance!(%{specified_by: specification.id}) diff --git a/test/provider/reference_test.exs b/test/provider/reference_test.exs index 2e7d24d..3e349bb 100644 --- a/test/provider/reference_test.exs +++ b/test/provider/reference_test.exs @@ -10,12 +10,11 @@ defmodule Diffo.Provider.ReferenceTest do test "encode json - success" do reference = %Diffo.Provider.Reference{ id: "8bcfbf9a-34a5-427a-8eae-5c3812466432", - href: - "serviceInventoryManagement/v4/service/siteConnection/8bcfbf9a-34a5-427a-8eae-5c3812466432" + href: "serviceInventoryManagement/v4/service/8bcfbf9a-34a5-427a-8eae-5c3812466432" } assert Jason.encode!(reference) == - "{\"id\":\"8bcfbf9a-34a5-427a-8eae-5c3812466432\",\"href\":\"serviceInventoryManagement/v4/service/siteConnection/8bcfbf9a-34a5-427a-8eae-5c3812466432\"}" + "{\"id\":\"8bcfbf9a-34a5-427a-8eae-5c3812466432\",\"href\":\"serviceInventoryManagement/v4/service/8bcfbf9a-34a5-427a-8eae-5c3812466432\"}" end end @@ -24,13 +23,11 @@ defmodule Diffo.Provider.ReferenceTest do @id_and_href %Diffo.Provider.Reference{ id: "8bcfbf9a-34a5-427a-8eae-5c3812466432", - href: - "serviceInventoryManagement/v4/service/siteConnection/8bcfbf9a-34a5-427a-8eae-5c3812466432" + href: "serviceInventoryManagement/v4/service/8bcfbf9a-34a5-427a-8eae-5c3812466432" } @id_only %Diffo.Provider.Reference{id: "8bcfbf9a-34a5-427a-8eae-5c3812466432"} @href_only %Diffo.Provider.Reference{ - href: - "serviceInventoryManagement/v4/service/siteConnection/8bcfbf9a-34a5-427a-8eae-5c3812466432" + href: "serviceInventoryManagement/v4/service/8bcfbf9a-34a5-427a-8eae-5c3812466432" } @any_id_and_href %Diffo.Provider.Reference{ id: &Outstand.any_bitstring/1, @@ -38,8 +35,7 @@ defmodule Diffo.Provider.ReferenceTest do } @instance_id_and_href %Diffo.Provider.Instance{ id: "8bcfbf9a-34a5-427a-8eae-5c3812466432", - href: - "serviceInventoryManagement/v4/service/siteConnection/8bcfbf9a-34a5-427a-8eae-5c3812466432", + href: "serviceInventoryManagement/v4/service/8bcfbf9a-34a5-427a-8eae-5c3812466432", type: :service } diff --git a/test/provider/relationship_test.exs b/test/provider/relationship_test.exs index 9eb1343..b950820 100644 --- a/test/provider/relationship_test.exs +++ b/test/provider/relationship_test.exs @@ -6,6 +6,8 @@ defmodule Diffo.Provider.RelationshipTest do @moduledoc false use ExUnit.Case + alias Diffo.Type.Value + setup_all do AshNeo4j.BoltyHelper.start() end @@ -287,14 +289,14 @@ defmodule Diffo.Provider.RelationshipTest do first_characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: "worker", + value: Value.primitive("string", "worker"), type: :relationship }) second_characteristic = Diffo.Provider.create_characteristic!(%{ name: :type, - value: :evpl, + value: Value.primitive("string", "evpl"), type: :relationship }) @@ -318,14 +320,14 @@ defmodule Diffo.Provider.RelationshipTest do first_characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: "worker", + value: Value.primitive("string", "worker"), type: :relationship }) second_characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: "protect", + value: Value.primitive("string", "protect"), type: :relationship }) @@ -352,14 +354,14 @@ defmodule Diffo.Provider.RelationshipTest do first_characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: "worker", + value: Value.primitive("string", "worker"), type: :relationship }) second_characteristic = Diffo.Provider.create_characteristic!(%{ name: :type, - value: :evpl, + value: Value.primitive("string", "evpl"), type: :relationship }) @@ -442,7 +444,7 @@ defmodule Diffo.Provider.RelationshipTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: :gateway, + value: Value.primitive("string", "gateway"), type: :relationship }) @@ -457,7 +459,7 @@ defmodule Diffo.Provider.RelationshipTest do encoding = Jason.encode!(relationship) assert encoding == - ~s({\"type\":\"bestows\",\"service\":{\"id\":\"#{child_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/device/#{child_instance.id}\"},\"serviceRelationshipCharacteristic\":[{\"name\":\"role\",\"value\":\"gateway\"}]}) + ~s({\"type\":\"bestows\",\"service\":{\"id\":\"#{child_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{child_instance.id}\"},\"serviceRelationshipCharacteristic\":[{\"name\":\"role\",\"value\":\"gateway\"}]}) end test "encode service instance resourceRelationship json - success" do @@ -478,7 +480,7 @@ defmodule Diffo.Provider.RelationshipTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: :primary, + value: Value.primitive("string", "primary"), type: :relationship }) @@ -493,7 +495,7 @@ defmodule Diffo.Provider.RelationshipTest do encoding = Jason.encode!(relationship) assert encoding == - ~s({\"type\":\"isAssigned\",\"resource\":{\"id\":\"#{resource_instance.id}\",\"href\":\"resourceInventoryManagement/v4/resource/can/#{resource_instance.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"role\",\"value\":\"primary\"}]}) + ~s({\"type\":\"isAssigned\",\"resource\":{\"id\":\"#{resource_instance.id}\",\"href\":\"resourceInventoryManagement/v4/resource/#{resource_instance.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"role\",\"value\":\"primary\"}]}) end test "encode resource instance serviceRelationship json - success" do @@ -521,7 +523,7 @@ defmodule Diffo.Provider.RelationshipTest do encoding = Jason.encode!(relationship) assert encoding == - ~s({\"type\":\"assignedTo\",\"service\":{\"id\":\"#{service_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/adslAccess/#{service_instance.id}\"}}) + ~s({\"type\":\"assignedTo\",\"service\":{\"id\":\"#{service_instance.id}\",\"href\":\"serviceInventoryManagement/v4/service/#{service_instance.id}\"}}) end end @@ -601,7 +603,7 @@ defmodule Diffo.Provider.RelationshipTest do characteristic = Diffo.Provider.create_characteristic!(%{ name: :role, - value: :gateway, + value: Value.primitive("string", "gateway"), type: :relationship }) diff --git a/test/support/characteristics.ex b/test/support/characteristics.ex index 54c43e5..f16b472 100644 --- a/test/support/characteristics.ex +++ b/test/support/characteristics.ex @@ -25,7 +25,7 @@ defmodule Diffo.Test.Characteristics do Enum.each( expected, fn {field, expected_value} -> - assert expected_value --- Map.get(characteristic.value, field) == nil + assert expected_value --- Map.get(Diffo.Unwrap.unwrap(characteristic.value), field) == nil end ) diff --git a/test/support/type/patch.ex b/test/support/type/patch.ex new file mode 100644 index 0000000..fbdc20f --- /dev/null +++ b/test/support/type/patch.ex @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defmodule Diffo.Test.Patch do + @moduledoc false + + use Ash.TypedStruct, extensions: [AshJason.TypedStruct, AshOutstanding.TypedStruct] + + jason do + pick [:aEnd, :zEnd] + end + + outstanding do + expect [:aEnd, :zEnd] + end + + typed_struct do + field :aEnd, :integer, constraints: [min: 0] + field :zEnd, :integer, constraints: [min: 0] + end +end diff --git a/test/test_helper.exs b/test/test_helper.exs index 5d462db..f268772 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -4,5 +4,4 @@ Mix.Task.run("app.start") ExUnit.start() -level = Application.get_env(:logger, :console) |> Keyword.get(:level) -Logger.put_application_level(:ash_neo4j, level) +Logger.put_application_level(:ash_neo4j, :warning) diff --git a/test/type/dynamic_test.exs b/test/type/dynamic_test.exs new file mode 100644 index 0000000..2e534e7 --- /dev/null +++ b/test/type/dynamic_test.exs @@ -0,0 +1,81 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defmodule Diffo.Type.DynamicTest do + use ExUnit.Case + + use Outstand + alias Diffo.Type.Dynamic + alias Diffo.Test.Patch + alias Diffo.Test.CardValue + + describe "dynamic cast and dump" do + test "cast_input from struct" do + value = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + + assert {:ok, %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}}} = + Ash.Type.cast_input(Dynamic, value, []) + end + + test "dump_to_native" do + value = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + assert {:ok, _dumped} = Ash.Type.dump_to_native(Dynamic, value, []) + end + + test "cast_stored roundtrip" do + value = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + {:ok, dumped} = Ash.Type.dump_to_native(Dynamic, value, []) + + assert {:ok, %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}}} = + Ash.Type.cast_stored(Dynamic, dumped, []) + end + end + + describe "dynamic json" do + test "Dynamic implements Jason.Encoder" do + expected = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + assert Jason.Encoder.impl_for(expected) == Jason.Encoder.Diffo.Type.Dynamic + end + + test "dynamic struct renders value only" do + value = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + assert Jason.encode!(value) == ~s({"aEnd":1,"zEnd":42}) + end + end + + describe "dynamic outstanding" do + test "Dynamic implements Outstanding" do + expected = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + assert Outstanding.impl_for(expected) == Outstanding.Diffo.Type.Dynamic + end + + test "actual is missing" do + expected = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + actual = nil + assert expected --- actual == expected + assert expected >>> actual == true + end + + test "actual is wrong type and value" do + expected = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + actual = %Dynamic{type: CardValue, value: %CardValue{name: "test"}} + assert expected --- actual == expected + assert expected >>> actual == true + end + + test "actual is wrong value" do + expected = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + actual = %Dynamic{type: Patch, value: %Patch{aEnd: 3, zEnd: 42}} + assert expected --- actual == %Dynamic{type: nil, value: %Patch{aEnd: 1}} + assert expected >>> actual == true + end + + test "expected is resolved" do + expected = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + actual = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + assert expected --- actual == nil + assert expected >>> actual == false + end + end +end diff --git a/test/type/primitive_test.exs b/test/type/primitive_test.exs new file mode 100644 index 0000000..c1437b7 --- /dev/null +++ b/test/type/primitive_test.exs @@ -0,0 +1,122 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defmodule Diffo.Type.PrimitiveTest do + use ExUnit.Case + + use Outstand + alias Diffo.Type.Primitive + + describe "primitive json" do + test "Primitive implements Json.Encode" do + expected = Primitive.wrap("string", "connectivity") + assert Jason.Encoder.impl_for(expected) == Jason.Encoder.Diffo.Type.Primitive + end + + test "primitive string renders" do + value = Primitive.wrap("string", "connectivity") + assert Jason.encode!(value) == "\"connectivity\"" + end + + test "primitive integer renders" do + value = Primitive.wrap("integer", 5) + assert Jason.encode!(value) == "5" + end + + test "primitive float renders" do + value = Primitive.wrap("float", 5.0) + assert Jason.encode!(value) == "5.0" + end + + test "primitive boolean renders" do + value = Primitive.wrap("boolean", true) + assert Jason.encode!(value) == "true" + end + + test "primitive date renders" do + value = Primitive.wrap("date", ~D[2026-04-16]) + assert Jason.encode!(value) == "\"2026-04-16\"" + end + + test "primitive time renders" do + value = Primitive.wrap("time", ~T[15:43:13.817332]) + assert Jason.encode!(value) == "\"15:43:13.817332\"" + end + + test "primitive datetime renders" do + value = Primitive.wrap("datetime", ~U[2026-04-16 15:43:13.817332Z]) + assert Jason.encode!(value) == "\"2026-04-16T15:43:13.817332Z\"" + end + + test "primitive duration renders" do + value = Primitive.wrap("duration", %Duration{hour: 1}) + assert Jason.encode!(value) == "\"PT1H\"" + end + + def unwrap(%{type: "string", string: value}), do: value + def unwrap(%{type: "integer", integer: value}), do: value + def unwrap(%{type: "float", float: value}), do: value + def unwrap(%{type: "boolean", boolean: value}), do: value + def unwrap(%{type: "date", date: value}), do: value + def unwrap(%{type: "time", time: value}), do: value + def unwrap(%{type: "datetime", datetime: value}), do: value + def unwrap(%{type: "duration", duration: value}), do: value + end + + describe "primitive outstanding" do + test "Primitive implements Outstanding" do + expected = Primitive.wrap("string", "connectivity") + assert Outstanding.impl_for(expected) == Outstanding.Diffo.Type.Primitive + end + + test "actual is missing" do + expected = Primitive.wrap("string", "connectivity") + actual = nil + assert expected --- actual == %{type: "string", value: "connectivity"} + assert expected >>> actual == true + end + + test "actual is wrong type and value" do + expected = Primitive.wrap("string", "connectivity") + actual = Primitive.wrap("boolean", true) + assert expected --- actual == %{type: "string", value: "connectivity"} + assert expected >>> actual == true + end + + test "actual is wrong value" do + expected = Primitive.wrap("string", "connectivity") + actual = Primitive.wrap("string", "Connectivity") + assert expected --- actual == %{value: "connectivity"} + assert expected >>> actual == true + end + + test "actual is wrong type" do + expected = Primitive.wrap("float", 4) + actual = Primitive.wrap("integer", 4) + assert expected --- actual == %{type: "float"} + assert expected >>> actual == true + end + + test "value function is outstanding" do + expected = Primitive.wrap("string", &any_bitstring/1) + actual = Primitive.wrap("string", nil) + assert expected --- actual == %{value: :any_bitstring} + assert expected >>> actual == true + end + + test "expected string is resolved" do + expected = Primitive.wrap("string", "connectivity") + actual = Primitive.wrap("string", "connectivity") + assert expected --- actual == nil + assert expected >>> actual == false + end + + test "expected function is resolved" do + expected = Primitive.wrap("string", &any_bitstring/1) + actual = Primitive.wrap("string", "connectivity") + assert expected --- actual == nil + assert expected >>> actual == false + end + end +end diff --git a/test/type/value_test.exs b/test/type/value_test.exs new file mode 100644 index 0000000..586415f --- /dev/null +++ b/test/type/value_test.exs @@ -0,0 +1,166 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT + +defmodule Diffo.Type.ValueTest do + use ExUnit.Case + + use Outstand + alias Diffo.Type.Value + alias Diffo.Type.Primitive + alias Diffo.Type.Dynamic + alias Diffo.Test.Patch + + describe "value cast and dump" do + test "cast_input dynamic using Value.dynamic" do + value = Value.dynamic(Patch, %Patch{aEnd: 1, zEnd: 42}) + + assert {:ok, %Ash.Union{type: :dynamic, value: %Dynamic{type: Patch}}} = + Ash.Type.cast_input(Value, value, Value.subtype_constraints()) + end + + test "cast_input primitive using Value.primitive" do + value = Value.primitive("string", "hello") + + assert {:ok, %Ash.Union{type: :string, value: %Primitive{type: "string", string: "hello"}}} = + Ash.Type.cast_input(Value, value, Value.subtype_constraints()) + end + + test "cast_input primitive string" do + value = Primitive.wrap("string", "hello") + + assert {:ok, %Ash.Union{type: :string, value: %Primitive{type: "string", string: "hello"}}} = + Ash.Type.cast_input(Value, value, Value.subtype_constraints()) + end + + @tag bugged: "raw Dynamic struct cast_input requires Value.dynamic/2 wrapper" + @tag :skip + test "cast_input dynamic" do + value = %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + + assert {:ok, %Ash.Union{type: :dynamic, value: %Dynamic{type: Patch}}} = + Ash.Type.cast_input(Value, value, Value.subtype_constraints()) + end + + test "dump_to_native primitive" do + value = %Ash.Union{type: :string, value: Primitive.wrap("string", "hello")} + + assert {:ok, %{"type" => :string, "value" => _}} = + Ash.Type.dump_to_native(Value, value, Value.subtype_constraints()) + end + + test "dump_to_native dynamic" do + value = %Ash.Union{ + type: :dynamic, + value: %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + } + + assert {:ok, %{"type" => :dynamic, "value" => %{"type" => _, "value" => _}}} = + Ash.Type.dump_to_native(Value, value, Value.subtype_constraints()) + end + + test "cast_stored roundtrip primitive" do + value = %Ash.Union{type: :string, value: Primitive.wrap("string", "hello")} + {:ok, dumped} = Ash.Type.dump_to_native(Value, value, Value.subtype_constraints()) + + assert {:ok, %Ash.Union{type: :string}} = + Ash.Type.cast_stored(Value, dumped, Value.subtype_constraints()) + end + + test "cast_stored roundtrip dynamic" do + value = %Ash.Union{ + type: :dynamic, + value: %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + } + + {:ok, dumped} = Ash.Type.dump_to_native(Value, value, Value.subtype_constraints()) + + assert {:ok, + %Ash.Union{ + type: :dynamic, + value: %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + }} = + Ash.Type.cast_stored(Value, dumped, Value.subtype_constraints()) + end + + test "roundtrip primitive from Value.primitive" do + value = Value.primitive("string", "hello") + {:ok, cast} = Ash.Type.cast_input(Value, value, Value.subtype_constraints()) + {:ok, dumped} = Ash.Type.dump_to_native(Value, cast, Value.subtype_constraints()) + {:ok, result} = Ash.Type.cast_stored(Value, dumped, Value.subtype_constraints()) + assert Diffo.Unwrap.unwrap(result) == "hello" + end + + test "roundtrip dynamic from Value.dynamic" do + value = Value.dynamic(Patch, %Patch{aEnd: 1, zEnd: 42}) + {:ok, cast} = Ash.Type.cast_input(Value, value, Value.subtype_constraints()) + {:ok, dumped} = Ash.Type.dump_to_native(Value, cast, Value.subtype_constraints()) + {:ok, result} = Ash.Type.cast_stored(Value, dumped, Value.subtype_constraints()) + assert Diffo.Unwrap.unwrap(result) == %Patch{aEnd: 1, zEnd: 42} + end + end + + describe "value json" do + test "Value implements Jason.Encoder" do + expected = %Ash.Union{type: :string, value: Primitive.wrap("string", "connectivity")} + assert Jason.Encoder.impl_for(expected) == Jason.Encoder.Ash.Union + end + + test "primitive string value renders" do + value = %Ash.Union{type: :string, value: Primitive.wrap("string", "connectivity")} + assert Jason.encode!(value) == "\"connectivity\"" + end + + test "dynamic value renders" do + value = %Ash.Union{ + type: :dynamic, + value: %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + } + + assert Jason.encode!(value) == ~s({"aEnd":1,"zEnd":42}) + end + end + + describe "value outstanding" do + test "Value implements Outstanding" do + expected = %Ash.Union{type: :string, value: Primitive.wrap("string", "connectivity")} + assert Outstanding.impl_for(expected) == Outstanding.Ash.Union + end + + test "actual is missing" do + expected = %Ash.Union{type: :string, value: Primitive.wrap("string", "connectivity")} + actual = nil + assert expected --- actual == expected + assert expected >>> actual == true + end + + test "actual is wrong value" do + expected = %Ash.Union{type: :string, value: Primitive.wrap("string", "connectivity")} + actual = %Ash.Union{type: :string, value: Primitive.wrap("string", "wrong")} + assert expected --- actual != nil + assert expected >>> actual == true + end + + test "expected string is resolved" do + expected = %Ash.Union{type: :string, value: Primitive.wrap("string", "connectivity")} + actual = %Ash.Union{type: :string, value: Primitive.wrap("string", "connectivity")} + assert expected --- actual == nil + assert expected >>> actual == false + end + + test "dynamic value is resolved" do + expected = %Ash.Union{ + type: :dynamic, + value: %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + } + + actual = %Ash.Union{ + type: :dynamic, + value: %Dynamic{type: Patch, value: %Patch{aEnd: 1, zEnd: 42}} + } + + assert expected --- actual == nil + assert expected >>> actual == false + end + end +end From a510f7c1be314d1381679c514dd99132e6cb79ee Mon Sep 17 00:00:00 2001 From: Matt Beanland Date: Fri, 17 Apr 2026 16:26:39 +0930 Subject: [PATCH 2/2] reuse compliance fix --- lib/diffo/type/primitive.ex | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/diffo/type/primitive.ex b/lib/diffo/type/primitive.ex index 3e6f952..1294c85 100644 --- a/lib/diffo/type/primitive.ex +++ b/lib/diffo/type/primitive.ex @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2025 diffo contributors +# +# SPDX-License-Identifier: MIT defmodule Diffo.Type.Primitive do @moduledoc """ Diffo - TMF Service and Resource Management with a difference