1+ package objects_test
2+
3+ import (
4+ "context"
5+ "fmt"
6+ "testing"
7+
8+ "github.com/MontFerret/ferret/pkg/runtime"
9+ "github.com/MontFerret/ferret/pkg/stdlib/objects"
10+
11+ . "github.com/smartystreets/goconvey/convey"
12+ )
13+
14+ func TestHasEdgeCases (t * testing.T ) {
15+ Convey ("Edge cases for Has function" , t , func () {
16+ Convey ("When key is empty string" , func () {
17+ obj := runtime .NewObjectWith (
18+ runtime .NewObjectProperty ("" , runtime .NewString ("empty" )),
19+ )
20+
21+ val , err := objects .Has (context .Background (), obj , runtime .NewString ("" ))
22+ valBool := val .(runtime.Boolean )
23+
24+ So (err , ShouldEqual , nil )
25+ So (bool (valBool ), ShouldEqual , true )
26+ })
27+
28+ Convey ("When object has many keys" , func () {
29+ properties := make ([]* runtime.ObjectProperty , 100 )
30+ for i := 0 ; i < 100 ; i ++ {
31+ properties [i ] = runtime .NewObjectProperty (
32+ fmt .Sprintf ("key%d" , i ),
33+ runtime .NewInt (i ),
34+ )
35+ }
36+ obj := runtime .NewObjectWith (properties ... )
37+
38+ // Test existing key
39+ val , err := objects .Has (context .Background (), obj , runtime .NewString ("key50" ))
40+ valBool := val .(runtime.Boolean )
41+
42+ So (err , ShouldEqual , nil )
43+ So (bool (valBool ), ShouldEqual , true )
44+
45+ // Test non-existing key
46+ val , err = objects .Has (context .Background (), obj , runtime .NewString ("key999" ))
47+ valBool = val .(runtime.Boolean )
48+
49+ So (err , ShouldEqual , nil )
50+ So (bool (valBool ), ShouldEqual , false )
51+ })
52+ })
53+ }
54+
55+ func TestKeysEdgeCases (t * testing.T ) {
56+ Convey ("Edge cases for Keys function" , t , func () {
57+ Convey ("When object has special character keys" , func () {
58+ obj := runtime .NewObjectWith (
59+ runtime .NewObjectProperty ("key with spaces" , runtime .NewInt (1 )),
60+ runtime .NewObjectProperty ("key_with_underscores" , runtime .NewInt (2 )),
61+ runtime .NewObjectProperty ("key-with-dashes" , runtime .NewInt (3 )),
62+ runtime .NewObjectProperty ("key.with.dots" , runtime .NewInt (4 )),
63+ )
64+
65+ keys , err := objects .Keys (context .Background (), obj , runtime .NewBoolean (true ))
66+ keysArray := keys .(* runtime.Array )
67+
68+ So (err , ShouldEqual , nil )
69+ actualLength , _ := keysArray .Length (context .Background ())
70+ So (actualLength , ShouldEqual , 4 )
71+
72+ // Check sorted order
73+ expectedKeys := []string {"key with spaces" , "key-with-dashes" , "key.with.dots" , "key_with_underscores" }
74+ for idx , expectedKey := range expectedKeys {
75+ actualKey , _ := keysArray .Get (context .Background (), runtime .NewInt (idx ))
76+ So (actualKey .String (), ShouldEqual , expectedKey )
77+ }
78+ })
79+ })
80+ }
81+
82+ func TestValuesEdgeCases (t * testing.T ) {
83+ Convey ("Edge cases for Values function" , t , func () {
84+ Convey ("When object has nil values" , func () {
85+ obj := runtime .NewObjectWith (
86+ runtime .NewObjectProperty ("none" , runtime .None ),
87+ runtime .NewObjectProperty ("bool" , runtime .NewBoolean (false )),
88+ runtime .NewObjectProperty ("empty_string" , runtime .NewString ("" )),
89+ )
90+
91+ actual , err := objects .Values (context .Background (), obj )
92+ actualArray := actual .(* runtime.Array )
93+
94+ So (err , ShouldBeNil )
95+ actualLength , _ := actualArray .Length (context .Background ())
96+ So (actualLength , ShouldEqual , 3 )
97+
98+ // Verify all values are present
99+ foundNone := false
100+ foundBool := false
101+ foundEmptyString := false
102+
103+ actualArray .ForEach (context .Background (), func (ctx context.Context , val runtime.Value , idx runtime.Int ) (runtime.Boolean , error ) {
104+ if runtime .CompareValues (val , runtime .None ) == 0 {
105+ foundNone = true
106+ }
107+ if runtime .CompareValues (val , runtime .NewBoolean (false )) == 0 {
108+ foundBool = true
109+ }
110+ if runtime .CompareValues (val , runtime .NewString ("" )) == 0 {
111+ foundEmptyString = true
112+ }
113+ return true , nil
114+ })
115+
116+ So (foundNone , ShouldBeTrue )
117+ So (foundBool , ShouldBeTrue )
118+ So (foundEmptyString , ShouldBeTrue )
119+ })
120+
121+ Convey ("When object has deeply nested structures" , func () {
122+ deepObject := runtime .NewObjectWith (
123+ runtime .NewObjectProperty ("level1" , runtime .NewObjectWith (
124+ runtime .NewObjectProperty ("level2" , runtime .NewObjectWith (
125+ runtime .NewObjectProperty ("level3" , runtime .NewString ("deep" )),
126+ )),
127+ )),
128+ )
129+
130+ obj := runtime .NewObjectWith (
131+ runtime .NewObjectProperty ("deep" , deepObject ),
132+ )
133+
134+ actual , err := objects .Values (context .Background (), obj )
135+ actualArray := actual .(* runtime.Array )
136+
137+ So (err , ShouldBeNil )
138+ actualLength , _ := actualArray .Length (context .Background ())
139+ So (actualLength , ShouldEqual , 1 )
140+
141+ // Get the deep object and verify it's independent
142+ returnedDeep , _ := actualArray .Get (context .Background (), runtime .NewInt (0 ))
143+ returnedDeepObj := returnedDeep .(* runtime.Object )
144+
145+ // Modify the original deep object
146+ deepObject .Set (context .Background (), runtime .NewString ("modified" ), runtime .NewString ("value" ))
147+
148+ // Check that the returned object wasn't affected
149+ hasModified , _ := returnedDeepObj .ContainsKey (context .Background (), runtime .NewString ("modified" ))
150+ So (hasModified , ShouldEqual , runtime .False )
151+ })
152+ })
153+ }
154+
155+ func TestZipEdgeCases (t * testing.T ) {
156+ Convey ("Edge cases for Zip function" , t , func () {
157+ Convey ("When keys contain special characters" , func () {
158+ keys := runtime .NewArrayWith (
159+ runtime .NewString ("key with spaces" ),
160+ runtime .NewString ("key_with_underscores" ),
161+ runtime .NewString ("key-with-dashes" ),
162+ )
163+ vals := runtime .NewArrayWith (
164+ runtime .NewInt (1 ),
165+ runtime .NewInt (2 ),
166+ runtime .NewInt (3 ),
167+ )
168+
169+ actual , err := objects .Zip (context .Background (), keys , vals )
170+ actualObj := actual .(* runtime.Object )
171+
172+ So (err , ShouldBeNil )
173+
174+ // Check all keys are present
175+ val1 , _ := actualObj .Get (context .Background (), runtime .NewString ("key with spaces" ))
176+ So (runtime .CompareValues (val1 , runtime .NewInt (1 )), ShouldEqual , 0 )
177+
178+ val2 , _ := actualObj .Get (context .Background (), runtime .NewString ("key_with_underscores" ))
179+ So (runtime .CompareValues (val2 , runtime .NewInt (2 )), ShouldEqual , 0 )
180+
181+ val3 , _ := actualObj .Get (context .Background (), runtime .NewString ("key-with-dashes" ))
182+ So (runtime .CompareValues (val3 , runtime .NewInt (3 )), ShouldEqual , 0 )
183+ })
184+
185+ Convey ("When values are all None" , func () {
186+ keys := runtime .NewArrayWith (
187+ runtime .NewString ("k1" ),
188+ runtime .NewString ("k2" ),
189+ )
190+ vals := runtime .NewArrayWith (
191+ runtime .None ,
192+ runtime .None ,
193+ )
194+
195+ actual , err := objects .Zip (context .Background (), keys , vals )
196+ actualObj := actual .(* runtime.Object )
197+
198+ So (err , ShouldBeNil )
199+
200+ val1 , _ := actualObj .Get (context .Background (), runtime .NewString ("k1" ))
201+ So (runtime .CompareValues (val1 , runtime .None ), ShouldEqual , 0 )
202+
203+ val2 , _ := actualObj .Get (context .Background (), runtime .NewString ("k2" ))
204+ So (runtime .CompareValues (val2 , runtime .None ), ShouldEqual , 0 )
205+ })
206+ })
207+ }
208+
209+ func TestMergeEdgeCases (t * testing.T ) {
210+ Convey ("Edge cases for Merge functions" , t , func () {
211+ Convey ("Merge with empty objects" , func () {
212+ obj1 := runtime .NewObject ()
213+ obj2 := runtime .NewObjectWith (
214+ runtime .NewObjectProperty ("key" , runtime .NewString ("value" )),
215+ )
216+
217+ merged , err := objects .Merge (context .Background (), obj1 , obj2 )
218+ mergedObj := merged .(* runtime.Object )
219+
220+ So (err , ShouldBeNil )
221+
222+ val , _ := mergedObj .Get (context .Background (), runtime .NewString ("key" ))
223+ So (runtime .CompareValues (val , runtime .NewString ("value" )), ShouldEqual , 0 )
224+ })
225+
226+ Convey ("MergeRecursive with identical objects" , func () {
227+ obj := runtime .NewObjectWith (
228+ runtime .NewObjectProperty ("key" , runtime .NewString ("value" )),
229+ )
230+
231+ merged , err := objects .MergeRecursive (context .Background (), obj , obj )
232+
233+ So (err , ShouldBeNil )
234+ So (runtime .CompareValues (merged , obj ), ShouldEqual , 0 )
235+ })
236+ })
237+ }
0 commit comments