98 lines
3.0 KiB
Go
98 lines
3.0 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.stormux.org/storm/cthulhu/internal/atspi"
|
|
"git.stormux.org/storm/cthulhu/internal/input"
|
|
"git.stormux.org/storm/cthulhu/internal/review"
|
|
)
|
|
|
|
type listTestSource struct {
|
|
keys *uiTestKeys
|
|
selected chan int
|
|
count int
|
|
}
|
|
|
|
func (source *listTestSource) ListDocument(context.Context, review.DocumentTarget, int) (review.DocumentListSnapshot, error) {
|
|
list := review.DocumentListSnapshot{Selected: source.count - 1}
|
|
for index := 0; index < source.count; index++ {
|
|
list.Entries = append(list.Entries, review.DocumentListEntry{DocumentPosition: review.DocumentPosition{Snapshot: atspi.Snapshot{Name: fmt.Sprintf("Example %03d", index), Role: "link"}}})
|
|
}
|
|
return list, nil
|
|
}
|
|
func (source *listTestSource) SelectDocumentList(_ review.DocumentListSnapshot, index int) error {
|
|
if source.keys.InternalUISession() != 0 {
|
|
index = -1
|
|
}
|
|
source.selected <- index
|
|
return nil
|
|
}
|
|
|
|
func TestBrowserListNavigationSelectionAndCancellation(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
keys := &uiTestKeys{}
|
|
source := &listTestSource{keys: keys, selected: make(chan int, 1), count: 300}
|
|
output := &ocrTestOutput{speech: make(chan speechRequest, 16)}
|
|
ui := &internalUI{keys: keys, documents: source, speech: output, gate: &focusGate{}, events: make(chan input.CommandEvent, 16), done: make(chan struct{})}
|
|
go ui.run(ctx)
|
|
defer func() { cancel(); <-ui.done }()
|
|
wait := func(want string) {
|
|
t.Helper()
|
|
select {
|
|
case message := <-output.speech:
|
|
if message.Text != want {
|
|
t.Fatalf("got %q want %q", message.Text, want)
|
|
}
|
|
case <-ctx.Done():
|
|
t.Fatal(ctx.Err())
|
|
}
|
|
}
|
|
send := func(symbol uint32) {
|
|
ui.Handle(input.CommandEvent{Command: input.InternalUIKey, UISession: 1, Chord: input.CommandChord{Symbol: symbol}})
|
|
}
|
|
ui.Handle(input.CommandEvent{Command: input.DocumentListLinks})
|
|
wait("Links: 300 items found. Example 299")
|
|
send(0xff50)
|
|
wait("Example 000")
|
|
send(0xff54)
|
|
wait("Example 001")
|
|
send(0xff0d)
|
|
select {
|
|
case index := <-source.selected:
|
|
if index != 1 {
|
|
t.Fatalf("selected %d or keyboard capture retained", index)
|
|
}
|
|
case <-ctx.Done():
|
|
t.Fatal("selection did not finish")
|
|
}
|
|
ui.Handle(input.CommandEvent{Command: input.DocumentListLinks})
|
|
wait("Links: 300 items found. Example 299")
|
|
send(0xff1b)
|
|
// A second request is processed after Escape, establishing cancellation
|
|
// without a timing assumption or a selection callback.
|
|
ui.Handle(input.CommandEvent{Command: input.DocumentListLinks})
|
|
wait("Links: 300 items found. Example 299")
|
|
select {
|
|
case <-source.selected:
|
|
t.Fatal("Escape selected an item")
|
|
default:
|
|
}
|
|
send(0xff1b)
|
|
}
|
|
|
|
func TestBrowserListCatalogMapsAllOrcaListTypes(t *testing.T) {
|
|
for _, binding := range input.DocumentListBindings() {
|
|
if documentListTarget(binding) == 0 {
|
|
t.Fatalf("unhandled %s", binding.Command)
|
|
}
|
|
}
|
|
}
|