Files
OpsLog/uploadconfigured_test.go
T
rouggy 2808bead97 fix(uploads): Club Log is configured — it never needed an API key
The guard I added for services with no credentials demanded one, and
nobody has ever set it: OpsLog carries its own Club Log APPLICATION key
(clublogAppAPIKey), so the account is an email, a password and the
logbook callsign. An operator whose live upload had been working for
months was told the service was not configured the moment he sent QSOs by
hand after an import.

Written in app.go, the rules drifted from the uploaders on the first try.
They now live in internal/extsvc beside the Upload* functions that
enforce them, each case mirroring that function's own guard — which also
caught Cloudlog, where the station profile is required and the check did
not ask for it. The message names the fields actually missing rather than
listing everything the service takes.
2026-09-06 18:06:06 +02:00

75 lines
2.8 KiB
Go

package main
import (
"strings"
"testing"
"hamlog/internal/extsvc"
)
// An upload to a service with no credentials used to look exactly like one that
// worked: it ran on its own goroutine and reported into the QSL Manager's
// console, which is not open when the command came from the QSO list.
func TestUploadRefusesAnUnconfiguredService(t *testing.T) {
var empty extsvc.ExternalServices
for _, svc := range []extsvc.Service{
extsvc.ServiceCloudlog, extsvc.ServiceQRZ, extsvc.ServiceClublog,
extsvc.ServiceHRDLog, extsvc.ServiceEQSL, extsvc.ServiceHamQTH, extsvc.ServiceLoTW,
} {
err := uploadConfigured(svc, empty)
if err == nil {
t.Errorf("%s: an unconfigured service was accepted", svc)
continue
}
if !strings.Contains(err.Error(), "Settings") {
t.Errorf("%s: %q does not say where to fix it", svc, err)
}
}
}
// And a CONFIGURED service is not turned away. Club Log is the one that was:
// its API key is OpsLog's own application key, embedded and never entered, so
// demanding it refused every operator who had the service working.
func TestAConfiguredServiceIsAccepted(t *testing.T) {
var cfg extsvc.ExternalServices
cfg.Clublog.Email, cfg.Clublog.Password, cfg.Clublog.Callsign = "[email protected]", "secret", "F4BPO"
cfg.QRZ.APIKey = "1234-5678"
cfg.Cloudlog.URL, cfg.Cloudlog.APIKey, cfg.Cloudlog.StationID = "https://log.example.com", "cl-key", "3"
cfg.EQSL.Username, cfg.EQSL.Password = "F4BPO", "secret"
cfg.HamQTH.Username, cfg.HamQTH.Password = "f4bpo", "secret"
cfg.HRDLog.Callsign, cfg.HRDLog.Code = "F4BPO", "12345"
cfg.LoTW.TQSLPath, cfg.LoTW.StationLocation = `C:\Program Files (x86)\TrustedQSL\tqsl.exe`, "Home"
for _, svc := range []extsvc.Service{
extsvc.ServiceCloudlog, extsvc.ServiceQRZ, extsvc.ServiceClublog,
extsvc.ServiceHRDLog, extsvc.ServiceEQSL, extsvc.ServiceHamQTH, extsvc.ServiceLoTW,
} {
if err := uploadConfigured(svc, cfg); err != nil {
t.Errorf("%s: a configured service was refused: %v", svc, err)
}
}
}
// The message names what is actually missing, so the operator opens the right
// field rather than checking three that were already filled in.
func TestTheRefusalNamesTheMissingFields(t *testing.T) {
var cfg extsvc.ExternalServices
cfg.Clublog.Email = "[email protected]"
err := uploadConfigured(extsvc.ServiceClublog, cfg)
if err == nil {
t.Fatal("a half-configured Club Log was accepted")
}
msg := err.Error()
if strings.Contains(msg, "email") {
t.Errorf("%q asks for the one field that IS set", msg)
}
for _, want := range []string{"password", "logbook callsign"} {
if !strings.Contains(msg, want) {
t.Errorf("%q does not mention the missing %s", msg, want)
}
}
if strings.Contains(strings.ToLower(msg), "api key") {
t.Errorf("%q asks for the API key — it is OpsLog's own, embedded", msg)
}
}