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) } }