omarchy-send/internal/client/message_test.go
28allday 098c34c546 Clipboard send/copy, PIN for messages, and quiet stdlib logging
- Messages to a PIN-protected peer now prompt for the PIN and retry, like
  file sends (was a silent failure). SendMessage takes a pin argument and the
  TUI tracks whether a pending send is a message or files.
- Copy a received message to the clipboard with `y` (in the Messages tab or
  while reading one).
- Send the clipboard as a message with `v` on a device: it opens the compose
  box pre-filled with the clipboard text to review before sending.
- New internal/clipboard package shells out to wl-clipboard / xclip / xsel,
  and falls back to tmux's paste buffer when running inside tmux on a headless
  box (tmux load-buffer -w also reaches the outer clipboard via set-clipboard,
  which omaterm enables by default). No system tool -> "clipboard unavailable".
- Route the standard logger to the debug log (or discard) at startup so stray
  stdlib logging — e.g. net/http's "unsolicited response on idle channel"
  notice after a peer sends a late response — can't paint over the TUI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 22:06:24 +01:00

54 lines
1.6 KiB
Go

package client
import (
"context"
"os"
"testing"
"time"
"omarchy-send/internal/discovery"
"omarchy-send/internal/protocol"
"omarchy-send/internal/server"
)
// A sent message must arrive on the receiver's Messages channel with its text
// and sender intact, and must NOT be written to disk as a file.
func TestSendMessageEndToEnd(t *testing.T) {
recvDir := t.TempDir()
recvInfo := protocol.DeviceInfo{
Alias: "recv", Version: protocol.ProtocolVersion, Port: 53990, Protocol: "http",
}
// AutoAccept is false on purpose: messages must bypass the accept prompt.
srv := server.New(server.Options{Info: recvInfo, ReceiveDir: recvDir, AutoAccept: false})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
if err := srv.Start(ctx); err != nil {
t.Fatalf("server start: %v", err)
}
go func() {
for range srv.Transfers() {
}
}()
time.Sleep(50 * time.Millisecond)
sender := New(protocol.DeviceInfo{Alias: "sender", Fingerprint: "snd1", Version: "2.1", Protocol: "http"})
peer := discovery.Peer{Info: recvInfo, IP: "127.0.0.1"}
sender.SendMessage(peer, "hello over the wire\nsecond line", "")
select {
case m := <-srv.Messages():
if m.Text != "hello over the wire\nsecond line" {
t.Fatalf("message text = %q", m.Text)
}
if m.From != "sender" {
t.Errorf("message from = %q, want \"sender\"", m.From)
}
case <-time.After(3 * time.Second):
t.Fatal("timed out waiting for the message")
}
// A message is not a file: nothing should land in the receive dir.
if entries, _ := os.ReadDir(recvDir); len(entries) != 0 {
t.Fatalf("message should not be saved; found %d entries in receive dir", len(entries))
}
}