2023-11-02 15:18:11 +03:00
|
|
|
defmodule PlausibleWeb.Live.SitesTest do
|
|
|
|
use PlausibleWeb.ConnCase, async: true
|
|
|
|
|
|
|
|
import Phoenix.LiveViewTest
|
|
|
|
import Plausible.Test.Support.HTML
|
|
|
|
|
2023-11-13 11:08:26 +03:00
|
|
|
alias Plausible.Repo
|
|
|
|
|
2023-11-02 15:18:11 +03:00
|
|
|
setup [:create_user, :log_in]
|
|
|
|
|
|
|
|
describe "/sites" do
|
|
|
|
test "renders empty sites page", %{conn: conn} do
|
|
|
|
{:ok, _lv, html} = live(conn, "/sites")
|
|
|
|
|
|
|
|
assert text(html) =~ "You don't have any sites yet"
|
|
|
|
end
|
|
|
|
|
2023-12-20 17:56:49 +03:00
|
|
|
@tag :full_build_only
|
|
|
|
test "renders ownership transfer invitation for a case with no plan", %{
|
|
|
|
conn: conn,
|
|
|
|
user: user
|
|
|
|
} do
|
|
|
|
site = insert(:site)
|
|
|
|
|
|
|
|
invitation =
|
|
|
|
insert(:invitation,
|
|
|
|
site_id: site.id,
|
|
|
|
inviter: build(:user),
|
|
|
|
email: user.email,
|
|
|
|
role: :owner
|
|
|
|
)
|
|
|
|
|
|
|
|
{:ok, _lv, html} = live(conn, "/sites")
|
|
|
|
|
|
|
|
invitation_data = get_invitation_data(html)
|
|
|
|
|
|
|
|
assert get_in(invitation_data, ["invitations", invitation.invitation_id, "no_plan"])
|
|
|
|
end
|
|
|
|
|
|
|
|
@tag :full_build_only
|
|
|
|
test "renders ownership transfer invitation for a case with exceeded limits", %{
|
|
|
|
conn: conn,
|
|
|
|
user: user
|
|
|
|
} do
|
|
|
|
site = insert(:site)
|
|
|
|
|
|
|
|
insert(:growth_subscription, user: user)
|
|
|
|
|
|
|
|
# fill site quota
|
|
|
|
insert_list(10, :site, members: [user])
|
|
|
|
|
|
|
|
invitation =
|
|
|
|
insert(:invitation,
|
|
|
|
site_id: site.id,
|
|
|
|
inviter: build(:user),
|
|
|
|
email: user.email,
|
|
|
|
role: :owner
|
|
|
|
)
|
|
|
|
|
|
|
|
{:ok, _lv, html} = live(conn, "/sites")
|
|
|
|
|
|
|
|
invitation_data = get_invitation_data(html)
|
|
|
|
|
|
|
|
assert get_in(invitation_data, ["invitations", invitation.invitation_id, "exceeded_limits"]) ==
|
|
|
|
"site limit"
|
|
|
|
end
|
|
|
|
|
|
|
|
@tag :full_build_only
|
|
|
|
test "renders ownership transfer invitation for a case with missing features", %{
|
|
|
|
conn: conn,
|
|
|
|
user: user
|
|
|
|
} do
|
|
|
|
site = insert(:site, allowed_event_props: ["dummy"])
|
|
|
|
|
|
|
|
insert(:growth_subscription, user: user)
|
|
|
|
|
|
|
|
invitation =
|
|
|
|
insert(:invitation,
|
|
|
|
site_id: site.id,
|
|
|
|
inviter: build(:user),
|
|
|
|
email: user.email,
|
|
|
|
role: :owner
|
|
|
|
)
|
|
|
|
|
|
|
|
{:ok, _lv, html} = live(conn, "/sites")
|
|
|
|
|
|
|
|
invitation_data = get_invitation_data(html)
|
|
|
|
|
|
|
|
assert get_in(invitation_data, ["invitations", invitation.invitation_id, "missing_features"]) ==
|
|
|
|
"Custom Properties"
|
|
|
|
end
|
|
|
|
|
2023-11-02 15:18:11 +03:00
|
|
|
test "renders 24h visitors correctly", %{conn: conn, user: user} do
|
|
|
|
site = insert(:site, members: [user])
|
|
|
|
|
|
|
|
populate_stats(site, [build(:pageview), build(:pageview), build(:pageview)])
|
|
|
|
|
|
|
|
{:ok, _lv, html} = live(conn, "/sites")
|
|
|
|
|
|
|
|
site_card = text_of_element(html, "li[data-domain=\"#{site.domain}\"]")
|
|
|
|
assert site_card =~ "3 visitors in last 24h"
|
|
|
|
assert site_card =~ site.domain
|
|
|
|
end
|
|
|
|
|
|
|
|
test "filters by domain", %{conn: conn, user: user} do
|
|
|
|
_site1 = insert(:site, domain: "first.example.com", members: [user])
|
|
|
|
_site2 = insert(:site, domain: "second.example.com", members: [user])
|
|
|
|
_site3 = insert(:site, domain: "first-another.example.com", members: [user])
|
|
|
|
|
|
|
|
{:ok, lv, _html} = live(conn, "/sites")
|
|
|
|
|
|
|
|
type_into_input(lv, "filter_text", "firs")
|
|
|
|
html = render(lv)
|
|
|
|
|
|
|
|
assert html =~ "first.example.com"
|
|
|
|
assert html =~ "first-another.example.com"
|
|
|
|
refute html =~ "second.example.com"
|
|
|
|
end
|
|
|
|
|
|
|
|
test "filtering plays well with pagination", %{conn: conn, user: user} do
|
|
|
|
_site1 = insert(:site, domain: "first.another.example.com", members: [user])
|
|
|
|
_site2 = insert(:site, domain: "second.example.com", members: [user])
|
|
|
|
_site3 = insert(:site, domain: "third.another.example.com", members: [user])
|
|
|
|
|
|
|
|
{:ok, lv, html} = live(conn, "/sites?page_size=2")
|
|
|
|
|
|
|
|
assert html =~ "first.another.example.com"
|
|
|
|
assert html =~ "second.example.com"
|
|
|
|
refute html =~ "third.another.example.com"
|
|
|
|
assert html =~ "page=2"
|
|
|
|
refute html =~ "page=1"
|
|
|
|
|
|
|
|
type_into_input(lv, "filter_text", "anot")
|
|
|
|
html = render(lv)
|
|
|
|
|
|
|
|
assert html =~ "first.another.example.com"
|
|
|
|
refute html =~ "second.example.com"
|
|
|
|
assert html =~ "third.another.example.com"
|
|
|
|
refute html =~ "page=1"
|
|
|
|
refute html =~ "page=2"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-11-13 11:08:26 +03:00
|
|
|
describe "pinning" do
|
|
|
|
test "renders pin site option when site not pinned", %{conn: conn, user: user} do
|
|
|
|
site = insert(:site, members: [user])
|
|
|
|
|
|
|
|
{:ok, _lv, html} = live(conn, "/sites")
|
|
|
|
|
|
|
|
assert text_of_element(
|
|
|
|
html,
|
2023-12-13 11:59:20 +03:00
|
|
|
~s/li[data-domain="#{site.domain}"] a[phx-value-domain]/
|
2023-11-13 11:08:26 +03:00
|
|
|
) == "Pin Site"
|
|
|
|
end
|
|
|
|
|
|
|
|
test "site state changes when pin toggled", %{conn: conn, user: user} do
|
|
|
|
site = insert(:site, members: [user])
|
|
|
|
|
|
|
|
{:ok, lv, _html} = live(conn, "/sites")
|
|
|
|
|
2023-12-13 11:59:20 +03:00
|
|
|
button_selector = ~s/li[data-domain="#{site.domain}"] a[phx-value-domain]/
|
2023-11-13 11:08:26 +03:00
|
|
|
|
|
|
|
html =
|
|
|
|
lv
|
|
|
|
|> element(button_selector)
|
|
|
|
|> render_click()
|
|
|
|
|
|
|
|
assert html =~ "Site pinned"
|
|
|
|
|
|
|
|
assert text_of_element(html, button_selector) == "Unpin Site"
|
|
|
|
|
|
|
|
html =
|
|
|
|
lv
|
|
|
|
|> element(button_selector)
|
|
|
|
|> render_click()
|
|
|
|
|
|
|
|
assert html =~ "Site unpinned"
|
|
|
|
|
|
|
|
assert text_of_element(html, button_selector) == "Pin Site"
|
|
|
|
end
|
|
|
|
|
|
|
|
test "shows error when pins limit hit", %{conn: conn, user: user} do
|
|
|
|
for _ <- 1..9 do
|
|
|
|
site = insert(:site, members: [user])
|
|
|
|
assert {:ok, _} = Plausible.Sites.toggle_pin(user, site)
|
|
|
|
end
|
|
|
|
|
|
|
|
site = insert(:site, members: [user])
|
|
|
|
|
|
|
|
{:ok, lv, _html} = live(conn, "/sites")
|
|
|
|
|
2023-12-13 11:59:20 +03:00
|
|
|
button_selector = ~s/li[data-domain="#{site.domain}"] a[phx-value-domain]/
|
2023-11-13 11:08:26 +03:00
|
|
|
|
|
|
|
html =
|
|
|
|
lv
|
|
|
|
|> element(button_selector)
|
|
|
|
|> render_click()
|
|
|
|
|
|
|
|
assert text(html) =~ "Looks like you've hit the pinned sites limit!"
|
|
|
|
end
|
|
|
|
|
|
|
|
test "does not allow pinning site user doesn't have access to", %{conn: conn, user: user} do
|
|
|
|
site = insert(:site)
|
|
|
|
|
|
|
|
{:ok, lv, _html} = live(conn, "/sites")
|
|
|
|
|
|
|
|
render_click(lv, "pin-toggle", %{"domain" => site.domain})
|
|
|
|
|
|
|
|
refute Repo.get_by(Plausible.Site.UserPreference, user_id: user.id, site_id: site.id)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-11-02 15:18:11 +03:00
|
|
|
defp type_into_input(lv, id, text) do
|
|
|
|
lv
|
|
|
|
|> element("form")
|
|
|
|
|> render_change(%{id => text})
|
|
|
|
end
|
2023-12-20 17:56:49 +03:00
|
|
|
|
|
|
|
defp get_invitation_data(html) do
|
|
|
|
html
|
|
|
|
|> text_of_attr("div[x-data]", "x-data")
|
|
|
|
|> String.trim("dropdown")
|
|
|
|
|> String.replace("selectedInvitation:", "\"selectedInvitation\":")
|
|
|
|
|> String.replace("invitationOpen:", "\"invitationOpen\":")
|
|
|
|
|> String.replace("invitations:", "\"invitations\":")
|
|
|
|
|> Jason.decode!()
|
|
|
|
end
|
2023-11-02 15:18:11 +03:00
|
|
|
end
|