Files
cthulhu/internal/app/clipboard_copy_test.go

111 lines
2.9 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package app
import (
"context"
"testing"
"time"
"git.stormux.org/storm/cthulhu/internal/input"
"git.stormux.org/storm/cthulhu/internal/ocr"
)
func TestCopyFeedbackRequiresClipboardChangeAndNewCopyKey(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
changes := make(chan struct{})
tracker := &input.IntentTracker{}
speech := &fakeSpeechQueue{spoken: make(chan string, 4), interrupt: make(chan struct{}, 4)}
done := runCopyFeedback(ctx, changes, tracker, speech, nil, nil)
checkSilent := func() {
t.Helper()
select {
case got := <-speech.spoken:
t.Fatalf("unexpected speech %q", got)
case <-time.After(30 * time.Millisecond):
}
}
change := func() { changes <- struct{}{} }
change()
checkSilent()
tracker.Observe(input.NewKeyEvent(0, true, "Control_L"))
tracker.Observe(input.NewKeyEvent(0, true, "c"))
checkSilent()
change()
select {
case got := <-speech.spoken:
if got != "copied to clipboard" {
t.Fatalf("copy speech = %q", got)
}
case <-time.After(time.Second):
t.Fatal("copy was not announced")
}
change()
checkSilent()
tracker.Observe(input.NewKeyEvent(0, true, "c"))
change()
select {
case got := <-speech.spoken:
if got != "copied to clipboard" {
t.Fatalf("second copy speech = %q", got)
}
case <-time.After(time.Second):
t.Fatal("second copy was not announced")
}
tracker.Observe(input.NewKeyEvent(0, true, "v"))
change()
checkSilent()
cancel()
select {
case <-done:
case <-time.After(time.Second):
t.Fatal("copy worker did not stop")
}
}
func TestCopyFeedbackDoesNotRepeatOCRCopy(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
changes := make(chan struct{})
tracker := &input.IntentTracker{}
speech := &fakeSpeechQueue{spoken: make(chan string, 2), interrupt: make(chan struct{}, 2)}
session := &ocrSession{cursor: ocr.NewCursor(ocr.Result{Text: "OCR"}), cancel: func() {}}
done := runCopyFeedback(ctx, changes, tracker, speech, nil, session)
tracker.Observe(input.NewKeyEvent(0, true, "Control_L"))
tracker.Observe(input.NewKeyEvent(0, true, "c"))
changes <- struct{}{}
select {
case got := <-speech.spoken:
t.Fatalf("duplicate OCR copy feedback %q", got)
case <-time.After(30 * time.Millisecond):
}
session.mu.Lock()
session.cursor, session.cancel = nil, nil
session.mu.Unlock()
changes <- struct{}{}
select {
case got := <-speech.spoken:
t.Fatalf("late duplicate OCR copy feedback %q", got)
case <-time.After(30 * time.Millisecond):
}
tracker.Observe(input.NewKeyEvent(0, true, "c"))
changes <- struct{}{}
select {
case got := <-speech.spoken:
if got != "copied to clipboard" {
t.Fatal(got)
}
case <-time.After(time.Second):
t.Fatal("ordinary copy feedback was suppressed")
}
cancel()
select {
case <-done:
case <-time.After(time.Second):
t.Fatal("copy worker did not stop")
}
}