2019-12-16 13:20:44 +13:00
|
|
|
defmodule Ash.Test.Filter.FilterTest do
|
2020-06-02 17:47:25 +12:00
|
|
|
@moduledoc false
|
2019-12-16 13:20:44 +13:00
|
|
|
use ExUnit.Case, async: true
|
|
|
|
|
2020-06-19 14:59:30 +12:00
|
|
|
alias Ash.Filter
|
|
|
|
|
2020-10-08 18:22:55 +13:00
|
|
|
require Ash.Query
|
|
|
|
|
2019-12-20 18:30:27 +13:00
|
|
|
defmodule Profile do
|
2020-06-02 17:47:25 +12:00
|
|
|
@moduledoc false
|
2020-06-14 18:39:11 +12:00
|
|
|
use Ash.Resource, data_layer: Ash.DataLayer.Ets
|
|
|
|
|
|
|
|
ets do
|
|
|
|
private?(true)
|
|
|
|
end
|
2019-12-20 18:30:27 +13:00
|
|
|
|
|
|
|
actions do
|
|
|
|
read :default
|
|
|
|
create :default
|
|
|
|
update :default
|
|
|
|
end
|
|
|
|
|
|
|
|
attributes do
|
2021-01-13 09:40:55 +13:00
|
|
|
uuid_primary_key :id
|
2019-12-20 18:30:27 +13:00
|
|
|
attribute :bio, :string
|
2020-12-30 18:49:32 +13:00
|
|
|
attribute :private, :string, private?: true
|
2019-12-20 18:30:27 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
relationships do
|
2019-12-24 17:22:31 +13:00
|
|
|
belongs_to :user, Ash.Test.Filter.FilterTest.User
|
2019-12-20 18:30:27 +13:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-12-16 13:20:44 +13:00
|
|
|
defmodule User do
|
2020-06-02 17:47:25 +12:00
|
|
|
@moduledoc false
|
2020-06-14 18:39:11 +12:00
|
|
|
use Ash.Resource, data_layer: Ash.DataLayer.Ets
|
|
|
|
|
|
|
|
ets do
|
|
|
|
private?(true)
|
|
|
|
end
|
2019-12-16 13:20:44 +13:00
|
|
|
|
|
|
|
actions do
|
|
|
|
read :default
|
|
|
|
create :default
|
2019-12-20 18:30:27 +13:00
|
|
|
update :default
|
2019-12-16 13:20:44 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
attributes do
|
2021-01-13 09:40:55 +13:00
|
|
|
uuid_primary_key :id
|
2019-12-16 13:20:44 +13:00
|
|
|
attribute :name, :string
|
|
|
|
attribute :allow_second_author, :boolean
|
|
|
|
end
|
|
|
|
|
|
|
|
relationships do
|
2020-06-22 16:34:44 +12:00
|
|
|
has_many :posts, Ash.Test.Filter.FilterTest.Post, destination_field: :author1_id
|
2019-12-20 18:30:27 +13:00
|
|
|
|
2020-06-22 16:34:44 +12:00
|
|
|
has_many :second_posts, Ash.Test.Filter.FilterTest.Post, destination_field: :author1_id
|
2019-12-24 17:22:31 +13:00
|
|
|
|
2020-06-05 15:34:44 +12:00
|
|
|
has_one :profile, Profile, destination_field: :user_id
|
2019-12-20 18:30:27 +13:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defmodule PostLink do
|
2020-06-02 17:47:25 +12:00
|
|
|
@moduledoc false
|
2020-06-14 18:39:11 +12:00
|
|
|
use Ash.Resource, data_layer: Ash.DataLayer.Ets
|
|
|
|
|
|
|
|
ets do
|
|
|
|
private?(true)
|
|
|
|
end
|
2019-12-20 18:30:27 +13:00
|
|
|
|
|
|
|
actions do
|
|
|
|
read :default
|
|
|
|
|
|
|
|
create :default
|
|
|
|
update :default
|
|
|
|
end
|
|
|
|
|
|
|
|
relationships do
|
2021-01-13 09:40:55 +13:00
|
|
|
belongs_to :source_post, Ash.Test.Filter.FilterTest.Post,
|
|
|
|
primary_key?: true,
|
|
|
|
required?: true
|
|
|
|
|
|
|
|
belongs_to :destination_post, Ash.Test.Filter.FilterTest.Post,
|
|
|
|
primary_key?: true,
|
|
|
|
required?: true
|
2019-12-16 13:20:44 +13:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defmodule Post do
|
2020-06-02 17:47:25 +12:00
|
|
|
@moduledoc false
|
2020-06-14 18:39:11 +12:00
|
|
|
use Ash.Resource, data_layer: Ash.DataLayer.Ets
|
|
|
|
|
|
|
|
ets do
|
|
|
|
private?(true)
|
|
|
|
end
|
2019-12-16 13:20:44 +13:00
|
|
|
|
|
|
|
actions do
|
|
|
|
read :default
|
|
|
|
|
|
|
|
create :default
|
2019-12-20 18:30:27 +13:00
|
|
|
|
|
|
|
update :default
|
2019-12-16 13:20:44 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
attributes do
|
2021-01-13 09:40:55 +13:00
|
|
|
uuid_primary_key :id
|
2019-12-16 13:20:44 +13:00
|
|
|
attribute :title, :string
|
|
|
|
attribute :contents, :string
|
2019-12-20 18:30:27 +13:00
|
|
|
attribute :points, :integer
|
2021-01-22 09:21:58 +13:00
|
|
|
attribute :approved_at, :utc_datetime
|
2019-12-16 13:20:44 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
relationships do
|
|
|
|
belongs_to :author1, User,
|
|
|
|
destination_field: :id,
|
|
|
|
source_field: :author1_id
|
|
|
|
|
|
|
|
belongs_to :author2, User,
|
|
|
|
destination_field: :id,
|
|
|
|
source_field: :author2_id
|
2019-12-20 18:30:27 +13:00
|
|
|
|
|
|
|
many_to_many :related_posts, __MODULE__,
|
|
|
|
through: PostLink,
|
|
|
|
source_field_on_join_table: :source_post_id,
|
2020-06-22 16:34:44 +12:00
|
|
|
destination_field_on_join_table: :destination_post_id
|
2019-12-16 13:20:44 +13:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-09-20 07:46:34 +12:00
|
|
|
defmodule SoftDeletePost do
|
|
|
|
@moduledoc false
|
|
|
|
use Ash.Resource, data_layer: Ash.DataLayer.Ets
|
|
|
|
|
|
|
|
ets do
|
|
|
|
private? true
|
|
|
|
end
|
|
|
|
|
|
|
|
resource do
|
|
|
|
base_filter is_nil: :deleted_at
|
|
|
|
end
|
|
|
|
|
|
|
|
actions do
|
|
|
|
read :default
|
|
|
|
create :default
|
|
|
|
|
|
|
|
destroy :default do
|
|
|
|
soft? true
|
|
|
|
|
|
|
|
change set_attribute(:deleted_at, &DateTime.utc_now/0)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
attributes do
|
2021-01-13 09:40:55 +13:00
|
|
|
uuid_primary_key :id
|
2020-09-20 07:46:34 +12:00
|
|
|
attribute :deleted_at, :utc_datetime
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-12-16 13:20:44 +13:00
|
|
|
defmodule Api do
|
2020-06-02 17:47:25 +12:00
|
|
|
@moduledoc false
|
2019-12-16 13:20:44 +13:00
|
|
|
use Ash.Api
|
|
|
|
|
2020-06-14 18:39:11 +12:00
|
|
|
resources do
|
|
|
|
resource(Post)
|
2020-09-20 07:46:34 +12:00
|
|
|
resource(SoftDeletePost)
|
2020-06-14 18:39:11 +12:00
|
|
|
resource(User)
|
|
|
|
resource(Profile)
|
|
|
|
resource(PostLink)
|
|
|
|
end
|
2019-12-16 13:20:44 +13:00
|
|
|
end
|
|
|
|
|
2020-07-12 18:25:53 +12:00
|
|
|
import Ash.Changeset
|
|
|
|
|
2019-12-20 18:30:27 +13:00
|
|
|
describe "simple attribute filters" do
|
|
|
|
setup do
|
2020-07-12 18:25:53 +12:00
|
|
|
post1 =
|
|
|
|
Post
|
2020-07-15 17:38:42 +12:00
|
|
|
|> new(%{title: "title1", contents: "contents1", points: 1})
|
2020-07-12 18:25:53 +12:00
|
|
|
|> Api.create!()
|
|
|
|
|
|
|
|
post2 =
|
|
|
|
Post
|
2020-07-15 17:38:42 +12:00
|
|
|
|> new(%{title: "title2", contents: "contents2", points: 2})
|
2020-07-12 18:25:53 +12:00
|
|
|
|> Api.create!()
|
2019-12-20 18:30:27 +13:00
|
|
|
|
|
|
|
%{post1: post1, post2: post2}
|
|
|
|
end
|
|
|
|
|
|
|
|
test "single filter field", %{post1: post1} do
|
2020-05-10 14:23:23 +12:00
|
|
|
assert [^post1] =
|
2020-05-14 03:54:44 +12:00
|
|
|
Post
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(title == ^post1.title)
|
2020-05-14 03:54:44 +12:00
|
|
|
|> Api.read!()
|
2019-12-20 18:30:27 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
test "multiple filter field matches", %{post1: post1} do
|
2020-05-10 14:23:23 +12:00
|
|
|
assert [^post1] =
|
2020-05-14 03:54:44 +12:00
|
|
|
Post
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(title == ^post1.title and contents == ^post1.contents)
|
2020-05-14 03:54:44 +12:00
|
|
|
|> Api.read!()
|
2019-12-20 18:30:27 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
test "no field matches" do
|
2020-05-10 14:23:23 +12:00
|
|
|
assert [] =
|
2020-05-14 03:54:44 +12:00
|
|
|
Post
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(title == "no match")
|
2020-05-14 03:54:44 +12:00
|
|
|
|> Api.read!()
|
2019-12-20 18:30:27 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
test "no field matches single record, but each matches one record", %{
|
|
|
|
post1: post1,
|
|
|
|
post2: post2
|
|
|
|
} do
|
2020-05-10 14:23:23 +12:00
|
|
|
assert [] =
|
2020-05-14 03:54:44 +12:00
|
|
|
Post
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(title == ^post1.title and contents == ^post2.contents)
|
2020-05-14 03:54:44 +12:00
|
|
|
|> Api.read!()
|
2019-12-20 18:30:27 +13:00
|
|
|
end
|
2020-06-29 15:36:38 +12:00
|
|
|
|
|
|
|
test "less than works", %{
|
|
|
|
post1: post1,
|
|
|
|
post2: post2
|
|
|
|
} do
|
|
|
|
assert [^post1] =
|
|
|
|
Post
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(points < 2)
|
2020-06-29 15:36:38 +12:00
|
|
|
|> Api.read!()
|
|
|
|
|
|
|
|
assert [^post1, ^post2] =
|
|
|
|
Post
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(points < 3)
|
2020-06-29 15:36:38 +12:00
|
|
|
|> Ash.Query.sort(points: :asc)
|
|
|
|
|> Api.read!()
|
|
|
|
end
|
|
|
|
|
|
|
|
test "greater than works", %{
|
|
|
|
post1: post1,
|
|
|
|
post2: post2
|
|
|
|
} do
|
|
|
|
assert [^post2] =
|
|
|
|
Post
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(points > 1)
|
2020-06-29 15:36:38 +12:00
|
|
|
|> Api.read!()
|
|
|
|
|
|
|
|
assert [^post1, ^post2] =
|
|
|
|
Post
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(points > 0)
|
2020-06-29 15:36:38 +12:00
|
|
|
|> Ash.Query.sort(points: :asc)
|
|
|
|
|> Api.read!()
|
|
|
|
end
|
2019-12-20 18:30:27 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
describe "relationship filters" do
|
|
|
|
setup do
|
2020-07-12 18:25:53 +12:00
|
|
|
post1 =
|
|
|
|
Post
|
2020-07-15 17:38:42 +12:00
|
|
|
|> new(%{title: "title1", contents: "contents1", points: 1})
|
2020-07-12 18:25:53 +12:00
|
|
|
|> Api.create!()
|
|
|
|
|
|
|
|
post2 =
|
|
|
|
Post
|
2020-07-15 17:38:42 +12:00
|
|
|
|> new(%{title: "title2", contents: "contents2", points: 2})
|
2020-07-12 18:25:53 +12:00
|
|
|
|> Api.create!()
|
2019-12-20 18:30:27 +13:00
|
|
|
|
2019-12-22 21:17:29 +13:00
|
|
|
post3 =
|
2020-07-12 18:25:53 +12:00
|
|
|
Post
|
2020-07-15 17:38:42 +12:00
|
|
|
|> new(%{title: "title3", contents: "contents3", points: 3})
|
2020-07-12 18:25:53 +12:00
|
|
|
|> replace_relationship(:related_posts, [post1, post2])
|
|
|
|
|> Api.create!()
|
2019-12-20 18:30:27 +13:00
|
|
|
|
2019-12-24 17:22:31 +13:00
|
|
|
post4 =
|
2020-07-12 18:25:53 +12:00
|
|
|
Post
|
2020-07-15 17:38:42 +12:00
|
|
|
|> new(%{title: "title4", contents: "contents4", points: 4})
|
2020-07-12 18:25:53 +12:00
|
|
|
|> replace_relationship(:related_posts, [post3])
|
|
|
|
|> Api.create!()
|
2019-12-24 17:22:31 +13:00
|
|
|
|
2020-07-12 18:25:53 +12:00
|
|
|
profile1 =
|
|
|
|
Profile
|
2020-07-15 17:38:42 +12:00
|
|
|
|> new(%{bio: "dope"})
|
2020-07-12 18:25:53 +12:00
|
|
|
|> Api.create!()
|
2019-12-20 18:30:27 +13:00
|
|
|
|
|
|
|
user1 =
|
2020-07-12 18:25:53 +12:00
|
|
|
User
|
2020-07-15 17:38:42 +12:00
|
|
|
|> new(%{name: "broseph"})
|
2020-07-12 18:25:53 +12:00
|
|
|
|> replace_relationship(:posts, [post1, post2])
|
|
|
|
|> replace_relationship(:profile, profile1)
|
|
|
|
|> Api.create!()
|
|
|
|
|
|
|
|
user2 =
|
|
|
|
User
|
2020-07-15 17:38:42 +12:00
|
|
|
|> new(%{name: "broseph"})
|
2020-07-12 18:25:53 +12:00
|
|
|
|> replace_relationship(:posts, [post2])
|
|
|
|
|> Api.create!()
|
|
|
|
|
|
|
|
profile2 =
|
|
|
|
Profile
|
2020-07-15 17:38:42 +12:00
|
|
|
|> new(%{bio: "dope2"})
|
2020-07-12 18:25:53 +12:00
|
|
|
|> replace_relationship(:user, user2)
|
|
|
|
|> Api.create!()
|
2019-12-20 18:30:27 +13:00
|
|
|
|
2019-12-22 22:06:33 +13:00
|
|
|
%{
|
2019-12-24 17:22:31 +13:00
|
|
|
post1: Api.reload!(post1),
|
|
|
|
post2: Api.reload!(post2),
|
|
|
|
post3: Api.reload!(post3),
|
|
|
|
post4: Api.reload!(post4),
|
|
|
|
profile1: Api.reload!(profile1),
|
|
|
|
user1: Api.reload!(user1),
|
|
|
|
user2: Api.reload!(user2),
|
|
|
|
profile2: Api.reload!(profile2)
|
2019-12-22 22:06:33 +13:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2021-01-23 10:41:32 +13:00
|
|
|
test "filtering on a has_one relationship", %{profile2: profile2, user2: %{id: user2_id}} do
|
|
|
|
assert [%{id: ^user2_id}] =
|
2020-05-14 03:54:44 +12:00
|
|
|
User
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(profile == ^profile2.id)
|
2020-05-14 03:54:44 +12:00
|
|
|
|> Api.read!()
|
2019-12-24 17:22:31 +13:00
|
|
|
end
|
|
|
|
|
2021-01-23 10:41:32 +13:00
|
|
|
test "filtering on a belongs_to relationship", %{profile1: %{id: id}, user1: user1} do
|
|
|
|
assert [%{id: ^id}] =
|
2020-05-14 03:54:44 +12:00
|
|
|
Profile
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(user == ^user1.id)
|
2020-05-14 03:54:44 +12:00
|
|
|
|> Api.read!()
|
2019-12-24 17:22:31 +13:00
|
|
|
end
|
|
|
|
|
2021-01-23 10:41:32 +13:00
|
|
|
test "filtering on a has_many relationship", %{user2: %{id: user2_id}, post2: post2} do
|
|
|
|
assert [%{id: ^user2_id}] =
|
2020-05-14 03:54:44 +12:00
|
|
|
User
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(posts == ^post2.id)
|
2020-05-14 03:54:44 +12:00
|
|
|
|> Api.read!()
|
2019-12-24 17:22:31 +13:00
|
|
|
end
|
|
|
|
|
2021-01-23 10:41:32 +13:00
|
|
|
test "filtering on a many_to_many relationship", %{post4: %{id: post4_id}, post3: post3} do
|
|
|
|
assert [%{id: ^post4_id}] =
|
2020-05-14 03:54:44 +12:00
|
|
|
Post
|
2020-10-08 18:22:55 +13:00
|
|
|
|> Ash.Query.filter(related_posts == ^post3.id)
|
2020-05-14 03:54:44 +12:00
|
|
|
|> Api.read!()
|
2019-12-24 17:22:31 +13:00
|
|
|
end
|
2019-12-16 13:20:44 +13:00
|
|
|
end
|
2020-06-19 14:59:30 +12:00
|
|
|
|
|
|
|
describe "filter subset logic" do
|
|
|
|
test "can detect a filter is a subset of itself" do
|
2020-07-09 18:55:09 +12:00
|
|
|
filter = Filter.parse!(Post, %{points: 1})
|
2020-06-19 14:59:30 +12:00
|
|
|
|
|
|
|
assert Filter.strict_subset_of?(filter, filter)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "can detect a filter is a subset of itself *and* something else" do
|
2020-07-09 18:55:09 +12:00
|
|
|
filter = Filter.parse!(Post, points: 1)
|
2020-06-19 14:59:30 +12:00
|
|
|
|
|
|
|
candidate = Filter.add_to_filter!(filter, title: "Title")
|
|
|
|
|
|
|
|
assert Filter.strict_subset_of?(filter, candidate)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "can detect a filter is not a subset of itself *or* something else" do
|
2020-07-09 18:55:09 +12:00
|
|
|
filter = Filter.parse!(Post, points: 1)
|
2020-06-19 14:59:30 +12:00
|
|
|
|
2020-07-23 17:09:59 +12:00
|
|
|
candidate = Filter.add_to_filter!(filter, [title: "Title"], :or)
|
2020-06-19 14:59:30 +12:00
|
|
|
|
|
|
|
refute Filter.strict_subset_of?(filter, candidate)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "can detect a filter is a subset based on a simplification" do
|
2020-07-09 18:55:09 +12:00
|
|
|
filter = Filter.parse!(Post, points: [in: [1, 2]])
|
2020-06-19 14:59:30 +12:00
|
|
|
|
2020-07-09 18:55:09 +12:00
|
|
|
candidate = Filter.parse!(Post, points: 1)
|
2020-06-19 14:59:30 +12:00
|
|
|
|
|
|
|
assert Filter.strict_subset_of?(filter, candidate)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "can detect a filter is not a subset based on a simplification" do
|
2020-07-09 18:55:09 +12:00
|
|
|
filter = Filter.parse!(Post, points: [in: [1, 2]])
|
2020-06-19 14:59:30 +12:00
|
|
|
|
2020-07-09 18:55:09 +12:00
|
|
|
candidate = Filter.parse!(Post, points: 3)
|
2020-06-19 14:59:30 +12:00
|
|
|
|
|
|
|
refute Filter.strict_subset_of?(filter, candidate)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "can detect a more complicated scenario" do
|
2020-10-06 17:58:06 +13:00
|
|
|
filter = Filter.parse!(Post, or: [[points: [in: [1, 2, 3]]], [points: 4], [points: 5]])
|
2020-06-19 14:59:30 +12:00
|
|
|
|
2020-10-06 17:58:06 +13:00
|
|
|
candidate = Filter.parse!(Post, or: [[points: 1], [points: 3], [points: 5]])
|
2020-06-19 14:59:30 +12:00
|
|
|
|
|
|
|
assert Filter.strict_subset_of?(filter, candidate)
|
|
|
|
end
|
|
|
|
|
2020-10-06 17:58:06 +13:00
|
|
|
test "can detect less than and greater than closing in on a single value" do
|
|
|
|
filter = Filter.parse!(Post, points: [greater_than: 1, less_than: 3])
|
|
|
|
|
|
|
|
candidate = Filter.parse!(Post, points: 2)
|
|
|
|
|
|
|
|
assert Filter.strict_subset_of?(filter, candidate)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "doesnt have false positives on less than and greater than closing in on a single value" do
|
|
|
|
filter = Filter.parse!(Post, points: [greater_than: 1, less_than: 3])
|
|
|
|
|
|
|
|
candidate = Filter.parse!(Post, points: 4)
|
|
|
|
|
|
|
|
refute Filter.strict_subset_of?(filter, candidate)
|
|
|
|
end
|
|
|
|
|
2020-06-19 14:59:30 +12:00
|
|
|
test "understands unrelated negations" do
|
2020-10-06 17:58:06 +13:00
|
|
|
filter = Filter.parse!(Post, or: [[points: [in: [1, 2, 3]]], [points: 4], [points: 5]])
|
2020-06-19 14:59:30 +12:00
|
|
|
|
2020-10-06 17:58:06 +13:00
|
|
|
candidate =
|
|
|
|
Filter.parse!(Post, or: [[points: 1], [points: 3], [points: 5]], not: [points: 7])
|
2020-06-19 14:59:30 +12:00
|
|
|
|
|
|
|
assert Filter.strict_subset_of?(filter, candidate)
|
|
|
|
end
|
2020-06-22 15:26:47 +12:00
|
|
|
|
|
|
|
test "understands relationship filter subsets" do
|
|
|
|
id1 = Ecto.UUID.generate()
|
|
|
|
id2 = Ecto.UUID.generate()
|
2020-07-09 18:55:09 +12:00
|
|
|
filter = Filter.parse!(Post, author1: [id: [in: [id1, id2]]])
|
2020-06-22 15:26:47 +12:00
|
|
|
|
2020-07-09 18:55:09 +12:00
|
|
|
candidate = Filter.parse!(Post, author1: id1)
|
2020-06-22 15:26:47 +12:00
|
|
|
|
|
|
|
assert Filter.strict_subset_of?(filter, candidate)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "understands relationship filter subsets when a value coincides with the join field" do
|
|
|
|
id1 = Ecto.UUID.generate()
|
|
|
|
id2 = Ecto.UUID.generate()
|
2020-07-09 18:55:09 +12:00
|
|
|
filter = Filter.parse!(Post, author1: [id: [in: [id1, id2]]])
|
2020-06-22 15:26:47 +12:00
|
|
|
|
2020-07-09 18:55:09 +12:00
|
|
|
candidate = Filter.parse!(Post, author1_id: id1)
|
2020-06-22 15:26:47 +12:00
|
|
|
|
|
|
|
assert Filter.strict_subset_of?(filter, candidate)
|
|
|
|
end
|
2020-06-19 14:59:30 +12:00
|
|
|
end
|
2020-09-20 07:46:34 +12:00
|
|
|
|
2020-12-30 18:49:32 +13:00
|
|
|
describe "parse_input" do
|
|
|
|
test "parse_input works when no private attributes are used" do
|
|
|
|
Ash.Filter.parse_input!(Profile, bio: "foo")
|
|
|
|
end
|
|
|
|
|
|
|
|
test "parse_input fails when a private attribute is used" do
|
|
|
|
Ash.Filter.parse!(Profile, private: "private")
|
|
|
|
|
|
|
|
assert_raise(Ash.Error.Query.NoSuchAttributeOrRelationship, fn ->
|
|
|
|
Ash.Filter.parse_input!(Profile, private: "private")
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-09-20 07:46:34 +12:00
|
|
|
describe "base_filter" do
|
|
|
|
test "resources that apply to the base filter are returned" do
|
|
|
|
%{id: id} =
|
|
|
|
SoftDeletePost
|
|
|
|
|> new(%{})
|
|
|
|
|> Api.create!()
|
|
|
|
|
|
|
|
assert [%{id: ^id}] = Api.read!(SoftDeletePost)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "resources that don't apply to the base filter are not returned" do
|
|
|
|
SoftDeletePost
|
|
|
|
|> new(%{})
|
|
|
|
|> Api.create!()
|
|
|
|
|> Api.destroy()
|
|
|
|
|
|
|
|
assert [] = Api.read!(SoftDeletePost)
|
|
|
|
end
|
|
|
|
end
|
2021-01-22 09:21:58 +13:00
|
|
|
|
|
|
|
describe "calls in filters" do
|
|
|
|
test "calls are evaluated and can be used in predicates" do
|
|
|
|
post1 =
|
|
|
|
Post
|
|
|
|
|> new(%{title: "title1", contents: "contents1", points: 2})
|
|
|
|
|> Api.create!()
|
|
|
|
|
|
|
|
post_id = post1.id
|
|
|
|
|
|
|
|
assert [%Post{id: ^post_id}] =
|
|
|
|
Post
|
|
|
|
|> Ash.Query.filter(points + 1 == 3)
|
|
|
|
|> Api.read!()
|
|
|
|
end
|
|
|
|
|
|
|
|
test "function calls are evaluated properly" do
|
|
|
|
post1 =
|
|
|
|
Post
|
|
|
|
|> new(%{title: "title1", approved_at: Timex.shift(Timex.now(), weeks: -1)})
|
|
|
|
|> Api.create!()
|
|
|
|
|
|
|
|
Post
|
|
|
|
|> new(%{title: "title1", approved_at: Timex.shift(Timex.now(), weeks: -4)})
|
|
|
|
|> Api.create!()
|
|
|
|
|
|
|
|
post_id = post1.id
|
|
|
|
|
|
|
|
assert [%Post{id: ^post_id}] =
|
|
|
|
Post
|
|
|
|
|> Ash.Query.filter(approved_at > ago(2, :week))
|
|
|
|
|> Api.read!()
|
|
|
|
end
|
|
|
|
end
|
2019-12-16 13:20:44 +13:00
|
|
|
end
|