Skip to content

Commit

Permalink
tests and fixes for list_works/1
Browse files Browse the repository at this point in the history
  • Loading branch information
zkat committed Feb 20, 2024
1 parent e1c2267 commit 33d3b79
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 11 deletions.
4 changes: 3 additions & 1 deletion lib/banchan/accounts/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ defmodule Banchan.Accounts.User do
:roles,
:confirmed_at,
:totp_secret,
:totp_activated
:totp_activated,
:mature_ok,
:muted
])
|> validate_handle(:handle)
|> validate_required([:email])
Expand Down
2 changes: 1 addition & 1 deletion lib/banchan/studios/studios.ex
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ defmodule Banchan.Studios do
be unable to further interact with commissions associated with this Studio,
request new commissions, or even view the Studio profile.
"""
def block_user(%User{} = actor, %Studio{} = studio, %User{} = user, attrs) do
def block_user(%User{} = actor, %Studio{} = studio, %User{} = user, attrs \\ %{}) do
Ecto.Multi.new()
|> Ecto.Multi.run(:checked_actor, fn _repo, _changes ->
check_studio_member(studio, actor, [])
Expand Down
23 changes: 15 additions & 8 deletions lib/banchan/works/works.ex
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,17 @@ defmodule Banchan.Works do
## Getting/Listing

@doc """
Über query for listing works across various use cases on the site.
Accepts several options that affect its behavior.
Über query for listing works across various use cases on the site. Accepts
several options that affect its behavior.
## Options
* `:page` - Page number to return results for. Defaults to 1.
* `:page_size` - Number of results to return per page. Defaults to 20.
* `:query` - Websearch-syntax search query used to match against the
work's `search_vector`. Defaults to nil.
* `:client` - Filter works only to those whose client is a given
`%User{}`.
* `:studio` - Filter works only to those belonging to the given
`%Studio{}`.
* `:offering` - Filter works only to those belonging to the given
Expand All @@ -95,12 +97,12 @@ defmodule Banchan.Works do
* Remove works from studios that have blocked this user.
* `:order_by` - The order to sort the offerings by. Some of these will
also filter some offerings out.
* `:featured` - Orders by the newest work/studio pair. Also filters
out any works that don't have a decription.
* `:featured` - Orders by the newest work/studio pair. Also filters out
any works that don't have a decription.
* `:oldest` - Show oldest works first.
* `:newest` - Show newest works first.
* `:related_to` - Accepts another `%Work{}` and returns works that
are related to it. Defaults to nil.
* `:related_to` - Accepts another `%Work{}` and returns works that are
related to it. Defaults to nil.
"""
def list_works(opts \\ []) do
Expand Down Expand Up @@ -211,7 +213,12 @@ defmodule Banchan.Works do
)
|> where(
[work: w, current_user: current_user, artist: artist],
artist == current_user or w.client == current_user or w.private == false
artist == current_user or w.client_id == current_user.id or w.private == false
)
|> where(
[work: w, current_user: current_user, artist: artist],
artist == current_user or is_nil(current_user.muted) or
not fragment("(?).muted_filter_query @@ (?).search_vector", current_user, w)
)
|> join(:left, [studio: s], block in assoc(s, :blocklist), as: :blocklist)
|> where(
Expand Down Expand Up @@ -257,7 +264,7 @@ defmodule Banchan.Works do

defp filter_related_to(q, opts) do
case Keyword.fetch(opts, :related_to) do
{:ok, %Offering{} = related} ->
{:ok, %Work{} = related} ->
q
|> join(:inner, [work: w], rel in Work,
on: rel.id == ^related.id and rel.id != w.id,
Expand Down
179 changes: 178 additions & 1 deletion test/banchan/works_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ defmodule Banchan.WorksTest do
use Banchan.DataCase

import Banchan.AccountsFixtures
import Banchan.CommissionsFixtures
import Banchan.OfferingsFixtures
import Banchan.StudiosFixtures
import Banchan.WorksFixtures

alias Ecto.Adapters.SQL.Sandbox

alias Banchan.Studios
alias Banchan.Uploads
alias Banchan.Works
alias Banchan.Works.Work
Expand All @@ -26,10 +29,184 @@ defmodule Banchan.WorksTest do
test "returns all works" do

Check failure on line 29 in test/banchan/works_test.exs

View workflow job for this annotation

GitHub Actions / Unit Tests (1.14.5, 25)

test list_works/1 returns all works (Banchan.WorksTest)
work = work_fixture()

assert Works.list_works().entries
assert Works.list_works(page_size: 200).entries
|> Enum.map(&Repo.preload(&1, :uploads))
|> Enum.find(&(&1 == work))
end

test "supports free text query" do

Check failure on line 37 in test/banchan/works_test.exs

View workflow job for this annotation

GitHub Actions / Unit Tests (1.14.5, 25)

test list_works/1 supports free text query (Banchan.WorksTest)
work1 = work_fixture(%{description: "foo"})
work2 = work_fixture(%{title: "foo"})
work3 = work_fixture(%{tags: ["foo"]})
work4 = work_fixture(%{title: "bar", description: "bar"})

listing = Works.list_works(query: "foo", page_size: 200).entries

assert Enum.find(listing, &(&1.id == work1.id))
assert Enum.find(listing, &(&1.id == work2.id))
assert Enum.find(listing, &(&1.id == work3.id))
assert Enum.find(listing, &(&1.id == work4.id)) == nil
end

test "supports filtering by studio" do
artist = user_fixture(%{roles: [:artist]})
studio = studio_fixture([artist])

work1 = work_fixture(%{artist: artist, studio: studio})
work2 = work_fixture()

listing = Works.list_works(studio: studio, page_size: 200).entries

assert Enum.find(listing, &(&1.id == work1.id))
assert Enum.find(listing, &(&1.id == work2.id)) == nil
end

test "supports filtering by client" do
client = user_fixture()

work1 = work_fixture(%{client: client})
work2 = work_fixture()

listing = Works.list_works(client: client, page_size: 200).entries

assert Enum.find(listing, &(&1.id == work1.id))
assert Enum.find(listing, &(&1.id == work2.id)) == nil
end

test "supports filtering by offering" do

Check failure on line 76 in test/banchan/works_test.exs

View workflow job for this annotation

GitHub Actions / Unit Tests (1.14.5, 25)

test list_works/1 supports filtering by offering (Banchan.WorksTest)
artist = user_fixture(%{roles: [:artist]})
studio = studio_fixture([artist])
offering = offering_fixture(studio)

work1 = work_fixture(%{artist: artist, studio: studio, offering: offering})
work2 = work_fixture()

listing = Works.list_works(offering: offering, page_size: 200).entries

assert Enum.find(listing, &(&1.id == work1.id))
assert Enum.find(listing, &(&1.id == work2.id)) == nil
end

test "supports filtering by commission" do

Check failure on line 90 in test/banchan/works_test.exs

View workflow job for this annotation

GitHub Actions / Unit Tests (1.14.5, 25)

test list_works/1 supports filtering by commission (Banchan.WorksTest)
artist = user_fixture(%{roles: [:artist]})
studio = studio_fixture([artist])
offering = offering_fixture(studio)

commission =
commission_fixture(%{
artist: artist,
studio: studio,
offering: offering
})

work1 = work_fixture(%{artist: artist, studio: studio, commission: commission})
work2 = work_fixture()

listing = Works.list_works(commission: commission, page_size: 200).entries

assert Enum.find(listing, &(&1.id == work1.id))
assert Enum.find(listing, &(&1.id == work2.id)) == nil
end

test "filters out works if studio has current user blocked" do

Check failure on line 111 in test/banchan/works_test.exs

View workflow job for this annotation

GitHub Actions / Unit Tests (1.14.5, 25)

test list_works/1 filters out works if studio has current user blocked (Banchan.WorksTest)
blocked_user = user_fixture()
artist = user_fixture(%{roles: [:artist]})
studio = studio_fixture([artist])

Studios.block_user(artist, studio, blocked_user)

blocked_work = work_fixture(%{artist: artist, studio: studio})

listing = Works.list_works(current_user: blocked_user, page_size: 200).entries

assert Enum.find(listing, &(&1.id == blocked_work.id)) == nil
end

test "filters out works based on mature setting" do

Check failure on line 125 in test/banchan/works_test.exs

View workflow job for this annotation

GitHub Actions / Unit Tests (1.14.5, 25)

test list_works/1 filters out works based on mature setting (Banchan.WorksTest)
user = user_fixture(%{mature_ok: false})
mature_user = user_fixture(%{mature_ok: true})
work = work_fixture(%{mature: true})

no_user_listing = Works.list_works(page_size: 200).entries
assert Enum.find(no_user_listing, &(&1.id == work.id)) == nil

with_user = Works.list_works(current_user: user, page_size: 200).entries
assert Enum.find(with_user, &(&1.id == work.id)) == nil

with_mature_user = Works.list_works(current_user: mature_user, page_size: 200).entries
assert Enum.find(with_mature_user, &(&1.id == work.id))
end

test "filters out works based on current user's mutes" do
user = user_fixture()
muted_user = user_fixture(%{muted: "foo bar baz"})

work1 = work_fixture(%{title: "foo"})
work2 = work_fixture(%{description: "bar"})
work3 = work_fixture(%{tags: ["baz"]})

no_user_listing = Works.list_works(page_size: 200).entries
assert Enum.find(no_user_listing, &(&1.id == work1.id))
assert Enum.find(no_user_listing, &(&1.id == work2.id))
assert Enum.find(no_user_listing, &(&1.id == work3.id))

user_listing = Works.list_works(current_user: user, page_size: 200).entries
assert Enum.find(user_listing, &(&1.id == work1.id))
assert Enum.find(user_listing, &(&1.id == work2.id))
assert Enum.find(user_listing, &(&1.id == work3.id))

muted_user_listing = Works.list_works(current_user: muted_user, page_size: 200).entries
assert Enum.find(muted_user_listing, &(&1.id == work1.id)) == nil
assert Enum.find(muted_user_listing, &(&1.id == work2.id)) == nil
assert Enum.find(muted_user_listing, &(&1.id == work3.id)) == nil
end

test "does not list private works unless there's a current user who's either an artist for the studio, or the client" do

Check failure on line 164 in test/banchan/works_test.exs

View workflow job for this annotation

GitHub Actions / Unit Tests (1.14.5, 25)

test list_works/1 does not list private works unless there's a current user who's either an artist for the studio, or the client (Banchan.WorksTest)
user = user_fixture()
client = user_fixture()
artist = user_fixture()
studio = studio_fixture([artist])

private_work =
work_fixture(%{
artist: artist,
studio: studio,
client: client,
private: true
})

no_user_listing = Works.list_works(page_size: 200).entries
assert Enum.find(no_user_listing, &(&1.id == private_work.id)) == nil

user_listing = Works.list_works(current_user: user, page_size: 200).entries
assert Enum.find(user_listing, &(&1.id == private_work.id)) == nil

client_listing = Works.list_works(current_user: client, page_size: 200).entries
assert Enum.find(client_listing, &(&1.id == private_work.id))

artist_listing = Works.list_works(current_user: artist, page_size: 200).entries
assert Enum.find(artist_listing, &(&1.id == private_work.id))
end

test "supports listing related Works" do

Check failure on line 191 in test/banchan/works_test.exs

View workflow job for this annotation

GitHub Actions / Unit Tests (1.14.5, 25)

test list_works/1 supports listing related Works (Banchan.WorksTest)
unrelated_work = work_fixture()
work1 = work_fixture(%{title: "foo", description: "bar", tags: ["bar", "baz"]})
work2 = work_fixture(%{title: "foo"})
work3 = work_fixture(%{description: "bar"})
work4 = work_fixture(%{tags: ["bar"]})
work5 = work_fixture(%{tags: ["baz"]})
work6 = work_fixture(%{title: "bar", description: "foo"})

listing = Works.list_works(related_to: work1, page_size: 200).entries

assert Enum.find(listing, &(&1.id == unrelated_work.id)) == nil
assert Enum.find(listing, &(&1.id == work1.id)) == nil
assert Enum.find(listing, &(&1.id == work2.id))
assert Enum.find(listing, &(&1.id == work3.id))
assert Enum.find(listing, &(&1.id == work4.id))
assert Enum.find(listing, &(&1.id == work5.id))
assert Enum.find(listing, &(&1.id == work6.id))
end
end

describe "get_work!/1" do
Expand Down

0 comments on commit 33d3b79

Please sign in to comment.