From 4397eef5fa2f628cb926bbfd055c800d7c8b0d40 Mon Sep 17 00:00:00 2001 From: Marek Stransky <77441794+Hopsaheysa@users.noreply.github.com> Date: Tue, 16 Jan 2024 10:40:22 +0100 Subject: [PATCH] Fixed attribute deserialization (#141) * #140: fix attribute deserialization * Add attributes deserialization test * Improve deserialization test conditions * Simplify test conditions --- .../UserOperation/WMTOperationFormData.swift | 20 +++++++++++++++++-- .../NetworkingObjectsTests.swift | 20 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/WultraMobileTokenSDK/Operations/Model/UserOperation/WMTOperationFormData.swift b/WultraMobileTokenSDK/Operations/Model/UserOperation/WMTOperationFormData.swift index 90854e8..9e1161a 100644 --- a/WultraMobileTokenSDK/Operations/Model/UserOperation/WMTOperationFormData.swift +++ b/WultraMobileTokenSDK/Operations/Model/UserOperation/WMTOperationFormData.swift @@ -39,8 +39,24 @@ public class WMTOperationFormData: Codable { let c = try decoder.container(keyedBy: Keys.self) title = try c.decode(String.self, forKey: .title) message = try c.decode(String.self, forKey: .message) - // attributes are optional - attributes = (try? c.decode([WMTOperationAttributeDecodable].self, forKey: .attributes).map { $0.attrObject }) ?? [] + + var operationAttributes: [WMTOperationAttribute] = [] + do { + var container = try c.nestedUnkeyedContainer(forKey: .attributes) + // If decoding fails log it and continue decoding until the end of container + while container.isAtEnd == false { + do { + let attribute = try WMTOperationAttributeDecodable(from: container.superDecoder()) + operationAttributes.append(attribute.attrObject) + } catch { + D.error("Error decoding WMTOperationFormData attribute: \(error)") + } + } + } catch { + D.print("No attributes in WMTOperationFormData: \(error)") + } + + attributes = operationAttributes } public init(title: String, message: String, attributes: [WMTOperationAttribute]) { diff --git a/WultraMobileTokenSDKTests/NetworkingObjectsTests.swift b/WultraMobileTokenSDKTests/NetworkingObjectsTests.swift index 8d24a02..f02018e 100644 --- a/WultraMobileTokenSDKTests/NetworkingObjectsTests.swift +++ b/WultraMobileTokenSDKTests/NetworkingObjectsTests.swift @@ -367,6 +367,26 @@ class NetworkingObjectsTests: XCTestCase { XCTAssert(obj.filter({ $0.status == val }).count == 1) } } + + func testAttributesDeserializationNotInterupted() { + // Non-optional amount removed from AMOUNT Attribute + let response = """ +{"status":"OK", "currentTimestamp":"2023-02-10T12:30:42+0000", "responseObject":[{"id":"930febe7-f350-419a-8bc0-c8883e7f71e3", "name":"authorize_payment", "data":"A1*A100CZK*Q238400856/0300**D20170629*NUtility Bill Payment - 05/2017", "operationCreated":"2018-08-08T12:30:42+0000", "operationExpires":"2018-08-08T12:35:43+0000", "allowedSignatureType": {"type":"2FA", "variants": ["possession_knowledge", "possession_biometry"]}, "formData": {"title":"Potvrzení platby", "message":"Dobrý den,prosíme o potvrzení následující platby:", "attributes": [{"type":"AMOUNT", "id":"operation.amount", "label":"Částka", "currency":"CZK"}, { "type": "AMOUNT_CONVERSION", "id": "operation.conversion", "label": "Conversion", "dynamic": true, "sourceAmount": 1.26, "sourceCurrency": "ETC", "targetAmount": 1710.98, "targetCurrency": "USD"}]}}]} +""" + + guard let result = try? jsonDecoder.decode(WPNResponseArray.self, from: response.data(using: .utf8)!) else { + XCTFail("Failed to parse JSON data") + return + } + + guard let attributes = result.responseObject?[0].formData.attributes else { + XCTFail("Failed to get attributes") + return + } + + XCTAssertTrue(attributes.count == 1, "There should be one Conversion Attribute but the count is: \(attributes.count)") + XCTAssert(attributes.first is WMTOperationAttributeAmountConversion, "The First attribute should be a Conversion Attribute.") + } } extension WPNRequestBase {