Cthulhu is no longer a fork. Now it is a screen reader written in Golang.
This commit is contained in:
1 parent
a998fe67de
commit
069fc674dc
708 files changed
+112482
-532
No files matched your search
@@ -0,0 +1,141 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.stormux.org/storm/cthulhu/internal/config"
|
||||
"git.stormux.org/storm/cthulhu/internal/datetime"
|
||||
"git.stormux.org/storm/cthulhu/internal/input"
|
||||
"git.stormux.org/storm/cthulhu/internal/preferences"
|
||||
)
|
||||
|
||||
func TestDateTimeFormats(t *testing.T) {
|
||||
now := time.Date(2026, 9, 17, 19, 5, 0, 0, time.UTC)
|
||||
for _, tc := range []struct {
|
||||
command input.Command
|
||||
format, want string
|
||||
}{
|
||||
{input.PresentTime, "locale", "19:05:00"},
|
||||
{input.PresentTime, "12-hour", "07:05 PM"},
|
||||
{input.PresentTime, "12-hour-seconds", "07:05:00 PM"},
|
||||
{input.PresentTime, "24-hour-seconds", "19:05:00"},
|
||||
{input.PresentTime, "24-hour-seconds-words", "19 hours, 05 minutes and 00 seconds"},
|
||||
{input.PresentTime, "24-hour", "19:05"},
|
||||
{input.PresentTime, "24-hour-words", "19 hours and 05 minutes"},
|
||||
{input.PresentDate, "locale", "09/17/26"},
|
||||
{input.PresentDate, "numbers-dm", "17/09"},
|
||||
{input.PresentDate, "numbers-md", "09/17"},
|
||||
{input.PresentDate, "numbers-dmy", "17/09/2026"},
|
||||
{input.PresentDate, "numbers-mdy", "09/17/2026"},
|
||||
{input.PresentDate, "numbers-ymd", "2026/09/17"},
|
||||
{input.PresentDate, "full-dm", "Thursday, 17 September"},
|
||||
{input.PresentDate, "full-md", "Thursday, September 17"},
|
||||
{input.PresentDate, "full-dmy", "Thursday, 17 September, 2026"},
|
||||
{input.PresentDate, "full-mdy", "Thursday, September 17, 2026"},
|
||||
{input.PresentDate, "full-ymd", "2026. September 17, Thursday"},
|
||||
{input.PresentDate, "abbreviated-dm", "Thu, 17 Sep"},
|
||||
{input.PresentDate, "abbreviated-md", "Thu, Sep 17"},
|
||||
{input.PresentDate, "abbreviated-dmy", "Thu, 17 Sep, 2026"},
|
||||
{input.PresentDate, "abbreviated-mdy", "Thu, Sep 17, 2026"},
|
||||
{input.PresentDate, "abbreviated-ymd", "2026. Sep 17, Thu"},
|
||||
} {
|
||||
settings := config.DefaultSettings()
|
||||
if tc.command == input.PresentTime {
|
||||
settings.TimeFormat = tc.format
|
||||
} else {
|
||||
settings.DateFormat = tc.format
|
||||
}
|
||||
queue := &fakeSpeechQueue{spoken: make(chan string, 1), interrupt: make(chan struct{}, 1)}
|
||||
presentDateTime(queue, settings, tc.command, now)
|
||||
if got := <-queue.spoken; got != tc.want {
|
||||
t.Errorf("%s: %q want %q", tc.format, got, tc.want)
|
||||
}
|
||||
if len(queue.interrupt) != 1 {
|
||||
t.Fatal("command did not interrupt")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDateTimeOptionCounts(t *testing.T) {
|
||||
now := time.Date(2026, 9, 17, 19, 5, 0, 0, time.UTC)
|
||||
timeOptions := datetime.TimeOptions(now)
|
||||
dateOptions := datetime.DateOptions(now)
|
||||
wantTime := []string{
|
||||
"locale", "12-hour", "12-hour-seconds", "24-hour-seconds",
|
||||
"24-hour-seconds-words", "24-hour", "24-hour-words",
|
||||
}
|
||||
wantDate := []string{
|
||||
"locale", "numbers-dm", "numbers-md", "numbers-dmy", "numbers-mdy",
|
||||
"numbers-ymd", "full-dm", "full-md", "full-dmy", "full-mdy",
|
||||
"full-ymd", "abbreviated-dm", "abbreviated-md", "abbreviated-dmy",
|
||||
"abbreviated-mdy", "abbreviated-ymd",
|
||||
}
|
||||
if len(timeOptions) != len(wantTime) {
|
||||
t.Fatalf("time options: got %d, want %d", len(timeOptions), len(wantTime))
|
||||
}
|
||||
if len(dateOptions) != len(wantDate) {
|
||||
t.Fatalf("date options: got %d, want %d", len(dateOptions), len(wantDate))
|
||||
}
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
options []datetime.Option
|
||||
expected []string
|
||||
}{
|
||||
{"time", timeOptions, wantTime},
|
||||
{"date", dateOptions, wantDate},
|
||||
} {
|
||||
for index, option := range test.options {
|
||||
if option.Value != test.expected[index] {
|
||||
t.Fatalf("%s option %d = %q, want %q", test.name, index,
|
||||
option.Value, test.expected[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, option := range append(timeOptions, dateOptions...) {
|
||||
if option.Value == "" || option.Label == "" {
|
||||
t.Fatalf("empty option: %+v", option)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDateTimePreferencesLiveAndSaved(t *testing.T) {
|
||||
settings := config.DefaultSettings()
|
||||
settings.Path = filepath.Join(t.TempDir(), "settings.toml")
|
||||
live := &liveSettings{}
|
||||
live.Store(settings)
|
||||
worker := newPreferencesWorker(slog.New(slog.DiscardHandler), settings, nil)
|
||||
worker.live = live
|
||||
values := preferences.FromSettings(settings)
|
||||
values.TimeFormat, values.DateFormat = "24-hour-words", "abbreviated-mdy"
|
||||
response := worker.apply(context.Background(), preferences.Request{Values: values, Save: true, Close: true})
|
||||
if !response.Accepted || !response.Close {
|
||||
t.Fatalf("apply: %+v", response)
|
||||
}
|
||||
loaded, err := config.Load(settings.Path)
|
||||
if err != nil || loaded.TimeFormat != "24-hour-words" || loaded.DateFormat != "abbreviated-mdy" {
|
||||
t.Fatalf("saved formats: %+v %v", loaded, err)
|
||||
}
|
||||
queue := &fakeSpeechQueue{spoken: make(chan string, 1)}
|
||||
presentDateTime(queue, live.Load(), input.PresentTime, time.Date(2026, 9, 17, 0, 1, 0, 0, time.Local))
|
||||
if got := <-queue.spoken; got != "00 hours and 01 minutes" {
|
||||
t.Fatalf("live time: %s", got)
|
||||
}
|
||||
for _, field := range []string{"time", "date"} {
|
||||
bad := values
|
||||
if field == "time" {
|
||||
bad.TimeFormat = "invalid"
|
||||
} else {
|
||||
bad.DateFormat = "invalid"
|
||||
}
|
||||
if worker.apply(context.Background(), preferences.Request{Values: bad, Save: true}).Accepted {
|
||||
t.Fatal("invalid format accepted")
|
||||
}
|
||||
}
|
||||
if live.Load().TimeFormat != "24-hour-words" || live.Load().DateFormat != "abbreviated-mdy" {
|
||||
t.Fatal("invalid draft changed live settings")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user