From 9d2a6561041a59497567026189b1d8e011b4e903 Mon Sep 17 00:00:00 2001 From: Aly Raffauf Date: Sun, 5 Jul 2026 13:54:50 -0400 Subject: [PATCH] Move default browser logic to host package and unify test commands --- .github/workflows/ci.yml | 8 ++----- gtk/config.go | 21 ------------------ gtk/dialog_default_browser.go | 3 ++- gtk/window_settings.go | 3 ++- internal/host/host.go | 19 ++++++++++++++++ internal/host/host_test.go | 42 +++++++++++++++++++++++++++++++++++ justfile | 18 ++++----------- 7 files changed, 71 insertions(+), 43 deletions(-) create mode 100644 internal/host/host_test.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 868d309..25071b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,12 +29,8 @@ jobs: run: | scripts/generate-flatpak-go-modules.py git diff --exit-code -- flatpak/go-modules.json - - name: Test routing package with coverage - run: just test-routing-coverage - - name: Test config package - run: just test-config - - name: Test browser package - run: just test-browser + - name: Test internal packages with coverage + run: just test-coverage - name: Display coverage summary run: | echo "## Test Coverage Summary" >> $GITHUB_STEP_SUMMARY diff --git a/gtk/config.go b/gtk/config.go index a22536d..e666361 100644 --- a/gtk/config.go +++ b/gtk/config.go @@ -5,10 +5,8 @@ package gtk import ( "fmt" "os" - "strings" appconfig "github.com/alyraffauf/switchyard/internal/config" - "github.com/alyraffauf/switchyard/internal/host" "github.com/alyraffauf/switchyard/internal/routing" ) @@ -34,25 +32,6 @@ func saveConfig(config *Config) error { return appconfig.Save(configPath(), config) } -func isDefaultBrowser() bool { - cmd := host.HostCommand("xdg-settings", "get", "default-web-browser") - - output, err := cmd.Output() - if err != nil { - return false - } - - defaultBrowser := strings.TrimSpace(string(output)) - desktopFile := getAppID() + ".desktop" - return defaultBrowser == desktopFile -} - -func setAsDefaultBrowser() error { - desktopFile := getAppID() + ".desktop" - cmd := host.HostCommand("xdg-settings", "set", "default-web-browser", desktopFile) - return cmd.Run() -} - func exportConfig(config *Config, path string) error { return appconfig.Export(path, config) } diff --git a/gtk/dialog_default_browser.go b/gtk/dialog_default_browser.go index fbac13d..cc247e9 100644 --- a/gtk/dialog_default_browser.go +++ b/gtk/dialog_default_browser.go @@ -3,6 +3,7 @@ package gtk import ( + "github.com/alyraffauf/switchyard/internal/host" "github.com/diamondburned/gotk4-adwaita/pkg/adw" "github.com/diamondburned/gotk4/pkg/gtk/v4" ) @@ -25,7 +26,7 @@ func showDefaultBrowserPrompt(parent gtk.Widgetter, cfg *Config, updateUI func() dialog.ConnectResponse(func(response string) { if response == "yes" { - setAsDefaultBrowser() + host.SetDefaultBrowser(getAppID()) cfg.CheckDefaultBrowser = false saveConfig(cfg) updateUI() diff --git a/gtk/window_settings.go b/gtk/window_settings.go index d27e2ff..a522000 100644 --- a/gtk/window_settings.go +++ b/gtk/window_settings.go @@ -5,6 +5,7 @@ package gtk import ( "context" + "github.com/alyraffauf/switchyard/internal/host" "github.com/diamondburned/gotk4-adwaita/pkg/adw" "github.com/diamondburned/gotk4/pkg/gio/v2" "github.com/diamondburned/gotk4/pkg/glib/v2" @@ -34,7 +35,7 @@ func showSettingsWindow(app *adw.Application, browsers []*Browser, cfg *Config) win.SetContent(splitView) - if cfg.CheckDefaultBrowser && !isDefaultBrowser() { + if cfg.CheckDefaultBrowser && !host.IsDefaultBrowser(getAppID()) { showDefaultBrowserPrompt(win, cfg, func() {}) } diff --git a/internal/host/host.go b/internal/host/host.go index 5a28abf..5d143fc 100644 --- a/internal/host/host.go +++ b/internal/host/host.go @@ -8,8 +8,11 @@ package host import ( "os" "os/exec" + "strings" ) +const desktopSuffix = ".desktop" + // InFlatpak reports whether the process is running inside a Flatpak sandbox. func InFlatpak() bool { return os.Getenv("FLATPAK_ID") != "" @@ -24,3 +27,19 @@ func HostCommand(name string, args ...string) *exec.Cmd { hostArgs := append([]string{"--host", name}, args...) return exec.Command("flatpak-spawn", hostArgs...) } + +// IsDefaultBrowser reports whether appID's desktop entry is the system default +// web browser, per xdg-settings. +func IsDefaultBrowser(appID string) bool { + output, err := HostCommand("xdg-settings", "get", "default-web-browser").Output() + if err != nil { + return false + } + return strings.TrimSpace(string(output)) == appID+desktopSuffix +} + +// SetDefaultBrowser registers appID's desktop entry as the system default web +// browser, per xdg-settings. +func SetDefaultBrowser(appID string) error { + return HostCommand("xdg-settings", "set", "default-web-browser", appID+desktopSuffix).Run() +} diff --git a/internal/host/host_test.go b/internal/host/host_test.go new file mode 100644 index 0000000..184359c --- /dev/null +++ b/internal/host/host_test.go @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package host + +import ( + "slices" + "testing" +) + +func TestInFlatpak(t *testing.T) { + t.Setenv("FLATPAK_ID", "") + if InFlatpak() { + t.Fatal("want false when FLATPAK_ID is empty") + } + + t.Setenv("FLATPAK_ID", "io.example.App") + if !InFlatpak() { + t.Fatal("want true when FLATPAK_ID is set") + } +} + +func TestHostCommandRunsDirectlyWhenNotSandboxed(t *testing.T) { + t.Setenv("FLATPAK_ID", "") + + cmd := HostCommand("xdg-open", "https://example.com") + + want := []string{"xdg-open", "https://example.com"} + if !slices.Equal(cmd.Args, want) { + t.Fatalf("args: got %v, want %v", cmd.Args, want) + } +} + +func TestHostCommandWrapsWithSpawnWhenSandboxed(t *testing.T) { + t.Setenv("FLATPAK_ID", "io.example.App") + + cmd := HostCommand("xdg-open", "https://example.com") + + want := []string{"flatpak-spawn", "--host", "xdg-open", "https://example.com"} + if !slices.Equal(cmd.Args, want) { + t.Fatalf("args: got %v, want %v", cmd.Args, want) + } +} diff --git a/justfile b/justfile index 91ba68b..fe531d1 100644 --- a/justfile +++ b/justfile @@ -55,27 +55,17 @@ update-go-deps: scripts/generate-flatpak-go-modules.py # Run unit tests -test-routing: - go test -v ./internal/routing - -test-config: - go test -v ./internal/config - -test-browser: - go test -v ./internal/browser - -test: test-routing test-config test-browser +test: + go test ./internal/... # Run tests with coverage report -test-routing-coverage: +test-coverage: @echo "Running tests with coverage..." - go test -v -coverprofile=coverage.out ./internal/routing + go test -coverprofile=coverage.out ./internal/... go tool cover -func=coverage.out @echo "" @echo "To view HTML coverage report, run: go tool cover -html=coverage.out" -test-coverage: test-config test-browser test-routing-coverage - # Build and install Flatpak (development version) flatpak: [ -f build-repo/config ] || rm -rf build-repo -- 2.51.2