Files

94 lines
4.0 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package interaction
import "testing"
func secretForm(text string) Form {
return Form{Title: "Connection", Elements: []Element{
{ID: "key", Label: "Channel key", Kind: Entry, Secret: true, Text: text, Required: true, MaxLength: 12},
{ID: "connect", Label: "Connect", Kind: Button},
}}
}
func TestSecretEntryEditingAndPresentation(t *testing.T) {
session, err := NewSession(secretForm("猫é123"))
if err != nil {
t.Fatal(err)
}
if got := session.Opening(); got.Speech != "Connection. Channel key, password edit, 5 characters" || got.Braille != "Channel key, password edit: *****" || got.Cursor != 33 {
t.Fatalf("unexpected masked opening: %+v", got)
}
steps := []struct {
event Event
speech, text, braille string
}{
{Event{Key: Home}, "Hidden character", "猫é123", "Channel key, password edit: *****"},
{Event{Key: Right, Shift: true}, "Hidden character, selected", "猫é123", "Channel key, password edit: ***** (selected 1 characters)"},
{Event{Text: "密"}, "Inserted 1 character", "密é123", "Channel key, password edit: *****"},
{Event{Key: Delete}, "Deleted 1 character", "密123", "Channel key, password edit: ****"},
{Event{Key: Backspace}, "Deleted 1 character", "123", "Channel key, password edit: ***"},
{Event{Key: End}, "End of text", "123", "Channel key, password edit: ***"},
{Event{Text: "a", Control: true}, "Selected all", "123", "Channel key, password edit: *** (selected 3 characters)"},
{Event{Text: "c", Control: true}, "Copy and cut are unavailable for password fields", "123", "Channel key, password edit: *** (selected 3 characters)"},
{Event{Text: "x", Control: true}, "Copy and cut are unavailable for password fields", "123", "Channel key, password edit: *** (selected 3 characters)"},
{Event{Key: Backspace}, "Deleted 3 characters", "", "Channel key, password edit: "},
{Event{Key: Enter}, "Channel key is required", "", "Channel key is required"},
}
for index, step := range steps {
effect := session.Handle(step.event)
if effect.Speech != step.speech || effect.Braille != step.braille || effect.Copy != nil || effect.Activated != "" || session.Values()["key"].Text != step.text {
t.Fatalf("secret editing step %d failed", index)
}
}
if !session.Handle(Event{Text: "v", Control: true}).Paste {
t.Fatal("explicit paste not requested")
}
if effect := session.Insert("pasted猫"); effect.Speech != "Inserted 7 characters" || effect.Braille != "Channel key, password edit: *******" {
t.Fatal("paste was not masked")
}
for _, text := range []string{"oversized content", "bad\ntext", string([]byte{0xff})} {
session.Insert(text)
if session.Values()["key"].Text != "pasted猫" {
t.Fatal("invalid paste modified secret")
}
}
session.Handle(Event{Key: Tab})
if got := session.Handle(Event{Key: Tab, Shift: true}); got.Speech != "Channel key, password edit, 7 characters" {
t.Fatal("returning to password did not mask it")
}
session.Handle(Event{Key: Tab})
if effect := session.Handle(Event{Key: Enter}); effect.Activated != "connect" || session.Values()["key"].Text != "pasted猫" {
t.Fatal("submission lost the actual secret")
}
}
func TestSecretEntryCloseAndValidation(t *testing.T) {
for _, escape := range []bool{false, true} {
session, _ := NewSession(secretForm("fixture"))
if escape {
if !session.Handle(Event{Key: Escape}).Cancelled {
t.Fatal("escape did not cancel")
}
} else {
session.Close()
}
session.Close()
if session.Values() != nil || session.Presentation() != (Presentation{}) || session.Insert("more") != (Effect{}) {
t.Fatal("closed editor retained or accepted a secret")
}
}
for _, kind := range []Kind{List, CheckBox, Button} {
form := secretForm("")
form.Elements[0].Kind = kind
if _, err := NewSession(form); err == nil {
t.Fatal("secret accepted on non-entry")
}
}
if err := ValidatePreferences(secretForm("fixture")); err == nil {
t.Fatal("secret accepted in persistent preferences")
}
}