1package tui
2
3import (
4 "bytes"
5 "context"
6 "errors"
7 "os"
8 "path/filepath"
9 "runtime"
10 "testing"
11)
12
13func TestReadClipboardTextCommandsUsesAvailableCommand(t *testing.T) {
14 if runtime.GOOS == "windows" {
15 t.Skip("test helper is a shell script")
16 }
17 dir := t.TempDir()
18 path := filepath.Join(dir, "clipboard-test")
19 if err := os.WriteFile(path, []byte("#!/bin/sh\nprintf 'clipboard text'\n"), 0o700); err != nil {
20 t.Fatal(err)
21 }
22 t.Setenv("PATH", dir)
23
24 text, ok, err := readClipboardTextCommands(clipboardTextCommand{name: "clipboard-test"})
25 if err != nil {
26 t.Fatal(err)
27 }
28 if !ok || text != "clipboard text" {
29 t.Fatalf("text = %q, ok = %v", text, ok)
30 }
31}
32
33func TestReadClipboardTextCommandsReportsUnavailable(t *testing.T) {
34 t.Setenv("PATH", t.TempDir())
35 _, ok, err := readClipboardTextCommands(clipboardTextCommand{name: "missing-clipboard-command"})
36 if ok || err != errClipboardCommandUnavailable {
37 t.Fatalf("ok = %v, err = %v", ok, err)
38 }
39}
40
41func TestWriteClipboardTextCommandsPassesTextOnStdin(t *testing.T) {
42 if runtime.GOOS == "windows" {
43 t.Skip("test helper is a shell script")
44 }
45 dir := t.TempDir()
46 payload := filepath.Join(dir, "clipboard-payload")
47 path := filepath.Join(dir, "clipboard-test")
48 if err := os.WriteFile(path, []byte("#!/bin/sh\n/bin/cat > \"$CLIPBOARD_TEST_PAYLOAD\"\n"), 0o700); err != nil {
49 t.Fatal(err)
50 }
51 t.Setenv("PATH", dir)
52 t.Setenv("CLIPBOARD_TEST_PAYLOAD", payload)
53
54 if err := writeClipboardTextCommands(context.Background(), "https://example.com/oauth?state=xyz", clipboardTextCommand{name: "clipboard-test"}); err != nil {
55 t.Fatal(err)
56 }
57 got, err := os.ReadFile(payload)
58 if err != nil {
59 t.Fatal(err)
60 }
61 if string(got) != "https://example.com/oauth?state=xyz" {
62 t.Fatalf("clipboard payload = %q", got)
63 }
64}
65
66func TestWriteClipboardTextCommandsHonorsCancellation(t *testing.T) {
67 if runtime.GOOS == "windows" {
68 t.Skip("test helper is a shell script")
69 }
70 dir := t.TempDir()
71 path := filepath.Join(dir, "clipboard-test")
72 if err := os.WriteFile(path, []byte("#!/bin/sh\nexit 0\n"), 0o700); err != nil {
73 t.Fatal(err)
74 }
75 t.Setenv("PATH", dir)
76 ctx, cancel := context.WithCancel(context.Background())
77 cancel()
78
79 err := writeClipboardTextCommands(ctx, "clipboard text", clipboardTextCommand{name: "clipboard-test"})
80 if !errors.Is(err, context.Canceled) {
81 t.Fatalf("error = %v, want context cancellation", err)
82 }
83}
84
85func TestWriteClipboardTextOSC52EncodesPayload(t *testing.T) {
86 var out bytes.Buffer
87 if err := WriteClipboardTextOSC52(&out, "https://example.com/oauth?state=xyz"); err != nil {
88 t.Fatal(err)
89 }
90 const want = "\x1b]52;c;aHR0cHM6Ly9leGFtcGxlLmNvbS9vYXV0aD9zdGF0ZT14eXo=\a"
91 if got := out.String(); got != want {
92 t.Fatalf("OSC 52 = %q, want %q", got, want)
93 }
94}
95
96func TestSupportsOSC52ClipboardForVev(t *testing.T) {
97 t.Setenv("TERM_PROGRAM", "vev")
98 if !SupportsOSC52Clipboard() {
99 t.Fatal("Vev terminal did not advertise OSC 52 clipboard support")
100 }
101}
102
103func TestSupportsOSC52ClipboardRejectsUnknownTerminal(t *testing.T) {
104 t.Setenv("TERM_PROGRAM", "")
105 if SupportsOSC52Clipboard() {
106 t.Fatal("unknown terminal advertised OSC 52 clipboard support")
107 }
108}