Skip to content

Commit 41b2d19

Browse files
authored
Add the missing/extra attribute names to the error message for knownvalue.ObjectExact (#455)
* issue #451 fix * add changelog
1 parent b505110 commit 41b2d19

File tree

3 files changed

+80
-13
lines changed

3 files changed

+80
-13
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: ENHANCEMENTS
2+
body: 'knownvalue: Updated the `ObjectExact` error message to report extra/missing attributes from the actual object.'
3+
time: 2025-03-17T18:27:30.206493-04:00
4+
custom:
5+
Issue: "451"

knownvalue/object.go

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ package knownvalue
55

66
import (
77
"fmt"
8+
"maps"
9+
"slices"
810
"sort"
911
)
1012

@@ -24,18 +26,14 @@ func (v objectExact) CheckValue(other any) error {
2426
}
2527

2628
if len(otherVal) != len(v.value) {
27-
expectedAttributes := "attributes"
28-
actualAttributes := "attributes"
29-
30-
if len(v.value) == 1 {
31-
expectedAttributes = "attribute"
32-
}
33-
34-
if len(otherVal) == 1 {
35-
actualAttributes = "attribute"
29+
deltaMsg := ""
30+
if len(otherVal) > len(v.value) {
31+
deltaMsg = createDeltaString(otherVal, v.value, "actual value has extra attribute(s): ")
32+
} else {
33+
deltaMsg = createDeltaString(v.value, otherVal, "actual value is missing attribute(s): ")
3634
}
3735

38-
return fmt.Errorf("expected %d %s for ObjectExact check, got %d %s", len(v.value), expectedAttributes, len(otherVal), actualAttributes)
36+
return fmt.Errorf("expected %d attribute(s) for ObjectExact check, got %d attribute(s): %s", len(v.value), len(otherVal), deltaMsg)
3937
}
4038

4139
var keys []string
@@ -92,3 +90,27 @@ func ObjectExact(value map[string]Check) objectExact {
9290
value: value,
9391
}
9492
}
93+
94+
// createDeltaString prints the map keys that are present in mapA and not present in mapB
95+
func createDeltaString[T any, V any](mapA map[string]T, mapB map[string]V, msgPrefix string) string {
96+
deltaMsg := ""
97+
98+
deltaMap := make(map[string]T, len(mapA))
99+
maps.Copy(deltaMap, mapA)
100+
for key := range mapB {
101+
delete(deltaMap, key)
102+
}
103+
104+
deltaKeys := slices.Sorted(maps.Keys(deltaMap))
105+
106+
for i, k := range deltaKeys {
107+
if i == 0 {
108+
deltaMsg += msgPrefix
109+
} else if i != 0 {
110+
deltaMsg += ", "
111+
}
112+
deltaMsg += fmt.Sprintf("%q", k)
113+
}
114+
115+
return deltaMsg
116+
}

knownvalue/object_test.go

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ func TestObjectValue_CheckValue(t *testing.T) {
5353
"three": knownvalue.Float64Exact(7.89),
5454
}),
5555
other: map[string]any{},
56-
expectedError: fmt.Errorf("expected 3 attributes for ObjectExact check, got 0 attributes"),
56+
expectedError: fmt.Errorf("expected 3 attribute(s) for ObjectExact check, got 0 attribute(s): actual value is missing attribute(s): \"one\", \"three\", \"two\""),
5757
},
58-
"wrong-length": {
58+
"missing-one-attribute": {
5959
self: knownvalue.ObjectExact(map[string]knownvalue.Check{
6060
"one": knownvalue.Float64Exact(1.23),
6161
"two": knownvalue.Float64Exact(4.56),
@@ -65,7 +65,47 @@ func TestObjectValue_CheckValue(t *testing.T) {
6565
"one": json.Number("1.23"),
6666
"two": json.Number("4.56"),
6767
},
68-
expectedError: fmt.Errorf("expected 3 attributes for ObjectExact check, got 2 attributes"),
68+
expectedError: fmt.Errorf("expected 3 attribute(s) for ObjectExact check, got 2 attribute(s): actual value is missing attribute(s): \"three\""),
69+
},
70+
"missing-multiple-attributes": {
71+
self: knownvalue.ObjectExact(map[string]knownvalue.Check{
72+
"one": knownvalue.Float64Exact(1.23),
73+
"two": knownvalue.Float64Exact(4.56),
74+
"three": knownvalue.Float64Exact(7.89),
75+
"four": knownvalue.Float64Exact(0.12),
76+
"five": knownvalue.Float64Exact(3.45),
77+
}),
78+
other: map[string]any{
79+
"one": json.Number("1.23"),
80+
"two": json.Number("4.56"),
81+
},
82+
expectedError: fmt.Errorf("expected 5 attribute(s) for ObjectExact check, got 2 attribute(s): actual value is missing attribute(s): \"five\", \"four\", \"three\""),
83+
},
84+
"extra-one-attribute": {
85+
self: knownvalue.ObjectExact(map[string]knownvalue.Check{
86+
"one": knownvalue.Float64Exact(1.23),
87+
"two": knownvalue.Float64Exact(4.56),
88+
}),
89+
other: map[string]any{
90+
"one": json.Number("1.23"),
91+
"two": json.Number("4.56"),
92+
"three": json.Number("7.89"),
93+
},
94+
expectedError: fmt.Errorf("expected 2 attribute(s) for ObjectExact check, got 3 attribute(s): actual value has extra attribute(s): \"three\""),
95+
},
96+
"extra-multiple-attributes": {
97+
self: knownvalue.ObjectExact(map[string]knownvalue.Check{
98+
"one": knownvalue.Float64Exact(1.23),
99+
"two": knownvalue.Float64Exact(4.56),
100+
}),
101+
other: map[string]any{
102+
"one": json.Number("1.23"),
103+
"two": json.Number("4.56"),
104+
"three": json.Number("7.89"),
105+
"four": json.Number("0.12"),
106+
"five": json.Number("3.45"),
107+
},
108+
expectedError: fmt.Errorf("expected 2 attribute(s) for ObjectExact check, got 5 attribute(s): actual value has extra attribute(s): \"five\", \"four\", \"three\""),
69109
},
70110
"not-equal": {
71111
self: knownvalue.ObjectExact(map[string]knownvalue.Check{

0 commit comments

Comments
 (0)