Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/live_debugger_web.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule LiveDebuggerWeb do

on_mount({LiveDebuggerWeb.Hooks.Flash, :add_hook})
on_mount({LiveDebuggerWeb.Hooks.IframeCheck, :add_hook})
on_mount({LiveDebuggerWeb.Hooks.URL, :add_hook})

import Phoenix.HTML
import LiveDebuggerWeb.Helpers
Expand Down
5 changes: 3 additions & 2 deletions lib/live_debugger_web/components/navbar.ex
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,18 @@ defmodule LiveDebuggerWeb.Components.Navbar do

def return_link(assigns) do
~H"""
<.link patch={@return_link} class={@class}>
<.link patch={@return_link} class={@class} id="return-button">
<.nav_icon icon="icon-arrow-left" />
</.link>
"""
end

attr(:class, :any, default: nil, doc: "Additional classes to add to the link.")
attr(:return_to, :any, default: nil, doc: "Return to URL.")

def settings_button(assigns) do
~H"""
<.link navigate={RoutesHelper.settings()} class={@class}>
<.link navigate={RoutesHelper.settings(@return_to)} class={@class} id="settings-button">
<.nav_icon icon="icon-settings" />
</.link>
"""
Expand Down
11 changes: 2 additions & 9 deletions lib/live_debugger_web/components/tab_group.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,13 @@ defmodule LiveDebuggerWeb.Components.TabGroup do

attr(:transport_pid, :any, required: true)
attr(:grouped_lv_processes, :list, required: true)
attr(:window_link?, :boolean, default: true)

def group(assigns) do
~H"""
<div class="w-full h-max flex flex-col shadow-custom rounded-sm bg-surface-2-bg border border-default-border">
<div class="pl-4 p-3 flex items-center h-10 border-b border-default-border">
<p class="text-primary-text text-xs font-medium">
<%= if @window_link? do %>
<.link navigate={RoutesHelper.window_dashboard(@transport_pid)} class="window-link">
<%= Parsers.pid_to_string(@transport_pid) %>
</.link>
<% else %>
<%= Parsers.pid_to_string(@transport_pid) %>
<% end %>
<p class="text-primary-text text-xs font-medium transport-pid">
<%= Parsers.pid_to_string(@transport_pid) %>
</p>
</div>
<div class="w-full flex bg-surface-0-bg">
Expand Down
8 changes: 7 additions & 1 deletion lib/live_debugger_web/helpers/routes_helper.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ defmodule LiveDebuggerWeb.Helpers.RoutesHelper do
end

@spec settings() :: String.t()
def settings() do
def settings(return_to \\ nil)

def settings(nil) do
~p"/settings"
end

def settings(return_to) do
~p"/settings?return_to=#{return_to}"
end
end
55 changes: 41 additions & 14 deletions lib/live_debugger_web/hooks/iframe_check.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,47 @@ defmodule LiveDebuggerWeb.Hooks.IframeCheck do
@moduledoc """
This hook is used to check if the current page is inside an iframe.
It assigns the `:in_iframe?` assign based on the connect params.

Mock is created for it to simulate LiveDebugger in iframe in e2e tests.
"""
import Phoenix.LiveView
import Phoenix.Component

def on_mount(:add_hook, _params, _session, socket) do
in_iframe? =
if connected?(socket) do
socket
|> get_connect_params()
|> Map.get("in_iframe?", false)
else
false
end

{:cont, assign(socket, :in_iframe?, in_iframe?)}

@callback on_mount(
:add_hook,
params :: map(),
session :: map(),
socket :: Phoenix.LiveView.Socket.t()
) ::
{:cont, Phoenix.LiveView.Socket.t()}

def on_mount(:add_hook, params, session, socket) do
impl().on_mount(:add_hook, params, session, socket)
end

defp impl() do
Application.get_env(
:live_debugger,
:iframe_check,
__MODULE__.Impl
)
end

defmodule Impl do
@moduledoc false

import Phoenix.LiveView
import Phoenix.Component

def on_mount(:add_hook, _params, _session, socket) do
in_iframe? =
if connected?(socket) do
socket
|> get_connect_params()
|> Map.get("in_iframe?", false)
else
false
end

{:cont, assign(socket, :in_iframe?, in_iframe?)}
end
end
end
23 changes: 23 additions & 0 deletions lib/live_debugger_web/hooks/url.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule LiveDebuggerWeb.Hooks.URL do
@moduledoc """
This hook assigns the `:url` assign based on the current URL.
It is triggered on handle_params callback.
"""

import Phoenix.LiveView
import Phoenix.Component

alias LiveDebugger.Utils.URL

def on_mount(:add_hook, :not_mounted_at_router, _session, socket) do
{:cont, socket}
end

def on_mount(:add_hook, _params, _session, socket) do
{:cont, attach_hook(socket, :url, :handle_params, &handle_params/3)}
end

defp handle_params(_params, url, socket) do
{:cont, assign(socket, :url, URL.to_relative(url))}
end
end
6 changes: 2 additions & 4 deletions lib/live_debugger_web/live/channel_dashboard_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ defmodule LiveDebuggerWeb.ChannelDashboardLive do
alias LiveDebuggerWeb.Helpers.RoutesHelper
alias LiveDebuggerWeb.Components.Navbar
alias Phoenix.LiveView.JS
alias LiveDebugger.Utils.URL

alias LiveDebugger.Structs.TreeNode

Expand All @@ -21,10 +20,9 @@ defmodule LiveDebuggerWeb.ChannelDashboardLive do
alias LiveDebuggerWeb.Components.NavigationMenu

@impl true
def handle_params(params, url, socket) do
def handle_params(params, _url, socket) do
socket
|> assign_node_id(params)
|> assign(:url, URL.to_relative(url))
|> noreply()
end

Expand Down Expand Up @@ -55,7 +53,7 @@ defmodule LiveDebuggerWeb.ChannelDashboardLive do
pid={Parsers.pid_to_string(@lv_process.result.pid)}
/>
<div class="flex items-center gap-2">
<Navbar.settings_button />
<Navbar.settings_button return_to={@url} />
<span :if={@lv_process.ok?} class="h-5 border-r border-default-border lg:hidden"></span>
<.nav_icon
:if={@lv_process.ok?}
Expand Down
2 changes: 1 addition & 1 deletion lib/live_debugger_web/live/live_views_dashboard_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule LiveDebuggerWeb.LiveViewsDashboardLive do
<div class="flex-1 min-w-[25rem] grid grid-rows-[auto_1fr]">
<Navbar.navbar class="flex justify-between">
<Navbar.live_debugger_logo />
<Navbar.settings_button />
<Navbar.settings_button return_to={@url} />
</Navbar.navbar>
<div class="flex-1 max-lg:p-8 pt-8 lg:w-[60rem] lg:m-auto">
<div class="flex items-center justify-between">
Expand Down
9 changes: 8 additions & 1 deletion lib/live_debugger_web/live/settings_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@ defmodule LiveDebuggerWeb.SettingsLive do
alias LiveDebuggerWeb.Components.Navbar
alias LiveDebuggerWeb.Helpers.RoutesHelper

@impl true
def handle_params(params, _url, socket) do
socket
|> assign(:return_to, params["return_to"])
|> noreply()
end

@impl true
def render(assigns) do
~H"""
<div class="flex-1 min-w-[25rem] grid grid-rows-[auto_1fr]">
<Navbar.navbar class="flex">
<Navbar.return_link return_link={RoutesHelper.live_views_dashboard()} />
<Navbar.return_link return_link={@return_to || RoutesHelper.live_views_dashboard()} />
<Navbar.live_debugger_logo />
</Navbar.navbar>
<div class="flex-1 max-lg:p-8 pt-8 lg:w-[60rem] lg:m-auto">
Expand Down
10 changes: 8 additions & 2 deletions lib/live_debugger_web/live/window_dashboard_live.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
defmodule LiveDebuggerWeb.WindowDashboardLive do
@moduledoc """
This view is a variant of the LiveViews dashboard, but it is used to display LiveViews in the given window.
It cannot be accessed from the browser directly, but:
- it is used when there are many LiveViews in the same window, and we cannot find a single successor.
- in case of extension this replaces the LiveViews dashboard, since extension works in a single window.
"""

use LiveDebuggerWeb, :live_view

alias LiveDebugger.Utils.Parsers
Expand Down Expand Up @@ -35,7 +42,7 @@ defmodule LiveDebuggerWeb.WindowDashboardLive do
/>
<Navbar.live_debugger_logo />
<Navbar.fill />
<Navbar.settings_button />
<Navbar.settings_button return_to={@url} />
</Navbar.navbar>
<div class="flex-1 max-lg:p-8 pt-8 lg:w-[60rem] lg:m-auto">
<div class="flex items-center justify-between">
Expand Down Expand Up @@ -68,7 +75,6 @@ defmodule LiveDebuggerWeb.WindowDashboardLive do
<% else %>
<TabGroup.group
:for={{transport_pid, grouped_lv_processes} <- grouped_lv_processes}
window_link?={false}
transport_pid={transport_pid}
grouped_lv_processes={grouped_lv_processes}
/>
Expand Down
49 changes: 46 additions & 3 deletions test/live_debugger/channel_dashboard_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ defmodule LiveDebugger.ChannelDashboardTest do
end

@sessions 2
feature "settings button exists and redirects to settings page", %{
feature "settings button exists and redirects works as expected", %{
sessions: [dev_app, debugger]
} do
dev_app
Expand All @@ -118,9 +118,48 @@ defmodule LiveDebugger.ChannelDashboardTest do
debugger
|> visit("/")
|> click(first_link())
|> assert_has(css("navbar a[href=\"/settings\"]"))
|> click(css("navbar a[href=\"/settings\"]"))
|> assert_has(css("div#traces", text: "Callback traces"))
|> assert_has(settings_button())
|> click(settings_button())
|> assert_has(css("h1", text: "Settings"))
|> assert_has(return_button())
|> click(return_button())
|> assert_has(css("div#traces", text: "Callback traces"))
end

@sessions 2
feature "return button redirects to window dashboard in case of iframe", %{
sessions: [dev_app, debugger]
} do
LiveDebugger.MockIframeCheck
|> stub(:on_mount, fn _, _, _, socket ->
{:cont, Phoenix.Component.assign(socket, :in_iframe?, true)}
end)

dev_app
|> visit(@dev_app_url)

debugger
|> visit("/")
|> click(first_link())
|> assert_has(css("div#traces", text: "Callback traces"))
|> click(return_button())
|> assert_has(css("h1", text: "Active LiveViews in a single window"))
end

@sessions 2
feature "return button redirects to active live views dashboard not in iframe", %{
sessions: [dev_app, debugger]
} do
dev_app
|> visit(@dev_app_url)

debugger
|> visit("/")
|> click(first_link())
|> assert_has(css("div#traces", text: "Callback traces"))
|> click(return_button())
|> assert_has(css("h1", text: "Active LiveViews"))
end

@sessions 2
Expand Down Expand Up @@ -371,4 +410,8 @@ defmodule LiveDebugger.ChannelDashboardTest do
defp many_assigns_15_node_button() do
css("#tree-node-button-15-component-tree-sidebar-content")
end

defp settings_button(), do: css("navbar a#settings-button")

defp return_button(), do: css("navbar a#return-button")
end
13 changes: 10 additions & 3 deletions test/live_debugger/live_views_dashboard_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,29 @@ defmodule LiveDebugger.LiveViewsDashboardTest do
end

@sessions 2
feature "settings button exists and redirects to settings page", %{
feature "settings button exists and redirects works as expected", %{
sessions: [dev_app, debugger]
} do
dev_app
|> visit(@dev_app_url)

debugger
|> visit("/")
|> assert_has(css("navbar a[href=\"/settings\"]"))
|> click(css("navbar a[href=\"/settings\"]"))
|> assert_has(settings_button())
|> click(settings_button())
|> assert_has(css("h1", text: "Settings"))
|> assert_has(return_button())
|> click(return_button())
|> assert_has(title(text: "Active LiveViews"))
end

defp title(text: text), do: css("h1", text: text)

defp live_sessions(count: count), do: css("#live-sessions > div", count: count)

defp refresh_button(), do: css("button[phx-click=\"refresh\"]")

defp settings_button(), do: css("navbar a#settings-button")

defp return_button(), do: css("navbar a#return-button")
end
Loading