feat(t239): persist freight item metadata
This commit is contained in:
@@ -86,8 +86,11 @@ func TestNormalizeFreightFixtureUsesOnlyAllowlist(t *testing.T) {
|
||||
order := result.Orders[0]
|
||||
if order.ExternalStockID != "12" || order.SourceCode != "SANITIZED-CODE-12" ||
|
||||
order.ShopName == nil || *order.ShopName != "Sanitized shop" ||
|
||||
order.Items[0].ExternalItemID != "88" || order.Items[0].SKU != "BLACK-L" ||
|
||||
order.Items[0].Quantity == nil || *order.Items[0].Quantity != 2 {
|
||||
order.Items[0].ExternalItemID != "88" || order.Items[0].SKU != "Black,L" ||
|
||||
order.Items[0].Quantity == nil || *order.Items[0].Quantity != 2 ||
|
||||
order.Items[0].OriginalUnitPriceMinor == nil ||
|
||||
*order.Items[0].OriginalUnitPriceMinor != 12950 ||
|
||||
order.Items[0].OriginalCurrency != domain.FreightCurrencyTWD {
|
||||
t.Fatalf("allowlist result = %#v", order)
|
||||
}
|
||||
encoded, err := json.Marshal(result)
|
||||
@@ -105,6 +108,77 @@ func TestNormalizeFreightFixtureUsesOnlyAllowlist(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeFreightPriceAndThumbContract(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
price any
|
||||
thumb any
|
||||
wantMinor *int64
|
||||
wantThumb *string
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "integer", price: json.Number("12"), thumb: json.Number("190"), wantMinor: int64Pointer(1200), wantThumb: stringPointer("190")},
|
||||
{name: "one decimal", price: "12.3", thumb: "0190", wantMinor: int64Pointer(1230), wantThumb: stringPointer("190")},
|
||||
{name: "two decimals", price: json.Number("12.34"), wantMinor: int64Pointer(1234)},
|
||||
{name: "missing", price: "", thumb: "", wantMinor: nil, wantThumb: nil},
|
||||
{name: "negative", price: "-1", wantErr: true},
|
||||
{name: "exponent", price: json.Number("1e2"), wantErr: true},
|
||||
{name: "excess precision", price: "1.001", wantErr: true},
|
||||
{name: "overflow", price: "92233720368547758.08", wantErr: true},
|
||||
{name: "invalid thumb text", price: "1", thumb: "https://invalid.example/image", wantErr: true},
|
||||
{name: "invalid thumb zero", price: "1", thumb: 0, wantErr: true},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
result, err := NormalizeFreightResult(
|
||||
RawQuery{Mode: domain.FreightSyncOrderNumber},
|
||||
[]RawRecord{{
|
||||
Stock: map[string]any{"id": 12, "code": "SANITIZED"},
|
||||
Detail: map[string]any{
|
||||
"id": 12,
|
||||
"details": []any{map[string]any{
|
||||
"id": 88,
|
||||
"productSpec": "Black,L",
|
||||
"productPrice": test.price,
|
||||
"productThumb": test.thumb,
|
||||
}},
|
||||
},
|
||||
}},
|
||||
)
|
||||
if test.wantErr {
|
||||
if !errors.Is(err, domain.ErrFreightSourceProtocol) {
|
||||
t.Fatalf("NormalizeFreightResult() error = %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("NormalizeFreightResult() error = %v", err)
|
||||
}
|
||||
item := result.Orders[0].Items[0]
|
||||
if !equalInt64Pointer(item.OriginalUnitPriceMinor, test.wantMinor) ||
|
||||
!equalStringPointer(item.ProductThumbRef, test.wantThumb) ||
|
||||
item.ProductSpec != "Black,L" || item.SKU != "Black,L" ||
|
||||
item.OriginalCurrency != domain.FreightCurrencyTWD {
|
||||
t.Fatalf("normalized item = %#v", item)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func int64Pointer(value int64) *int64 {
|
||||
return &value
|
||||
}
|
||||
|
||||
func equalInt64Pointer(left, right *int64) bool {
|
||||
return left == nil && right == nil ||
|
||||
left != nil && right != nil && *left == *right
|
||||
}
|
||||
|
||||
func equalStringPointer(left, right *string) bool {
|
||||
return left == nil && right == nil ||
|
||||
left != nil && right != nil && *left == *right
|
||||
}
|
||||
|
||||
func TestNormalizeFreightNeverLeaksRawValuesInErrors(t *testing.T) {
|
||||
_, err := NormalizeFreightResult(
|
||||
RawQuery{Mode: domain.FreightSyncOrderNumber},
|
||||
|
||||
Reference in New Issue
Block a user