package docx import ( "strings" "testing" ) // docBody wraps a inner string into a full document.xml. func docBody(inner string) string { return `` + `` + `` + inner + `` } func TestImportForAuthoring_PreviewIsRunAddressable(t *testing.T) { body := docBody( `Az. 4c O 12/23` + `Klägerin GmbH`) view, err := ImportForAuthoring(minimalMergeDOCX(t, body)) if err != nil { t.Fatalf("ImportForAuthoring: %v", err) } // Three → three run spans, indexed 0,1,2 in document order. for i, want := range []string{`data-run="0"`, `data-run="1"`, `data-run="2"`} { if !strings.Contains(view.PreviewHTML, want) { t.Errorf("preview missing %s (run %d); html=%s", want, i, view.PreviewHTML) } } if !strings.Contains(view.PreviewHTML, "Az. 4c O 12/23") { t.Errorf("preview missing run text; html=%s", view.PreviewHTML) } // Two paragraphs. if n := strings.Count(view.PreviewHTML, "

"); n != 2 { t.Errorf("paragraph count = %d; want 2", n) } if len(view.Slots) != 0 { t.Errorf("fresh doc should have no slots; got %v", view.Slots) } } func TestImportForAuthoring_DetectsExistingSlots(t *testing.T) { body := docBody(`Az. {{project.case_number}} vor {{project.court}}`) view, err := ImportForAuthoring(minimalMergeDOCX(t, body)) if err != nil { t.Fatalf("ImportForAuthoring: %v", err) } if len(view.Slots) != 2 { t.Fatalf("slots = %d; want 2 (%v)", len(view.Slots), view.Slots) } if view.Slots[0].Key != "project.case_number" || view.Slots[0].Anchor != "{{project.case_number}}" { t.Errorf("slot[0] = %+v; want project.case_number", view.Slots[0]) } if view.Slots[1].Key != "project.court" { t.Errorf("slot[1].Key = %q; want project.court", view.Slots[1].Key) } } func TestInjectSlot_ReplacesSelectionWithPlaceholder(t *testing.T) { body := docBody(`Az. 4c O 12/23 vor dem LG`) out, err := InjectSlot(minimalMergeDOCX(t, body), 0, "4c O 12/23", "project.case_number") if err != nil { t.Fatalf("InjectSlot: %v", err) } doc := readMergeDocumentXML(t, out) if !strings.Contains(doc, "Az. {{project.case_number}} vor dem LG") { t.Errorf("injected doc wrong; got %s", doc) } // Round-trips: re-importing finds the new slot. view, err := ImportForAuthoring(out) if err != nil { t.Fatalf("re-import: %v", err) } if len(view.Slots) != 1 || view.Slots[0].Key != "project.case_number" { t.Errorf("re-imported slots = %v; want [project.case_number]", view.Slots) } } func TestInjectSlot_TargetsTheNamedRun(t *testing.T) { // "GmbH" appears in run 1 only; "Müller" (with umlaut) in run 0. body := docBody( `Müller GmbH`) out, err := InjectSlot(minimalMergeDOCX(t, body), 0, "Müller", "parties.claimant.name") if err != nil { t.Fatalf("InjectSlot: %v", err) } doc := readMergeDocumentXML(t, out) if !strings.Contains(doc, "{{parties.claimant.name}}") { t.Errorf("umlaut selection not replaced; got %s", doc) } if !strings.Contains(doc, " GmbH") { t.Errorf("run 1 should be untouched; got %s", doc) } } func TestInjectSlot_ErrorsWhenSelectionNotInRun(t *testing.T) { body := docBody(`Hello`) if _, err := InjectSlot(minimalMergeDOCX(t, body), 0, "Goodbye", "firm.name"); err == nil { t.Error("expected error when selection absent from run; got nil") } // Out-of-range run index. if _, err := InjectSlot(minimalMergeDOCX(t, body), 9, "Hello", "firm.name"); err == nil { t.Error("expected error for out-of-range run index; got nil") } } func TestInjectSlot_RejectsInvalidSlotKey(t *testing.T) { body := docBody(`Hello`) if _, err := InjectSlot(minimalMergeDOCX(t, body), 0, "Hello", "9bad-key!"); err == nil { t.Error("expected error for invalid slot key; got nil") } }