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" or html =~ "phx-click=\"approve\"" end end end