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)
}
}
}