Files
cthulhu/internal/app/clipboard_watch_test.go

100 lines
3.7 KiB
Go

package app
import (
"bytes"
"context"
"encoding/json"
"log/slog"
"testing"
"time"
"git.stormux.org/storm/cthulhu/internal/clipboard"
"git.stormux.org/storm/cthulhu/internal/config"
"git.stormux.org/storm/cthulhu/internal/input"
)
func TestAutomaticClipboardQueuesTextAndNormalInputCancels(t *testing.T) {
live := &liveSettings{}
settings := config.DefaultSettings()
if settings.Reading.AutomaticallyReadClipboardChanges {
t.Fatal("clipboard reading defaults on")
}
settings.Reading.AutomaticallyReadClipboardChanges = true
live.Store(settings)
worker := newSpeechWorker(slog.New(slog.DiscardHandler), nil)
worker.running = true // Inspect the real FIFO without a delivery goroutine.
changes := make(chan clipboard.TextChange, 6)
changes <- clipboard.TextChange{Text: "First", Epoch: 1, Timestamp: 10}
changes <- clipboard.TextChange{Text: "Second", Epoch: 1, Timestamp: 20}
changes <- clipboard.TextChange{Text: "", Epoch: 1, Timestamp: 30}
changes <- clipboard.TextChange{Text: "Third", Epoch: 1, Timestamp: 40}
close(changes)
var output bytes.Buffer
serve_clipboard_changes(context.Background(), live, nil, worker, json.NewEncoder(&output), changes, nil)
if len(worker.pending) != 3 {
t.Fatalf("clipboard queue = %+v", worker.pending)
}
for i, want := range []string{"First", "Second", "Third"} {
if worker.pending[i].Text != want || !worker.pending[i].Append {
t.Fatalf("clipboard request %d = %+v", i, worker.pending[i])
}
}
if !worker.InterruptForInput(input.Event{Pressed: true, Name: "Control_L", Timestamp: 50}) || len(worker.pending) != 0 {
t.Fatal("normal input did not clear clipboard queue")
}
worker.Enqueue(speechRequest{Text: "Late old clipboard", Cause: "clipboard", Append: true, ClipboardTimestamp: 40})
if len(worker.pending) != 0 {
t.Fatal("old asynchronous clipboard reply replayed after interruption")
}
worker.Enqueue(speechRequest{Text: "New clipboard", Cause: "clipboard", Append: true, ClipboardTimestamp: 60})
if len(worker.pending) != 1 {
t.Fatal("new clipboard change suppressed after interruption")
}
worker.Enqueue(speechRequest{Text: "Same millisecond copy", Cause: "clipboard", Append: true, ClipboardTimestamp: 50})
if len(worker.pending) != 2 {
t.Fatal("copy result in same server millisecond as input was suppressed")
}
}
func TestAutomaticClipboardRejectsDisabledAndStaleApplications(t *testing.T) {
for _, tc := range []struct {
name string
enabled, pending bool
}{
{"disabled", false, false}, {"switching", true, true}, {"stale epoch", true, false},
} {
t.Run(tc.name, func(t *testing.T) {
live := &liveSettings{}
settings := config.DefaultSettings()
settings.Reading.AutomaticallyReadClipboardChanges = tc.enabled
live.Store(settings)
if tc.pending {
name := "Other Application"
live.requestedApplication.Store(&name)
}
changes := make(chan clipboard.TextChange, 1)
changes <- clipboard.TextChange{Text: "Do not speak", Epoch: 0}
close(changes)
speech := &fakeSpeechQueue{spoken: make(chan string, 1), interrupt: make(chan struct{}, 1)}
var output bytes.Buffer
serve_clipboard_changes(context.Background(), live, nil, speech, json.NewEncoder(&output), changes, nil)
if len(speech.spoken) != 0 || len(speech.interrupt) != 0 {
t.Fatal("disabled/stale clipboard was spoken")
}
})
}
}
func TestAutomaticClipboardDisabledStartsNoHelperAndStops(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
live := &liveSettings{clipboardChanges: make(chan struct{}, 1)}
live.Store(config.DefaultSettings())
done := run_automatic_clipboard(ctx, slog.New(slog.DiscardHandler), live, nil, discardSpeech{})
cancel()
select {
case <-done:
case <-time.After(time.Second):
t.Fatal("disabled clipboard worker did not stop")
}
}