Vectrum
Sign In
134 lines · 4.0 KB · Go
package attach

import (
	"bytes"
	"encoding/hex"
	"errors"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
)

// fakeDesktop stands in for whatever helper this machine would have used.
// "cat" is the helper here: it exists everywhere this runs and it writes the
// bytes it is given, which is all any of the real ones do.
func fakeDesktop(t *testing.T, gs []grabber) {
	t.Helper()
	if runtime.GOOS == "windows" {
		t.Skip("the stand-in helper is a unix one")
	}
	old := grabbers
	grabbers = gs
	t.Cleanup(func() { grabbers = old })
}

func writeTemp(t *testing.T, name string, data []byte) string {
	t.Helper()
	p := filepath.Join(t.TempDir(), name)
	if err := os.WriteFile(p, data, 0o644); err != nil {
		t.Fatal(err)
	}
	return p
}

func TestClipboardReadsWhatTheHelperWrites(t *testing.T) {
	want := tinyPNG(t)
	fakeDesktop(t, []grabber{{cmd: "cat", args: []string{writeTemp(t, "clip.png", want)}}})

	im, err := Clipboard()
	if err != nil {
		t.Fatal(err)
	}
	if im.Media != "image/png" || !bytes.Equal(im.Data, want) {
		t.Errorf("got %s, %d bytes; want image/png, %d", im.Media, len(im.Data), len(want))
	}
	if im.Origin != "clipboard" {
		t.Errorf("origin = %q", im.Origin)
	}
}

// Text on the clipboard is what ctrl-V usually finds, and it has to come back
// as "no image" rather than as an error worth interrupting anyone over.
func TestClipboardOfTextIsNoImage(t *testing.T) {
	fakeDesktop(t, []grabber{{cmd: "cat", args: []string{writeTemp(t, "clip.txt", []byte("some copied words"))}}})

	if _, err := Clipboard(); !errors.Is(err, ErrNoImage) {
		t.Fatalf("err = %v; want ErrNoImage", err)
	}
}

// A helper that is not installed is not a failure: the next one in the list
// may be the one this desktop uses.
func TestClipboardFallsThroughToTheNextHelper(t *testing.T) {
	want := tinyPNG(t)
	fakeDesktop(t, []grabber{
		{cmd: "codey-no-such-clipboard-helper"},
		{cmd: "cat", args: []string{writeTemp(t, "clip.png", want)}},
	})

	im, err := Clipboard()
	if err != nil || !bytes.Equal(im.Data, want) {
		t.Fatalf("second helper not reached: %v", err)
	}
}

func TestClipboardWithNoHelperInstalledSaysSo(t *testing.T) {
	fakeDesktop(t, []grabber{{cmd: "codey-no-such-clipboard-helper"}})

	_, err := Clipboard()
	if err == nil {
		t.Fatal("a machine with no helper reported success")
	}
	// The message has to name the fix; "no image" would send someone looking
	// at their clipboard instead of at their packages.
	if !strings.Contains(err.Error(), "helper") {
		t.Errorf("unhelpful message: %v", err)
	}
}

// An image found and too big is worth saying out loud, unlike an empty
// clipboard: the person can see the screenshot they copied.
func TestClipboardReportsAnOversizeImage(t *testing.T) {
	big := append(tinyPNG(t), make([]byte, MaxBytes)...)
	fakeDesktop(t, []grabber{{cmd: "cat", args: []string{writeTemp(t, "big.png", big)}}})

	_, err := Clipboard()
	if !errors.Is(err, ErrTooBig) {
		t.Fatalf("err = %v; want ErrTooBig", err)
	}
}

func TestDecodeAppleScriptUnwrapsHexData(t *testing.T) {
	want := tinyPNG(t)
	out := "«data PNGf" + hex.EncodeToString(want) + "»\n"

	got, err := decodeAppleScript([]byte(out))
	if err != nil || !bytes.Equal(got, want) {
		t.Fatalf("decode = %d bytes, %v; want %d bytes", len(got), err, len(want))
	}
}

func TestDecodeAppleScriptOnAnEmptyClipboard(t *testing.T) {
	// osascript answers a clipboard with no PNG on it by failing, but an
	// empty or surprising line must not decode into rubbish either.
	if _, err := decodeAppleScript([]byte("\n")); err == nil {
		t.Error("nothing decoded into something")
	}
}

func TestDecodeHexLine(t *testing.T) {
	want := tinyPNG(t)
	got, err := decodeHexLine([]byte(strings.ToUpper(hex.EncodeToString(want)) + "\r\n"))
	if err != nil || !bytes.Equal(got, want) {
		t.Fatalf("decode = %d bytes, %v", len(got), err)
	}
}

// Whatever this machine is, it must offer some way to try.
func TestDefaultGrabbersExist(t *testing.T) {
	if len(defaultGrabbers()) == 0 {
		t.Fatal("no clipboard helpers are even attempted on " + runtime.GOOS)
	}
}