Files
descrybe/apps/api/internal/feeds/sync_deltas_test.go
T

126 lines
4.2 KiB
Go
Raw Normal View History

package feeds
import (
"encoding/json"
"testing"
"github.com/google/uuid"
)
func TestDetectMappedChangesPriceStock(t *testing.T) {
t.Parallel()
old := []byte(`{"price":"10","stock":"5","title":"A"}`)
changes := detectMappedChanges(old, map[string]any{"price": "12", "stock": "5", "title": "A"})
if len(changes) != 1 || changes[0] != "price" {
t.Fatalf("changes=%v", changes)
}
changes = detectMappedChanges(old, map[string]any{"price": "10", "stock": "0", "title": "A"})
if len(changes) != 1 || changes[0] != "stock" {
t.Fatalf("stock changes=%v", changes)
}
changes = detectMappedChanges(old, map[string]any{"price": "11", "stock": "1", "title": "B", "availability": "out"})
want := map[string]bool{"price": true, "stock": true, "title": true, "availability": true}
for _, c := range changes {
if !want[c] {
t.Fatalf("unexpected %s in %v", c, changes)
}
delete(want, c)
}
if len(want) != 0 {
t.Fatalf("missing %v from %v", want, changes)
}
}
func TestClassifyUpsertOpsStampsSyncChanges(t *testing.T) {
t.Parallel()
idUpdate := uuid.MustParse("22222222-2222-2222-2222-222222222222")
existing := map[string]existingProduct{
"update": {ID: idUpdate, MappedData: []byte(`{"price":"10","title":"Old"}`)},
}
chunk := []pendingProduct{
{GTIN: "new", RawData: map[string]string{"EAN": "new"}, MappedData: map[string]any{"title": "N"}},
{GTIN: "update", RawData: map[string]string{"EAN": "update"}, MappedData: map[string]any{"price": "12", "title": "Old"}},
}
ops, skipped := classifyUpsertOps(chunk, existing)
if skipped != 0 || len(ops) != 2 {
t.Fatalf("ops=%d skipped=%d", len(ops), skipped)
}
if ops[0].kind != upsertOpInsert || len(ops[0].changes) != 1 || ops[0].changes[0] != "new" {
t.Fatalf("insert op=%+v", ops[0])
}
var mapped map[string]any
if err := json.Unmarshal(ops[0].mappedJSON, &mapped); err != nil {
t.Fatal(err)
}
tags, _ := mapped[syncChangesMappedKey].([]any)
if len(tags) != 1 || tags[0] != "new" {
t.Fatalf("insert mapped meta=%v", mapped[syncChangesMappedKey])
}
if ops[1].kind != upsertOpUpdate || len(ops[1].changes) != 1 || ops[1].changes[0] != "price" {
t.Fatalf("update op=%+v", ops[1])
}
}
func TestSyncDeltaCountsAddChanges(t *testing.T) {
t.Parallel()
var d syncDeltaCounts
d.addChanges([]string{"price", "stock"})
d.addChanges([]string{"new"})
d.addChanges(nil)
if d.PriceChanged != 1 || d.StockChanged != 1 || d.New != 1 || d.OtherChanged != 1 {
t.Fatalf("%+v", d)
}
}
func TestPreserveSyncedExtrasKeepsCategory(t *testing.T) {
t.Parallel()
existing := []byte(`{"price":"10","category":"46","title":"Roborock"}`)
mapped := map[string]any{"price": "12", "title": "Roborock"}
got := preserveSyncedExtras(existing, mapped)
if got["category"] != "46" {
t.Fatalf("category=%v want 46", got["category"])
}
if got["price"] != "12" {
t.Fatalf("price=%v want 12", got["price"])
}
// Explicit new category wins.
mapped2 := map[string]any{"price": "12", "category": "120"}
got2 := preserveSyncedExtras(existing, mapped2)
if got2["category"] != "120" {
t.Fatalf("category=%v want 120", got2["category"])
}
// Empty / none prior must not invent a category.
got3 := preserveSyncedExtras([]byte(`{"category":"none"}`), map[string]any{"title": "X"})
if _, ok := got3["category"]; ok {
t.Fatalf("unexpected category=%v", got3["category"])
}
}
func TestClassifyUpsertOpsPreservesCategory(t *testing.T) {
t.Parallel()
idUpdate := uuid.MustParse("33333333-3333-3333-3333-333333333333")
existing := map[string]existingProduct{
"keep": {ID: idUpdate, MappedData: []byte(`{"price":"10","category":"46","title":"Old"}`)},
}
chunk := []pendingProduct{
{GTIN: "keep", RawData: map[string]string{"EAN": "keep"}, MappedData: map[string]any{"price": "12", "title": "Old"}},
}
ops, skipped := classifyUpsertOps(chunk, existing)
if skipped != 0 || len(ops) != 1 {
t.Fatalf("ops=%d skipped=%d", len(ops), skipped)
}
if ops[0].kind != upsertOpUpdate {
t.Fatalf("kind=%v want update", ops[0].kind)
}
var mapped map[string]any
if err := json.Unmarshal(ops[0].mappedJSON, &mapped); err != nil {
t.Fatal(err)
}
if mapped["category"] != "46" {
t.Fatalf("category wiped: %v", mapped["category"])
}
if mapped["price"] != "12" {
t.Fatalf("price=%v", mapped["price"])
}
}