mirror of
https://github.com/plausible/analytics.git
synced 2024-12-26 02:55:02 +03:00
f464ceae88
* Revert "Remove site pins for now"
This reverts commit 5eccf4eaf6
.
* Implement basic site pin schema level logic within user specific preferences
* Add vertical ellipsis menu markup
* Implement basic changesets for user preferences
* Implement pin toggling
* Try to fix pin sorting
* Implement pin toggling in LV
* Adjust moduledocs for new schema(s)
* Remove unnecessary `distinct` from query
* Use `button` for pin/unpin action
* Generalize preference setting
* Rename schema and fields for clarity
* Rename `list_type` -> `entry_type`
* Safeguard setting options
* Test `set_option/4` and `toggle_pin/2`
* Add test for listing pinned sites via `Sites.list`
* Disallow pinning sites outside page explicitly
* Test pinning in LV
* Test conditional rendering of site settings in /sites
* Remove unnecessary TODO comment
* Safeguard `Sites.set_option/4` against invalid user/site combo
* Handle pinned sites in dashboard site picker
* Clear flashes upon (un)pinning sites
* Update CHANGELOG
* Prevent blinking of hamburger menu items on first paint
* Highlight hamburger handle on hover in /sites
* Start showing hotkeys in site picker again
* Sort pinned sites in the order they were pinned
* Update sites list order immediately after pin/unpin toggle
* Refactor and split `Sites.list/3`, extracting `Sites.list_with_invitations/3`
* Cap number of pinned sites at 9 per user
* First pass on visual indication of site cards (dis)appearing
* Apply ellipsis gradient+shadow on card hover
* Fix responsive padding of site cards
* Sort by invitations first, pinned sites second and then the rest
* Revert "Apply ellipsis gradient+shadow on card hover"
This reverts commit 0608796612639030ccbb12df639709f78edc1434.
* Apply more subtle hover effect on the ellipsis menu
* Make error and success flash LV boxes use separate component containers
* Promote `pinned_at` in table migration to a column
* Switch logic to using `pinned_at` as a standard schema field
* Refactor `Sites.list*` getting rid of subquery (h/t @ukutaht)
* Remove migration which is already merged upstream
---------
Co-authored-by: Adam Rutkowski <hq@mtod.org>
194 lines
6.3 KiB
Elixir
194 lines
6.3 KiB
Elixir
defmodule PlausibleWeb.Api.InternalControllerTest do
|
|
use PlausibleWeb.ConnCase, async: true
|
|
use Plausible.Repo
|
|
|
|
describe "GET /api/:domain/status" do
|
|
setup [:create_user, :log_in]
|
|
|
|
test "is WAITING when site has no pageviews", %{conn: conn, user: user} do
|
|
site = insert(:site, members: [user])
|
|
conn = get(conn, "/api/#{site.domain}/status")
|
|
|
|
assert json_response(conn, 200) == "WAITING"
|
|
end
|
|
|
|
test "is READY when site has at least 1 pageview", %{conn: conn, user: user} do
|
|
site = insert(:site, members: [user])
|
|
Plausible.TestUtils.create_pageviews([%{site: site}])
|
|
|
|
conn = get(conn, "/api/#{site.domain}/status")
|
|
|
|
assert json_response(conn, 200) == "READY"
|
|
end
|
|
|
|
test "is WAITING when unauthenticated", %{user: user} do
|
|
site = insert(:site, members: [user])
|
|
Plausible.TestUtils.create_pageviews([%{site: site}])
|
|
|
|
conn = get(build_conn(), "/api/#{site.domain}/status")
|
|
|
|
assert json_response(conn, 200) == "WAITING"
|
|
end
|
|
|
|
test "is WAITING when non-existing site", %{conn: conn} do
|
|
conn = get(conn, "/api/example.com/status")
|
|
|
|
assert json_response(conn, 200) == "WAITING"
|
|
end
|
|
end
|
|
|
|
describe "GET /api/sites" do
|
|
setup [:create_user, :log_in]
|
|
|
|
test "returns a list of site domains for the current user", %{conn: conn, user: user} do
|
|
site = insert(:site, members: [user])
|
|
site2 = insert(:site, members: [user])
|
|
conn = get(conn, "/api/sites")
|
|
|
|
%{"data" => sites} = json_response(conn, 200)
|
|
|
|
assert %{"domain" => site.domain} in sites
|
|
assert %{"domain" => site2.domain} in sites
|
|
end
|
|
|
|
test "returns a list of max 9 site domains for the current user, putting pinned first", %{
|
|
conn: conn,
|
|
user: user
|
|
} do
|
|
inserted =
|
|
for i <- 1..10 do
|
|
i = to_string(i)
|
|
|
|
insert(:site,
|
|
members: [user],
|
|
domain: "site#{String.pad_leading(i, 2, "0")}.example.com"
|
|
)
|
|
end
|
|
|
|
_rogue = insert(:site, domain: "site00.example.com")
|
|
|
|
insert(:site,
|
|
domain: "friend.example.com",
|
|
invitations: [
|
|
build(:invitation, email: user.email, inviter: build(:user), role: :viewer)
|
|
]
|
|
)
|
|
|
|
insert(:invitation,
|
|
email: "friend@example.com",
|
|
inviter: user,
|
|
role: :viewer,
|
|
site: hd(inserted)
|
|
)
|
|
|
|
{:ok, _} =
|
|
Plausible.Sites.toggle_pin(user, Plausible.Sites.get_by_domain!("site07.example.com"))
|
|
|
|
{:ok, _} =
|
|
Plausible.Sites.toggle_pin(user, Plausible.Sites.get_by_domain!("site05.example.com"))
|
|
|
|
conn = get(conn, "/api/sites")
|
|
|
|
%{"data" => sites} =
|
|
json_response(conn, 200)
|
|
|
|
assert Enum.count(sites) == 9
|
|
|
|
assert [
|
|
%{"domain" => "site05.example.com"},
|
|
%{"domain" => "site07.example.com"},
|
|
%{"domain" => "site01.example.com"} | _
|
|
] = sites
|
|
|
|
assert %{"domain" => "site09.example.com"} in sites
|
|
refute %{"domain" => "sites10.example.com"} in sites
|
|
end
|
|
end
|
|
|
|
describe "GET /api/sites - user not logged in" do
|
|
test "returns 401 unauthorized", %{conn: conn} do
|
|
conn = get(conn, "/api/sites")
|
|
|
|
assert json_response(conn, 401) == %{
|
|
"error" => "You need to be logged in to request a list of sites"
|
|
}
|
|
end
|
|
end
|
|
|
|
describe "PUT /api/:domain/disable-feature" do
|
|
setup [:create_user, :log_in]
|
|
|
|
test "when the logged-in user is an admin of the site", %{conn: conn, user: user} do
|
|
site = insert(:site)
|
|
insert(:site_membership, user: user, site: site, role: :admin)
|
|
|
|
conn = put(conn, "/api/#{site.domain}/disable-feature", %{"feature" => "conversions"})
|
|
|
|
assert json_response(conn, 200) == "ok"
|
|
assert %{conversions_enabled: false} = Plausible.Sites.get_by_domain(site.domain)
|
|
end
|
|
|
|
test "can disable conversions, funnels, and props with admin access", %{
|
|
conn: conn,
|
|
user: user
|
|
} do
|
|
site = insert(:site)
|
|
insert(:site_membership, user: user, site: site, role: :admin)
|
|
|
|
put(conn, "/api/#{site.domain}/disable-feature", %{"feature" => "conversions"})
|
|
put(conn, "/api/#{site.domain}/disable-feature", %{"feature" => "funnels"})
|
|
put(conn, "/api/#{site.domain}/disable-feature", %{"feature" => "props"})
|
|
|
|
assert %{conversions_enabled: false, funnels_enabled: false, props_enabled: false} =
|
|
Plausible.Sites.get_by_domain(site.domain)
|
|
end
|
|
|
|
test "when the logged-in user is an owner of the site", %{conn: conn, user: user} do
|
|
site = insert(:site, memberships: [build(:site_membership, user: user, role: :owner)])
|
|
conn = put(conn, "/api/#{site.domain}/disable-feature", %{"feature" => "conversions"})
|
|
|
|
assert json_response(conn, 200) == "ok"
|
|
assert %{conversions_enabled: false} = Plausible.Sites.get_by_domain(site.domain)
|
|
end
|
|
|
|
test "returns 401 when the logged-in user is a viewer of the site", %{conn: conn, user: user} do
|
|
site = insert(:site)
|
|
insert(:site_membership, user: user, site: site, role: :viewer)
|
|
|
|
conn = put(conn, "/api/#{site.domain}/disable-feature", %{"feature" => "conversions"})
|
|
|
|
assert json_response(conn, 401) == %{
|
|
"error" => "You need to be logged in as the owner or admin account of this site"
|
|
}
|
|
|
|
assert %{conversions_enabled: true} = Plausible.Sites.get_by_domain(site.domain)
|
|
end
|
|
|
|
test "returns 401 when the logged-in user doesn't have site access at all", %{conn: conn} do
|
|
site = insert(:site)
|
|
|
|
conn = put(conn, "/api/#{site.domain}/disable-feature", %{"feature" => "conversions"})
|
|
|
|
assert json_response(conn, 401) == %{
|
|
"error" => "You need to be logged in as the owner or admin account of this site"
|
|
}
|
|
|
|
assert %{conversions_enabled: true} = Plausible.Sites.get_by_domain(site.domain)
|
|
end
|
|
end
|
|
|
|
describe "PUT /api/:domain/disable-feature - user not logged in" do
|
|
test "returns 401 unauthorized", %{conn: conn} do
|
|
site = insert(:site)
|
|
|
|
conn = put(conn, "/api/#{site.domain}/disable-feature", %{"feature" => "conversions"})
|
|
|
|
assert json_response(conn, 401) == %{
|
|
"error" => "You need to be logged in as the owner or admin account of this site"
|
|
}
|
|
|
|
assert %{conversions_enabled: true} = Plausible.Sites.get_by_domain(site.domain)
|
|
end
|
|
end
|
|
end
|