add tests for reviews liveviews and worker
All checks were successful
deploy / deploy (push) Successful in 39s
All checks were successful
deploy / deploy (push) Successful in 39s
- admin reviews test: list, filter, search, moderation (approve/reject/delete) - review form test: rendering, validation, submission, edit flow - review request worker test: email sending, edge cases, scheduling Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
234
test/berrypod_web/live/admin/reviews_test.exs
Normal file
234
test/berrypod_web/live/admin/reviews_test.exs
Normal file
@@ -0,0 +1,234 @@
|
||||
defmodule BerrypodWeb.Admin.ReviewsTest do
|
||||
use BerrypodWeb.ConnCase, async: false
|
||||
|
||||
import Phoenix.LiveViewTest
|
||||
import Berrypod.AccountsFixtures
|
||||
import Berrypod.ProductsFixtures
|
||||
|
||||
alias Berrypod.Reviews
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
%{user: user}
|
||||
end
|
||||
|
||||
defp create_review(product, attrs \\ %{}) do
|
||||
defaults = %{
|
||||
product_id: product.id,
|
||||
email: "reviewer-#{System.unique_integer([:positive])}@example.com",
|
||||
author_name: "Test Reviewer",
|
||||
rating: 4
|
||||
}
|
||||
|
||||
{:ok, review} = Reviews.create_review(Map.merge(defaults, attrs))
|
||||
review
|
||||
end
|
||||
|
||||
describe "unauthenticated" do
|
||||
test "redirects to login", %{conn: conn} do
|
||||
{:error, redirect} = live(conn, ~p"/admin/reviews")
|
||||
assert {:redirect, %{to: path}} = redirect
|
||||
assert path == ~p"/users/log-in"
|
||||
end
|
||||
end
|
||||
|
||||
describe "review list" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "renders empty state when no reviews", %{conn: conn} do
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
assert html =~ "No reviews to show"
|
||||
assert html =~ "Reviews"
|
||||
end
|
||||
|
||||
test "renders reviews list", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
create_review(product, %{author_name: "Jane Doe", rating: 5})
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
assert html =~ product.title
|
||||
assert html =~ "Jane Doe"
|
||||
assert html =~ "pending"
|
||||
end
|
||||
|
||||
test "shows status counts in tabs", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
_pending = create_review(product, %{email: "p@test.com"})
|
||||
approved = create_review(product, %{email: "a@test.com"})
|
||||
Reviews.approve_review(approved)
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
# Should show counts - pending has badge
|
||||
assert html =~ "Pending"
|
||||
assert html =~ "Approved"
|
||||
end
|
||||
|
||||
test "filters by pending status", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
_pending = create_review(product, %{email: "pending@test.com", author_name: "Pending User"})
|
||||
|
||||
approved =
|
||||
create_review(product, %{email: "approved@test.com", author_name: "Approved User"})
|
||||
|
||||
Reviews.approve_review(approved)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
html = render_click(view, "filter", %{"status" => "pending"})
|
||||
|
||||
assert html =~ "Pending User"
|
||||
refute html =~ "Approved User"
|
||||
end
|
||||
|
||||
test "filters by approved status", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
_pending = create_review(product, %{email: "pending@test.com", author_name: "Pending User"})
|
||||
|
||||
approved =
|
||||
create_review(product, %{email: "approved@test.com", author_name: "Approved User"})
|
||||
|
||||
Reviews.approve_review(approved)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
html = render_click(view, "filter", %{"status" => "approved"})
|
||||
|
||||
assert html =~ "Approved User"
|
||||
refute html =~ "Pending User"
|
||||
end
|
||||
|
||||
test "filters by rejected status", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
_pending = create_review(product, %{email: "pending@test.com", author_name: "Pending User"})
|
||||
|
||||
rejected =
|
||||
create_review(product, %{email: "rejected@test.com", author_name: "Rejected User"})
|
||||
|
||||
Reviews.reject_review(rejected)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
html = render_click(view, "filter", %{"status" => "rejected"})
|
||||
|
||||
assert html =~ "Rejected User"
|
||||
refute html =~ "Pending User"
|
||||
end
|
||||
|
||||
test "search filters by author name", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
create_review(product, %{email: "a@test.com", author_name: "Alice"})
|
||||
create_review(product, %{email: "b@test.com", author_name: "Bob"})
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
html = render_submit(view, "search", %{"search" => %{"query" => "Alice"}})
|
||||
|
||||
assert html =~ "Alice"
|
||||
refute html =~ "Bob"
|
||||
end
|
||||
end
|
||||
|
||||
describe "review moderation" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "expands review to show details", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
review = create_review(product, %{title: "Great product!", body: "Would buy again."})
|
||||
|
||||
{:ok, view, html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
# Initially collapsed - body not visible
|
||||
refute html =~ "Would buy again."
|
||||
|
||||
# Expand the review
|
||||
html = render_click(view, "expand", %{"id" => review.id})
|
||||
|
||||
assert html =~ "Great product!"
|
||||
assert html =~ "Would buy again."
|
||||
end
|
||||
|
||||
test "approves a pending review", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
review = create_review(product, %{author_name: "Jane"})
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
# Expand first to see approve button
|
||||
render_click(view, "expand", %{"id" => review.id})
|
||||
html = render_click(view, "approve", %{"id" => review.id})
|
||||
|
||||
assert html =~ "Review approved"
|
||||
|
||||
# Verify in database
|
||||
updated = Reviews.get_review(review.id)
|
||||
assert updated.status == "approved"
|
||||
end
|
||||
|
||||
test "rejects a pending review", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
review = create_review(product, %{author_name: "Jane"})
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
# Expand first to see reject button
|
||||
render_click(view, "expand", %{"id" => review.id})
|
||||
html = render_click(view, "reject", %{"id" => review.id})
|
||||
|
||||
assert html =~ "Review rejected"
|
||||
|
||||
# Verify in database
|
||||
updated = Reviews.get_review(review.id)
|
||||
assert updated.status == "rejected"
|
||||
end
|
||||
|
||||
test "deletes a review", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
review = create_review(product, %{author_name: "Jane"})
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
# Expand first to see delete button
|
||||
render_click(view, "expand", %{"id" => review.id})
|
||||
html = render_click(view, "delete", %{"id" => review.id})
|
||||
|
||||
assert html =~ "Review deleted"
|
||||
|
||||
# Verify removed from database
|
||||
assert Reviews.get_review(review.id) == nil
|
||||
end
|
||||
|
||||
test "shows rating only message when no title/body", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
review = create_review(product, %{title: nil, body: nil})
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/reviews")
|
||||
|
||||
html = render_click(view, "expand", %{"id" => review.id})
|
||||
|
||||
assert html =~ "No written review — rating only"
|
||||
end
|
||||
|
||||
test "approve button hidden for already approved reviews", %{conn: conn} do
|
||||
product = product_fixture()
|
||||
review = create_review(product)
|
||||
{:ok, review} = Reviews.approve_review(review)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/admin/reviews?status=approved")
|
||||
|
||||
html = render_click(view, "expand", %{"id" => review.id})
|
||||
|
||||
# Should show reject but not approve
|
||||
assert html =~ "Reject"
|
||||
refute html =~ ">Approve</button>" or html =~ "phx-click=\"approve\""
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user