129 lines
4.2 KiB
Go
129 lines
4.2 KiB
Go
// Fenrir console screen reader.
|
|
// Copyright (c) 2026 Storm Dragon
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package interaction
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func grid_form() Form {
|
|
return Form{Type: TabForm, Title: "Picker", Tabs: []Tab{{ID: "one", Label: "One", Controls: []Control{{
|
|
ID: "grid", Label: "Items", Kind: Grid, Columns: 3, Action: "choose",
|
|
Choices: []Choice{{ID: "a", Label: "Apple"}, {ID: "b", Label: "Bat"}, {ID: "c", Label: "Cat"},
|
|
{ID: "d", Label: "Dog"}, {ID: "j", Label: "Jack o'lantern"}, {ID: "jp", Label: "Japan"}, {ID: "é", Label: "Éclair"}},
|
|
}}}}}
|
|
}
|
|
|
|
func TestGridNavigationRaggedRowsAndActivation(t *testing.T) {
|
|
session, err := New_session(grid_form())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
session.Handle(Key{Name: "tab"})
|
|
for _, trial := range []struct{ key, want string }{
|
|
{"right", "b"}, {"up", "b"}, {"down", "j"}, {"down", "é"}, {"down", "é"},
|
|
{"up", "d"}, {"left", "c"}, {"home", "a"}, {"left", "a"}, {"end", "é"}, {"right", "é"},
|
|
} {
|
|
session.Handle(Key{Name: trial.key})
|
|
control, _ := session.Focused_control()
|
|
if got := control.Choices[control.Selected].ID; got != trial.want {
|
|
t.Fatalf("%s: got %s, want %s", trial.key, got, trial.want)
|
|
}
|
|
}
|
|
// XLookupString supplies carriage return alongside the named Enter key.
|
|
if got := session.Handle(Key{Name: "enter", Text: "\r"}); got.Action != "choose" {
|
|
t.Fatal(got)
|
|
}
|
|
}
|
|
|
|
func TestGridPrefixEmptyResultsUnicodeAndIsolation(t *testing.T) {
|
|
form := grid_form()
|
|
session, err := New_session(form)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
session.Handle(Key{Name: "tab"})
|
|
if got := session.Handle(Key{Text: "J"}); !strings.Contains(got.Speech, "Jack o'lantern") || !strings.Contains(got.Speech, "1 of 2") {
|
|
t.Fatal(got)
|
|
}
|
|
session.Handle(Key{Name: "right"})
|
|
control, _ := session.Focused_control()
|
|
if control.Selected != 5 {
|
|
t.Fatal("filtered selection lost catalog index", control)
|
|
}
|
|
control.Choices[5].Label = "changed"
|
|
if got := session.Handle(Key{Text: "z"}); !strings.Contains(got.Speech, "No matches") {
|
|
t.Fatal(got)
|
|
}
|
|
if got := session.Handle(Key{Name: "enter"}); got.Action != "" {
|
|
t.Fatal("empty results activated", got)
|
|
}
|
|
session.Handle(Key{Name: "backspace"})
|
|
if got := session.Handle(Key{Name: "right"}); !strings.Contains(got.Speech, "Japan") {
|
|
t.Fatal("focused value aliased session", got)
|
|
}
|
|
session.Handle(Key{Name: "backspace", Ctrl: true})
|
|
if got := session.Handle(Key{Text: "é"}); !strings.Contains(got.Speech, "Éclair") {
|
|
t.Fatal(got)
|
|
}
|
|
session.Handle(Key{Name: "backspace"})
|
|
control, _ = session.Focused_control()
|
|
if control.Text != "" || form.Tabs[0].Controls[0].Selected != 0 || form.Tabs[0].Controls[0].Text != "" {
|
|
t.Fatal("Unicode deletion or form isolation failed", control)
|
|
}
|
|
if got := session.Handle(Key{Name: "escape"}); !got.Cancelled {
|
|
t.Fatal(got)
|
|
}
|
|
}
|
|
|
|
func TestGridValidation(t *testing.T) {
|
|
form := grid_form()
|
|
form.Tabs[0].Controls[0].Columns = 0
|
|
if _, err := New_session(form); err == nil {
|
|
t.Fatal("zero-width grid accepted")
|
|
}
|
|
form = grid_form()
|
|
form.Tabs[0].Controls[0].Choices[1].ID = "a"
|
|
if _, err := New_session(form); err == nil {
|
|
t.Fatal("duplicate values accepted")
|
|
}
|
|
}
|
|
|
|
func TestGridSpeechDetailOptions(t *testing.T) {
|
|
for _, trial := range []struct {
|
|
coordinates, position bool
|
|
want, filtered string
|
|
}{
|
|
{true, true, "Bat. row 1, column 2. 2 of 7", "Japan. row 1, column 2. 2 of 2"},
|
|
{true, false, "Bat. row 1, column 2", "Japan. row 1, column 2"},
|
|
{false, true, "Bat. 2 of 7", "Japan. 2 of 2"},
|
|
{false, false, "Bat", "Japan"},
|
|
} {
|
|
session, err := New_session(grid_form())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
session.Configure_grid(trial.coordinates, trial.position)
|
|
session.Handle(Key{Name: "tab"})
|
|
if got := session.Handle(Key{Name: "right"}).Speech; got != trial.want {
|
|
t.Fatalf("%+v: %q", trial, got)
|
|
}
|
|
if got := session.Describe(); got != "Items grid. "+trial.want {
|
|
t.Fatal(got)
|
|
}
|
|
session.Handle(Key{Text: "j"})
|
|
if got := session.Handle(Key{Name: "right"}).Speech; got != trial.filtered {
|
|
t.Fatal(got)
|
|
}
|
|
if got := session.Handle(Key{Name: "enter"}).Action; got != "choose" {
|
|
t.Fatal(got)
|
|
}
|
|
if got := session.Handle(Key{Text: "zzz"}).Speech; got != "Search jzzz. No matches" {
|
|
t.Fatal(got)
|
|
}
|
|
}
|
|
}
|