Adding likes to tweets
This commit is contained in:
117
test/mixer/posts/tweet_like_test.exs
Normal file
117
test/mixer/posts/tweet_like_test.exs
Normal file
@@ -0,0 +1,117 @@
|
||||
defmodule Mixer.Posts.TweetLikeTest do
|
||||
use Mixer.DataCase, async: true
|
||||
|
||||
import Ash.Expr
|
||||
|
||||
alias Mixer.Accounts.User
|
||||
alias Mixer.Posts.Tweet
|
||||
alias Mixer.Posts.TweetLike
|
||||
|
||||
describe "tweet likes" do
|
||||
test "a user can like a tweet once and liked_by_me reflects the actor" do
|
||||
user = user_fixture("liker@example.com")
|
||||
tweet = tweet_fixture(user, "first post")
|
||||
|
||||
assert {:ok, liked_tweet} =
|
||||
tweet
|
||||
|> Ash.Changeset.for_update(:like, %{}, actor: user)
|
||||
|> Ash.update()
|
||||
|
||||
assert liked_tweet.likes == 1
|
||||
assert count_likes(tweet.id) == 1
|
||||
|
||||
tweet_for_actor =
|
||||
Tweet
|
||||
|> Ash.get!(tweet.id, actor: user, load: [:liked_by_me], authorize?: false)
|
||||
|
||||
refute Ash.ForbiddenField.forbidden?(tweet_for_actor.liked_by_me)
|
||||
assert tweet_for_actor.liked_by_me
|
||||
|
||||
tweet_without_actor =
|
||||
Tweet
|
||||
|> Ash.get!(tweet.id, load: [:liked_by_me], authorize?: false)
|
||||
|
||||
refute Ash.ForbiddenField.forbidden?(tweet_without_actor.liked_by_me)
|
||||
refute tweet_without_actor.liked_by_me
|
||||
end
|
||||
|
||||
test "liking the same tweet twice does not create duplicate rows or inflate the counter" do
|
||||
user = user_fixture("duplicate@example.com")
|
||||
tweet = tweet_fixture(user, "duplicate like test")
|
||||
|
||||
assert {:ok, _tweet} =
|
||||
tweet
|
||||
|> Ash.Changeset.for_update(:like, %{}, actor: user)
|
||||
|> Ash.update()
|
||||
|
||||
assert {:ok, liked_again} =
|
||||
tweet
|
||||
|> Ash.Changeset.for_update(:like, %{}, actor: user)
|
||||
|> Ash.update()
|
||||
|
||||
assert liked_again.likes == 1
|
||||
assert count_likes(tweet.id) == 1
|
||||
end
|
||||
|
||||
test "unliking removes the relation and decrements the counter without going negative" do
|
||||
user = user_fixture("unlike@example.com")
|
||||
tweet = tweet_fixture(user, "unlike test")
|
||||
|
||||
tweet
|
||||
|> Ash.Changeset.for_update(:like, %{}, actor: user)
|
||||
|> Ash.update!()
|
||||
|
||||
assert {:ok, unliked_tweet} =
|
||||
tweet
|
||||
|> Ash.Changeset.for_update(:unlike, %{}, actor: user)
|
||||
|> Ash.update()
|
||||
|
||||
assert unliked_tweet.likes == 0
|
||||
assert count_likes(tweet.id) == 0
|
||||
|
||||
assert {:ok, still_unliked} =
|
||||
tweet
|
||||
|> Ash.Changeset.for_update(:unlike, %{}, actor: user)
|
||||
|> Ash.update()
|
||||
|
||||
assert still_unliked.likes == 0
|
||||
assert count_likes(tweet.id) == 0
|
||||
end
|
||||
|
||||
test "guests cannot like tweets" do
|
||||
owner = user_fixture("owner@example.com")
|
||||
tweet = tweet_fixture(owner, "guest like test")
|
||||
|
||||
assert {:error, error} =
|
||||
tweet
|
||||
|> Ash.Changeset.for_update(:like, %{})
|
||||
|> Ash.update()
|
||||
|
||||
assert Exception.message(error) =~ "forbidden"
|
||||
assert count_likes(tweet.id) == 0
|
||||
end
|
||||
end
|
||||
|
||||
defp user_fixture(email) do
|
||||
User
|
||||
|> Ash.Changeset.for_create(:register_with_password, %{
|
||||
email: email,
|
||||
password: "password1234",
|
||||
password_confirmation: "password1234"
|
||||
})
|
||||
|> Ash.create!()
|
||||
end
|
||||
|
||||
defp tweet_fixture(user, content) do
|
||||
Tweet
|
||||
|> Ash.Changeset.for_create(:create, %{content: content}, actor: user)
|
||||
|> Ash.create!()
|
||||
end
|
||||
|
||||
defp count_likes(tweet_id) do
|
||||
TweetLike
|
||||
|> Ash.Query.filter(expr(tweet_id == ^tweet_id))
|
||||
|> Ash.read!(authorize?: false)
|
||||
|> length()
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user