1package client
2
3import (
4 "io"
5 "log/slog"
6 "testing"
7
8 "github.com/stretchr/testify/mock"
9 "github.com/stretchr/testify/require"
10
11 "github.com/bnema/vev/internal/ports"
12 portsmocks "github.com/bnema/vev/internal/ports/mocks"
13)
14
15func TestClipboardInterceptCtrlV(t *testing.T) {
16 tests := []struct {
17 name string
18 in string
19 hasImage bool
20 reads bool
21 wantNext []string
22 wantImages int
23 }{
24 {name: "legacy with image", in: "a\x16b", hasImage: true, wantNext: []string{"a", "b"}, wantImages: 1},
25 {name: "kitty with image", in: "a\x1b[118;5ub", hasImage: true, wantNext: []string{"a", "b"}, wantImages: 1},
26 {name: "legacy without image forwards byte", in: "\x16", reads: true, wantNext: []string{"\x16"}},
27 {name: "kitty without image forwards sequence", in: "\x1b[118;5u", reads: true, wantNext: []string{"\x1b[118;5u"}},
28 {name: "kitty cyrillic layout base key", in: "\x1b[1084::118;5u", hasImage: true, wantImages: 1},
29 {name: "kitty with caps lock", in: "\x1b[118;69u", hasImage: true, wantImages: 1},
30 {name: "kitty release ignored", in: "\x1b[118;5:3u", wantNext: []string{"\x1b[118;5:3u"}},
31 {name: "other kitty key untouched", in: "\x1b[118;7u", wantNext: []string{"\x1b[118;7u"}},
32 {name: "inside paste untouched", in: "\x1b[200~\x1b[118;5u\x1b[201~", wantNext: []string{"\x1b[200~\x1b[118;5u\x1b[201~"}},
33 }
34 for _, tt := range tests {
35 t.Run(tt.name, func(t *testing.T) {
36 reader := portsmocks.NewMockClipboardReader(t)
37 if tt.hasImage {
38 reader.EXPECT().ReadImage(mock.Anything).Return("image/png", []byte{1}, nil).Times(tt.wantImages)
39 } else if tt.reads {
40 reader.EXPECT().ReadImage(mock.Anything).Return("", nil, ports.ErrNoClipboardImage).Once()
41 }
42 var next []string
43 images := 0
44 c := &clipboardIntercept{
45 coalescer: newPasteCoalescer(nil, func([]byte) {}),
46 reader: reader,
47 log: slog.New(slog.NewTextHandler(io.Discard, nil)),
48 sendImage: func(string, []byte) { images++ },
49 next: func(b []byte) { next = append(next, string(b)) },
50 }
51 c.Scan([]byte(tt.in))
52 require.Equal(t, tt.wantNext, next)
53 require.Equal(t, tt.wantImages, images)
54 })
55 }
56}