72 lines
2.2 KiB
Go
72 lines
2.2 KiB
Go
package models
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
)
|
|
|
|
/*
|
|
A missing string must reach a client as "", never as an absent key.
|
|
|
|
`unitvalue` and `productunit` were both `omitempty`, and on this platform
|
|
`unitvalue` is empty for every product — measured 2026-09-02 on R mart: 24
|
|
products, 0 with both fields, 7 with a unit and no value. So the key vanished
|
|
from the JSON, a client read `undefined`, and joining it to the unit rendered
|
|
the literal text "null kg" on a shopper's screen.
|
|
|
|
The same applies to money: a price of 0 is a real answer ("this has no price
|
|
set"), and a client that receives no key at all cannot tell that from a field
|
|
it forgot to request.
|
|
*/
|
|
|
|
func fieldsOf(t *testing.T, v any) map[string]any {
|
|
t.Helper()
|
|
raw, err := json.Marshal(v)
|
|
if err != nil {
|
|
t.Fatalf("marshal: %v", err)
|
|
}
|
|
var out map[string]any
|
|
if err := json.Unmarshal(raw, &out); err != nil {
|
|
t.Fatalf("unmarshal: %v", err)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func TestAnEmptyUnitIsSentAsEmptyNotOmitted(t *testing.T) {
|
|
got := fieldsOf(t, Products{Productid: 1})
|
|
for _, key := range []string{"unitvalue", "productunit"} {
|
|
if _, present := got[key]; !present {
|
|
t.Errorf("%q was omitted; a client reads that as null and renders it", key)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAZeroPriceIsSentAsZeroNotOmitted(t *testing.T) {
|
|
got := fieldsOf(t, Products{Productid: 1})
|
|
if _, present := got["retailprice"]; !present {
|
|
t.Error("retailprice was omitted; 0 is a real answer and must be visible")
|
|
}
|
|
}
|
|
|
|
func TestAVariantAlwaysCarriesItsPriceAndUnit(t *testing.T) {
|
|
got := fieldsOf(t, Productvariant{Variantid: 1})
|
|
for _, key := range []string{"price", "variantprice", "variantunitvalue", "variantproductunit"} {
|
|
if _, present := got[key]; !present {
|
|
t.Errorf("variant option omitted %q", key)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAProductWithNoVariantsSendsAnEmptyListNotNull(t *testing.T) {
|
|
// The case that lets an order proceed: [] means "order this one directly".
|
|
// A JSON null would force every client to null-check before counting.
|
|
got := fieldsOf(t, Products{Productid: 1, Variantoptions: []Productvariant{}})
|
|
list, ok := got["variantoptions"].([]any)
|
|
if !ok {
|
|
t.Fatalf("variantoptions was %T, want a list", got["variantoptions"])
|
|
}
|
|
if len(list) != 0 {
|
|
t.Errorf("expected an empty list, got %d", len(list))
|
|
}
|
|
}
|