Files
aura-crm/production/backend/internal/pcbuilder/compat_test.go
T

174 lines
6.0 KiB
Go

package pcbuilder
import "testing"
func hasLevel(issues []Issue, level string) bool {
for _, i := range issues {
if i.Level == level {
return true
}
}
return false
}
func TestCheckEmptySelectionOnlyReportsMissing(t *testing.T) {
res := Check(map[string]*Component{}, nil)
if hasLevel(res.Issues, "error") || hasLevel(res.Issues, "warning") {
t.Errorf("empty selection should have no error/warning issues, got %+v", res.Issues)
}
if !hasLevel(res.Issues, "info") {
t.Errorf("empty selection should report missing required slots, got %+v", res.Issues)
}
}
func TestCheckSocketMismatchIsError(t *testing.T) {
res := Check(map[string]*Component{
"cpu": {Type: "cpu", Spec: Spec{Socket: "AM5"}},
"motherboard": {Type: "motherboard", Spec: Spec{Socket: "LGA1700"}},
}, nil)
if !hasLevel(res.Issues, "error") {
t.Errorf("expected a socket-mismatch error, got %+v", res.Issues)
}
}
func TestCheckMatchingSocketNoError(t *testing.T) {
res := Check(map[string]*Component{
"cpu": {Type: "cpu", Spec: Spec{Socket: "AM5"}},
"motherboard": {Type: "motherboard", Spec: Spec{Socket: "am5"}}, // case-insensitive match
}, nil)
if hasLevel(res.Issues, "error") {
t.Errorf("matching sockets (case-insensitive) should not error, got %+v", res.Issues)
}
}
// A CPU whose socket the scraper never extracted (server sockets like
// SP3/SP5 — see internal/scraper/spec.go's socketRe) must not read as
// "mismatched" against a board that does have a socket filled in. Missing
// data means unknown, not incompatible.
func TestCheckCPUMissingSocketNoError(t *testing.T) {
res := Check(map[string]*Component{
"cpu": {Type: "cpu", Spec: Spec{Socket: ""}},
"motherboard": {Type: "motherboard", Spec: Spec{Socket: "AM5"}},
}, nil)
if hasLevel(res.Issues, "error") {
t.Errorf("cpu with no socket data should not error against a board with one, got %+v", res.Issues)
}
}
func TestCheckMotherboardMissingSocketNoError(t *testing.T) {
res := Check(map[string]*Component{
"cpu": {Type: "cpu", Spec: Spec{Socket: "AM5"}},
"motherboard": {Type: "motherboard", Spec: Spec{Socket: ""}},
}, nil)
if hasLevel(res.Issues, "error") {
t.Errorf("motherboard with no socket data should not error against a cpu with one, got %+v", res.Issues)
}
}
func TestCheckRAMTypeMismatchIsError(t *testing.T) {
res := Check(map[string]*Component{
"motherboard": {Type: "motherboard", Spec: Spec{RAMType: "DDR5"}},
}, map[string][]MultiEntry{
"ram": {{Component: &Component{Type: "ram", Spec: Spec{RAMType: "DDR4"}}, Qty: 1}},
})
if !hasLevel(res.Issues, "error") {
t.Errorf("expected a RAM-type-mismatch error, got %+v", res.Issues)
}
}
func TestCheckRAMTotalCapacityExceedsMaxIsWarning(t *testing.T) {
res := Check(map[string]*Component{
"motherboard": {Type: "motherboard", Spec: Spec{RAMType: "DDR5", MaxRAMGB: 32}},
}, map[string][]MultiEntry{
"ram": {{Component: &Component{Type: "ram", Spec: Spec{RAMType: "DDR5", RAMCapacityGB: 16}}, Qty: 3}}, // 48GB > 32GB max
})
if !hasLevel(res.Issues, "warning") {
t.Errorf("expected a RAM-capacity-exceeds-max warning, got %+v", res.Issues)
}
}
func TestCheckRAMWithinMaxCapacityNoWarning(t *testing.T) {
res := Check(map[string]*Component{
"motherboard": {Type: "motherboard", Spec: Spec{RAMType: "DDR5", MaxRAMGB: 128}},
}, map[string][]MultiEntry{
"ram": {{Component: &Component{Type: "ram", Spec: Spec{RAMType: "DDR5", RAMCapacityGB: 16}}, Qty: 2}}, // 32GB
})
if hasLevel(res.Issues, "warning") {
t.Errorf("RAM within max should not warn, got %+v", res.Issues)
}
}
func TestCheckMultipleStorageSumsPrice(t *testing.T) {
res := Check(map[string]*Component{}, map[string][]MultiEntry{
"storage": {
{Component: &Component{Type: "storage", Price: "5000"}, Qty: 1},
{Component: &Component{Type: "storage", Price: "3000"}, Qty: 2},
},
})
if res.TotalPrice != 11000 {
t.Errorf("TotalPrice = %v, want 11000 (5000 + 3000*2)", res.TotalPrice)
}
}
func TestCheckGPUTooLongForCaseIsError(t *testing.T) {
res := Check(map[string]*Component{
"gpu": {Type: "gpu", Spec: Spec{LengthMM: 350}},
"case": {Type: "case", Spec: Spec{MaxGPULengthMM: 300}},
}, nil)
if !hasLevel(res.Issues, "error") {
t.Errorf("expected a GPU-too-long error, got %+v", res.Issues)
}
}
func TestCheckPSUInsufficientIsWarning(t *testing.T) {
res := Check(map[string]*Component{
"cpu": {Type: "cpu", Spec: Spec{TDPWatts: 150}},
"gpu": {Type: "gpu", Spec: Spec{TDPWatts: 300}},
"psu": {Type: "psu", Spec: Spec{WattageW: 400}}, // 150+300+100 buffer = 550 > 400
}, nil)
if !hasLevel(res.Issues, "warning") {
t.Errorf("expected a PSU-insufficient warning, got %+v", res.Issues)
}
}
func TestCheckPSUSufficientNoWarning(t *testing.T) {
res := Check(map[string]*Component{
"cpu": {Type: "cpu", Spec: Spec{TDPWatts: 65}},
"gpu": {Type: "gpu", Spec: Spec{TDPWatts: 150}},
"psu": {Type: "psu", Spec: Spec{WattageW: 650}},
}, nil)
if hasLevel(res.Issues, "warning") {
t.Errorf("sufficient PSU should not warn, got %+v", res.Issues)
}
}
func TestCheckTotalPriceSumsAllSelected(t *testing.T) {
res := Check(map[string]*Component{
"cpu": {Type: "cpu", Price: "20000"},
"gpu": {Type: "gpu", Price: "45000.50"},
}, nil)
if res.TotalPrice != 65000.50 {
t.Errorf("TotalPrice = %v, want 65000.50", res.TotalPrice)
}
}
func TestCheckCoolerSocketUnsupportedIsError(t *testing.T) {
res := Check(map[string]*Component{
"cpu": {Type: "cpu", Spec: Spec{Socket: "LGA1700"}},
"cooler": {Type: "cooler", Spec: Spec{SocketsSupported: []string{"AM5", "AM4"}}},
}, nil)
if !hasLevel(res.Issues, "error") {
t.Errorf("expected a cooler-socket error, got %+v", res.Issues)
}
}
func TestCheckCaseFormFactorUnsupportedIsError(t *testing.T) {
res := Check(map[string]*Component{
"motherboard": {Type: "motherboard", Spec: Spec{FormFactor: "ATX"}},
"case": {Type: "case", Spec: Spec{FormFactorsSupported: []string{"mATX", "ITX"}}},
}, nil)
if !hasLevel(res.Issues, "error") {
t.Errorf("expected a case-form-factor error, got %+v", res.Issues)
}
}