@@ -16,6 +16,7 @@ type testCase struct {
1616 want any
1717 wantSelf bool
1818 errFmt string
19+ notFound string // if set, expect NotFoundError with this message
1920 typeHasPath bool
2021}
2122
@@ -81,8 +82,8 @@ func makeOuterNoFSF() outerNoFSF {
8182 Name : "x" ,
8283 },
8384 Items : []inner {
84- {ID : "i0" },
85- {ID : "i1" },
85+ {ID : "i0" , Name : "first" },
86+ {ID : "i1" , Name : "second" },
8687 },
8788 Labels : map [string ]string {
8889 "env" : "dev" ,
@@ -101,8 +102,8 @@ func makeOuterWithFSF() outerWithFSF {
101102 Name : "x" ,
102103 },
103104 Items : []inner {
104- {ID : "i0" },
105- {ID : "i1" },
105+ {ID : "i0" , Name : "first" },
106+ {ID : "i1" , Name : "second" },
106107 },
107108 Labels : map [string ]string {
108109 "env" : "dev" ,
@@ -198,7 +199,7 @@ func runCommonTests(t *testing.T, obj any) {
198199 {
199200 name : "out of range index" ,
200201 path : "items[5]" ,
201- errFmt : "items[5]: index out of range, length is 2" ,
202+ notFound : "items[5]: index out of range, length is 2" ,
202203 typeHasPath : true ,
203204 },
204205 {
@@ -225,28 +226,67 @@ func runCommonTests(t *testing.T, obj any) {
225226 {
226227 name : "map missing key" ,
227228 path : "labels.missing" ,
228- errFmt : "labels.missing: key \" missing\" not found in map" ,
229+ notFound : "labels.missing: key \" missing\" not found in map" ,
229230 typeHasPath : true ,
230231 },
231232 {
232233 name : "json dash ignored" ,
233234 path : "ignored" ,
234235 errFmt : "ignored: field \" ignored\" not found in " + typeName ,
235236 },
237+
238+ // Key-value selector tests
239+ {
240+ name : "key-value selector" ,
241+ path : "items[id='i1']" ,
242+ want : inner {ID : "i1" , Name : "second" },
243+ },
244+ {
245+ name : "key-value selector then field" ,
246+ path : "items[id='i0'].name" ,
247+ want : "first" ,
248+ },
249+ {
250+ name : "key-value no match" ,
251+ path : "items[id='missing']" ,
252+ notFound : "items[id='missing']: no element found with id=\" missing\" " ,
253+ typeHasPath : true ,
254+ },
255+ {
256+ name : "key-value on non-slice" ,
257+ path : "connection[id='abc']" ,
258+ errFmt : "connection[id='abc']: cannot use key-value syntax on struct" ,
259+ },
260+ {
261+ name : "key-value field not found" ,
262+ path : "items[missing='value']" ,
263+ notFound : "items[missing='value']: no element found with missing=\" value\" " ,
264+ typeHasPath : true ,
265+ },
236266 }
237267
238268 for _ , tt := range tests {
239269 t .Run (tt .name , func (t * testing.T ) {
240270 hasPathError := ValidateByString (reflect .TypeOf (obj ), tt .path )
241- if tt .errFmt == "" || tt .typeHasPath {
271+ if tt .errFmt == "" && tt . notFound == "" || tt .typeHasPath {
242272 require .NoError (t , hasPathError )
243- } else {
273+ } else if tt . errFmt != "" {
244274 require .EqualError (t , hasPathError , tt .errFmt )
275+ } else if tt .notFound != "" {
276+ require .EqualError (t , hasPathError , tt .notFound )
245277 }
246278
247279 got , err := GetByString (obj , tt .path )
280+ if tt .notFound != "" {
281+ require .EqualError (t , err , tt .notFound )
282+ var notFound * NotFoundError
283+ require .ErrorAs (t , err , & notFound )
284+ return
285+ }
248286 if tt .errFmt != "" {
249287 require .EqualError (t , err , tt .errFmt )
288+ var notFound * NotFoundError
289+ require .NotErrorAs (t , err , & notFound , "non-NotFoundError should not match" )
250290 return
251291 }
252292 require .NoError (t , err )
@@ -700,3 +740,39 @@ func TestPipeline(t *testing.T) {
700740 require .Equal (t , "ingestion_definition: cannot access nil value" , err .Error ())
701741 require .Nil (t , v )
702742}
743+
744+ func TestGetKeyValue_NestedMultiple (t * testing.T ) {
745+ type Item struct {
746+ ID string `json:"id"`
747+ Name string `json:"name"`
748+ }
749+ type Group struct {
750+ GroupID string `json:"group_id"`
751+ Items []Item `json:"items"`
752+ }
753+ type Container struct {
754+ Groups []Group `json:"groups"`
755+ }
756+
757+ c := Container {
758+ Groups : []Group {
759+ {
760+ GroupID : "g1" ,
761+ Items : []Item {
762+ {ID : "i1" , Name : "item1" },
763+ {ID : "i2" , Name : "item2" },
764+ },
765+ },
766+ {
767+ GroupID : "g2" ,
768+ Items : []Item {
769+ {ID : "i3" , Name : "item3" },
770+ },
771+ },
772+ },
773+ }
774+
775+ name , err := GetByString (& c , "groups[group_id='g2'].items[id='i3'].name" )
776+ require .NoError (t , err )
777+ require .Equal (t , "item3" , name )
778+ }
0 commit comments