Let the operator edit the station config in the window instead of hand-editing the file and relaunching.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+80
-53
@@ -4,12 +4,11 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"encoding/json/v2"
|
||||
)
|
||||
|
||||
func TestResolveConfigPathDefaultIsHome(t *testing.T) {
|
||||
@@ -86,20 +85,15 @@ func TestOpenStationUsesResolvedPath(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "custom.json")
|
||||
|
||||
_, err := openStation([]string{"-c", path})
|
||||
if err == nil {
|
||||
t.Fatal("openStation() error = nil, want rejection after creating the file")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "created") {
|
||||
t.Fatalf("openStation() error = %q, want it to say the file was created", err.Error())
|
||||
}
|
||||
|
||||
info, err := os.Stat(path)
|
||||
st, err := openStation([]string{"-c", path})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := info.Mode().Perm(), os.FileMode(0o600); got != want {
|
||||
t.Fatalf("mode = %o, want %o", got, want)
|
||||
if _, statErr := os.Stat(path); !os.IsNotExist(statErr) {
|
||||
t.Fatalf("stat = %v, want the file absent until Save", statErr)
|
||||
}
|
||||
if !st.State().NeedsConfig || !st.State().ConfigOpen {
|
||||
t.Fatalf("State = %+v, want the Config window open", st.State())
|
||||
}
|
||||
|
||||
// Same rules as the home file: a second open with a filled config works.
|
||||
@@ -116,7 +110,7 @@ func TestOpenStationUsesResolvedPath(t *testing.T) {
|
||||
if err := os.WriteFile(path, []byte(body), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, err := openStation([]string{"--config", path})
|
||||
st, err = openStation([]string{"--config", path})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -136,52 +130,35 @@ func TestConfigEqualsFlagSelectsTheFile(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatedFileViaFlagMatchesHomeTemplate(t *testing.T) {
|
||||
func TestMissingFileOpensWithoutStderr(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "lab.json")
|
||||
var stderr bytes.Buffer
|
||||
st, err := openStationReported([]string{"-c", path}, &stderr)
|
||||
if st != nil {
|
||||
t.Fatal("station = non-nil, want nil before the window")
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("error = nil, want the file created")
|
||||
}
|
||||
if got, want := err.Error(), "created "+path; got != want {
|
||||
t.Fatalf("error = %q, want %q", got, want)
|
||||
}
|
||||
if got, want := stderr.String(), err.Error()+"\n"; got != want {
|
||||
t.Fatalf("stderr = %q, want %q", got, want)
|
||||
}
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := info.Mode().Perm(), os.FileMode(0o600); got != want {
|
||||
t.Fatalf("mode = %o, want %o", got, want)
|
||||
if st == nil {
|
||||
t.Fatal("station = nil, want a station so the window can open")
|
||||
}
|
||||
body, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
if stderr.Len() != 0 {
|
||||
t.Fatalf("stderr = %q, want empty", stderr.String())
|
||||
}
|
||||
var got map[string]any
|
||||
if err := json.Unmarshal(body, &got); err != nil {
|
||||
t.Fatalf("created file is not JSON: %v\n%s", err, body)
|
||||
if _, statErr := os.Stat(path); !os.IsNotExist(statErr) {
|
||||
t.Fatalf("stat = %v, want the file absent", statErr)
|
||||
}
|
||||
if got["host"] != "" || got["callsign"] != "" || got["authKey"] != "" {
|
||||
t.Fatalf("string fields = %#v, want empty host, callsign, and authKey", got)
|
||||
if !st.State().NeedsConfig || !st.State().ConfigOpen {
|
||||
t.Fatalf("State = %+v, want the Config window open", st.State())
|
||||
}
|
||||
if got["port"] != float64(0) || got["talkGroup"] != float64(0) {
|
||||
t.Fatalf("numeric fields = %#v, want port and talkGroup at zero", got)
|
||||
}
|
||||
if got["enableLogging"] != false {
|
||||
t.Fatalf("enableLogging = %#v, want false", got["enableLogging"])
|
||||
form := st.Config().Form
|
||||
if form.Host != "" || form.Callsign != "" || form.AuthKey != "" || form.Port != 0 || form.TalkGroup != 0 || form.EnableLogging || form.CertificateDir != "./funknetz" {
|
||||
t.Fatalf("Form = %+v, want template defaults", form)
|
||||
}
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got["logFile"] != filepath.Join(home, "funknetz.log") {
|
||||
t.Fatalf("logFile = %#v, want funknetz.log in the home directory", got["logFile"])
|
||||
if form.LogFile != filepath.Join(home, "funknetz.log") {
|
||||
t.Fatalf("LogFile = %q, want funknetz.log in the home directory", form.LogFile)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +248,7 @@ func TestExtraWordsDoNotChangeTheSelectedFile(t *testing.T) {
|
||||
|
||||
func TestSelectedFileIsLeftByteForByte(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "lab.json")
|
||||
original := []byte("{\"host\":\"127.0.0.1\",\"port\":5308,\"callsign\":\"DL1ABC\",\"authKey\":\"a b\",\"talkGroup\":20,\"enableLogging\":false,\"logFile\":\"/tmp/funknetz.log\"}\n")
|
||||
original := []byte("{\"host\":\"127.0.0.1\",\"port\":5308,\"callsign\":\"DL1ABC\",\"authKey\":\"a b\",\"talkGroup\":20,\"certificateDir\":\"./funknetz\",\"enableLogging\":false,\"logFile\":\"/tmp/funknetz.log\"}\n")
|
||||
if err := os.WriteFile(path, original, 0o640); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -292,7 +269,7 @@ func TestSelectedFileIsLeftByteForByte(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyHostOnSelectedFileNamesHost(t *testing.T) {
|
||||
func TestEmptyHostOnSelectedFileOpensConfig(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "lab.json")
|
||||
body := []byte("{\"host\":\"\",\"port\":5308,\"callsign\":\"DL1ABC\",\"authKey\":\"key\",\"talkGroup\":20,\"enableLogging\":false,\"logFile\":\"/tmp/funknetz.log\"}\n")
|
||||
if err := os.WriteFile(path, body, 0o600); err != nil {
|
||||
@@ -300,14 +277,64 @@ func TestEmptyHostOnSelectedFileNamesHost(t *testing.T) {
|
||||
}
|
||||
var stderr bytes.Buffer
|
||||
st, err := openStationReported([]string{"-c", path}, &stderr)
|
||||
if st != nil {
|
||||
t.Fatal("station = non-nil, want nil")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err == nil || !strings.Contains(err.Error(), "host") {
|
||||
t.Fatalf("error = %v, want it to name host", err)
|
||||
if st == nil || !st.State().ConfigOpen || !strings.Contains(st.State().Detail, "host") {
|
||||
t.Fatalf("State = %+v, want the Config window open naming host", st.State())
|
||||
}
|
||||
if stderr.String() != err.Error()+"\n" {
|
||||
t.Fatalf("stderr = %q, want the error line", stderr.String())
|
||||
if stderr.Len() != 0 {
|
||||
t.Fatalf("stderr = %q, want empty", stderr.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelWithoutALoadedConfigQuits(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "missing.json")
|
||||
st, err := openStation([]string{"-c", path})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
quit := false
|
||||
app := &App{
|
||||
station: st,
|
||||
ctx: t.Context(),
|
||||
quit: func(context.Context) { quit = true },
|
||||
}
|
||||
app.CancelConfig()
|
||||
if !quit {
|
||||
t.Fatal("CancelConfig() left the app running")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelAfterLoadKeepsTheSession(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "lab.json")
|
||||
body := []byte("{\"host\":\"127.0.0.1\",\"port\":5308,\"callsign\":\"DL1ABC\",\"authKey\":\"key\",\"talkGroup\":20,\"certificateDir\":\"./funknetz\",\"enableLogging\":false,\"logFile\":\"/tmp/funknetz.log\"}\n")
|
||||
if err := os.WriteFile(path, body, 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
st, err := openStation([]string{"-c", path})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
quit := false
|
||||
app := &App{
|
||||
station: st,
|
||||
ctx: t.Context(),
|
||||
quit: func(context.Context) { quit = true },
|
||||
}
|
||||
app.CancelConfig()
|
||||
if quit {
|
||||
t.Fatal("CancelConfig() quit after a loaded config")
|
||||
}
|
||||
if st.State().ConfigOpen {
|
||||
t.Fatal("Config window stayed open")
|
||||
}
|
||||
got, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(got) != string(body) {
|
||||
t.Fatalf("file = %s, want it left unchanged", got)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user