// Fenrir console screen reader. // Copyright (c) 2026 Storm Dragon // SPDX-License-Identifier: GPL-3.0-or-later package app import ( "context" "errors" "reflect" "testing" "git.stormux.org/storm/fenrir/internal/clipboard" "git.stormux.org/storm/fenrir/internal/command" "git.stormux.org/storm/fenrir/internal/interaction" ) func TestEmojiMenuCancellationCopyAndStaleClipboardSync(t *testing.T) { for _, query := range []string{"Jack", "Black cat", "United States", "Coffin"} { t.Run(query, func(t *testing.T) { host, worker, _, _ := clipboard_fixture() host.add("original", false) host.poll() stale := worker.requests[0] keys, voice := &fakeKeys{}, &fakeVoice{} ui := new_internal_ui(context.Background(), keys, voice) ui.open_emoji(host) if voice.messages[0] != "Emoji Menu. All tab" { t.Fatal(voice.messages) } ui.handle(interaction.Key{Name: "tab"}) ui.handle(interaction.Key{Text: query}) ui.handle(interaction.Key{Name: "escape"}) if got, _ := host.history.Current(); got != "original" || host.revision != stale.Revision { t.Fatal("cancel changed clipboard", got) } ui.open_emoji(host) ui.handle(interaction.Key{Name: "tab"}) ui.handle(interaction.Key{Text: query + "zzzz"}) ui.handle(interaction.Key{Name: "enter"}) if !ui.active { t.Fatal("empty results closed menu") } ui.handle(interaction.Key{Name: "backspace", Ctrl: true}) ui.handle(interaction.Key{Text: query}) ui.handle(interaction.Key{Name: "enter"}) want := map[string]string{"Jack": "πŸŽƒ", "Black cat": "πŸˆβ€β¬›", "United States": "πŸ‡ΊπŸ‡Έ", "Coffin": "⚰️"}[query] if got, _ := host.history.Current(); got != want || ui.active || !host.dirty { t.Fatal("selection not copied", got, ui.active, host.dirty) } host.result(clipboard.Result{Request: stale, Text: "stale X clipboard"}) if got, _ := host.history.Current(); got != want { t.Fatal("stale import replaced emoji", got) } host.poll() request := worker.requests[len(worker.requests)-1] if request.Command != command.ExportXClipboard || request.Text != want { t.Fatal("emoji not offered to sync", request) } host.history.Move(1) if got, _ := host.history.Current(); got != "original" { t.Fatal("history lost", got) } if !reflect.DeepEqual(keys.captures, []bool{true, false, true, false}) { t.Fatal(keys.captures) } }) } } func TestEmojiMenuCaptureFailureDoesNotChangeClipboard(t *testing.T) { host, _, _, _ := clipboard_fixture() keys, voice := &fakeKeys{captureErr: errors.New("capture refused")}, &fakeVoice{} ui := new_internal_ui(context.Background(), keys, voice) ui.open_emoji(host) if ui.active || host.revision != 0 || len(voice.messages) != 1 { t.Fatal(ui.active, host.revision, voice.messages) } }