ajhahn.de
← eeco
Go 157 lines
package clip

import (
	"errors"
	"os/exec"
	"strings"
	"testing"
)

func withFakes(t *testing.T, os string, env map[string]string, present map[string]bool, capture *capturedRun) {
	t.Helper()
	oldGoos, oldEnv, oldLook, oldRunner := goos, getenv, lookPath, runner
	t.Cleanup(func() {
		goos, getenv, lookPath, runner = oldGoos, oldEnv, oldLook, oldRunner
	})
	goos = func() string { return os }
	getenv = func(k string) string { return env[k] }
	lookPath = func(name string) (string, error) {
		if present[name] {
			return "/fake/bin/" + name, nil
		}
		return "", exec.ErrNotFound
	}
	if capture != nil {
		runner = func(name string, args []string, stdin string) error {
			capture.name = name
			capture.args = args
			capture.stdin = stdin
			capture.calls++
			return capture.err
		}
	}
}

type capturedRun struct {
	name  string
	args  []string
	stdin string
	calls int
	err   error
}

func TestDetect_DarwinUsesPbcopy(t *testing.T) {
	withFakes(t, "darwin", nil, map[string]bool{"pbcopy": true}, nil)
	name, args, ok := detect()
	if !ok || name != "pbcopy" || len(args) != 0 {
		t.Fatalf("got name=%q args=%v ok=%v, want pbcopy [] true", name, args, ok)
	}
}

func TestDetect_LinuxWaylandPrefersWlCopy(t *testing.T) {
	withFakes(t, "linux",
		map[string]string{"WAYLAND_DISPLAY": "wayland-0"},
		map[string]bool{"wl-copy": true, "xclip": true},
		nil,
	)
	name, _, ok := detect()
	if !ok || name != "wl-copy" {
		t.Fatalf("got name=%q ok=%v, want wl-copy true", name, ok)
	}
}

func TestDetect_LinuxX11FallsBackToXclip(t *testing.T) {
	withFakes(t, "linux", nil, map[string]bool{"xclip": true, "xsel": true}, nil)
	name, args, ok := detect()
	if !ok || name != "xclip" || strings.Join(args, " ") != "-selection clipboard" {
		t.Fatalf("got name=%q args=%v ok=%v, want xclip -selection clipboard true", name, args, ok)
	}
}

func TestDetect_LinuxXselFallback(t *testing.T) {
	withFakes(t, "linux", nil, map[string]bool{"xsel": true}, nil)
	name, args, ok := detect()
	if !ok || name != "xsel" || strings.Join(args, " ") != "--clipboard --input" {
		t.Fatalf("got name=%q args=%v ok=%v, want xsel --clipboard --input true", name, args, ok)
	}
}

func TestDetect_LinuxNoWaylandEnvButWlCopyPresent(t *testing.T) {
	// No X11 tool; wl-copy reachable but WAYLAND_DISPLAY unset. The
	// final fallback inside the linux branch picks it up.
	withFakes(t, "linux", nil, map[string]bool{"wl-copy": true}, nil)
	name, _, ok := detect()
	if !ok || name != "wl-copy" {
		t.Fatalf("got name=%q ok=%v, want wl-copy true", name, ok)
	}
}

func TestDetect_WindowsUsesClipExe(t *testing.T) {
	withFakes(t, "windows", nil, map[string]bool{"clip.exe": true}, nil)
	name, _, ok := detect()
	if !ok || name != "clip.exe" {
		t.Fatalf("got name=%q ok=%v, want clip.exe true", name, ok)
	}
}

func TestDetect_NoToolReturnsFalse(t *testing.T) {
	withFakes(t, "linux", nil, nil, nil)
	if _, _, ok := detect(); ok {
		t.Fatalf("detect() ok=true with no tools present; want false")
	}
}

func TestDetect_UnknownGoosReturnsFalse(t *testing.T) {
	withFakes(t, "plan9", nil, map[string]bool{"pbcopy": true}, nil)
	if _, _, ok := detect(); ok {
		t.Fatalf("detect() ok=true on unknown GOOS; want false")
	}
}

func TestCopy_PipesTextToTool(t *testing.T) {
	var cap capturedRun
	withFakes(t, "darwin", nil, map[string]bool{"pbcopy": true}, &cap)
	if err := Copy("hello brief"); err != nil {
		t.Fatalf("Copy: %v", err)
	}
	if cap.name != "pbcopy" || cap.stdin != "hello brief" || cap.calls != 1 {
		t.Fatalf("got name=%q stdin=%q calls=%d, want pbcopy hello brief 1", cap.name, cap.stdin, cap.calls)
	}
}

func TestCopy_NoToolReturnsSentinel(t *testing.T) {
	withFakes(t, "linux", nil, nil, &capturedRun{})
	err := Copy("anything")
	if !errors.Is(err, ErrNoClipboardTool) {
		t.Fatalf("Copy err=%v, want ErrNoClipboardTool", err)
	}
}

func TestCopy_RunnerErrorIsWrapped(t *testing.T) {
	cap := capturedRun{err: errors.New("boom")}
	withFakes(t, "darwin", nil, map[string]bool{"pbcopy": true}, &cap)
	err := Copy("payload")
	if err == nil || !strings.Contains(err.Error(), "clip: pbcopy") || !strings.Contains(err.Error(), "boom") {
		t.Fatalf("Copy err=%v, want wrapped clip: pbcopy: boom", err)
	}
}

func TestInstallHint_PlatformSpecific(t *testing.T) {
	cases := []struct {
		os   string
		want string
	}{
		{"darwin", "pbcopy"},
		{"linux", "wl-copy"},
		{"windows", "clip.exe"},
		{"plan9", "no clipboard tool"},
	}
	for _, c := range cases {
		withFakes(t, c.os, nil, nil, nil)
		got := InstallHint()
		if !strings.Contains(got, c.want) {
			t.Errorf("InstallHint on %s = %q, want substring %q", c.os, got, c.want)
		}
	}
}