feat(iace): wire crossref into tech-file, library UI, and contract tests
Three follow-ups to the 671-norm cross-reference matrix: 1. Tech-file renderer (Go): standards_applied section now gets a deterministic Markdown appendix with the DIN/ANSI/GB/JIS mappings for the project's suggested norms. Built from registry, never hallucinated by LLM. Applied both to LLM and fallback content paths. 2. Frontend NormCrossRefPanel (Next.js): expandable row in the IACE library norms tab now has a "Internationale Aequivalenzen anzeigen" button that lazy-loads /iace/norms-library/:id/crossref and renders a colour-coded table (relation + confidence). Region labels humanised (US — ANSI, China (GB), Japan (JIS), etc.). 3. Contract tests (Go): 4 new handler tests pinning the response shape of GetNormCrossRef and ListNormCrossRefs. Equivalent to an OpenAPI snapshot for these specific endpoints — ai-compliance-sdk has no full OpenAPI baseline yet (separate ticket). Tests: 6 renderer tests + 4 handler contract tests, all green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
package iace
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRenderCrossRefAppendix_EmptyInput(t *testing.T) {
|
||||
got := RenderCrossRefAppendix(nil)
|
||||
if got != "" {
|
||||
t.Errorf("expected empty string for nil input, got %d bytes", len(got))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderCrossRefAppendix_UnknownIDs(t *testing.T) {
|
||||
got := RenderCrossRefAppendix([]string{"ISO-DOES-NOT-EXIST", "EN-ALSO-MISSING"})
|
||||
if got != "" {
|
||||
t.Errorf("expected empty string when no IDs match, got:\n%s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderCrossRefAppendix_ISO12100_RendersAllRegions(t *testing.T) {
|
||||
got := RenderCrossRefAppendix([]string{"ISO-12100"})
|
||||
if got == "" {
|
||||
t.Fatal("expected non-empty appendix for ISO-12100")
|
||||
}
|
||||
for _, want := range []string{
|
||||
"## Anhang: Internationale Aequivalenzen",
|
||||
"ISO-12100",
|
||||
"EU-DIN",
|
||||
"US-ANSI",
|
||||
"CN-GB",
|
||||
"JP-JIS",
|
||||
"DIN EN ISO 12100",
|
||||
"GB/T 15706",
|
||||
} {
|
||||
if !strings.Contains(got, want) {
|
||||
t.Errorf("expected appendix to contain %q, got:\n%s", want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderCrossRefAppendix_RegionOrdering(t *testing.T) {
|
||||
got := RenderCrossRefAppendix([]string{"EN-60204-1"})
|
||||
if got == "" {
|
||||
t.Fatal("expected non-empty appendix for EN-60204-1")
|
||||
}
|
||||
// EU-DIN must appear before US-NFPA which must appear before CN-GB.
|
||||
euIdx := strings.Index(got, "EU-DIN")
|
||||
usIdx := strings.Index(got, "US-NFPA")
|
||||
cnIdx := strings.Index(got, "CN-GB")
|
||||
if euIdx < 0 || usIdx < 0 || cnIdx < 0 {
|
||||
t.Fatalf("missing one of EU-DIN/US-NFPA/CN-GB markers, got:\n%s", got)
|
||||
}
|
||||
if !(euIdx < usIdx && usIdx < cnIdx) {
|
||||
t.Errorf("expected region order EU-DIN < US-NFPA < CN-GB, got positions %d, %d, %d", euIdx, usIdx, cnIdx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderCrossRefAppendix_MultipleNorms_SortedByID(t *testing.T) {
|
||||
got := RenderCrossRefAppendix([]string{"ISO-13850", "ISO-12100", "EN-60204-1"})
|
||||
if got == "" {
|
||||
t.Fatal("expected non-empty appendix")
|
||||
}
|
||||
// Expect EN-60204-1 first (alphabetical), then ISO-12100, then ISO-13850.
|
||||
en := strings.Index(got, "EN-60204-1")
|
||||
iso12100 := strings.Index(got, "ISO-12100")
|
||||
iso13850 := strings.Index(got, "ISO-13850")
|
||||
if en < 0 || iso12100 < 0 || iso13850 < 0 {
|
||||
t.Fatalf("missing one of the IDs in output:\n%s", got)
|
||||
}
|
||||
if !(en < iso12100 && iso12100 < iso13850) {
|
||||
t.Errorf("expected source-norm ordering by alphabetical ID, got positions %d, %d, %d", en, iso12100, iso13850)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderCrossRefAppendix_PipeEscape(t *testing.T) {
|
||||
got := RenderCrossRefAppendix([]string{"ISO-12100"})
|
||||
// Find a line that came from a mapping with the pipe character — none of
|
||||
// our identifiers contain literal '|' so this just checks that the table
|
||||
// header is intact (no accidental pipe injection).
|
||||
if !strings.Contains(got, "| EU Norm (verwendet) |") {
|
||||
t.Errorf("table header malformed:\n%s", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user