package main import ( "encoding/json" "testing" ) func makeProduct(price float64, extra map[string]any) *ProductItem { m := map[string]json.RawMessage{} for k, v := range extra { b, _ := json.Marshal(v) m[k] = b } return &ProductItem{Price: price, Extra: m} } func TestAreaFromItem(t *testing.T) { tests := []struct { name string extra map[string]any want float64 }{ {"floors small window to min", map[string]any{"width": 5, "height": 6}, 0.4}, // 500*600/1e6 = 0.30 -> floor 0.4 {"normal window", map[string]any{"width": 10, "height": 10}, 1.0}, // 1000*1000/1e6 = 1.0 {"numeric strings", map[string]any{"width": "10", "height": "10"}, 1.0}, // JS Number() parity {"missing height", map[string]any{"width": 10}, 0}, {"zero width", map[string]any{"width": 0, "height": 10}, 0}, {"non-numeric", map[string]any{"width": "abc", "height": 10}, 0}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { got := areaFromItem(makeProduct(0, tc.extra)) if got != tc.want { t.Errorf("areaFromItem = %v, want %v", got, tc.want) } }) } if got := areaFromItem(nil); got != 0 { t.Errorf("areaFromItem(nil) = %v, want 0", got) } } func TestAccessoryPrice(t *testing.T) { // area 1.0 m^2, child 100.00 -> 100.00 * 100 * 1.0 = 10000 minor units. parent := makeProduct(0, map[string]any{"width": 10, "height": 10}) if got := accessoryPrice(parent, makeProduct(100, nil)); got != 10000 { t.Errorf("accessoryPrice = %d, want 10000", got) } // area floored to 0.4, child 9952.78 -> round(9952.78 * 100 * 0.4) = 398111. small := makeProduct(0, map[string]any{"width": 5, "height": 6}) if got := accessoryPrice(small, makeProduct(9952.78, nil)); got != 398111 { t.Errorf("accessoryPrice = %d, want 398111", got) } // parent without dimensions -> area 0 -> price 0. if got := accessoryPrice(makeProduct(0, nil), makeProduct(500, nil)); got != 0 { t.Errorf("accessoryPrice (no dims) = %d, want 0", got) } }