// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package app import ( "context" "log/slog" "reflect" "testing" "git.stormux.org/storm/cthulhu/internal/atspi" "git.stormux.org/storm/cthulhu/internal/presentation" "git.stormux.org/storm/cthulhu/internal/sound" ) func TestComboSelectionSpeaksValueWithoutRepeatingRoleSound(t *testing.T) { for _, kind := range []string{atspi.FocusEvent, atspi.FocusedStateEvent, atspi.AccessibleNameEvent, atspi.AccessibleValueEvent, atspi.ValueChangedEvent} { t.Run(kind, func(t *testing.T) { queue := &modeSoundQueue{speech: &fakeSpeechQueue{spoken: make(chan string, 16)}, sounds: make(chan sound.Cue, 16)} adapter := &fakeAdapter{events: make(chan atspi.Event, 16)} combo := atspi.Snapshot{BusName: ":1.70", Path: "/combo", Role: "combo box", Focused: true, ValueText: "bacon"} focus := atspi.NewEvent(atspi.FocusEvent, combo) adapter.events <- focus adapter.events <- focus // Providers can repeat focus while the combo stays active. for _, value := range []string{"hamburger", "steak", "hamburger", "bacon"} { combo.ValueText = value changed := atspi.NewEvent(kind, combo) changed.Detail1 = 1 changed.OriginPath = combo.Path adapter.events <- changed } adapter.events <- atspi.NewEvent(atspi.FocusEvent, atspi.Snapshot{BusName: combo.BusName, Path: "/other", Role: "entry", Name: "Other", Focused: true}) adapter.events <- focus close(adapter.events) options := presentation.DefaultOptions() options.EnableSound, options.PlaySoundForRole = true, true options.RoleSoundPresentation = "sound_only" processEventsWithInput(context.Background(), slog.New(slog.DiscardHandler), queue, adapter, nil, nil, 0, nil, nil, nil, nil, options) close(queue.speech.spoken) var got []string for text := range queue.speech.spoken { got = append(got, text) } want := []string{"bacon", "hamburger", "steak", "hamburger", "bacon", "Other, entry", "bacon"} if !reflect.DeepEqual(got, want) { t.Fatalf("speech = %q, want %q", got, want) } if len(queue.sounds) != 2 { t.Fatalf("got %d sounds, want only initial and returning focus", len(queue.sounds)) } for range 2 { if cue := <-queue.sounds; cue.Name != "combobox" { t.Fatalf("cue = %+v", cue) } } }) } }