How to test policies correctly?

Hello, I am confused a tiny bit about policy testing. As an example, right now what I do is the following:
assert match?({:error, _}, Accounts.get_user_by_email(users.admin.email, actor: users.user))
assert match?({:error, _}, Accounts.get_user_by_email(users.admin.email, actor: users.user))
Previously, I was doing this:
assert Accounts.get_user_by_email(
users.admin.email,
actor: users.user,
not_found_error?: false
) == {:ok, nil}
assert Accounts.get_user_by_email(
users.admin.email,
actor: users.user,
not_found_error?: false
) == {:ok, nil}
Both pass, but I am unsure as to what I should be doing... Maybe matching on the type of error is better (not found, forbidden, etc), instead of matching on any error?
Solution:
You can use Ash.can or for code interfaces their can_ variant
Jump to solution
6 Replies
Solution
ZachDaniel
ZachDaniel•2mo ago
You can use Ash.can or for code interfaces their can_ variant
ZachDaniel
ZachDaniel•2mo ago
And assert on the result of that You can provide data to assert that a particular record wouldn't or would be seen by that request refute Accounts.can_get_user_by_email?(actor, users.admin.email, actor: actor, data: users.admin)
theopechli
theopechliOP•2mo ago
You're right, forgot about that yea, I understand. Thanks!
theopechli
theopechliOP•2mo ago
I am just gonna drop one more comment here if anyone in the future reads this. The can_ variant doesn't work exactly as I would expect due to the default acceses_type (filter). This means that it returns a not found error when I call my read action, which in turn means that can_ actually returns true even when I would expect it to return false.
Assertion with == failed
code: assert Accounts.can_get_user_by_email?(users.admin.email, actor: users.user) == false
left: true
right: false
Assertion with == failed
code: assert Accounts.can_get_user_by_email?(users.admin.email, actor: users.user) == false
left: true
right: false
Assertion with == failed
code: assert Accounts.get_user_by_email(users.admin.email, actor: users.user) == nil
left: {:error, %Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{primary_key: nil, resource: Brioche.Accounts.User, splode: Ash.Error, bread_crumbs: [], vars: [], path: [], stacktrace: #Splode.Stacktrace<>, class: :invalid}]}}
right: nil
Assertion with == failed
code: assert Accounts.get_user_by_email(users.admin.email, actor: users.user) == nil
left: {:error, %Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{primary_key: nil, resource: Brioche.Accounts.User, splode: Ash.Error, bread_crumbs: [], vars: [], path: [], stacktrace: #Splode.Stacktrace<>, class: :invalid}]}}
right: nil
All in all, I am just gonna match on the error probably 😛
ZachDaniel
ZachDaniel•2mo ago
That's the purpose of the data option It means "if you run this action does it return specifically this thing" Causing it to return false
theopechli
theopechliOP•2mo ago
Hmmm, I'll read the docs about it later again. Thanks for your help!

Did you find this page helpful?