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