diff --git a/config/dev.exs b/config/dev.exs index adc6e40..0f96636 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -1,3 +1,5 @@ import Config +config :resource_kit, ResourceKit.Deref, adapter: ResourceKit.Deref.Local + config :resource_kit, ResourceKitCLI.Endpoint, server: true diff --git a/config/test.exs b/config/test.exs index 83d5ab4..df699bd 100644 --- a/config/test.exs +++ b/config/test.exs @@ -1,5 +1,8 @@ import Config +config :resource_kit, ResourceKit.Deref, + adapter: {ResourceKit.Deref.Local, directory: "test/fixtures"} + config :resource_kit, ResourceKit.Repo, hostname: "localhost", database: "resource_kit_test", diff --git a/lib/resource_kit.ex b/lib/resource_kit.ex index 4572de1..299882d 100644 --- a/lib/resource_kit.ex +++ b/lib/resource_kit.ex @@ -1,7 +1,7 @@ defmodule ResourceKit do @moduledoc false - defdelegate insert(action, params), to: ResourceKit.Action.Insert, as: :run + defdelegate insert(action, params, opts), to: ResourceKit.Action.Insert, as: :run - defdelegate list(action, params), to: ResourceKit.Action.List, as: :run + defdelegate list(action, params, opts), to: ResourceKit.Action.List, as: :run end diff --git a/lib/resource_kit/action/skeleton.ex b/lib/resource_kit/action/skeleton.ex index b1e6eb0..fa6110c 100644 --- a/lib/resource_kit/action/skeleton.ex +++ b/lib/resource_kit/action/skeleton.ex @@ -55,14 +55,17 @@ defmodule ResourceKit.Action.Skeleton do alias ResourceKit.Pipeline.Compile.Token, as: CompileToken alias ResourceKit.Pipeline.Execute.Token, as: ExecuteToken - def run(action, params) do - with {:ok, %{action: action, references: references}} <- __compile__(action) do - __execute__(action, references, params) + def run(action, params, opts) do + with {:ok, %{action: action, references: references}} <- __compile__(action, opts) do + __execute__(action, references, params, opts) end end - defp __compile__(action) do - %CompileToken{action: action} + defp __compile__(action, opts) do + root = Keyword.fetch!(opts, :root) + context = %CompileToken.Context{root: root, current: root} + + %CompileToken{action: action, context: context} |> Pluggable.run([&__MODULE__.compile(&1, [])]) |> case do %CompileToken{halted: false} = token -> {:ok, token.assigns} @@ -70,8 +73,11 @@ defmodule ResourceKit.Action.Skeleton do end end - defp __execute__(action, references, params) do - %ExecuteToken{action: action, references: references, params: params} + defp __execute__(action, references, params, opts) do + root = Keyword.fetch!(opts, :root) + context = %ExecuteToken.Context{root: root, current: root} + + %ExecuteToken{action: action, references: references, params: params, context: context} |> Pluggable.run([&__MODULE__.execute(&1, [])]) |> case do %ExecuteToken{halted: false} = token -> ExecuteToken.fetch_assign(token, :result) diff --git a/lib/resource_kit/deref.ex b/lib/resource_kit/deref.ex new file mode 100644 index 0000000..98a875e --- /dev/null +++ b/lib/resource_kit/deref.ex @@ -0,0 +1,67 @@ +defmodule ResourceKit.Deref do + @moduledoc """ + A behavior definition that developers can use to implement their own dereferencing logic. + + ## Options + + * `adapter` - A module that implemented the deref behaviour. Or `{adapter, opts}` if the adapter has options. + """ + + alias ResourceKit.Types + + alias ResourceKit.Deref.Context + alias ResourceKit.Schema.Ref + + @conf Application.compile_env(:resource_kit, [__MODULE__, :adapter], ResourceKit.Deref.Local) + @adapter if is_tuple(@conf), do: elem(@conf, 0), else: @conf + @opts if is_tuple(@conf), do: elem(@conf, 1), else: [] + + @callback resolve(ref :: Ref.t(), ctx :: Context.t()) :: + {:ok, Ref.t()} | {:error, Types.error()} + + @callback fetch(ref :: Ref.t(), ctx :: Context.t()) :: + {:ok, Types.json_value()} | {:error, Types.error()} + + defmacro __using__(_args) do + quote location: :keep do + @behaviour unquote(__MODULE__) + + import unquote(__MODULE__) + + @impl unquote(__MODULE__) + def resolve(ref, ctx) do + unquote(__MODULE__).absolute(ref, ctx) + end + + defoverridable resolve: 2 + end + end + + defguard is_absolute(term) when is_struct(term, Ref) and is_binary(term.uri.scheme) + + @spec absolute(ref :: Ref.t(), ctx :: Context.t()) :: {:ok, Ref.t()} | {:error, Types.error()} + def absolute(ref, ctx) + + def absolute(%Ref{} = ref, %Context{}) when is_absolute(ref) do + {:ok, ref} + end + + def absolute(%Ref{uri: uri}, %Context{current: %Ref{uri: current}}) do + {:ok, %Ref{uri: %{current | path: Path.expand(uri.path, current.path)}}} + end + + @spec resolve(ref :: Ref.t(), ctx :: Context.t()) :: {:ok, Ref.t()} | {:error, Types.error()} + def resolve(ref, ctx) do + @adapter.resolve(ref, put_options(ctx)) + end + + @spec fetch(ref :: Ref.t(), ctx :: Context.t()) :: + {:ok, Types.json_value()} | {:error, Types.error()} + def fetch(ref, ctx) do + @adapter.fetch(ref, put_options(ctx)) + end + + defp put_options(ctx) do + %{ctx | opts: @opts} + end +end diff --git a/lib/resource_kit/deref/context.ex b/lib/resource_kit/deref/context.ex new file mode 100644 index 0000000..fe2b5b0 --- /dev/null +++ b/lib/resource_kit/deref/context.ex @@ -0,0 +1,12 @@ +defmodule ResourceKit.Deref.Context do + @moduledoc false + + use TypedStruct + + alias ResourceKit.Schema.Ref + + typedstruct do + field :current, Ref.t(), enforce: true + field :opts, keyword(), default: [] + end +end diff --git a/lib/resource_kit/deref/local.ex b/lib/resource_kit/deref/local.ex new file mode 100644 index 0000000..9b27b7a --- /dev/null +++ b/lib/resource_kit/deref/local.ex @@ -0,0 +1,41 @@ +defmodule ResourceKit.Deref.Local do + @moduledoc """ + A deref implementation that loads a JSON document from a local directory. + + ## Options + + * `directory` - The root directory from which to load JSON documents. Defaults to `File.cwd/0`. + """ + + use ResourceKit.Deref + + alias ResourceKit.Deref.Context + alias ResourceKit.Schema.Ref + + @impl ResourceKit.Deref + def fetch(%Ref{uri: %URI{} = uri}, %Context{opts: opts}) do + directory = Keyword.get_lazy(opts, :directory, &File.cwd!/0) + file = uri.path |> Path.relative() |> Path.expand(directory) + + with {:ok, content} <- fetch_file(file), + {:ok, value} <- decode_json(content) do + {:ok, value} + else + {:error, message} -> {:error, {message, path: uri.path}} + end + end + + defp fetch_file(path) do + case File.read(path) do + {:ok, content} -> {:ok, content} + {:error, reason} -> {:error, "#{reason}"} + end + end + + defp decode_json(content) do + case Jason.decode(content) do + {:ok, value} -> {:ok, value} + {:error, reason} -> {:error, Exception.message(reason)} + end + end +end diff --git a/lib/resource_kit/json_pointer/utils.ex b/lib/resource_kit/json_pointer/utils.ex index 3bc5adc..df86f28 100644 --- a/lib/resource_kit/json_pointer/utils.ex +++ b/lib/resource_kit/json_pointer/utils.ex @@ -24,7 +24,10 @@ defmodule ResourceKit.JSONPointer.Utils do def resolve(parent, [], ctx), do: {:ok, parent, ctx} def resolve(parent, [key | rest], ctx) when is_map(parent) do - case Map.fetch(parent, key) do + parent + |> stringify_keys() + |> Map.fetch(key) + |> case do {:ok, data} -> resolve(data, rest, push_token(ctx, key)) :error -> {:error, {@key_not_exists, location: encode_location(ctx), key: key}} end @@ -43,6 +46,16 @@ defmodule ResourceKit.JSONPointer.Utils do end end + defp stringify_keys(data) when is_struct(data) do + data + |> Map.from_struct() + |> stringify_keys() + end + + defp stringify_keys(data) do + JetExt.Map.stringify_keys(data) + end + # leading zeros are not allowed for index defp parse_index(<> = index) do {:error, {@index_has_leading_zeros, index: index}} diff --git a/lib/resource_kit/pipeline/compile/deref.ex b/lib/resource_kit/pipeline/compile/deref.ex index c150fe4..2e841c3 100644 --- a/lib/resource_kit/pipeline/compile/deref.ex +++ b/lib/resource_kit/pipeline/compile/deref.ex @@ -15,6 +15,7 @@ defmodule ResourceKit.Pipeline.Compile.Deref do import ResourceKit.Guards + alias ResourceKit.Deref.Context, as: DerefContext alias ResourceKit.Pipeline.Compile.Token alias ResourceKit.Schema.Ref @@ -24,9 +25,9 @@ defmodule ResourceKit.Pipeline.Compile.Deref do @impl Pluggable def call(%Token{halted: true} = token, _opts), do: token - def call(%Token{action: action} = token, _opts) do - with {:ok, action} <- deref_schema(action), - {:ok, action} <- deref_returning_schema(action) do + def call(%Token{action: action, context: ctx} = token, _opts) do + with {:ok, action} <- deref_schema(action, ctx), + {:ok, action} <- deref_returning_schema(action, ctx) do Token.put_assign(token, :action, action) else {:error, reason} -> @@ -34,23 +35,23 @@ defmodule ResourceKit.Pipeline.Compile.Deref do end end - defp deref_schema(%{"schema" => ref} = action) when is_ref(ref) do + defp deref_schema(%{"schema" => ref} = action, ctx) when is_ref(ref) do with {:ok, ref} <- cast_ref(ref), - {:ok, schema} <- ResourceKit.Utils.deref(ref) do + {:ok, schema} <- ResourceKit.Deref.fetch(ref, %DerefContext{current: ctx.current}) do {:ok, Map.put(action, "schema", schema)} end end - defp deref_schema(action), do: {:ok, action} + defp deref_schema(action, _ctx), do: {:ok, action} - defp deref_returning_schema(%{"returning_schema" => ref} = action) when is_ref(ref) do + defp deref_returning_schema(%{"returning_schema" => ref} = action, ctx) when is_ref(ref) do with {:ok, ref} <- cast_ref(ref), - {:ok, returning} <- ResourceKit.Utils.deref(ref) do + {:ok, returning} <- ResourceKit.Deref.fetch(ref, %DerefContext{current: ctx.current}) do {:ok, Map.put(action, "returning_schema", returning)} end end - defp deref_returning_schema(action), do: {:ok, action} + defp deref_returning_schema(action, _ctx), do: {:ok, action} defp cast_ref(ref) do ref |> Ref.changeset() |> Ecto.Changeset.apply_action(:insert) diff --git a/lib/resource_kit/pipeline/compile/preload_reference.ex b/lib/resource_kit/pipeline/compile/preload_reference.ex index b491744..71f01d5 100644 --- a/lib/resource_kit/pipeline/compile/preload_reference.ex +++ b/lib/resource_kit/pipeline/compile/preload_reference.ex @@ -10,6 +10,7 @@ defmodule ResourceKit.Pipeline.Compile.PreloadReference do @behaviour Pluggable + alias ResourceKit.Deref.Context, as: DerefContext alias ResourceKit.Pipeline.Compile.Token alias ResourceKit.Schema.Column alias ResourceKit.Schema.Ref @@ -21,10 +22,10 @@ defmodule ResourceKit.Pipeline.Compile.PreloadReference do @impl Pluggable def call(%Token{halted: true} = token, _opts), do: token - def call(%Token{} = token, _opts) do + def call(%Token{context: context} = token, _opts) do action = Token.fetch_assign!(token, :action) - case preload_schema(action.schema) do + case preload_schema(action.schema, context) do {:ok, schema, references} -> token |> Token.put_assign(:action, %{action | schema: schema}) @@ -35,10 +36,10 @@ defmodule ResourceKit.Pipeline.Compile.PreloadReference do end end - defp preload_schema(%Schema{} = schema, references \\ %{}) do + defp preload_schema(%Schema{} = schema, context, references \\ %{}) do schema.columns |> Enum.reduce_while({:ok, [], references}, fn column, {:ok, columns, references} -> - case preload_column(column, references) do + case preload_column(column, context, references) do {:ok, column, references} -> {:cont, {:ok, [column | columns], references}} {:error, reason} -> {:halt, {:error, reason}} end @@ -49,31 +50,39 @@ defmodule ResourceKit.Pipeline.Compile.PreloadReference do end end - defp preload_column(column, references) + defp preload_column(column, context, references) - defp preload_column(%Column.Literal{} = column, references), do: {:ok, column, references} + defp preload_column(%Column.Literal{} = column, _context, references), + do: {:ok, column, references} - defp preload_column(column, references) + defp preload_column(column, context, references) when is_struct(column, Column.Belongs) or is_struct(column, Column.Has) do with {:ok, schema, references} <- - resolve_association_schema(column.association_schema, references), - {:ok, _schema, references} <- preload_schema(schema, references) do + resolve_association_schema(column.association_schema, context, references), + {:ok, _schema, references} <- + preload_schema(schema, update_context(column.association_schema, context), references) do {:ok, column, references} end end - defp resolve_association_schema(%Ref{} = ref, references) do - case resolve(ref, references) do + defp resolve_association_schema(%Ref{} = ref, context, references) do + case resolve(ref, context, references) do {:ok, schema} -> {:ok, schema, Map.put_new(references, ref, schema)} {:error, reason} -> {:error, reason} end end - defp resolve_association_schema(schema, references), do: {:ok, schema, references} + defp resolve_association_schema(schema, _context, references), do: {:ok, schema, references} - defp resolve(ref, references) do + defp update_context(%Ref{uri: uri}, context) do + %{context | current: uri} + end + + defp update_context(_schema, context), do: context + + defp resolve(ref, context, references) do with :error <- Map.fetch(references, ref) do - ResourceKit.Utils.resolve_association_schema(ref) + ResourceKit.Utils.resolve_association_schema(ref, %DerefContext{current: context.current}) end end end diff --git a/lib/resource_kit/pipeline/compile/token.ex b/lib/resource_kit/pipeline/compile/token.ex index 0884bd5..6bc8d98 100644 --- a/lib/resource_kit/pipeline/compile/token.ex +++ b/lib/resource_kit/pipeline/compile/token.ex @@ -1,9 +1,16 @@ defmodule ResourceKit.Pipeline.Compile.Token do @moduledoc false + use TypedStruct use ResourceKit.Pipeline.Token + typedstruct module: Context do + field :root, URI.t(), enforce: true + field :current, URI.t(), enforce: true + end + token do field :action, map(), enforce: true + field :context, Context.t(), enforce: true end end diff --git a/lib/resource_kit/pipeline/execute/build_params.ex b/lib/resource_kit/pipeline/execute/build_params.ex index c82a99e..bad396c 100644 --- a/lib/resource_kit/pipeline/execute/build_params.ex +++ b/lib/resource_kit/pipeline/execute/build_params.ex @@ -13,6 +13,7 @@ defmodule ResourceKit.Pipeline.Execute.BuildParams do @behaviour Pluggable + alias ResourceKit.Deref.Context, as: DerefContext alias ResourceKit.JSONPointer.Absolute alias ResourceKit.JSONPointer.Relative alias ResourceKit.Pipeline.Execute.Token @@ -24,6 +25,7 @@ defmodule ResourceKit.Pipeline.Execute.BuildParams do alias ResourceKit.Schema.Pointer.Context alias ResourceKit.Schema.Pointer.Data alias ResourceKit.Schema.Pointer.Value + alias ResourceKit.Schema.Ref @impl Pluggable def init(args), do: args @@ -81,12 +83,13 @@ defmodule ResourceKit.Pipeline.Execute.BuildParams do defp handle_column( %Association{value: %Data{value: %Absolute{} = pointer}} = assoc, - definition, + %HasColumn{association_schema: schema} = definition, scope ) do - with {:ok, definition} <- fetch_association_definition(definition, assoc.name), + with {:ok, definition} <- fetch_association_definition(definition, scope.context, assoc.name), {:ok, _value, location} <- __MODULE__.Scope.resolve(pointer, scope), scope = %{scope | current_value: scope.root_value, location: location}, + scope = update_context(schema, scope), {:ok, value} <- handle_changeset(assoc.changeset, definition, scope) do {:ok, assoc.name, value} else @@ -97,12 +100,13 @@ defmodule ResourceKit.Pipeline.Execute.BuildParams do defp handle_column( %Association{value: %Data{value: %Relative{} = pointer}} = assoc, - definition, + %HasColumn{association_schema: schema} = definition, scope ) do - with {:ok, definition} <- fetch_association_definition(definition, assoc.name), + with {:ok, definition} <- fetch_association_definition(definition, scope.context, assoc.name), {:ok, _value, location} <- __MODULE__.Scope.resolve(pointer, scope), scope = %{scope | location: location}, + scope = update_context(schema, scope), {:ok, value} <- handle_changeset(assoc.changeset, definition, scope) do {:ok, assoc.name, value} else @@ -115,9 +119,14 @@ defmodule ResourceKit.Pipeline.Execute.BuildParams do {:ok, assoc.name, nil} end - defp handle_column(%Association{value: %Value{value: value}} = assoc, definition, scope) do - with {:ok, definition} <- fetch_association_definition(definition, assoc.name), + defp handle_column( + %Association{value: %Value{value: value}} = assoc, + %HasColumn{association_schema: schema} = definition, + scope + ) do + with {:ok, definition} <- fetch_association_definition(definition, scope.context, assoc.name), scope = %{scope | current_value: value, location: []}, + scope = update_context(schema, scope), {:ok, value} <- handle_changeset(assoc.changeset, definition, scope) do {:ok, assoc.name, value} else @@ -132,8 +141,11 @@ defmodule ResourceKit.Pipeline.Execute.BuildParams do end end - defp fetch_association_definition(%HasColumn{association_schema: schema}, name) do - with {:ok, schema} <- ResourceKit.Utils.resolve_association_schema(schema) do + defp fetch_association_definition(%HasColumn{association_schema: schema}, context, name) do + with {:ok, schema} <- + ResourceKit.Utils.resolve_association_schema(schema, %DerefContext{ + current: context.current + }) do case Enum.find(schema.columns, &(&1.name === name)) do %HasColumn{} = definition -> {:ok, definition} %LiteralColumn{} -> {:error, {"is not an association definition", validation: :custom}} @@ -142,6 +154,12 @@ defmodule ResourceKit.Pipeline.Execute.BuildParams do end end + defp update_context(%Ref{uri: uri}, %__MODULE__.Scope{context: context} = scope) do + %{scope | context: %{context | current: uri}} + end + + defp update_context(_schema, scope), do: scope + defp resolve_value(%Context{value: pointer}, scope) do case ResourceKit.JSONPointer.resolve(pointer, scope.context) do {:ok, value, location} -> {:ok, value, location} diff --git a/lib/resource_kit/pipeline/execute/build_params/scope.ex b/lib/resource_kit/pipeline/execute/build_params/scope.ex index ff65885..73a2a69 100644 --- a/lib/resource_kit/pipeline/execute/build_params/scope.ex +++ b/lib/resource_kit/pipeline/execute/build_params/scope.ex @@ -20,11 +20,13 @@ defmodule ResourceKit.Pipeline.Execute.BuildParams.Scope do alias ResourceKit.JSONPointer.Context alias ResourceKit.JSONPointer.Relative + alias ResourceKit.Pipeline.Execute.Token + typedstruct do field :root_value, Types.json_value(), enforce: true field :current_value, Types.json_value(), enforce: true field :location, [token()], default: [] - field :context, map(), enforce: true + field :context, Token.Context.t(), enforce: true end @typep token() :: binary() | integer() diff --git a/lib/resource_kit/pipeline/execute/token.ex b/lib/resource_kit/pipeline/execute/token.ex index aa24cc7..01d9b88 100644 --- a/lib/resource_kit/pipeline/execute/token.ex +++ b/lib/resource_kit/pipeline/execute/token.ex @@ -1,16 +1,22 @@ defmodule ResourceKit.Pipeline.Execute.Token do @moduledoc false + use TypedStruct use ResourceKit.Pipeline.Token alias ResourceKit.Types alias ResourceKit.Schema.Ref + typedstruct module: Context do + field :root, URI.t(), enforce: true + field :current, URI.t(), enforce: true + end + token do field :action, struct(), enforce: true field :references, %{Ref.t() => map()}, enforce: true field :params, Types.json_value(), enforce: true - field :context, map(), default: %{} + field :context, Context.t(), enforce: true end end diff --git a/lib/resource_kit/utils.ex b/lib/resource_kit/utils.ex index 33bf1c2..1753ea2 100644 --- a/lib/resource_kit/utils.ex +++ b/lib/resource_kit/utils.ex @@ -5,6 +5,7 @@ defmodule ResourceKit.Utils do alias ResourceKit.Types + alias ResourceKit.Deref.Context, as: DerefContext alias ResourceKit.Schema.Column alias ResourceKit.Schema.Ref alias ResourceKit.Schema.Schema @@ -80,12 +81,6 @@ defmodule ResourceKit.Utils do Map.fetch!(@generators, type) end - # TODO: implement - @spec deref(ref :: map()) :: {:ok, Types.json_value()} - def deref(_ref) do - {:ok, %{}} - end - @spec fetch_primary_key(schema :: Schema.t(), opts :: keyword()) :: {:ok, atom()} | {:ok, {atom(), atom()}} | :error def fetch_primary_key(schema, opts \\ []) @@ -107,18 +102,17 @@ defmodule ResourceKit.Utils do end) end - @spec resolve_association_schema(ref_or_schema :: Ref.t() | Schema.t()) :: + @spec resolve_association_schema(ref_or_schema :: Ref.t() | Schema.t(), ctx :: DerefContext.t()) :: {:ok, Schema.t()} | {:error, Ecto.Changeset.t() | Types.error()} - def resolve_association_schema(%Ref{} = ref) do - # use qualified names of internal functions so that mimic works - with {:ok, params} <- __MODULE__.deref(ref) do + def resolve_association_schema(%Ref{} = ref, ctx) do + with {:ok, params} <- ResourceKit.Deref.fetch(ref, ctx) do params |> Schema.changeset() |> Ecto.Changeset.apply_action(:insert) end end - def resolve_association_schema(%Schema{} = schema), do: {:ok, schema} + def resolve_association_schema(%Schema{} = schema, _ctx), do: {:ok, schema} @spec __root__() :: binary() def __root__, do: "root" diff --git a/lib/resource_kit_plug/controller.ex b/lib/resource_kit_plug/controller.ex index 76a438f..898401f 100644 --- a/lib/resource_kit_plug/controller.ex +++ b/lib/resource_kit_plug/controller.ex @@ -4,9 +4,6 @@ defmodule ResourceKitPlug.Controller do alias ResourceKit.Schema.Ref alias ResourceKit.Schema.Request - # TODO: remove this when deref is implemented - @dialyzer {:no_match, fetch_action: 1} - for type <- [:insert, :list] do @spec unquote(type)(request :: map(), ctx :: PhxJsonRpc.Router.Context.t()) :: map() def unquote(type)(request, _ctx) do @@ -43,7 +40,9 @@ defmodule ResourceKitPlug.Controller do end defp fetch_action(%Request{uri: uri}) do - case ResourceKit.Utils.deref(%Ref{uri: uri}) do + alias ResourceKit.Deref.Context + + case ResourceKit.Deref.fetch(%Ref{uri: uri}, %Context{current: %Ref{uri: uri}}) do {:ok, action} -> {:ok, action} @@ -54,8 +53,8 @@ defmodule ResourceKitPlug.Controller do end end - defp run(%Request{params: params}, type, action) do - case apply(ResourceKit, type, [action, params]) do + defp run(%Request{uri: uri, params: params}, type, action) do + case apply(ResourceKit, type, [action, params, [root: uri]]) do {:ok, result} -> {:ok, result} diff --git a/test/fixtures/actions/insert_with_associations.json b/test/fixtures/actions/insert_with_associations.json index e27b5ad..4d17d52 100644 --- a/test/fixtures/actions/insert_with_associations.json +++ b/test/fixtures/actions/insert_with_associations.json @@ -9,7 +9,7 @@ "primary_key": true }, { - "name": "ip", + "name": "uri", "type": "text" }, { @@ -121,10 +121,10 @@ "changes": [ { "type": "column", - "name": "ip", + "name": "uri", "value": { "type": "context", - "value": "/ip" + "value": "/root" } }, { @@ -245,10 +245,10 @@ "returning_schema": [ { "type": "column", - "name": "ip", + "name": "uri", "value": { "type": "schema", - "value": "/ip" + "value": "/uri" } }, { diff --git a/test/resource_kit/action/insert_movie_test.exs b/test/resource_kit/action/insert_movie_test.exs index 10e3b47..74e87b5 100644 --- a/test/resource_kit/action/insert_movie_test.exs +++ b/test/resource_kit/action/insert_movie_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Action.InsertMovieTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true @movie_name "movies" @movie_columns [ @@ -20,6 +20,8 @@ defmodule ResourceKit.Action.InsertMovieTest do @tag jsons: [action: "actions/insert_movie.json"] test "works", %{action: action} do + root = URI.new!("actions/insert_movie.json") + params = %{ "title" => "Spy x Family Code: White", "likes" => 2878, @@ -37,11 +39,13 @@ defmodule ResourceKit.Action.InsertMovieTest do "release_date" => ~D[2024-04-30], "created_at" => ~U[2023-12-22 14:23:07.000000Z], "tags" => ["Animation", "Comedy"] - }} = ResourceKit.insert(action, params) + }} = ResourceKit.insert(action, params, root: root) end @tag jsons: [action: "actions/insert_movie.json"] test "failed", %{action: action} do + root = URI.new!("actions/insert_movie.json") + params = %{ "title" => "Spy x Family Code: White", "likes" => 2878, @@ -50,7 +54,7 @@ defmodule ResourceKit.Action.InsertMovieTest do "tags" => ["Animation", "Comedy"] } - assert {:error, changeset} = ResourceKit.insert(action, params) + assert {:error, changeset} = ResourceKit.insert(action, params, root: root) assert match?(%{release_date: ["is invalid"]}, errors_on(changeset)) end end diff --git a/test/resource_kit/action/insert_movie_with_comments_by_ref_association_schema_test.exs b/test/resource_kit/action/insert_movie_with_comments_by_ref_association_schema_test.exs index 9888c13..6ffd94b 100644 --- a/test/resource_kit/action/insert_movie_with_comments_by_ref_association_schema_test.exs +++ b/test/resource_kit/action/insert_movie_with_comments_by_ref_association_schema_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Action.InsertMovieWithCommentsByRefAssociationSchemaTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true @movie_name "movies" @poster_name "posters" @@ -44,10 +44,11 @@ defmodule ResourceKit.Action.InsertMovieWithCommentsByRefAssociationSchemaTest d setup :setup_tables setup :load_jsons - setup :deref_json @tag jsons: [action: "actions/insert_movie_with_comments_by_ref_association_schema.json"] test "works", %{action: action} do + root = URI.new!("actions/insert_movie_with_comments_by_ref_association_schema.json") + params = %{ "foo" => "foo", "title" => "Spy x Family Code: White", @@ -91,6 +92,6 @@ defmodule ResourceKit.Action.InsertMovieWithCommentsByRefAssociationSchemaTest d ] } ] - }} = ResourceKit.insert(action, params) + }} = ResourceKit.insert(action, params, root: root) end end diff --git a/test/resource_kit/action/insert_movie_with_comments_test.exs b/test/resource_kit/action/insert_movie_with_comments_test.exs index 327c783..d387188 100644 --- a/test/resource_kit/action/insert_movie_with_comments_test.exs +++ b/test/resource_kit/action/insert_movie_with_comments_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Action.InsertMovieWithCommentsTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true @movie_name "movies" @poster_name "posters" @@ -52,6 +52,8 @@ defmodule ResourceKit.Action.InsertMovieWithCommentsTest do @tag jsons: [action: "actions/insert_movie_with_comments.json"] test "works", %{action: action} do + root = URI.new!("actions/insert_movie_with_comments.json") + params = %{ "foo" => "foo", "title" => "Spy x Family Code: White", @@ -105,6 +107,6 @@ defmodule ResourceKit.Action.InsertMovieWithCommentsTest do ] } ] - }} = ResourceKit.insert(action, params) + }} = ResourceKit.insert(action, params, root: root) end end diff --git a/test/resource_kit/action/list_directors_with_movies_by_ref_association_schema_test.exs b/test/resource_kit/action/list_directors_with_movies_by_ref_association_schema_test.exs index 32d13a5..847fc59 100644 --- a/test/resource_kit/action/list_directors_with_movies_by_ref_association_schema_test.exs +++ b/test/resource_kit/action/list_directors_with_movies_by_ref_association_schema_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Action.ListDirectorsWithMoviesByRefAssociationSchemaTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true @director_name "directors" @movie_name "movies" @@ -17,7 +17,6 @@ defmodule ResourceKit.Action.ListDirectorsWithMoviesByRefAssociationSchemaTest d setup :setup_tables setup :load_jsons - setup :deref_json @tag tables: [{@director_name, @director_columns}, {@movie_name, @movie_columns}] @tag jsons: [action: "actions/list_directors_with_movies_by_ref_association_schema.json"] @@ -28,9 +27,11 @@ defmodule ResourceKit.Action.ListDirectorsWithMoviesByRefAssociationSchemaTest d {"M. Night Shyamalan", ["Trap", "The Watchers"]} ]) + root = URI.new!("actions/list_directors_with_movies_by_ref_association_schema.json") params = %{"pagination" => %{"offset" => 0, "limit" => 2}} - assert {:ok, %{"data" => data, "pagination" => pagination}} = ResourceKit.list(action, params) + assert {:ok, %{"data" => data, "pagination" => pagination}} = + ResourceKit.list(action, params, root: root) assert match?( [ diff --git a/test/resource_kit/action/list_directors_with_movies_test.exs b/test/resource_kit/action/list_directors_with_movies_test.exs index c26abc4..d1cd976 100644 --- a/test/resource_kit/action/list_directors_with_movies_test.exs +++ b/test/resource_kit/action/list_directors_with_movies_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Action.ListDirectorsWithMoviesTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true @director_name "directors" @movie_name "movies" @@ -27,9 +27,11 @@ defmodule ResourceKit.Action.ListDirectorsWithMoviesTest do {"M. Night Shyamalan", ["Trap", "The Watchers"]} ]) + root = URI.new!("actions/list_directors_with_movies.json") params = %{"pagination" => %{"offset" => 0, "limit" => 2}} - assert {:ok, %{"data" => data, "pagination" => pagination}} = ResourceKit.list(action, params) + assert {:ok, %{"data" => data, "pagination" => pagination}} = + ResourceKit.list(action, params, root: root) assert match?( [ diff --git a/test/resource_kit/action/list_directors_with_movies_through_test.exs b/test/resource_kit/action/list_directors_with_movies_through_test.exs index d1b970e..180d465 100644 --- a/test/resource_kit/action/list_directors_with_movies_through_test.exs +++ b/test/resource_kit/action/list_directors_with_movies_through_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Action.ListDirectorsWithMoviesThroughTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true @director_name "directors" @director_columns [ @@ -36,9 +36,11 @@ defmodule ResourceKit.Action.ListDirectorsWithMoviesThroughTest do {"M. Night Shyamalan", ["Trap", "The Watchers"]} ]) + root = URI.new!("actions/list_directors_with_movies_through.json") params = %{"pagination" => %{"offset" => 0, "limit" => 2}} - assert {:ok, %{"data" => data, "pagination" => pagination}} = ResourceKit.list(action, params) + assert {:ok, %{"data" => data, "pagination" => pagination}} = + ResourceKit.list(action, params, root: root) assert match?( [ diff --git a/test/resource_kit/action/list_movies_test.exs b/test/resource_kit/action/list_movies_test.exs index f49dff8..7c16f52 100644 --- a/test/resource_kit/action/list_movies_test.exs +++ b/test/resource_kit/action/list_movies_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Action.ListMoviesTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true @movie_name "movies" @movie_columns [ @@ -68,6 +68,8 @@ defmodule ResourceKit.Action.ListMoviesTest do setup_dataset(@movie_name, @movie_columns, rows) + root = URI.new!("actions/list_movies.json") + filter = %{ "operator" => "eq", "operands" => [ @@ -85,7 +87,7 @@ defmodule ResourceKit.Action.ListMoviesTest do } assert {:ok, %{"data" => data, "pagination" => pagination}} = - ResourceKit.list(action, params) + ResourceKit.list(action, params, root: root) assert match?([%{"标题" => "Longlegs"}, %{"标题" => "Trap"}], data) assert match?(%{"offset" => 0, "limit" => 2, "total" => 3}, pagination) @@ -97,7 +99,7 @@ defmodule ResourceKit.Action.ListMoviesTest do } assert {:ok, %{"data" => data, "pagination" => pagination}} = - ResourceKit.list(action, params) + ResourceKit.list(action, params, root: root) assert match?([%{"标题" => "Twisters"}], data) assert match?(%{"offset" => 2, "limit" => 2, "total" => 3}, pagination) diff --git a/test/resource_kit/action/list_movies_with_director_test.exs b/test/resource_kit/action/list_movies_with_director_test.exs index 78bc860..5c7098c 100644 --- a/test/resource_kit/action/list_movies_with_director_test.exs +++ b/test/resource_kit/action/list_movies_with_director_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Action.ListMoviesWithDirectorTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true @director_name "directors" @movie_name "movies" @@ -30,9 +30,11 @@ defmodule ResourceKit.Action.ListMoviesWithDirectorTest do {"M. Night Shyamalan", ["Trap", "The Watchers"]} ]) + root = URI.new!("actions/list_movies_with_director.json") params = %{"pagination" => %{"offset" => 0, "limit" => 2}} - assert {:ok, %{"data" => data, "pagination" => pagination}} = ResourceKit.list(action, params) + assert {:ok, %{"data" => data, "pagination" => pagination}} = + ResourceKit.list(action, params, root: root) assert match?( [ diff --git a/test/resource_kit/action/list_movies_with_poster_test.exs b/test/resource_kit/action/list_movies_with_poster_test.exs index 86c8ae5..405036a 100644 --- a/test/resource_kit/action/list_movies_with_poster_test.exs +++ b/test/resource_kit/action/list_movies_with_poster_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Action.ListMoviesWithPosterTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true @movie_name "movies" @poster_name "posters" @@ -29,9 +29,11 @@ defmodule ResourceKit.Action.ListMoviesWithPosterTest do {"The Watchers", "https://posters.movie.org/the-watchers.png"} ]) + root = URI.new!("actions/list_movies_with_poster.json") params = %{"pagination" => %{"offset" => 0, "limit" => 2}} - assert {:ok, %{"data" => data, "pagination" => pagination}} = ResourceKit.list(action, params) + assert {:ok, %{"data" => data, "pagination" => pagination}} = + ResourceKit.list(action, params, root: root) assert match?( [ diff --git a/test/resource_kit/action/list_movies_with_poster_through_test.exs b/test/resource_kit/action/list_movies_with_poster_through_test.exs index 99543fe..1c03e35 100644 --- a/test/resource_kit/action/list_movies_with_poster_through_test.exs +++ b/test/resource_kit/action/list_movies_with_poster_through_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Action.ListMoviesWithPosterThroughTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true @movie_name "movies" @movie_columns [ @@ -38,9 +38,11 @@ defmodule ResourceKit.Action.ListMoviesWithPosterThroughTest do {"The Watchers", "https://posters.movie.org/the-watchers.png"} ]) + root = URI.new!("actions/list_movies_with_poster_through.json") params = %{"pagination" => %{"offset" => 0, "limit" => 2}} - assert {:ok, %{"data" => data, "pagination" => pagination}} = ResourceKit.list(action, params) + assert {:ok, %{"data" => data, "pagination" => pagination}} = + ResourceKit.list(action, params, root: root) assert match?( [ diff --git a/test/resource_kit/deref_test.exs b/test/resource_kit/deref_test.exs new file mode 100644 index 0000000..edc05dd --- /dev/null +++ b/test/resource_kit/deref_test.exs @@ -0,0 +1,30 @@ +defmodule ResourceKit.DerefTest do + use ExUnit.Case, async: true + + alias ResourceKit.Deref.Context + alias ResourceKit.Schema.Ref + + @id "volume://action:deployment@/actions/movies/insert.json" + @ctx %Context{current: %Ref{uri: URI.new!(@id)}} + + test "absolute uri" do + uri = "volume://action:deployment@/actions/movies/insert.json" + assert {:ok, ^uri} = absolute(uri) + end + + test "relative uri" do + assert {:ok, "volume://action:deployment@/actions/movies/list.json"} = + absolute("../list.json") + end + + test "relative uri with many parent" do + assert {:ok, "volume://action:deployment@/list.json"} = absolute("../../../../list.json") + end + + defp absolute(uri) do + case ResourceKit.Deref.absolute(%Ref{uri: URI.new!(uri)}, @ctx) do + {:ok, ref} -> {:ok, URI.to_string(ref.uri)} + {:error, reason} -> {:error, reason} + end + end +end diff --git a/test/resource_kit/pipeline/compile/cast_test.exs b/test/resource_kit/pipeline/compile/cast_test.exs index e2b6dd7..c5cd070 100644 --- a/test/resource_kit/pipeline/compile/cast_test.exs +++ b/test/resource_kit/pipeline/compile/cast_test.exs @@ -1,5 +1,5 @@ defmodule ResourceKit.Pipeline.Compile.CastTest do - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true alias ResourceKit.Pipeline.Compile.Cast alias ResourceKit.Pipeline.Compile.Token @@ -38,8 +38,11 @@ defmodule ResourceKit.Pipeline.Compile.CastTest do end defp setup_token(ctx) do - %{action: action} = ctx + %{jsons: jsons, action: action} = ctx - [token: %Token{action: action, assigns: %{action: action}}] + uri = jsons |> Keyword.fetch!(:action) |> URI.new!() + context = %Token.Context{root: uri, current: uri} + + [token: %Token{action: action, context: context, assigns: %{action: action}}] end end diff --git a/test/resource_kit/pipeline/compile/deref_test.exs b/test/resource_kit/pipeline/compile/deref_test.exs index d7bb8d8..55e187c 100644 --- a/test/resource_kit/pipeline/compile/deref_test.exs +++ b/test/resource_kit/pipeline/compile/deref_test.exs @@ -1,19 +1,18 @@ defmodule ResourceKit.Pipeline.Compile.DerefTest do - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true alias ResourceKit.Pipeline.Compile.Deref alias ResourceKit.Pipeline.Compile.Token setup :load_jsons - setup :deref_json describe "call/2" do @tag jsons: [ action: "actions/insert_with_ref_schema.json", schema: "schemas/movies.json" ] - test "deref schema", %{action: action, schema: schema} do - token = %Token{action: action} + test "deref schema", %{schema: schema} = ctx do + token = build_token(ctx) assert %Token{halted: false} = token = Deref.call(token, []) assert {:ok, %{"schema" => ^schema}} = Token.fetch_assign(token, :action) @@ -23,11 +22,17 @@ defmodule ResourceKit.Pipeline.Compile.DerefTest do action: "actions/insert_with_ref_returning.json", returning: "returnings/movies.json" ] - test "deref returning", %{action: action, returning: returning} do - token = %Token{action: action} + test "deref returning", %{returning: returning} = ctx do + token = build_token(ctx) assert %Token{halted: false} = token = Deref.call(token, []) assert {:ok, %{"returning_schema" => ^returning}} = Token.fetch_assign(token, :action) end end + + defp build_token(ctx) do + %{jsons: jsons, action: action} = ctx + uri = jsons |> Keyword.fetch!(:action) |> URI.new!() + %Token{action: action, context: %Token.Context{root: uri, current: uri}} + end end diff --git a/test/resource_kit/pipeline/compile/preload_reference_test.exs b/test/resource_kit/pipeline/compile/preload_reference_test.exs index 5c95584..33fda47 100644 --- a/test/resource_kit/pipeline/compile/preload_reference_test.exs +++ b/test/resource_kit/pipeline/compile/preload_reference_test.exs @@ -1,13 +1,12 @@ defmodule ResourceKit.Pipeline.Compile.PreloadReferenceTest do use Snapshy - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true alias ResourceKit.Pipeline.Compile.Cast alias ResourceKit.Pipeline.Compile.PreloadReference alias ResourceKit.Pipeline.Compile.Token setup :load_jsons - setup :deref_json setup :setup_action @tag jsons: [action: "actions/insert_movie_with_comments_by_ref_association_schema.json"] @@ -21,10 +20,12 @@ defmodule ResourceKit.Pipeline.Compile.PreloadReferenceTest do end defp setup_action(ctx) do - %{action: action} = ctx + %{jsons: jsons, action: action} = ctx + uri = jsons |> Keyword.fetch!(:action) |> URI.new!() + context = %Token.Context{root: uri, current: uri} opts = Cast.init(schema: ResourceKit.Schema.Action.Insert) - [token: Cast.call(%Token{action: action, assigns: %{action: action}}, opts)] + [token: Cast.call(%Token{action: action, context: context, assigns: %{action: action}}, opts)] end end diff --git a/test/resource_kit/pipeline/execute/build_params_test.exs b/test/resource_kit/pipeline/execute/build_params_test.exs index 88f6559..eadd570 100644 --- a/test/resource_kit/pipeline/execute/build_params_test.exs +++ b/test/resource_kit/pipeline/execute/build_params_test.exs @@ -1,17 +1,16 @@ defmodule ResourceKit.Pipeline.Execute.BuildParamsTest do - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true alias ResourceKit.Pipeline.Compile alias ResourceKit.Pipeline.Execute setup :load_jsons - setup :deref_json setup :setup_action @tag jsons: [action: "actions/insert_with_associations.json"] test "works", %{action: action} do + uri = URI.new!("actions/insert_with_associations.json") caption = "Spy x Family Code: White" - ip = "192.168.168.192" params = %{ "caption" => caption, @@ -27,14 +26,14 @@ defmodule ResourceKit.Pipeline.Execute.BuildParamsTest do action: action, references: %{}, params: params, - context: %{"ip" => ip} + context: %Execute.Token.Context{root: uri, current: uri} } assert %Execute.Token{halted: false} = token = Execute.BuildParams.call(token, []) assert {:ok, %{ - "ip" => ^ip, + "uri" => ^uri, "title" => ^caption, "released" => true, "poster" => %{ @@ -51,8 +50,8 @@ defmodule ResourceKit.Pipeline.Execute.BuildParamsTest do @tag jsons: [action: "actions/insert_with_associations.json"] test "association could be nil", %{action: action} do + uri = URI.new!("actions/insert_with_associations.json") caption = "Spy x Family Code: White" - ip = "192.168.168.192" params = %{"caption" => caption, "default_age" => 24} @@ -60,14 +59,14 @@ defmodule ResourceKit.Pipeline.Execute.BuildParamsTest do action: action, references: %{}, params: params, - context: %{"ip" => ip} + context: %Execute.Token.Context{root: uri, current: uri} } assert %Execute.Token{halted: false} = token = Execute.BuildParams.call(token, []) assert {:ok, %{ - "ip" => ^ip, + "uri" => ^uri, "title" => ^caption, "released" => true, "poster" => %{ @@ -80,7 +79,7 @@ defmodule ResourceKit.Pipeline.Execute.BuildParamsTest do @tag jsons: [action: "actions/insert_with_associations.json"] test "column could be nil", %{action: action} do - ip = "192.168.168.192" + uri = URI.new!("actions/insert_with_associations.json") params = %{ "default_age" => 24, @@ -95,14 +94,14 @@ defmodule ResourceKit.Pipeline.Execute.BuildParamsTest do action: action, references: %{}, params: params, - context: %{"ip" => ip} + context: %Execute.Token.Context{root: uri, current: uri} } assert %Execute.Token{halted: false} = token = Execute.BuildParams.call(token, []) assert {:ok, %{ - "ip" => ^ip, + "uri" => ^uri, "title" => nil, "released" => true, "poster" => %{ @@ -118,7 +117,7 @@ defmodule ResourceKit.Pipeline.Execute.BuildParamsTest do end @tag jsons: [action: "actions/insert_movie_with_comments_by_ref_association_schema.json"] - test "association schema with ref", %{action: action} do + test "association schema with ref", ctx do params = %{ "foo" => "foo", "title" => "Spy x Family Code: White", @@ -142,7 +141,7 @@ defmodule ResourceKit.Pipeline.Execute.BuildParamsTest do ] } - token = %Execute.Token{action: action, references: %{}, params: params} + token = build_token(ctx, params) assert %Execute.Token{halted: false} = token = Execute.BuildParams.call(token, []) @@ -166,11 +165,26 @@ defmodule ResourceKit.Pipeline.Execute.BuildParamsTest do end defp setup_action(ctx) do - %{action: action} = ctx + %{jsons: jsons, action: action} = ctx + uri = jsons |> Keyword.fetch!(:action) |> URI.new!() opts = Compile.Cast.init(schema: ResourceKit.Schema.Action.Insert) - token = Compile.Cast.call(%Compile.Token{action: action, assigns: %{action: action}}, opts) + context = %Compile.Token.Context{root: uri, current: uri} + + token = + Compile.Cast.call( + %Compile.Token{action: action, context: context, assigns: %{action: action}}, + opts + ) [action: Compile.Token.fetch_assign!(token, :action)] end + + defp build_token(ctx, params) do + %{jsons: jsons, action: action} = ctx + + uri = jsons |> Keyword.fetch!(:action) |> URI.new!() + context = %Execute.Token.Context{root: uri, current: uri} + %Execute.Token{action: action, references: %{}, params: params, context: context} + end end diff --git a/test/resource_kit/pipeline/execute/build_returning_test.exs b/test/resource_kit/pipeline/execute/build_returning_test.exs index 25845a9..e653bc2 100644 --- a/test/resource_kit/pipeline/execute/build_returning_test.exs +++ b/test/resource_kit/pipeline/execute/build_returning_test.exs @@ -169,10 +169,17 @@ defmodule ResourceKit.Pipeline.Execute.BuildReturningTest do end defp setup_action(ctx) do - %{action: action} = ctx + %{jsons: jsons, action: action} = ctx + uri = jsons |> Keyword.fetch!(:action) |> URI.new!() opts = Compile.Cast.init(schema: ResourceKit.Schema.Action.Insert) - token = Compile.Cast.call(%Compile.Token{action: action, assigns: %{action: action}}, opts) + context = %Compile.Token.Context{root: uri, current: uri} + + token = + Compile.Cast.call( + %Compile.Token{action: action, context: context, assigns: %{action: action}}, + opts + ) [action: Compile.Token.fetch_assign!(token, :action)] end diff --git a/test/resource_kit/pipeline/execute/build_test.exs b/test/resource_kit/pipeline/execute/build_test.exs index f022373..949c5b8 100644 --- a/test/resource_kit/pipeline/execute/build_test.exs +++ b/test/resource_kit/pipeline/execute/build_test.exs @@ -1,5 +1,5 @@ defmodule ResourceKit.Pipeline.Execute.BuildTest do - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true use TypedStruct alias ResourceKit.Pipeline.Execute.Build @@ -24,6 +24,13 @@ defmodule ResourceKit.Pipeline.Execute.BuildTest do end defp build_token(action) do - Token.put_assign(%Token{action: action, references: %{}, params: %{}}, :params, %{}) + uri = URI.new!("uri") + context = %Token.Context{root: uri, current: uri} + + Token.put_assign( + %Token{action: action, references: %{}, params: %{}, context: context}, + :params, + %{} + ) end end diff --git a/test/resource_kit/pipeline/execute/run_test.exs b/test/resource_kit/pipeline/execute/run_test.exs index 3d59664..3216ecd 100644 --- a/test/resource_kit/pipeline/execute/run_test.exs +++ b/test/resource_kit/pipeline/execute/run_test.exs @@ -1,6 +1,6 @@ defmodule ResourceKit.Pipeline.Execute.RunTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true + use ResourceKit.Case.FileLoader, async: true alias ResourceKit.Pipeline.Execute.Run alias ResourceKit.Pipeline.Execute.Token @@ -39,6 +39,13 @@ defmodule ResourceKit.Pipeline.Execute.RunTest do end defp build_token(multi) do - Token.put_assign(%Token{action: %{}, references: %{}, params: %{}}, :multi, multi) + uri = URI.new!("uri") + context = %Token.Context{root: uri, current: uri} + + Token.put_assign( + %Token{action: %{}, references: %{}, params: %{}, context: context}, + :multi, + multi + ) end end diff --git a/test/resource_kit_plug/controller_test.exs b/test/resource_kit_plug/controller_test.exs index 58a692e..8ab582b 100644 --- a/test/resource_kit_plug/controller_test.exs +++ b/test/resource_kit_plug/controller_test.exs @@ -1,6 +1,5 @@ defmodule ResourceKitPlug.ControllerTest do use ResourceKit.Case.Database, async: true - use ResourceKit.Case.Pipeline, async: true @uri "volume://action:deployment@/actions/movies/insert.json" @movie_name "movies" @@ -38,9 +37,7 @@ defmodule ResourceKitPlug.ControllerTest do describe "fetch action" do test "fails" do - expect(ResourceKit.Utils, :deref, fn _ref -> {:error, {"does not exist", []}} end) - - assert_raise PhxJsonRpc.Error.InvalidParams, ~r|does not exist|, fn -> + assert_raise PhxJsonRpc.Error.InvalidParams, ~r|enoent|, fn -> execute(:insert, %{ uri: "volume://action:deployment@/actions/resources/operate.json", params: %{} @@ -51,7 +48,6 @@ defmodule ResourceKitPlug.ControllerTest do describe "run" do setup :setup_tables - setup :deref_json @tag [tables: [{@movie_name, @movie_columns}]] test "message" do diff --git a/test/support/resource_kit/case/pipeline.ex b/test/support/resource_kit/case/pipeline.ex deleted file mode 100644 index 0a5a095..0000000 --- a/test/support/resource_kit/case/pipeline.ex +++ /dev/null @@ -1,24 +0,0 @@ -defmodule ResourceKit.Case.Pipeline do - @moduledoc false - - use ExUnit.CaseTemplate - - using args do - directory = Keyword.get(args, :directory, "test/fixtures") - - quote location: :keep do - use Mimic - use ResourceKit.Case.FileLoader, unquote(args) - - alias ResourceKit.Schema.Ref - - def deref_json(_) do - stub(ResourceKit.Utils, :deref, fn %Ref{uri: uri} -> - {:ok, load_json!(unquote(directory), uri.path)} - end) - - :ok - end - end - end -end diff --git a/test/test_helper.exs b/test/test_helper.exs index eb8e5c2..30178b0 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -2,6 +2,4 @@ Ecto.Adapters.SQL.Sandbox.mode(ResourceKit.Repo, :manual) -Mimic.copy(ResourceKit.Utils) - ExUnit.start(capture_log: true)