test: pin the whole ADIF import path, not just the conversion step
CONTEST_ID was reported as not imported. It is imported: this drives an operator's own IOTA-contest record through a real SQLite logbook and reads the row back, confirming contest_id=RSGB-IOTA and iota=EU005 in the database. The conversion-level test was already green while the report stood, which is exactly why it was not enough — a promoted field can be dropped at any of five places between the file and the grid, and only the round trip says which. The answer here turned out to be none of them: the Contest columns are simply hidden by default in the QSO grid.
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package adif_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"hamlog/internal/adif"
|
||||
"hamlog/internal/db"
|
||||
"hamlog/internal/qso"
|
||||
)
|
||||
|
||||
// End to end: an operator's own record, through a real SQLite logbook and back.
|
||||
//
|
||||
// Written because CONTEST_ID was reported as "not imported". It is imported, and
|
||||
// this pins the whole path — parse, remap, insert, read back — rather than the
|
||||
// conversion step alone, which was already green while the report stood. A field
|
||||
// can be lost at five places between the file and the grid; only the round trip
|
||||
// says which.
|
||||
func TestContestIDSurvivesImport(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
conn, err := db.Open(filepath.Join(dir, "logbook.db"))
|
||||
if err != nil {
|
||||
t.Fatalf("open: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
const file = "<CALL:6>2E0CVN <QSO_DATE:8>20260725 <TIME_ON:6>120039 <STATE:5>EU005 <BAND:3>20M <FREQ:6>14.014 <MODE:2>CW <CONTEST_ID:9>RSGB-IOTA <RST_RCVD:3>599 <RST_SENT:3>599 <SRX_STRING:8>001EU005 <EOR>\n"
|
||||
path := filepath.Join(dir, "in.adi")
|
||||
if err := os.WriteFile(path, []byte(file), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
repo := qso.NewRepo(conn)
|
||||
im := &adif.Importer{Repo: repo, FieldMap: map[string]string{"state": "iota"}}
|
||||
res, err := im.ImportFile(context.Background(), path)
|
||||
if err != nil {
|
||||
t.Fatalf("import: %v", err)
|
||||
}
|
||||
t.Logf("result: %+v", res)
|
||||
|
||||
rows, err := conn.Query("SELECT callsign, contest_id, iota, state FROM qso")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
n := 0
|
||||
for rows.Next() {
|
||||
var call, contest, iota, state any
|
||||
if err := rows.Scan(&call, &contest, &iota, &state); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
n++
|
||||
t.Logf("stored: call=%v contest_id=%v iota=%v state=%v", call, contest, iota, state)
|
||||
if s := strings.TrimSpace(toS(contest)); s != "RSGB-IOTA" {
|
||||
t.Errorf("contest_id in the DATABASE = %q, want RSGB-IOTA", s)
|
||||
}
|
||||
}
|
||||
if n == 0 {
|
||||
t.Fatal("nothing was stored")
|
||||
}
|
||||
}
|
||||
|
||||
func toS(v any) string {
|
||||
switch x := v.(type) {
|
||||
case string:
|
||||
return x
|
||||
case []byte:
|
||||
return string(x)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user