Files
paliad/pkg/docforge/vars_test.go
mAi b8709b903d feat(docforge): slice 5 — docforge-editor pkg + variable catalogue SSOT (t-paliad-349)
Establish the shared frontend editor package and make the Go resolvers the
single source of truth for variable labels.

Go — catalogue SSOT:
  - VariableResolver gains Keys() []VariableKey; ResolverSet gains
    Catalogue(). The 7 submission resolvers implement Keys() with the
    bilingual labels ported from the TS VARIABLE_LABELS table (incl. the
    legacy rule.* aliases). Keys() is entity-independent, so
    SubmissionVariableCatalogue() builds a metadata-only ResolverSet.
  - GET /api/docforge/variables serves the catalogue (auth-gated, static).
  - Tests: docforge ResolverSet (BuildBag merge + Catalogue order) and the
    submission catalogue integrity (no dupes, labels present, spot-checks).

Frontend — frontend/src/lib/docforge-editor/ (new shared package):
  - dom.ts: escapeHtml + cssEscape (pure), with bun tests. Dedupes the two
    identical escapeHtml/escapeHTML copies + the cssEscape copy that lived
    in the submission editor.
  - catalogue.ts: fetchVariableCatalogue() + labelMap() — the client for
    the Go catalogue.
  - submission-draft.ts now imports escapeHtml/cssEscape from the lib and
    fetches the catalogue on boot into state.varLabels (labelFor reads it,
    falling back to the raw key if the fetch fails — graceful degrade). The
    hardcoded VARIABLE_LABELS table is removed; VARIABLE_GROUPS stays
    (presentation: which keys to show + how to section them, legitimately
    frontend).

Scope note: the DOM-coupled editor plumbing (wireDraftVars/focus
preservation/autosave debounce) is extracted in slice 6 alongside its first
reuse — the authoring page — rather than speculatively now (extract with the
consumer; same principle as slices 2-3). Slice 5 lands the pure utilities +
the catalogue, which the slice-6 authoring palette consumes.

Verification: go build/vet/test green (Go files gofmt-clean; handlers.go
pre-existing drift, added region clean); bun run build.ts clean;
bun test 274/274 (incl. 5 new docforge-editor tests).

m/paliad#157
2026-05-29 15:50:42 +02:00

61 lines
1.6 KiB
Go

package docforge
import "testing"
// fakeResolver is a test double: it owns a namespace, populates a fixed
// set of key/value pairs, and advertises a fixed catalogue.
type fakeResolver struct {
ns string
values map[string]string
catalog []VariableKey
}
func (f fakeResolver) Namespace() string { return f.ns }
func (f fakeResolver) Keys() []VariableKey { return f.catalog }
func (f fakeResolver) Populate(bag PlaceholderMap) {
for k, v := range f.values {
bag[k] = v
}
}
func TestResolverSet_BuildBagMergesDisjointNamespaces(t *testing.T) {
set := NewResolverSet(
fakeResolver{ns: "a", values: map[string]string{"a.x": "1", "a.y": "2"}},
fakeResolver{ns: "b", values: map[string]string{"b.z": "3"}},
)
bag := set.BuildBag()
if len(bag) != 3 {
t.Fatalf("bag size = %d; want 3", len(bag))
}
for k, want := range map[string]string{"a.x": "1", "a.y": "2", "b.z": "3"} {
if bag[k] != want {
t.Errorf("bag[%q] = %q; want %q", k, bag[k], want)
}
}
}
func TestResolverSet_AddAndCatalogueOrder(t *testing.T) {
set := NewResolverSet(
fakeResolver{ns: "a", catalog: []VariableKey{{Key: "a.x", Group: "a"}}},
)
set.Add(fakeResolver{ns: "b", catalog: []VariableKey{
{Key: "b.y", Group: "b"},
{Key: "b.z", Group: "b"},
}})
cat := set.Catalogue()
gotOrder := make([]string, len(cat))
for i, e := range cat {
gotOrder[i] = e.Key
}
want := []string{"a.x", "b.y", "b.z"} // resolver order, then Keys() order
if len(gotOrder) != len(want) {
t.Fatalf("catalogue len = %d; want %d", len(gotOrder), len(want))
}
for i := range want {
if gotOrder[i] != want[i] {
t.Errorf("catalogue[%d] = %q; want %q", i, gotOrder[i], want[i])
}
}
}