defmodule BDS.UI.ShellTest do use ExUnit.Case, async: true alias BDS.UI.Commands alias BDS.UI.Registry alias BDS.UI.Session alias BDS.UI.ShellPage alias BDS.UI.Workbench test "registry exposes the shared sidebar and editor contracts for the base shell" do sidebar_views = Registry.sidebar_views() editor_routes = Registry.editor_routes() assert Registry.default_sidebar_view() == :posts assert Enum.map(sidebar_views, & &1.id) == [ :posts, :pages, :media, :scripts, :templates, :tags, :chat, :import, :git, :settings ] assert Enum.find(sidebar_views, &(&1.id == :media)).activity_group == :top assert Enum.find(sidebar_views, &(&1.id == :git)).activity_group == :bottom assert Enum.any?(editor_routes, &(&1.id == :dashboard)) assert Enum.any?(editor_routes, &(&1.id == :post and &1.entity_tab == true)) assert Enum.any?(editor_routes, &(&1.id == :settings and &1.singleton == true)) end test "workbench session roundtrips tabs, dirty state, shell visibility, and widths" do state = Workbench.new(sidebar_visible: false, panel_visible: true) |> Workbench.set_sidebar_width(412) |> Workbench.set_assistant_sidebar_width(511) |> Workbench.open_tab(:post, "post-1", :pin) |> Workbench.open_tab(:media, "media-1", :preview) |> Workbench.mark_dirty(:post, "post-1") |> Workbench.click_activity(:media) payload = Session.serialize(state) restored = Session.restore(payload) assert restored.sidebar_visible == true assert restored.panel.visible == true assert restored.sidebar_width == 412 assert restored.assistant_sidebar_width == 511 assert restored.active_view == :media assert restored.active_tab == {:media, "media-1"} assert Workbench.dirty?(restored, :post, "post-1") == true assert Enum.map(restored.tabs, &{&1.type, &1.id, &1.is_transient}) == [ {:post, "post-1", false}, {:media, "media-1", true} ] end test "keyboard commands drive the same shared workbench policy" do state = Workbench.new(sidebar_visible: true) |> Workbench.open_tab(:post, "post-1", :pin) state = Commands.handle_shortcut(state, %{meta: true, key: "b"}) assert state.sidebar_visible == false state = Commands.handle_shortcut(state, %{meta: true, key: "w"}) assert state.tabs == [] assert state.editor_route == :dashboard end test "resizing is clamped to the shell limits and dirty flags only apply to post tabs" do state = Workbench.new() |> Workbench.set_sidebar_width(999) |> Workbench.set_assistant_sidebar_width(120) |> Workbench.open_tab(:media, "media-1", :pin) |> Workbench.mark_dirty(:media, "media-1") |> Workbench.open_tab(:post, "post-1", :pin) |> Workbench.mark_dirty(:post, "post-1") assert state.sidebar_width == 500 assert state.assistant_sidebar_width == 280 assert Workbench.dirty?(state, :media, "media-1") == false assert Workbench.dirty?(state, :post, "post-1") == true end test "shell page renders the inspectable base app with bootstrap data and shell controls" do html = ShellPage.render() assert html =~ ~s(