diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3a5a34..cc7c1a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,10 @@ jobs: - name: Ad-hoc sign run: codesign -s - --force --deep priv/native/macos/DesktopWebView || true - run: mix deps.get - - run: mix test + - name: Tests + run: | + mix test --exclude menu_crash + mix test --only menu_crash env: DESKTOP_WEBVIEW_BINARY: ${{ github.workspace }}/priv/native/macos/DesktopWebView @@ -78,7 +81,9 @@ jobs: run: ./scripts/build_linux.sh - run: mix deps.get - name: E2E under Xvfb - run: dbus-run-session -- xvfb-run -a mix test + run: | + dbus-run-session -- xvfb-run -a mix test --exclude menu_crash + dbus-run-session -- xvfb-run -a mix test --only menu_crash env: DESKTOP_WEBVIEW_BINARY: ${{ github.workspace }}/priv/native/linux/DesktopWebView WEBKIT_DISABLE_COMPOSITING_MODE: "1" @@ -108,7 +113,9 @@ jobs: - run: mix deps.get - name: E2E shell: pwsh - run: mix test + run: | + mix test --exclude menu_crash + mix test --only menu_crash env: DESKTOP_WEBVIEW_BINARY: ${{ github.workspace }}\priv\native\windows\DesktopWebView.exe WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS: --disable-gpu --disable-gpu-compositing diff --git a/test/e2e/e2e_test.exs b/test/e2e/e2e_test.exs index ec4c618..b4ce1b2 100644 --- a/test/e2e/e2e_test.exs +++ b/test/e2e/e2e_test.exs @@ -356,6 +356,65 @@ defmodule DesktopWebview.E2ETest do assert length(list) >= 2 end + defmodule IconMenu do + use Desktop.Menu, server: false + + def mount(menu), do: {:ok, menu} + def handle_event(_event, menu), do: {:noreply, menu} + def handle_info(_msg, menu), do: {:noreply, menu} + + def render(assigns) do + ~H""" +
+ """ + end + end + + @tag :menu_crash + test "menu process crash destroys native tray" do + assert {:ok, %{"icon_id" => iid}} = Transport.call("icon.create", %{}) + + # Own EventBridge from this process so Menu exit does not take it down. + DesktopWebview.EventBridge.ensure_started() + + test = self() + + parent = + spawn(fn -> + {:ok, pid} = + Desktop.Menu.start_link( + module: IconMenu, + adapter: DesktopWebview.Menu.Adapter, + wx: {:taskbar, {:icon, iid}} + ) + + send(test, {:menu, pid}) + + receive do + :crash -> exit(:crash) + end + end) + + assert_receive {:menu, menu}, 2000 + assert Process.alive?(menu) + + assert {:ok, trays} = Transport.call("test.tray.list", %{}) + assert Enum.any?(trays, &is_binary(&1["tray_id"])) + + ref = Process.monitor(menu) + + ExUnit.CaptureLog.capture_log(fn -> + send(parent, :crash) + assert_receive {:DOWN, ^ref, :process, ^menu, :crash}, 2000 + end) + + assert {:ok, []} = Transport.call("test.tray.list", %{}) + + restore_transport() + end + test "default edit menu is installed with copy/paste/cut/selectAll", %{platform: platform} do # The macOS host installs a default Edit submenu and exposes it via # test.menu.list. The Linux host uses GTK menu bars and does not yet @@ -395,6 +454,22 @@ defmodule DesktopWebview.E2ETest do end end + defp restore_transport do + case Process.whereis(Transport) do + pid when is_pid(pid) -> + if Process.alive?(pid) do + :ok + else + {:ok, _} = Transport.start_link([]) + :ok + end + + nil -> + {:ok, _} = Transport.start_link([]) + :ok + end + end + defp fixture_url(filename) do html = File.read!(Path.expand("test/fixtures/#{filename}")) "data:text/html;base64," <> Base.encode64(html)