94 lines
4.0 KiB
Go
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")
|
|
}
|
|
}
|