feat: more work on UI cleanup
This commit is contained in:
92
test/bds/desktop/shell_commands_test.exs
Normal file
92
test/bds/desktop/shell_commands_test.exs
Normal file
@@ -0,0 +1,92 @@
|
||||
defmodule BDS.Desktop.ShellCommandsTest do
|
||||
use ExUnit.Case, async: false
|
||||
|
||||
alias BDS.Desktop.ShellCommands
|
||||
|
||||
setup do
|
||||
:ok = Ecto.Adapters.SQL.Sandbox.checkout(BDS.Repo)
|
||||
Ecto.Adapters.SQL.Sandbox.mode(BDS.Repo, {:shared, self()})
|
||||
:ok = Ecto.Adapters.SQL.Sandbox.allow(BDS.Repo, self(), Process.whereis(BDS.Preview))
|
||||
:ok = Ecto.Adapters.SQL.Sandbox.allow(BDS.Repo, self(), Process.whereis(BDS.Publishing))
|
||||
|
||||
temp_dir =
|
||||
Path.join(System.tmp_dir!(), "bds-shell-commands-#{System.unique_integer([:positive])}")
|
||||
|
||||
File.mkdir_p!(temp_dir)
|
||||
|
||||
on_exit(fn ->
|
||||
File.rm_rf(temp_dir)
|
||||
_ = BDS.Preview.stop_preview("default")
|
||||
end)
|
||||
|
||||
{:ok, project} = BDS.Projects.create_project(%{name: "Shell Commands", data_path: temp_dir})
|
||||
{:ok, project} = BDS.Projects.set_active_project(project.id)
|
||||
|
||||
%{project: project, temp_dir: temp_dir}
|
||||
end
|
||||
|
||||
test "open_in_browser starts preview for the active project and returns a preview url", %{project: project} do
|
||||
assert {:ok, result} = ShellCommands.execute("open_in_browser")
|
||||
|
||||
assert result.kind == "open_url"
|
||||
assert result.action == "open_in_browser"
|
||||
assert result.url == "http://127.0.0.1:4123/"
|
||||
assert result.project_id == project.id
|
||||
end
|
||||
|
||||
test "validate_translations returns an editor payload with current translation gaps", %{project: project} do
|
||||
assert {:ok, _metadata} =
|
||||
BDS.Metadata.update_project_metadata(project.id, %{
|
||||
main_language: "en",
|
||||
blog_languages: ["en", "de"]
|
||||
})
|
||||
|
||||
assert {:ok, post} =
|
||||
BDS.Posts.create_post(%{
|
||||
project_id: project.id,
|
||||
title: "Hello",
|
||||
content: "World",
|
||||
language: "en"
|
||||
})
|
||||
|
||||
assert {:ok, _published_post} = BDS.Posts.publish_post(post.id)
|
||||
|
||||
assert {:ok, result} = ShellCommands.execute("validate_translations")
|
||||
|
||||
assert result.kind == "open_editor"
|
||||
assert result.route == "translation_validation"
|
||||
assert result.payload.summary.missing_count == 1
|
||||
post_id = post.id
|
||||
assert [%{"language" => "de", "post_id" => ^post_id}] = result.payload.missing
|
||||
end
|
||||
|
||||
test "reindex_text queues a tracked background task for the active project", %{project: project} do
|
||||
assert {:ok, result} = ShellCommands.execute("reindex_text")
|
||||
|
||||
assert result.kind == "task_queued"
|
||||
assert result.action == "reindex_text"
|
||||
assert result.project_id == project.id
|
||||
assert is_binary(result.task_id)
|
||||
|
||||
assert task = BDS.Tasks.get_task(result.task_id)
|
||||
assert task.group_name == "Search"
|
||||
assert wait_for_task(result.task_id, &(&1.status in [:completed, :failed])).status == :completed
|
||||
end
|
||||
|
||||
defp wait_for_task(task_id, matcher, timeout \\ 2_000)
|
||||
|
||||
defp wait_for_task(task_id, _matcher, timeout) when timeout <= 0 do
|
||||
BDS.Tasks.get_task(task_id)
|
||||
end
|
||||
|
||||
defp wait_for_task(task_id, matcher, timeout) do
|
||||
task = BDS.Tasks.get_task(task_id)
|
||||
|
||||
if task && matcher.(task) do
|
||||
task
|
||||
else
|
||||
Process.sleep(50)
|
||||
wait_for_task(task_id, matcher, timeout - 50)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -84,4 +84,64 @@ defmodule BDS.DesktopTest do
|
||||
assert conn.status == 200
|
||||
assert conn.resp_body =~ ~s(class="app")
|
||||
end
|
||||
|
||||
test "desktop router exposes live task status for shell polling" do
|
||||
assert {:ok, task} =
|
||||
BDS.Tasks.register_external_task("preview build", %{
|
||||
group_id: "generation",
|
||||
group_name: "Generation"
|
||||
})
|
||||
|
||||
on_exit(fn ->
|
||||
_ = BDS.Tasks.complete_task(task.id)
|
||||
end)
|
||||
|
||||
assert :ok = BDS.Tasks.report_progress(task.id, 0.5, "halfway")
|
||||
|
||||
conn = conn(:get, "/api/tasks?k=#{Desktop.Auth.login_key()}")
|
||||
conn = BDS.Desktop.Router.call(conn, BDS.Desktop.Router.init([]))
|
||||
|
||||
assert conn.status == 200
|
||||
assert Plug.Conn.get_resp_header(conn, "content-type") == ["application/json; charset=utf-8"]
|
||||
|
||||
payload = Jason.decode!(conn.resp_body)
|
||||
|
||||
assert payload["active_count"] >= 1
|
||||
assert payload["running_task_message"] == "preview build: halfway"
|
||||
|
||||
assert Enum.any?(payload["tasks"], fn item ->
|
||||
item["id"] == task.id and item["group_name"] == "Generation" and item["progress"] == 0.5
|
||||
end)
|
||||
end
|
||||
|
||||
test "desktop router executes shell commands through the JSON api" do
|
||||
:ok = Ecto.Adapters.SQL.Sandbox.checkout(BDS.Repo)
|
||||
:ok = Ecto.Adapters.SQL.Sandbox.allow(BDS.Repo, self(), Process.whereis(BDS.Preview))
|
||||
|
||||
temp_dir = Path.join(System.tmp_dir!(), "bds-desktop-router-#{System.unique_integer([:positive])}")
|
||||
File.mkdir_p!(temp_dir)
|
||||
|
||||
on_exit(fn ->
|
||||
File.rm_rf(temp_dir)
|
||||
_ = BDS.Preview.stop_preview("default")
|
||||
end)
|
||||
|
||||
{:ok, project} = BDS.Projects.create_project(%{name: "Desktop Router", data_path: temp_dir})
|
||||
{:ok, _project} = BDS.Projects.set_active_project(project.id)
|
||||
|
||||
conn =
|
||||
conn(:post, "/api/commands?k=#{Desktop.Auth.login_key()}", Jason.encode!(%{"action" => "open_in_browser"}))
|
||||
|> Plug.Conn.put_req_header("content-type", "application/json")
|
||||
|
||||
conn = BDS.Desktop.Router.call(conn, BDS.Desktop.Router.init([]))
|
||||
|
||||
assert conn.status == 200
|
||||
assert Plug.Conn.get_resp_header(conn, "content-type") == ["application/json; charset=utf-8"]
|
||||
|
||||
payload = Jason.decode!(conn.resp_body)
|
||||
|
||||
assert payload["result"]["kind"] == "open_url"
|
||||
assert payload["result"]["project_id"] == project.id
|
||||
assert payload["result"]["url"] == "http://127.0.0.1:4123/"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -115,6 +115,39 @@ defmodule BDS.TasksTest do
|
||||
:completed
|
||||
end
|
||||
|
||||
test "status_snapshot exposes active task details for the desktop shell" do
|
||||
assert {:ok, first} =
|
||||
BDS.Tasks.register_external_task("preview build", %{
|
||||
group_id: "generation",
|
||||
group_name: "Generation"
|
||||
})
|
||||
|
||||
assert {:ok, second} =
|
||||
BDS.Tasks.register_external_task("reindex text", %{
|
||||
group_id: "search",
|
||||
group_name: "Search"
|
||||
})
|
||||
|
||||
on_exit(fn ->
|
||||
_ = BDS.Tasks.complete_task(first.id)
|
||||
_ = BDS.Tasks.complete_task(second.id)
|
||||
end)
|
||||
|
||||
assert :ok = BDS.Tasks.report_progress(first.id, 0.5, "halfway")
|
||||
|
||||
snapshot = BDS.Tasks.status_snapshot()
|
||||
|
||||
assert snapshot.active_count == 2
|
||||
assert snapshot.running_task_overflow == 1
|
||||
assert snapshot.running_task_message == "preview build: halfway"
|
||||
|
||||
assert [%{id: first_id, status: :running, progress: 0.5, group_name: "Generation"}, %{id: second_id, status: :running}] =
|
||||
snapshot.tasks
|
||||
|
||||
assert first_id == first.id
|
||||
assert second_id == second.id
|
||||
end
|
||||
|
||||
defp receive_started do
|
||||
receive do
|
||||
{:started, name, pid} -> {name, pid}
|
||||
|
||||
@@ -66,6 +66,15 @@ defmodule BDS.UI.ShellTest do
|
||||
state = Commands.handle_shortcut(state, %{meta: true, key: "b"})
|
||||
assert state.sidebar_visible == false
|
||||
|
||||
state = Commands.handle_shortcut(state, %{meta: true, key: "j"})
|
||||
assert state.panel.visible == true
|
||||
|
||||
state = Commands.handle_shortcut(state, %{meta: true, key: "1"})
|
||||
assert state.active_view == :posts
|
||||
|
||||
state = Commands.handle_shortcut(state, %{meta: true, key: "2"})
|
||||
assert state.active_view == :media
|
||||
|
||||
state = Commands.handle_shortcut(state, %{meta: true, key: "w"})
|
||||
assert state.tabs == []
|
||||
assert state.editor_route == :dashboard
|
||||
@@ -99,7 +108,7 @@ defmodule BDS.UI.ShellTest do
|
||||
assert html =~ ~s(id="bds-shell-bootstrap")
|
||||
assert html =~ ~s(src="/assets/app.js")
|
||||
assert html =~ ~s(href="/assets/app.css")
|
||||
assert html =~ ~s(Desktop shell ready)
|
||||
assert html =~ ~s("task_status")
|
||||
end
|
||||
|
||||
test "static shell bundle exists for direct browser inspection" do
|
||||
@@ -134,9 +143,51 @@ defmodule BDS.UI.ShellTest do
|
||||
assert js =~ "window-titlebar-menu-bar is-hidden"
|
||||
|
||||
assert css =~ ".window-titlebar-menu-bar.is-hidden"
|
||||
assert css =~ "--vscode-statusBar-background: #181818"
|
||||
assert css =~ ".status-bar-left,"
|
||||
assert css =~ "gap: 4px"
|
||||
assert css =~ "padding: 0 8px"
|
||||
assert css =~ "height: 100%"
|
||||
assert css =~ ".status-bar-language-select"
|
||||
assert css =~ ".status-bar-item.language-badge"
|
||||
assert css =~ ".status-bar-item.offline-badge"
|
||||
|
||||
assert js =~ "renderLanguageOptions"
|
||||
assert js =~ "status-bar-language-select"
|
||||
assert js =~ "setUiLanguage"
|
||||
end
|
||||
|
||||
test "static shell bundle polls live task status and renders a task-backed lower panel" do
|
||||
js = File.read!("/Users/gb/Projects/bDS2/priv/ui/app.js")
|
||||
|
||||
assert js =~ "/api/tasks"
|
||||
assert js =~ "/api/commands"
|
||||
assert js =~ "fetchTaskStatus"
|
||||
assert js =~ "executeBackendShellCommand"
|
||||
assert js =~ "applyShellCommandResult"
|
||||
assert js =~ "openTasksPanel"
|
||||
assert js =~ "No background tasks running"
|
||||
assert js =~ "task-list"
|
||||
assert js =~ "output-list"
|
||||
assert js =~ "git-log-list"
|
||||
assert js =~ "data-panel-tab=\"output\""
|
||||
assert js =~ "data-panel-tab=\"git_log\""
|
||||
end
|
||||
|
||||
test "static shell bundle binds base shell hotkeys and menu actions to existing shell functionality" do
|
||||
js = File.read!("/Users/gb/Projects/bDS2/priv/ui/app.js")
|
||||
|
||||
assert js =~ "window.addEventListener(\"keydown\""
|
||||
assert js =~ "event.metaKey"
|
||||
assert js =~ "case \"j\""
|
||||
assert js =~ "case \"1\""
|
||||
assert js =~ "case \"2\""
|
||||
assert js =~ "case \"\\\\\""
|
||||
assert js =~ "case \"view_posts\""
|
||||
assert js =~ "case \"view_media\""
|
||||
assert js =~ "executeBackendShellCommand(action)"
|
||||
assert js =~ "case \"metadata_diff\""
|
||||
assert js =~ "case \"regenerate_calendar\""
|
||||
assert js =~ "case \"fill_missing_translations\""
|
||||
end
|
||||
end
|
||||
|
||||
@@ -181,8 +181,10 @@ defmodule BDS.UI.WorkbenchTest do
|
||||
|
||||
state = MenuBar.execute(state, :toggle_sidebar)
|
||||
state = MenuBar.execute(state, :toggle_panel)
|
||||
state = MenuBar.execute(state, :view_media)
|
||||
|
||||
assert state.sidebar_visible == true
|
||||
assert state.panel.visible == true
|
||||
assert state.active_view == :media
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user