defmodule DiogramosWeb.UserLive.ConnectedDevicesTest do
use DiogramosWeb.ConnCase, async: false
import Phoenix.LiveViewTest
import Diogramos.AccountsFixtures
alias Diogramos.Accounts
setup %{conn: conn} do
on_exit(fn -> System.delete_env("DIOGRAMOS_PUBLIC_URL") end)
user = user_fixture()
%{conn: log_in_user(conn, user), user: user}
end
describe "the panel" do
test "shows an empty state before any device is paired", %{conn: conn} do
{:ok, _lv, html} = live(conn, ~p"/users/settings")
assert html =~ "Connected devices"
assert html =~ "No tokens yet"
end
test "lists existing tokens with their labels", %{conn: conn, user: user} do
Accounts.create_api_token(user, %{label: "Pixel 7"})
{:ok, _lv, html} = live(conn, ~p"/users/settings")
assert html =~ "Pixel 7"
refute html =~ "No tokens yet"
end
test "labels an unlabelled token rather than rendering a blank row", %{
conn: conn,
user: user
} do
Accounts.create_api_token(user)
{:ok, _lv, html} = live(conn, ~p"/users/settings")
assert html =~ "(no label)"
end
test "does not list another user's tokens", %{conn: conn} do
Accounts.create_api_token(user_fixture(), %{label: "Someone else's phone"})
{:ok, _lv, html} = live(conn, ~p"/users/settings")
refute html =~ "Someone else's phone"
assert html =~ "No tokens yet"
end
end
describe "generating a token" do
test "renders a working token, a QR, and the pairing URI", %{conn: conn, user: user} do
System.put_env("DIOGRAMOS_PUBLIC_URL", "https://diagrams.example.com")
{:ok, lv, _html} = live(conn, ~p"/users/settings")
html =
lv
|> form("#token_form", token: %{label: "Pixel 7"})
|> render_submit()
assert html =~ "diogramos://pair?"
assert html =~ "https%3A%2F%2Fdiagrams.example.com"
assert html =~ "<svg"
assert html =~ "only time the token is shown"
# The token on screen is the real bearer, not a display stand-in.
[_, token] = Regex.run(~r/token=([A-Za-z0-9_-]+)/, html)
assert {fetched, _id} = Accounts.fetch_user_by_api_token(token)
assert fetched.id == user.id
assert [%{label: "Pixel 7"}] = Accounts.list_api_tokens(user)
end
test "an empty label is stored as none", %{conn: conn, user: user} do
{:ok, lv, _html} = live(conn, ~p"/users/settings")
lv |> form("#token_form", token: %{label: ""}) |> render_submit()
assert [%{label: nil}] = Accounts.list_api_tokens(user)
end
test "the panel can be dismissed, and the token is not shown again", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/users/settings")
html = lv |> form("#token_form", token: %{label: "Pixel"}) |> render_submit()
assert html =~ "diogramos://pair?"
html = lv |> element("button", "Done — hide") |> render_click()
refute html =~ "diogramos://pair?"
# ...but the device itself is still listed.
assert html =~ "Pixel"
end
end
describe "revoking" do
test "removes the row and kills the token", %{conn: conn, user: user} do
token = Accounts.create_api_token(user, %{label: "Old phone"})
[%{id: id}] = Accounts.list_api_tokens(user)
{:ok, lv, html} = live(conn, ~p"/users/settings")
assert html =~ "Old phone"
html = lv |> element("#api-token-#{id} button", "Revoke") |> render_click()
refute html =~ "Old phone"
assert html =~ "No tokens yet"
refute Accounts.fetch_user_by_api_token(token)
end
test "cannot revoke a token belonging to someone else", %{conn: conn, user: user} do
other = user_fixture()
their_token = Accounts.create_api_token(other)
[%{id: their_id}] = Accounts.list_api_tokens(other)
{:ok, lv, _html} = live(conn, ~p"/users/settings")
render_click(lv, "revoke_api_token", %{"id" => to_string(their_id)})
# Still valid: the id belongs to another user, so the delete is scoped out.
assert Accounts.fetch_user_by_api_token(their_token)
assert Accounts.list_api_tokens(user) == []
end
end
end
neiam
/diogramos
diogramos
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
4.1 KiB · text
History
dc2edab