@@ -13,7 +13,7 @@ class TestUtils {
1313 static let commonDeviceId : String = " deviceId "
1414 static let commonAppKey : String = " appkey "
1515 static let host : String = " https://testing.count.ly/ "
16- static let SDK_VERSION = " 25.1.1 "
16+ static let SDK_VERSION = " 25.4.8 "
1717 static let SDK_NAME = " objc-native-ios "
1818
1919 static func cleanup( ) -> Void {
@@ -50,21 +50,38 @@ class TestUtils {
5050 }
5151
5252 static func validateRequest( _ params: [ String : Any ] , _ idx: Int , _ customValidator: ( [ String : Any ] ) -> Void ) {
53+ guard let rq = getCurrentRQ ( ) else {
54+ XCTFail ( " Request queue is nil. " )
55+ return
56+ }
57+ guard rq. indices. contains ( idx) else {
58+ XCTFail ( " Request index \( idx) out of bounds. RQ count: \( rq. count) . " )
59+ return
60+ }
61+
5362 let requestStr = getCurrentRQ ( ) ![ idx]
5463 let request = parseQueryString ( requestStr)
5564 validateRequiredParams ( request)
5665
5766 for (key, value) in params {
5867 let reqValue = request [ key]
68+ guard let reqValue else {
69+ XCTFail ( " Missing key ' \( key) ' in request. Expected value: \( value) , Request: \( requestStr) " )
70+ continue
71+ }
5972
60- if let nestedMap = value as? [ String : Any ] {
61- let nestedReqValue = reqValue as! [ String : Any ]
73+ if let nestedMap = value as? [ String : Any ] {
74+ guard let nestedReqValue = reqValue as? [ String : Any ] else {
75+ XCTFail ( " Key ' \( key) ' expected to be nested dictionary but got: \( reqValue) " )
76+ continue
77+ }
78+
6279 for (nestedKey, nestedValue) in nestedMap {
6380 XCTAssertEqual ( " \( String ( describing: nestedReqValue [ nestedKey] ) ) " , " \( nestedValue) " )
6481 }
6582 XCTAssertEqual ( nestedMap. count, nestedReqValue. count)
6683 } else {
67- XCTAssertEqual ( " \( String ( describing: reqValue! ) ) " , " \( value) " )
84+ XCTAssertEqual ( " \( String ( describing: reqValue) ) " , " \( value) " )
6885 }
6986 }
7087
@@ -216,38 +233,45 @@ class TestUtils {
216233
217234 static func parseQueryString( _ queryString: String ) -> [ String : Any ] {
218235 var result : [ String : Any ] = [ : ]
219-
220- // Split the query string by '&' to get individual key-value pairs
236+
237+ // Split query string into pairs
221238 let pairs = queryString. split ( separator: " & " )
222239
223240 for pair in pairs {
224- // Split each pair by '=' to separate the key and value
225- let components = pair. split ( separator: " = " , maxSplits: 1 )
241+ // Always split into 2 parts; missing value becomes empty string
242+ let components = pair. split ( separator: " = " , maxSplits: 1 , omittingEmptySubsequences : false )
226243
227- if components. count == 2 {
228- let key = String ( components [ 0 ] )
229- let value = String ( components [ 1 ] )
230-
231- // If the value is a JSON string (starts and ends with '%7B' and '%7D' respectively after URL decoding), decode it
232- if let decodedValue = value. removingPercentEncoding, decodedValue. hasPrefix ( " { " ) , decodedValue. hasSuffix ( " } " ) {
233- if let jsonData = decodedValue. data ( using: . utf8) {
234- do {
235- let jsonObject = try JSONSerialization . jsonObject ( with: jsonData, options: [ ] )
236- result [ key] = jsonObject
237- continue
238- } catch {
239- print ( " Error decoding JSON for key \( key) : \( error) " )
240- }
241- }
244+ guard components. count == 2 else {
245+ continue
246+ }
247+
248+ let key = String ( components [ 0 ] )
249+ let value = String ( components [ 1 ] ) // <-- empty string stays empty string
250+
251+ let decodedKey = key. removingPercentEncoding ?? key
252+ let decodedValue = value. removingPercentEncoding ?? value
253+
254+ // JSON detection (only if non-empty)
255+ if !decodedValue. isEmpty,
256+ decodedValue. hasPrefix ( " { " ) ,
257+ decodedValue. hasSuffix ( " } " ) ,
258+ let jsonData = decodedValue. data ( using: . utf8)
259+ {
260+ do {
261+ let jsonObject = try JSONSerialization . jsonObject ( with: jsonData, options: [ ] )
262+ result [ decodedKey] = jsonObject
263+ continue
264+ } catch {
242265 }
243-
244- // Otherwise, simply assign the value to the key in the result dictionary
245- result [ key] = value. removingPercentEncoding ?? value
246266 }
267+
268+ // Assign empty string value properly
269+ result [ decodedKey] = decodedValue
247270 }
248-
271+
249272 return result
250273 }
274+
251275
252276 static func compareDictionaries( _ dict1: [ String : Any ] , _ dict2: [ String : Any ] ) -> Bool {
253277 guard dict1. count == dict2. count else {
0 commit comments