Files
descrybe/apps/api/internal/feeds/sync_mapping_gate_test.go
T
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

131 lines
3.8 KiB
Go

package feeds
import (
"strings"
"testing"
)
func TestValidateMappingsForSyncEmpty(t *testing.T) {
err := validateMappingsForSync(nil, nil)
if err == nil {
t.Fatal("expected error for empty mappings")
}
msg, ok := ClientError(err)
if !ok || !strings.Contains(msg, "Map at least one source field") {
t.Fatalf("got %v", err)
}
err = validateMappingsForSync([]FieldMapping{
{Source: "col", Target: "none"},
{Source: "", Target: "gtin"},
}, nil)
if err == nil {
t.Fatal("expected error when only inactive rows present")
}
}
func TestValidateMappingsForSyncOptionalUnmappedOK(t *testing.T) {
err := validateMappingsForSync([]FieldMapping{
{Source: "ean", Target: "gtin"},
{Source: "name", Target: "title"},
}, []requiredStandardField{
{Key: "gtin", Name: "GTIN/EAN"},
{Key: "title", Name: "Product name"},
})
if err != nil {
t.Fatalf("optional gaps should be allowed: %v", err)
}
}
func TestValidateMappingsForSyncMissingRequired(t *testing.T) {
err := validateMappingsForSync([]FieldMapping{
{Source: "ean", Target: "gtin"},
}, []requiredStandardField{
{Key: "gtin", Name: "GTIN/EAN"},
{Key: "title", Name: "Product name"},
{Key: "brand", Name: "Brand"},
})
if err == nil {
t.Fatal("expected missing required error")
}
msg, ok := ClientError(err)
if !ok {
t.Fatalf("expected ClientMsg, got %v", err)
}
if !strings.Contains(msg, "Map required fields before syncing") {
t.Fatalf("message=%q", msg)
}
if !strings.Contains(msg, "Product name") || !strings.Contains(msg, "Brand") {
t.Fatalf("expected missing labels in %q", msg)
}
if strings.Contains(msg, "GTIN") {
t.Fatalf("mapped required field should not appear: %q", msg)
}
}
func TestValidateMappingsForSyncNoRequiredConfigured(t *testing.T) {
err := validateMappingsForSync([]FieldMapping{
{Source: "sku", Target: "sku"},
}, nil)
if err != nil {
t.Fatalf("empty required list should pass when mappings exist: %v", err)
}
}
func TestMappingDocIncomplete(t *testing.T) {
required := []requiredStandardField{{Key: "gtin", Name: "GTIN"}}
xmlItem := map[string]any{"feed_type": "xml", "options": map[string]any{}}
csvItem := map[string]any{"feed_type": "csv"}
empty := []FieldMapping{}
if !mappingDocIncomplete(xmlItem, map[string]any{"fields": empty}, empty, required) {
t.Fatal("empty mappings should be incomplete")
}
withGTIN := []FieldMapping{{Source: "id", Target: "gtin"}}
rawNoPath := map[string]any{"fields": []any{map[string]any{"source": "id", "target": "gtin"}}}
if !mappingDocIncomplete(xmlItem, rawNoPath, withGTIN, required) {
t.Fatal("xml without item_path should be incomplete")
}
if mappingDocIncomplete(csvItem, rawNoPath, withGTIN, required) {
t.Fatal("csv without item_path should be complete when required mapped")
}
rawWithPath := map[string]any{
"item_path": "rss/channel/item",
"fields": []any{map[string]any{"source": "id", "target": "gtin"}},
}
if mappingDocIncomplete(xmlItem, rawWithPath, withGTIN, required) {
t.Fatal("xml with item_path + required should be complete")
}
}
func TestActiveMappingsFiltersNone(t *testing.T) {
got := activeMappings([]FieldMapping{
{Source: "a", Target: "gtin"},
{Source: "b", Target: "none"},
{Source: "c", FieldName: "None"},
{Column: "d", Field: "title"},
})
if len(got) != 2 {
t.Fatalf("got %d want 2: %#v", len(got), got)
}
if got[0].targetKey() != "gtin" || got[1].targetKey() != "title" {
t.Fatalf("unexpected: %#v", got)
}
}
func TestApplyMappingsSkipsNoneTarget(t *testing.T) {
row := map[string]string{"col": "value", "ean": "123"}
mapped, gtin := applyMappings(row, []FieldMapping{
{Source: "col", Target: "none"},
{Source: "ean", Target: "gtin"},
})
if _, ok := mapped["none"]; ok {
t.Fatalf("none target must not be applied: %#v", mapped)
}
if gtin != "123" || mapped["gtin"] != "123" {
t.Fatalf("expected gtin mapping, got mapped=%#v gtin=%q", mapped, gtin)
}
}