ash/test/actions/generic_actions_test.exs

143 lines
3.4 KiB
Elixir

defmodule Ash.Test.Actions.GenericActionsTest do
@moduledoc false
use ExUnit.Case, async: true
alias Ash.Test.Domain, as: Domain
defmodule PassingFredOrGeorge do
use Ash.Policy.SimpleCheck
def describe(_), do: "is one of the twins"
def match?(_, %{action_input: action_input}, _) do
String.downcase(action_input.arguments.name) in ["fred", "george"]
end
end
defmodule Post do
@moduledoc false
use Ash.Resource,
domain: Domain,
data_layer: Ash.DataLayer.Ets,
authorizers: [Ash.Policy.Authorizer]
ets do
private?(true)
end
actions do
default_accept :*
defaults [:read, :destroy, create: :*, update: :*]
action :hello, :string do
argument :name, :string, allow_nil?: false
run(fn input, _context ->
{:ok, "Hello #{input.arguments.name}"}
end)
end
action :do_nothing do
run fn _, _ -> :ok end
end
end
attributes do
uuid_primary_key :id
attribute(:title, :string, allow_nil?: false, public?: true)
timestamps()
end
policies do
policy action(:hello) do
authorize_if PassingFredOrGeorge
end
end
end
describe "generic actions can be called" do
test "generic actions can be run" do
assert "Hello fred" =
Post
|> Ash.ActionInput.for_action(:hello, %{name: "fred"})
|> Ash.run_action!()
end
test "generic actions validate their input" do
assert {:error, %Ash.Error.Invalid{}} =
Post
|> Ash.ActionInput.for_action(:hello, %{name: %{a: 10}})
|> Ash.run_action()
assert_raise Ash.Error.Invalid, ~r/Invalid Error/, fn ->
Post
|> Ash.ActionInput.for_action(:hello, %{name: %{a: 10}})
|> Ash.run_action!()
end
end
test "generic actions don't accept unknown keys" do
assert {:error, %Ash.Error.Invalid{}} =
Post
|> Ash.ActionInput.for_action(:hello, %{name: "fred", one: 1})
|> Ash.run_action()
assert_raise Ash.Error.Invalid, ~r/Invalid Error/, fn ->
Post
|> Ash.ActionInput.for_action(:hello, %{name: "fred", one: 1})
|> Ash.run_action!()
end
end
end
describe "authorization" do
test "generic actions can be authorized" do
assert "Hello fred" =
Post
|> Ash.ActionInput.for_action(:hello, %{name: "fred"})
|> Ash.run_action!(authorize?: true)
assert_raise Ash.Error.Forbidden, ~r/Forbidden/, fn ->
Post
|> Ash.ActionInput.for_action(:hello, %{name: "mike"})
|> Ash.run_action!(authorize?: true)
end
end
end
describe "generic actions wrapping a reactor" do
defmodule EchoReactor do
@moduledoc false
use Reactor
input :input
step :echo do
argument :echo, input(:input)
run &Map.fetch(&1, :echo)
end
end
defmodule EchoResource do
@moduledoc false
use Ash.Resource, domain: Domain
actions do
action :echo, :string do
argument :input, :string, allow_nil?: false
run EchoReactor
end
end
code_interface do
define :echo, args: [:input]
end
end
test "it automatically runs the reactor" do
assert {:ok, "Marty"} = EchoResource.echo("Marty")
end
end
end