diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+DefaultEmptyPolymorphicArrayValue.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+DefaultEmptyPolymorphicArrayValue.swift index 25d1cf7..dcf0787 100644 --- a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+DefaultEmptyPolymorphicArrayValue.swift +++ b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+DefaultEmptyPolymorphicArrayValue.swift @@ -13,37 +13,35 @@ extension KeyedDecodingContainer { _ type: DefaultEmptyPolymorphicArrayValue.Type, forKey key: Key ) throws -> DefaultEmptyPolymorphicArrayValue where T: PolymorphicCodableStrategy { - // Check if key exists - guard contains(key) else { + switch try polymorphicKeyPresence(forKey: key) { + case .missing: return DefaultEmptyPolymorphicArrayValue(wrappedValue: [], outcome: .keyNotFound) - } - // Check if value is null - if try decodeNil(forKey: key) { + case .null: return DefaultEmptyPolymorphicArrayValue(wrappedValue: [], outcome: .valueWasNil) - } - // Try to decode using the property wrapper's decoder - let decoder = try superDecoder(forKey: key) - return try DefaultEmptyPolymorphicArrayValue(from: decoder) + case .present: + // Try to decode using the property wrapper's decoder + let decoder = try superDecoder(forKey: key) + return try DefaultEmptyPolymorphicArrayValue(from: decoder) + } } public func decodeIfPresent( _ type: DefaultEmptyPolymorphicArrayValue.Type, forKey key: Self.Key ) throws -> DefaultEmptyPolymorphicArrayValue? where T: PolymorphicCodableStrategy { - // Check if key exists - guard contains(key) else { + switch try polymorphicKeyPresence(forKey: key) { + case .missing: return nil - } - // Check if value is null - if try decodeNil(forKey: key) { + case .null: return DefaultEmptyPolymorphicArrayValue(wrappedValue: [], outcome: .valueWasNil) - } - // Try to decode using the property wrapper's decoder - let decoder = try superDecoder(forKey: key) - return try DefaultEmptyPolymorphicArrayValue(from: decoder) + case .present: + // Try to decode using the property wrapper's decoder + let decoder = try superDecoder(forKey: key) + return try DefaultEmptyPolymorphicArrayValue(from: decoder) + } } } diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+LossyOptionalPolymorphicValue.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+LossyOptionalPolymorphicValue.swift index 5bf1633..f2da236 100644 --- a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+LossyOptionalPolymorphicValue.swift +++ b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+LossyOptionalPolymorphicValue.swift @@ -24,30 +24,29 @@ extension KeyedDecodingContainer { _ type: LossyOptionalPolymorphicValue.Type, forKey key: Self.Key ) throws -> LossyOptionalPolymorphicValue? where T: PolymorphicCodableStrategy { - // Check if key exists - guard contains(key) else { + switch try polymorphicKeyPresence(forKey: key) { + case .missing: return nil - } - // Check if value is null - if try decodeNil(forKey: key) { + case .null: return LossyOptionalPolymorphicValue(wrappedValue: nil, outcome: .valueWasNil) - } - // Try to decode the polymorphic value - do { - let decoder = try superDecoder(forKey: key) - let value = try T.decode(from: decoder) - return LossyOptionalPolymorphicValue(wrappedValue: value, outcome: .decodedSuccessfully) - } catch { - #if DEBUG - /// Report error to resilient decoding error reporter - let decoder = try? superDecoder(forKey: key) - decoder?.reportError(error) - return LossyOptionalPolymorphicValue(wrappedValue: nil, outcome: .recoveredFrom(error, wasReported: true)) - #else - return LossyOptionalPolymorphicValue(wrappedValue: nil, outcome: .recoveredFrom(error, wasReported: false)) - #endif + case .present: + // Try to decode the polymorphic value + do { + let decoder = try superDecoder(forKey: key) + let value = try T.decode(from: decoder) + return LossyOptionalPolymorphicValue(wrappedValue: value, outcome: .decodedSuccessfully) + } catch { + #if DEBUG + /// Report error to resilient decoding error reporter + let decoder = try? superDecoder(forKey: key) + decoder?.reportError(error) + return LossyOptionalPolymorphicValue(wrappedValue: nil, outcome: .recoveredFrom(error, wasReported: true)) + #else + return LossyOptionalPolymorphicValue(wrappedValue: nil, outcome: .recoveredFrom(error, wasReported: false)) + #endif + } } } } diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+OptionalPolymorphicArrayValue.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+OptionalPolymorphicArrayValue.swift index 9eee15e..161bd8d 100644 --- a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+OptionalPolymorphicArrayValue.swift +++ b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+OptionalPolymorphicArrayValue.swift @@ -24,35 +24,34 @@ extension KeyedDecodingContainer { _ type: OptionalPolymorphicArrayValue.Type, forKey key: Self.Key ) throws -> OptionalPolymorphicArrayValue? where T: PolymorphicCodableStrategy { - // Check if the key exists - guard contains(key) else { + switch try polymorphicKeyPresence(forKey: key) { + case .missing: return nil - } - // Check if the value is null - if try decodeNil(forKey: key) { + case .null: return OptionalPolymorphicArrayValue(wrappedValue: nil, outcome: .valueWasNil) - } - // Try to decode the array - do { - var container = try nestedUnkeyedContainer(forKey: key) - var elements = [T.ExpectedType]() + case .present: + // Try to decode the array + do { + var container = try nestedUnkeyedContainer(forKey: key) + var elements = [T.ExpectedType]() - while !container.isAtEnd { - // Use PolymorphicValue for decoding each element - let value = try container.decode(PolymorphicValue.self) - elements.append(value.wrappedValue) - } + while !container.isAtEnd { + // Use PolymorphicValue for decoding each element + let value = try container.decode(PolymorphicValue.self) + elements.append(value.wrappedValue) + } - return OptionalPolymorphicArrayValue(wrappedValue: elements, outcome: .decodedSuccessfully) - } catch { - #if DEBUG - // Report the error through superDecoder - let decoder = try superDecoder(forKey: key) - decoder.reportError(error) - #endif - throw error + return OptionalPolymorphicArrayValue(wrappedValue: elements, outcome: .decodedSuccessfully) + } catch { + #if DEBUG + // Report the error through superDecoder + let decoder = try superDecoder(forKey: key) + decoder.reportError(error) + #endif + throw error + } } } } diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+OptionalPolymorphicValue.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+OptionalPolymorphicValue.swift index 6f513f8..cf53190 100644 --- a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+OptionalPolymorphicValue.swift +++ b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+OptionalPolymorphicValue.swift @@ -24,24 +24,17 @@ extension KeyedDecodingContainer { _ type: OptionalPolymorphicValue.Type, forKey key: Self.Key ) throws -> OptionalPolymorphicValue? where T: PolymorphicCodableStrategy { - // Check if key exists - guard contains(key) else { + switch try polymorphicKeyPresence(forKey: key) { + case .missing: return nil - } - // Check if value is null - if try decodeNil(forKey: key) { + case .null: return OptionalPolymorphicValue(wrappedValue: nil, outcome: .valueWasNil) - } - // Try to decode the polymorphic value - do { - let decoder = try superDecoder(forKey: key) - let value = try T.decode(from: decoder) - return OptionalPolymorphicValue(wrappedValue: value, outcome: .decodedSuccessfully) - } catch { + case .present: // OptionalPolymorphicValue throws errors instead of recovering - throw error + let value = try T.decode(from: superDecoder(forKey: key)) + return OptionalPolymorphicValue(wrappedValue: value, outcome: .decodedSuccessfully) } } } diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+PolymorphicKeyPresence.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+PolymorphicKeyPresence.swift new file mode 100644 index 0000000..788a751 --- /dev/null +++ b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+PolymorphicKeyPresence.swift @@ -0,0 +1,30 @@ +// +// KeyedDecodingContainer+PolymorphicKeyPresence.swift +// KarrotCodableKit +// +// Copyright © 2025 Danggeun Market Inc. All rights reserved. +// + +import Foundation + +/// Three-way result of probing a key before polymorphic decoding. +enum PolymorphicKeyPresence { + /// The key is absent from the container. + case missing + /// The key is present but its value is JSON `null`. + case null + /// The key is present with a non-null value. + case present +} + +extension KeyedDecodingContainer { + /// Resolves whether a key is missing, null, or present. + /// + /// Centralizes the `contains` / `decodeNil` ordering that every polymorphic property-wrapper + /// decode overload previously duplicated. The caller acquires its own `superDecoder(forKey:)` or + /// `nestedUnkeyedContainer(forKey:)` in the `.present` case, matching each wrapper's existing path. + func polymorphicKeyPresence(forKey key: Key) throws -> PolymorphicKeyPresence { + guard contains(key) else { return .missing } + return try decodeNil(forKey: key) ? .null : .present + } +} diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+PolymorphicLossyArrayValue.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+PolymorphicLossyArrayValue.swift index 0960e0a..fd2c9a1 100644 --- a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+PolymorphicLossyArrayValue.swift +++ b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedDecodingContainer+PolymorphicLossyArrayValue.swift @@ -13,8 +13,9 @@ extension KeyedDecodingContainer { _: PolymorphicLossyArrayValue.Type, forKey key: Key ) throws -> PolymorphicLossyArrayValue where T: PolymorphicCodableStrategy { - // Return empty array if key is missing - guard contains(key) else { + switch try polymorphicKeyPresence(forKey: key) { + case .missing: + // Return empty array if key is missing #if DEBUG let context = DecodingError.Context( codingPath: codingPath + [key], @@ -31,10 +32,8 @@ extension KeyedDecodingContainer { #else return PolymorphicLossyArrayValue(wrappedValue: [], outcome: .keyNotFound) #endif - } - // Check if value is null - if try decodeNil(forKey: key) { + case .null: #if DEBUG let context = DecodingError.Context( codingPath: codingPath + [key], @@ -51,23 +50,24 @@ extension KeyedDecodingContainer { #else return PolymorphicLossyArrayValue(wrappedValue: [], outcome: .valueWasNil) #endif - } - // Try to decode the array - do { - let decoder = try superDecoder(forKey: key) - return try PolymorphicLossyArrayValue(from: decoder) - } catch { - // If decoding fails (e.g., not an array), return empty array - #if DEBUG - return PolymorphicLossyArrayValue( - wrappedValue: [], - outcome: .recoveredFrom(error, wasReported: false), - results: [] - ) - #else - return PolymorphicLossyArrayValue(wrappedValue: [], outcome: .recoveredFrom(error, wasReported: false)) - #endif + case .present: + // Try to decode the array + do { + let decoder = try superDecoder(forKey: key) + return try PolymorphicLossyArrayValue(from: decoder) + } catch { + // If decoding fails (e.g., not an array), return empty array + #if DEBUG + return PolymorphicLossyArrayValue( + wrappedValue: [], + outcome: .recoveredFrom(error, wasReported: false), + results: [] + ) + #else + return PolymorphicLossyArrayValue(wrappedValue: [], outcome: .recoveredFrom(error, wasReported: false)) + #endif + } } } @@ -75,13 +75,11 @@ extension KeyedDecodingContainer { _: PolymorphicLossyArrayValue.Type, forKey key: Self.Key ) throws -> PolymorphicLossyArrayValue? where T: PolymorphicCodableStrategy { - // Check if key exists - guard contains(key) else { + switch try polymorphicKeyPresence(forKey: key) { + case .missing: return nil - } - // Check if value is null - if try decodeNil(forKey: key) { + case .null: #if DEBUG let context = DecodingError.Context( codingPath: codingPath + [key], @@ -96,12 +94,14 @@ extension KeyedDecodingContainer { results: [] ) #else - return PolymorphicLossyArrayValue(wrappedValue: []) + // Match `decode(_:forKey:)`: a null value maps to `.valueWasNil`, not `.decodedSuccessfully`. + return PolymorphicLossyArrayValue(wrappedValue: [], outcome: .valueWasNil) #endif - } - // Try to decode using PolymorphicLossyArrayValue's decoder - let decoder = try superDecoder(forKey: key) - return try PolymorphicLossyArrayValue(from: decoder) + case .present: + // Try to decode using PolymorphicLossyArrayValue's decoder + let decoder = try superDecoder(forKey: key) + return try PolymorphicLossyArrayValue(from: decoder) + } } } diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+LossyOptionalPolymorphicValue.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+LossyOptionalPolymorphicValue.swift deleted file mode 100644 index ca5e9de..0000000 --- a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+LossyOptionalPolymorphicValue.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// KeyedEncodingContainer+LossyOptionalPolymorphicValue.swift -// KarrotCodableKit -// -// Created by Elon on 6/26/26. -// Copyright © 2026 Danggeun Market Inc. All rights reserved. -// - -import Foundation - -extension KeyedEncodingContainer { - /// Encodes a `LossyOptionalPolymorphicValue`, omitting the key entirely when the wrapped value is `nil`. - /// - /// This mirrors Apple's default `Codable` behavior for optional properties, where a `nil` value - /// results in the key being skipped rather than encoded as an explicit `null`. It is the encoding-side - /// counterpart to the `decode(_:forKey:)` overload that treats a missing key as `nil`. - public mutating func encode( - _ value: LossyOptionalPolymorphicValue, - forKey key: Key - ) throws where T: PolymorphicCodableStrategy { - guard value.wrappedValue != nil else { return } - try value.encode(to: superEncoder(forKey: key)) - } -} diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OmitNilPolymorphicEncodable.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OmitNilPolymorphicEncodable.swift new file mode 100644 index 0000000..1c4a80d --- /dev/null +++ b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OmitNilPolymorphicEncodable.swift @@ -0,0 +1,48 @@ +// +// KeyedEncodingContainer+OmitNilPolymorphicEncodable.swift +// KarrotCodableKit +// +// Copyright © 2026 Danggeun Market Inc. All rights reserved. +// + +import Foundation + +/// An optional polymorphic property wrapper whose key should be omitted when its value is `nil`. +public protocol OmitNilPolymorphicEncodable: Encodable { + /// `true` when the wrapped optional value is `nil`. + var isWrappedValueNil: Bool { get } +} + +extension KeyedEncodingContainer { + /// Encodes an omit-nil polymorphic wrapper, skipping the key entirely when its value is `nil`. + /// + /// This mirrors Apple's default `Codable` behavior for optional properties, where a `nil` value + /// results in the key being skipped rather than encoded as an explicit `null`. It is the encoding-side + /// counterpart to the `decode(_:forKey:)` overload that treats a missing key as `nil`. + /// + /// This overload is chosen by overload resolution over the generic `encode` because + /// its `OmitNilPolymorphicEncodable` constraint is more specific. + public mutating func encode( + _ value: Wrapper, + forKey key: Key + ) throws where Wrapper: OmitNilPolymorphicEncodable { + guard !value.isWrappedValueNil else { return } + try value.encode(to: superEncoder(forKey: key)) + } +} + +extension OptionalPolymorphicValue: OmitNilPolymorphicEncodable { + public var isWrappedValueNil: Bool { wrappedValue == nil } +} + +extension LossyOptionalPolymorphicValue: OmitNilPolymorphicEncodable { + public var isWrappedValueNil: Bool { wrappedValue == nil } +} + +extension OptionalPolymorphicArrayValue: OmitNilPolymorphicEncodable { + public var isWrappedValueNil: Bool { wrappedValue == nil } +} + +extension OptionalPolymorphicLossyArrayValue: OmitNilPolymorphicEncodable { + public var isWrappedValueNil: Bool { wrappedValue == nil } +} diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OptionalPolymorphicArrayValue.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OptionalPolymorphicArrayValue.swift deleted file mode 100644 index a259a47..0000000 --- a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OptionalPolymorphicArrayValue.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// KeyedEncodingContainer+OptionalPolymorphicArrayValue.swift -// KarrotCodableKit -// -// Created by Elon on 6/26/26. -// Copyright © 2026 Danggeun Market Inc. All rights reserved. -// - -import Foundation - -extension KeyedEncodingContainer { - /// Encodes an `OptionalPolymorphicArrayValue`, omitting the key entirely when the wrapped array is `nil`. - /// - /// This mirrors Apple's default `Codable` behavior for optional properties, where a `nil` value - /// results in the key being skipped rather than encoded as an explicit `null`. It is the encoding-side - /// counterpart to the `decode(_:forKey:)` overload that treats a missing key as `nil`. - public mutating func encode( - _ value: OptionalPolymorphicArrayValue, - forKey key: Key - ) throws where T: PolymorphicCodableStrategy { - guard value.wrappedValue != nil else { return } - try value.encode(to: superEncoder(forKey: key)) - } -} diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OptionalPolymorphicLossyArrayValue.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OptionalPolymorphicLossyArrayValue.swift deleted file mode 100644 index 59d6249..0000000 --- a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OptionalPolymorphicLossyArrayValue.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// KeyedEncodingContainer+OptionalPolymorphicLossyArrayValue.swift -// KarrotCodableKit -// -// Created by Elon on 6/26/26. -// Copyright © 2026 Danggeun Market Inc. All rights reserved. -// - -import Foundation - -extension KeyedEncodingContainer { - /// Encodes an `OptionalPolymorphicLossyArrayValue`, omitting the key entirely when the wrapped array is `nil`. - /// - /// This mirrors Apple's default `Codable` behavior for optional properties, where a `nil` value - /// results in the key being skipped rather than encoded as an explicit `null`. It is the encoding-side - /// counterpart to the `decode(_:forKey:)` overload that treats a missing key as `nil`. - public mutating func encode( - _ value: OptionalPolymorphicLossyArrayValue, - forKey key: Key - ) throws where T: PolymorphicCodableStrategy { - guard value.wrappedValue != nil else { return } - try value.encode(to: superEncoder(forKey: key)) - } -} diff --git a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OptionalPolymorphicValue.swift b/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OptionalPolymorphicValue.swift deleted file mode 100644 index ebd6e43..0000000 --- a/Sources/KarrotCodableKit/PolymorphicCodable/Extensions/KeyedEncodingContainer+OptionalPolymorphicValue.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// KeyedEncodingContainer+OptionalPolymorphicValue.swift -// KarrotCodableKit -// -// Created by Elon on 6/26/26. -// Copyright © 2026 Danggeun Market Inc. All rights reserved. -// - -import Foundation - -extension KeyedEncodingContainer { - /// Encodes an `OptionalPolymorphicValue`, omitting the key entirely when the wrapped value is `nil`. - /// - /// This mirrors Apple's default `Codable` behavior for optional properties, where a `nil` value - /// results in the key being skipped rather than encoded as an explicit `null`. It is the encoding-side - /// counterpart to the `decode(_:forKey:)` overload that treats a missing key as `nil`. - public mutating func encode( - _ value: OptionalPolymorphicValue, - forKey key: Key - ) throws where T: PolymorphicCodableStrategy { - guard value.wrappedValue != nil else { return } - try value.encode(to: superEncoder(forKey: key)) - } -} diff --git a/Tests/KarrotCodableKitTests/PolymorphicCodable/ArrayValue/PolymorphicLossyArrayNullOutcomeTests.swift b/Tests/KarrotCodableKitTests/PolymorphicCodable/ArrayValue/PolymorphicLossyArrayNullOutcomeTests.swift new file mode 100644 index 0000000..baf155d --- /dev/null +++ b/Tests/KarrotCodableKitTests/PolymorphicCodable/ArrayValue/PolymorphicLossyArrayNullOutcomeTests.swift @@ -0,0 +1,42 @@ +// +// PolymorphicLossyArrayNullOutcomeTests.swift +// KarrotCodableKit +// +// Copyright © 2025 Danggeun Market Inc. All rights reserved. +// + +import Testing +import Foundation + +import KarrotCodableKit + +/// Guards the shared `PolymorphicKeyPresence` null branch for `@PolymorphicLossyArray`. +/// +/// Note: the container `decodeIfPresent(_:forKey:)` overload is not reached by synthesized `Codable` +/// (the wrapper's `wrappedValue` is a non-optional `[T]`, so the compiler calls `decode`). The +/// release-mode `outcome` is also a zero-size, non-`Equatable` value and thus unobservable. These +/// tests therefore characterize the observable `decode` null/missing behavior and its DEBUG outcome. +@Suite struct PolymorphicLossyArrayNullOutcomeTests { + + @Test func nullArrayDecodesToEmptyArray() throws { + let json = #"{ "notices1": null }"#.data(using: .utf8)! + + let result = try JSONDecoder().decode(OptionalLossyArrayDummyResponse.self, from: json) + + #expect(result.notices1.isEmpty) + #expect(result.notices2.isEmpty) + } + + #if DEBUG + @Test func nullArrayIsTreatedAsRecoveredNotSuccessful() throws { + let json = #"{ "notices1": null }"#.data(using: .utf8)! + + let result = try JSONDecoder().decode(OptionalLossyArrayDummyResponse.self, from: json) + + // A null value must not be reported as a clean success. + #expect(result.$notices1.outcome != .decodedSuccessfully) + // A missing key is likewise recovered, not a clean success. + #expect(result.$notices2.outcome != .decodedSuccessfully) + } + #endif +}